annotate win32-mingw/include/kj/string-tree.h @ 83:ae30d91d2ffe

Replace these with versions built using an older toolset (so as to avoid ABI compatibilities when linking on Ubuntu 14.04 for packaging purposes)
author Chris Cannam
date Fri, 07 Feb 2020 11:51:13 +0000
parents eccd51b72864
children
rev   line source
Chris@64 1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
Chris@64 2 // Licensed under the MIT License:
Chris@64 3 //
Chris@64 4 // Permission is hereby granted, free of charge, to any person obtaining a copy
Chris@64 5 // of this software and associated documentation files (the "Software"), to deal
Chris@64 6 // in the Software without restriction, including without limitation the rights
Chris@64 7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
Chris@64 8 // copies of the Software, and to permit persons to whom the Software is
Chris@64 9 // furnished to do so, subject to the following conditions:
Chris@64 10 //
Chris@64 11 // The above copyright notice and this permission notice shall be included in
Chris@64 12 // all copies or substantial portions of the Software.
Chris@64 13 //
Chris@64 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Chris@64 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Chris@64 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
Chris@64 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
Chris@64 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
Chris@64 19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
Chris@64 20 // THE SOFTWARE.
Chris@64 21
Chris@64 22 #ifndef KJ_STRING_TREE_H_
Chris@64 23 #define KJ_STRING_TREE_H_
Chris@64 24
Chris@64 25 #if defined(__GNUC__) && !KJ_HEADER_WARNINGS
Chris@64 26 #pragma GCC system_header
Chris@64 27 #endif
Chris@64 28
Chris@64 29 #include "string.h"
Chris@64 30
Chris@64 31 namespace kj {
Chris@64 32
Chris@64 33 class StringTree {
Chris@64 34 // A long string, represented internally as a tree of strings. This data structure is like a
Chris@64 35 // String, but optimized for concatenation and iteration at the expense of seek time. The
Chris@64 36 // structure is intended to be used for building large text blobs from many small pieces, where
Chris@64 37 // repeatedly concatenating smaller strings into larger ones would waste copies. This structure
Chris@64 38 // is NOT intended for use cases requiring random access or computing substrings. For those,
Chris@64 39 // you should use a Rope, which is a much more complicated data structure.
Chris@64 40 //
Chris@64 41 // The proper way to construct a StringTree is via kj::strTree(...), which works just like
Chris@64 42 // kj::str(...) but returns a StringTree rather than a String.
Chris@64 43 //
Chris@64 44 // KJ_STRINGIFY() functions that construct large strings from many smaller strings are encouraged
Chris@64 45 // to return StringTree rather than a flat char container.
Chris@64 46
Chris@64 47 public:
Chris@64 48 inline StringTree(): size_(0) {}
Chris@64 49 inline StringTree(String&& text): size_(text.size()), text(kj::mv(text)) {}
Chris@64 50
Chris@64 51 StringTree(Array<StringTree>&& pieces, StringPtr delim);
Chris@64 52 // Build a StringTree by concatenating the given pieces, delimited by the given delimiter
Chris@64 53 // (e.g. ", ").
Chris@64 54
Chris@64 55 inline size_t size() const { return size_; }
Chris@64 56
Chris@64 57 template <typename Func>
Chris@64 58 void visit(Func&& func) const;
Chris@64 59
Chris@64 60 String flatten() const;
Chris@64 61 // Return the contents as a string.
Chris@64 62
Chris@64 63 // TODO(someday): flatten() when *this is an rvalue and when branches.size() == 0 could simply
Chris@64 64 // return `kj::mv(text)`. Requires reference qualifiers (Clang 3.3 / GCC 4.8).
Chris@64 65
Chris@64 66 void flattenTo(char* __restrict__ target) const;
Chris@64 67 // Copy the contents to the given character array. Does not add a NUL terminator.
Chris@64 68
Chris@64 69 private:
Chris@64 70 size_t size_;
Chris@64 71 String text;
Chris@64 72
Chris@64 73 struct Branch;
Chris@64 74 Array<Branch> branches; // In order.
Chris@64 75
Chris@64 76 inline void fill(char* pos, size_t branchIndex);
Chris@64 77 template <typename First, typename... Rest>
Chris@64 78 void fill(char* pos, size_t branchIndex, First&& first, Rest&&... rest);
Chris@64 79 template <typename... Rest>
Chris@64 80 void fill(char* pos, size_t branchIndex, StringTree&& first, Rest&&... rest);
Chris@64 81 template <typename... Rest>
Chris@64 82 void fill(char* pos, size_t branchIndex, Array<char>&& first, Rest&&... rest);
Chris@64 83 template <typename... Rest>
Chris@64 84 void fill(char* pos, size_t branchIndex, String&& first, Rest&&... rest);
Chris@64 85
Chris@64 86 template <typename... Params>
Chris@64 87 static StringTree concat(Params&&... params);
Chris@64 88 static StringTree&& concat(StringTree&& param) { return kj::mv(param); }
Chris@64 89
Chris@64 90 template <typename T>
Chris@64 91 static inline size_t flatSize(const T& t) { return t.size(); }
Chris@64 92 static inline size_t flatSize(String&& s) { return 0; }
Chris@64 93 static inline size_t flatSize(StringTree&& s) { return 0; }
Chris@64 94
Chris@64 95 template <typename T>
Chris@64 96 static inline size_t branchCount(const T& t) { return 0; }
Chris@64 97 static inline size_t branchCount(String&& s) { return 1; }
Chris@64 98 static inline size_t branchCount(StringTree&& s) { return 1; }
Chris@64 99
Chris@64 100 template <typename... Params>
Chris@64 101 friend StringTree strTree(Params&&... params);
Chris@64 102 };
Chris@64 103
Chris@64 104 inline StringTree&& KJ_STRINGIFY(StringTree&& tree) { return kj::mv(tree); }
Chris@64 105 inline const StringTree& KJ_STRINGIFY(const StringTree& tree) { return tree; }
Chris@64 106
Chris@64 107 inline StringTree KJ_STRINGIFY(Array<StringTree>&& trees) { return StringTree(kj::mv(trees), ""); }
Chris@64 108
Chris@64 109 template <typename... Params>
Chris@64 110 StringTree strTree(Params&&... params);
Chris@64 111 // Build a StringTree by stringifying the given parameters and concatenating the results.
Chris@64 112 // If any of the parameters stringify to StringTree rvalues, they will be incorporated as
Chris@64 113 // branches to avoid a copy.
Chris@64 114
Chris@64 115 // =======================================================================================
Chris@64 116 // Inline implementation details
Chris@64 117
Chris@64 118 namespace _ { // private
Chris@64 119
Chris@64 120 template <typename... Rest>
Chris@64 121 char* fill(char* __restrict__ target, const StringTree& first, Rest&&... rest) {
Chris@64 122 // Make str() work with stringifiers that return StringTree by patching fill().
Chris@64 123
Chris@64 124 first.flattenTo(target);
Chris@64 125 return fill(target + first.size(), kj::fwd<Rest>(rest)...);
Chris@64 126 }
Chris@64 127
Chris@64 128 template <typename T> constexpr bool isStringTree() { return false; }
Chris@64 129 template <> constexpr bool isStringTree<StringTree>() { return true; }
Chris@64 130
Chris@64 131 inline StringTree&& toStringTreeOrCharSequence(StringTree&& tree) { return kj::mv(tree); }
Chris@64 132 inline StringTree toStringTreeOrCharSequence(String&& str) { return StringTree(kj::mv(str)); }
Chris@64 133
Chris@64 134 template <typename T>
Chris@64 135 inline auto toStringTreeOrCharSequence(T&& value)
Chris@64 136 -> decltype(toCharSequence(kj::fwd<T>(value))) {
Chris@64 137 static_assert(!isStringTree<Decay<T>>(),
Chris@64 138 "When passing a StringTree into kj::strTree(), either pass it by rvalue "
Chris@64 139 "(use kj::mv(value)) or explicitly call value.flatten() to make a copy.");
Chris@64 140
Chris@64 141 return toCharSequence(kj::fwd<T>(value));
Chris@64 142 }
Chris@64 143
Chris@64 144 } // namespace _ (private)
Chris@64 145
Chris@64 146 struct StringTree::Branch {
Chris@64 147 size_t index;
Chris@64 148 // Index in `text` where this branch should be inserted.
Chris@64 149
Chris@64 150 StringTree content;
Chris@64 151 };
Chris@64 152
Chris@64 153 template <typename Func>
Chris@64 154 void StringTree::visit(Func&& func) const {
Chris@64 155 size_t pos = 0;
Chris@64 156 for (auto& branch: branches) {
Chris@64 157 if (branch.index > pos) {
Chris@64 158 func(text.slice(pos, branch.index));
Chris@64 159 pos = branch.index;
Chris@64 160 }
Chris@64 161 branch.content.visit(func);
Chris@64 162 }
Chris@64 163 if (text.size() > pos) {
Chris@64 164 func(text.slice(pos, text.size()));
Chris@64 165 }
Chris@64 166 }
Chris@64 167
Chris@64 168 inline void StringTree::fill(char* pos, size_t branchIndex) {
Chris@64 169 KJ_IREQUIRE(pos == text.end() && branchIndex == branches.size(),
Chris@64 170 kj::str(text.end() - pos, ' ', branches.size() - branchIndex).cStr());
Chris@64 171 }
Chris@64 172
Chris@64 173 template <typename First, typename... Rest>
Chris@64 174 void StringTree::fill(char* pos, size_t branchIndex, First&& first, Rest&&... rest) {
Chris@64 175 pos = _::fill(pos, kj::fwd<First>(first));
Chris@64 176 fill(pos, branchIndex, kj::fwd<Rest>(rest)...);
Chris@64 177 }
Chris@64 178
Chris@64 179 template <typename... Rest>
Chris@64 180 void StringTree::fill(char* pos, size_t branchIndex, StringTree&& first, Rest&&... rest) {
Chris@64 181 branches[branchIndex].index = pos - text.begin();
Chris@64 182 branches[branchIndex].content = kj::mv(first);
Chris@64 183 fill(pos, branchIndex + 1, kj::fwd<Rest>(rest)...);
Chris@64 184 }
Chris@64 185
Chris@64 186 template <typename... Rest>
Chris@64 187 void StringTree::fill(char* pos, size_t branchIndex, String&& first, Rest&&... rest) {
Chris@64 188 branches[branchIndex].index = pos - text.begin();
Chris@64 189 branches[branchIndex].content = StringTree(kj::mv(first));
Chris@64 190 fill(pos, branchIndex + 1, kj::fwd<Rest>(rest)...);
Chris@64 191 }
Chris@64 192
Chris@64 193 template <typename... Params>
Chris@64 194 StringTree StringTree::concat(Params&&... params) {
Chris@64 195 StringTree result;
Chris@64 196 result.size_ = _::sum({params.size()...});
Chris@64 197 result.text = heapString(
Chris@64 198 _::sum({StringTree::flatSize(kj::fwd<Params>(params))...}));
Chris@64 199 result.branches = heapArray<StringTree::Branch>(
Chris@64 200 _::sum({StringTree::branchCount(kj::fwd<Params>(params))...}));
Chris@64 201 result.fill(result.text.begin(), 0, kj::fwd<Params>(params)...);
Chris@64 202 return result;
Chris@64 203 }
Chris@64 204
Chris@64 205 template <typename... Params>
Chris@64 206 StringTree strTree(Params&&... params) {
Chris@64 207 return StringTree::concat(_::toStringTreeOrCharSequence(kj::fwd<Params>(params))...);
Chris@64 208 }
Chris@64 209
Chris@64 210 } // namespace kj
Chris@64 211
Chris@64 212 #endif // KJ_STRING_TREE_H_