@@ -102,16 +102,43 @@ class DocNode : public NodeImpl {
102102 LOG_DEBUG (VALUE (depth), k, ' :' , v);
103103 }
104104 }
105- void set_children (vector<Derived>&& nodes, bool _sort = true ) {
105+ struct Compare {
106+ const DocNode* _this;
107+ bool operator ()(uint32_t i, uint32_t j) const {
108+ auto si = _this->_children [i].get_key ();
109+ auto sj = _this->_children [j].get_key ();
110+ return si < sj || (si == sj && i < j);
111+ }
112+ bool operator ()(str s, uint32_t j) const {
113+ return s < _this->_children [j].get_key ();
114+ }
115+ bool operator ()(uint32_t i, str s) const {
116+ return _this->_children [i].get_key () < s;
117+ }
118+ };
119+ std::unique_ptr<uint32_t []> _index;
120+ void set_children (vector<Derived>&& nodes, bool _indexing = true ) {
106121 if (nodes.empty ()) return ;
107122 assert (nodes.size () <= MAX_NCHILDREN );
108123 if (nodes.size () > MAX_NCHILDREN )
109124 nodes.resize (MAX_NCHILDREN );
110- if (_sort)
111- sort (nodes.begin (), nodes.end ());
112- nodes.back ()._flags |= FLAG_IS_LAST ; // must be after sort!!!
113- _nchildren = nodes.size ();
114125 _children = std::move (nodes);
126+ _nchildren = _children.size ();
127+ if (_indexing) {
128+ _index.reset (new uint32_t [_nchildren]);
129+ for (size_t i = 0 ; i < _nchildren; ++i) _index[i] = i;
130+ std::sort (_index.get (), _index.get () + _nchildren, Compare{this });
131+ Derived *a, *b = &_children[_index[0 ]];
132+ for (size_t i = 1 ; i < _nchildren; ++i) {
133+ a = b; b = &_children[_index[i]];
134+ if (a->get_key () != b->get_key ())
135+ a->_flags |= FLAG_EQUAL_KEY_LAST ;
136+ }
137+ b->_flags |= FLAG_EQUAL_KEY_LAST ;
138+ }
139+ // user-side has no idea about # of children,
140+ // so we use this flag to indicate ending
141+ _children.back ()._flags |= FLAG_IS_LAST ;
115142 }
116143 ~DocNode () override {
117144 if (is_root ()) {
@@ -121,16 +148,20 @@ class DocNode : public NodeImpl {
121148 }
122149 }
123150 const NodeImpl* get (size_t i) const override {
124- return (i < _children. size () ) ? &_children[i] : nullptr ;
151+ return (i < _nchildren ) ? &_children[i] : nullptr ;
125152 }
126153 const NodeImpl* get (str key) const override {
127154 if (_children.empty ()) return nullptr ;
128- for (size_t i = 0 ; i < _children. size () - 1 ; ++i) {
155+ for (size_t i = 0 ; i < _nchildren - 1U ; ++i) {
129156 assert ((_children[i]._flags & FLAG_IS_LAST ) == 0 );
130157 }
131158 assert (_children.back ()._flags & FLAG_IS_LAST );
132- auto it = std::lower_bound (_children.begin (), _children.end (), key);
133- return (it == _children.end () || it->get_key () != key) ? nullptr : &*it;
159+ if (!_index) return nullptr ;
160+ auto end = _index.get () + _nchildren;
161+ auto it = std::lower_bound (_index.get (), end, key, Compare{this });
162+ if (it == end || *it >= _nchildren || key != _children[*it].get_key ())
163+ return nullptr ;
164+ return &_children[*it];
134165 }
135166};
136167
@@ -196,13 +227,13 @@ struct JHandler : public BaseReaderHandler<UTF8<>, JHandler> {
196227 commit (true );
197228 return true ;
198229 }
199- void commit (bool sort ) {
230+ void commit (bool _indexing ) {
200231 assert (_nodes.size () > 1 );
201232 auto temp = std::move (_nodes.back ());
202233 _nodes.pop_back ();
203234 assert (_nodes.back ().size () > 0 );
204- // LOG_DEBUG(temp.size(), " elements to ", _nodes.back().back().get_key(), " sort=", sort );
205- _nodes.back ().back ().set_children (std::move (temp), sort );
235+ // LOG_DEBUG(temp.size(), " elements to ", _nodes.back().back().get_key(), VALUE(_indexing) );
236+ _nodes.back ().back ().set_children (std::move (temp), _indexing );
206237 }
207238 bool StartArray () {
208239 emplace_back (0 , 0 );
@@ -318,7 +349,9 @@ Node parse(char* text, size_t size, int flags) {
318349 if (flags & DOC_FREE_TEXT_IF_PARSING_FAILED ) free (text);
319350 LOG_ERROR_RETURN (EINVAL , nullptr , " invalid document type " , HEX (i));
320351 }
321- return parsers[i](text, size, flags);
352+ auto r = parsers[i](text, size, flags);
353+ if (!r && (flags & DOC_FREE_TEXT_IF_PARSING_FAILED )) free (text);
354+ return r;
322355}
323356
324357Node parse_file (fs::IFile* file, int flags) {
0 commit comments