jptree.ipp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems®.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. #ifndef _PTREE_IPP
  14. #define _PTREE_IPP
  15. #include "jarray.hpp"
  16. #include "jexcept.hpp"
  17. #include "jhash.hpp"
  18. #include "jmutex.hpp"
  19. #include "jsuperhash.hpp"
  20. #include "jptree.hpp"
  21. #include "jbuff.hpp"
  22. #define ANE_APPEND -1
  23. #define ANE_SET -2
  24. ///////////////////
  25. class MappingStringToOwned : public MappingStringTo<IInterfacePtr,IInterfacePtr>
  26. {
  27. public:
  28. MappingStringToOwned(const char * k, IInterfacePtr a) :
  29. MappingStringTo<IInterfacePtr,IInterfacePtr>(k,a) { }
  30. ~MappingStringToOwned() { ::Release(val); }
  31. };
  32. typedef MapStringTo<IInterfacePtr, IInterfacePtr, MappingStringToOwned> MapStringToOwned;
  33. // case sensitive childmap
  34. class jlib_decl ChildMap : protected SuperHashTableOf<IPropertyTree, constcharptr>
  35. {
  36. protected:
  37. // SuperHashTable definitions
  38. virtual void onAdd(void *) {}
  39. virtual void onRemove(void *e)
  40. {
  41. IPropertyTree &elem= *(IPropertyTree *)e;
  42. elem.Release();
  43. }
  44. virtual unsigned getHashFromElement(const void *e) const;
  45. virtual unsigned getHashFromFindParam(const void *fp) const
  46. {
  47. return hashc((const unsigned char *)fp, (size32_t)strlen((const char *)fp), 0);
  48. }
  49. virtual const void *getFindParam(const void *e) const
  50. {
  51. const IPropertyTree &elem=*(const IPropertyTree *)e;
  52. return (void *)elem.queryName();
  53. }
  54. virtual bool matchesFindParam(const void *e, const void *fp, unsigned fphash) const
  55. {
  56. return (0 == strcmp(((IPropertyTree *)e)->queryName(), (const char *)fp));
  57. }
  58. public:
  59. IMPLEMENT_IINTERFACE;
  60. IMPLEMENT_SUPERHASHTABLEOF_REF_FIND(IPropertyTree, constcharptr);
  61. inline unsigned count() const { return SuperHashTableOf<IPropertyTree, constcharptr>::count(); }
  62. ChildMap() : SuperHashTableOf<IPropertyTree, constcharptr>(4)
  63. {
  64. }
  65. ~ChildMap()
  66. {
  67. _releaseAll();
  68. }
  69. virtual unsigned numChildren();
  70. virtual IPropertyTreeIterator *getIterator(bool sort);
  71. virtual bool set(const char *key, IPropertyTree *tree)
  72. {
  73. return SuperHashTableOf<IPropertyTree, constcharptr>::replace(* tree);
  74. }
  75. virtual bool replace(const char *key, IPropertyTree *tree) // provides different semantics, used if element being replaced is not to be treated as deleted.
  76. {
  77. return SuperHashTableOf<IPropertyTree, constcharptr>::replace(* tree);
  78. }
  79. virtual IPropertyTree *query(const char *key)
  80. {
  81. return find(*key);
  82. }
  83. virtual bool remove(const char *key)
  84. {
  85. return SuperHashTableOf<IPropertyTree, constcharptr>::remove(key);
  86. }
  87. virtual bool removeExact(IPropertyTree *child)
  88. {
  89. return SuperHashTableOf<IPropertyTree, constcharptr>::removeExact(child);
  90. }
  91. };
  92. // case insensitive childmap
  93. class jlib_decl ChildMapNC : public ChildMap
  94. {
  95. public:
  96. // SuperHashTable definitions
  97. virtual unsigned getHashFromFindParam(const void *fp) const
  98. {
  99. return hashnc((const unsigned char *)fp, (size32_t)strlen((const char *)fp), 0);
  100. }
  101. virtual bool matchesFindParam(const void *e, const void *fp, unsigned fphash) const
  102. {
  103. return (0 == stricmp(((IPropertyTree *)e)->queryName(), (const char *)fp));
  104. }
  105. };
  106. inline static int validJSONUtf8ChrLen(unsigned char c)
  107. {
  108. if (c <= 31)
  109. return 0;
  110. if ('\"' == c)
  111. return 0;
  112. if ('\\' == c)
  113. return 2;
  114. return utf8CharLen(c);
  115. }
  116. inline static bool isAttribute(const char *xpath) { return (xpath && *xpath == '@'); }
  117. jlib_decl const char *splitXPathUQ(const char *xpath, StringBuffer &path);
  118. jlib_decl const char *queryHead(const char *xpath, StringBuffer &head);
  119. jlib_decl const char *queryNextUnquoted(const char *str, char c);
  120. interface IPTArrayValue
  121. {
  122. virtual ~IPTArrayValue() { }
  123. virtual bool isArray() const = 0;
  124. virtual bool isCompressed() const = 0;
  125. virtual const void *queryValue() const = 0;
  126. virtual MemoryBuffer &getValue(MemoryBuffer &tgt, bool binary) const = 0;
  127. virtual StringBuffer &getValue(StringBuffer &tgt, bool binary) const = 0;
  128. virtual size32_t queryValueSize() const = 0;
  129. virtual IPropertyTree *queryElement(unsigned idx) const = 0;
  130. virtual void addElement(IPropertyTree *e) = 0;
  131. virtual void setElement(unsigned idx, IPropertyTree *e) = 0;
  132. virtual void removeElement(unsigned idx) = 0;
  133. virtual unsigned elements() const = 0;
  134. virtual const void *queryValueRaw() const = 0;
  135. virtual size32_t queryValueRawSize() const = 0;
  136. virtual void serialize(MemoryBuffer &tgt) = 0;
  137. virtual void deserialize(MemoryBuffer &src) = 0;
  138. };
  139. class CPTArray : implements IPTArrayValue, private IArray
  140. {
  141. public:
  142. virtual bool isArray() const { return true; }
  143. virtual bool isCompressed() const { return false; }
  144. virtual const void *queryValue() const { UNIMPLEMENTED; }
  145. virtual MemoryBuffer &getValue(MemoryBuffer &tgt, bool binary) const { UNIMPLEMENTED; }
  146. virtual StringBuffer &getValue(StringBuffer &tgt, bool binary) const { UNIMPLEMENTED; }
  147. virtual size32_t queryValueSize() const { UNIMPLEMENTED; }
  148. virtual IPropertyTree *queryElement(unsigned idx) const { return (idx<ordinality()) ? &((IPropertyTree &)item(idx)) : NULL; }
  149. virtual void addElement(IPropertyTree *tree) { append(*tree); }
  150. virtual void setElement(unsigned idx, IPropertyTree *tree) { add(*tree, idx); }
  151. virtual void removeElement(unsigned idx) { remove(idx); }
  152. virtual unsigned elements() const { return ordinality(); }
  153. virtual const void *queryValueRaw() const { UNIMPLEMENTED; return NULL; }
  154. virtual size32_t queryValueRawSize() const { UNIMPLEMENTED; return 0; }
  155. // serializable
  156. virtual void serialize(MemoryBuffer &tgt) { UNIMPLEMENTED; }
  157. virtual void deserialize(MemoryBuffer &src) { UNIMPLEMENTED; }
  158. };
  159. class jlib_decl CPTValue : implements IPTArrayValue, private MemoryAttr
  160. {
  161. public:
  162. CPTValue(MemoryBuffer &src)
  163. {
  164. deserialize(src);
  165. }
  166. CPTValue(size32_t size, const void *data, bool binary=false, bool raw=false, bool compressed=false);
  167. virtual bool isArray() const { return false; }
  168. virtual bool isCompressed() const { return compressed; }
  169. virtual const void *queryValue() const;
  170. virtual MemoryBuffer &getValue(MemoryBuffer &tgt, bool binary) const;
  171. virtual StringBuffer &getValue(StringBuffer &tgt, bool binary) const;
  172. virtual size32_t queryValueSize() const;
  173. virtual IPropertyTree *queryElement(unsigned idx) const { UNIMPLEMENTED; return NULL; }
  174. virtual void addElement(IPropertyTree *tree) { UNIMPLEMENTED; }
  175. virtual void setElement(unsigned idx, IPropertyTree *tree) { UNIMPLEMENTED; }
  176. virtual void removeElement(unsigned idx) { UNIMPLEMENTED; }
  177. virtual unsigned elements() const { UNIMPLEMENTED; return (unsigned)-1; }
  178. virtual const void *queryValueRaw() const { return get(); }
  179. virtual size32_t queryValueRawSize() const { return (size32_t)length(); }
  180. // serilizable
  181. virtual void serialize(MemoryBuffer &tgt);
  182. virtual void deserialize(MemoryBuffer &src);
  183. private:
  184. mutable bool compressed;
  185. };
  186. #define IptFlagTst(fs, f) (0!=(fs&(f)))
  187. #define IptFlagSet(fs, f) (fs |= (f))
  188. #define IptFlagClr(fs, f) (fs &= (~f))
  189. struct AttrStr
  190. {
  191. unsigned hash;
  192. unsigned short linkcount;
  193. char str[1];
  194. const char *get() const { return str; }
  195. };
  196. struct AttrValue
  197. {
  198. AttrStr *key;
  199. AttrStr *value;
  200. };
  201. #define AM_NOCASE_FLAG (0x8000)
  202. #define AM_NOCASE_MASK (0x7fff)
  203. #ifdef __64BIT__
  204. #pragma pack(push,1)
  205. // Byte-Pack AttrMap and PTree because very large numbers are created. However, this may cause problems on systems that
  206. // require aligned pointer access. Without overriding the packing the structure currently wastes 8 bytes.
  207. // Ideally the classes would be restructured to avoid this, but it would probably require AttrMap to move into PTree
  208. #endif
  209. class jlib_decl AttrMap
  210. {
  211. AttrValue *attrs;
  212. unsigned short numattrs; // use top bit for nocase flag
  213. static AttrValue **freelist; // entry 0 not used
  214. static unsigned freelistmax;
  215. static CLargeMemoryAllocator freeallocator;
  216. AttrValue *newArray(unsigned n);
  217. void freeArray(AttrValue *a,unsigned n);
  218. public:
  219. AttrMap()
  220. {
  221. attrs = NULL;
  222. numattrs = 0;
  223. }
  224. ~AttrMap()
  225. {
  226. kill();
  227. }
  228. inline unsigned count() const
  229. {
  230. return numattrs&AM_NOCASE_MASK;
  231. }
  232. inline AttrValue *item(unsigned i) const
  233. {
  234. return attrs+i;
  235. }
  236. void setNoCase(bool nc)
  237. {
  238. if (nc)
  239. numattrs |= AM_NOCASE_FLAG;
  240. else
  241. numattrs &= AM_NOCASE_MASK;
  242. }
  243. inline bool isNoCase() const
  244. {
  245. return (numattrs&AM_NOCASE_FLAG)!=0;
  246. }
  247. void kill();
  248. void set(const char *key, const char *val);
  249. const char *find(const char *key) const;
  250. bool remove(const char *key);
  251. void swap(AttrMap &other);
  252. static inline void killfreelist()
  253. {
  254. free(freelist);
  255. freelist = NULL;
  256. }
  257. };
  258. class jlib_decl PTree : public CInterfaceOf<IPropertyTree>
  259. {
  260. friend class SingleIdIterator;
  261. friend class PTLocalIteratorBase;
  262. friend class PTIdMatchIterator;
  263. friend class ChildMap;
  264. public:
  265. PTree(MemoryBuffer &mb);
  266. PTree(const char *_name=NULL, byte _flags=0, IPTArrayValue *_value=NULL, ChildMap *_children=NULL);
  267. ~PTree();
  268. IPropertyTree *queryParent() { return parent; }
  269. IPropertyTree *queryChild(unsigned index);
  270. ChildMap *queryChildren() { return children; }
  271. aindex_t findChild(IPropertyTree *child, bool remove=false);
  272. inline bool isnocase() const { return IptFlagTst(flags, ipt_caseInsensitive); }
  273. ipt_flags queryFlags() const { return (ipt_flags) flags; }
  274. public:
  275. void serializeCutOff(MemoryBuffer &tgt, int cutoff=-1, int depth=0);
  276. void serializeAttributes(MemoryBuffer &tgt);
  277. virtual void serializeSelf(MemoryBuffer &tgt);
  278. virtual void deserializeSelf(MemoryBuffer &src);
  279. virtual void createChildMap() { children = isnocase()?new ChildMapNC():new ChildMap(); }
  280. HashKeyElement *queryKey() { return name; }
  281. void setName(const char *_name);
  282. IPropertyTree *clone(IPropertyTree &srcTree, bool self=false, bool sub=true);
  283. void clone(IPropertyTree &srcTree, IPropertyTree &dstTree, bool sub=true);
  284. inline void setParent(IPropertyTree *_parent) { parent = _parent; }
  285. IPropertyTree *queryCreateBranch(IPropertyTree *branch, const char *prop, bool *existing=NULL);
  286. IPropertyTree *splitBranchProp(const char *xpath, const char *&_prop, bool error=false);
  287. IPTArrayValue *queryValue() { return value; }
  288. IPTArrayValue *detachValue() { IPTArrayValue *v = value; value = NULL; return v; }
  289. void setValue(IPTArrayValue *_value, bool binary) { if (value) delete value; value = _value; if (binary) IptFlagSet(flags, ipt_binary); }
  290. bool checkPattern(const char *&xxpath) const;
  291. void clear();
  292. // IPropertyTree impl.
  293. virtual bool hasProp(const char * xpath) const;
  294. virtual bool isBinary(const char *xpath=NULL) const;
  295. virtual bool isCompressed(const char *xpath=NULL) const;
  296. virtual bool renameProp(const char *xpath, const char *newName);
  297. virtual bool renameTree(IPropertyTree *tree, const char *newName);
  298. virtual const char *queryProp(const char *xpath) const;
  299. virtual bool getProp(const char *xpath, StringBuffer &ret) const;
  300. virtual void setProp(const char *xpath, const char *val);
  301. virtual void addProp(const char *xpath, const char *val);
  302. virtual void appendProp(const char *xpath, const char *val);
  303. virtual bool getPropBool(const char *xpath, bool dft=false) const;
  304. virtual void setPropBool(const char *xpath, bool val) { setPropInt(xpath, val); }
  305. virtual void addPropBool(const char *xpath, bool val) { addPropInt(xpath, val); }
  306. virtual __int64 getPropInt64(const char *xpath, __int64 dft=0) const;
  307. virtual void setPropInt64(const char * xpath, __int64 val);
  308. virtual void addPropInt64(const char *xpath, __int64 val);
  309. virtual int getPropInt(const char *xpath, int dft=0) const;
  310. virtual void setPropInt(const char *xpath, int val);
  311. virtual void addPropInt(const char *xpath, int val);
  312. virtual bool getPropBin(const char * xpath, MemoryBuffer &ret) const;
  313. virtual void setPropBin(const char * xpath, size32_t size, const void *data);
  314. virtual void appendPropBin(const char *xpath, size32_t size, const void *data);
  315. virtual void addPropBin(const char *xpath, size32_t size, const void *data);
  316. virtual IPropertyTree *getPropTree(const char *xpath) const;
  317. virtual IPropertyTree *queryPropTree(const char *xpath) const;
  318. virtual IPropertyTree *getBranch(const char *xpath) const { return LINK(queryBranch(xpath)); }
  319. virtual IPropertyTree *queryBranch(const char *xpath) const { return queryPropTree(xpath); }
  320. virtual IPropertyTree *setPropTree(const char *xpath, IPropertyTree *val);
  321. virtual IPropertyTree *addPropTree(const char *xpath, IPropertyTree *val);
  322. virtual bool removeTree(IPropertyTree *child);
  323. virtual bool removeProp(const char *xpath);
  324. virtual aindex_t queryChildIndex(IPropertyTree *child);
  325. virtual const char *queryName() const;
  326. virtual StringBuffer &getName(StringBuffer &ret) const;
  327. virtual IAttributeIterator *getAttributes(bool sorted=false) const;
  328. virtual IPropertyTreeIterator *getElements(const char *xpath, IPTIteratorCodes flags = iptiter_null) const;
  329. virtual void localizeElements(const char *xpath, bool allTail=false);
  330. virtual bool hasChildren() const { return children && children->count()?true:false; }
  331. virtual unsigned numUniq() { return checkChildren()?children->count():0; }
  332. virtual unsigned numChildren();
  333. virtual bool isCaseInsensitive() { return isnocase(); }
  334. virtual unsigned getCount(const char *xpath);
  335. // serializable impl.
  336. virtual void serialize(MemoryBuffer &tgt);
  337. virtual void deserialize(MemoryBuffer &src);
  338. const AttrMap &queryAttributes() const { return attributes; }
  339. protected:
  340. virtual ChildMap *checkChildren() const;
  341. virtual bool isEquivalent(IPropertyTree *tree) { return (NULL != QUERYINTERFACE(tree, PTree)); }
  342. virtual void setLocal(size32_t l, const void *data, bool binary=false);
  343. virtual void appendLocal(size32_t l, const void *data, bool binary=false);
  344. virtual void setAttr(const char *attr, const char *val);
  345. virtual bool removeAttr(const char *attr);
  346. virtual void addingNewElement(IPropertyTree &child, int pos) { }
  347. virtual void removingElement(IPropertyTree *tree, unsigned pos) { }
  348. virtual IPropertyTree *create(const char *name=NULL, IPTArrayValue *value=NULL, ChildMap *children=NULL, bool existing=false) = 0;
  349. virtual IPropertyTree *create(MemoryBuffer &mb) = 0;
  350. virtual IPropertyTree *ownPTree(IPropertyTree *tree);
  351. aindex_t getChildMatchPos(const char *xpath);
  352. private:
  353. void init();
  354. void addLocal(size32_t l, const void *data, bool binary=false, int pos=-1);
  355. void resolveParentChild(const char *xpath, IPropertyTree *&parent, IPropertyTree *&child, StringAttr &path, StringAttr &qualifier);
  356. void replaceSelf(IPropertyTree *val);
  357. protected: // data
  358. IPropertyTree *parent; // ! currently only used if tree embedded into array, used to locate position.
  359. HashKeyElement *name;
  360. ChildMap *children;
  361. IPTArrayValue *value;
  362. //The packing (#pragma pack) is overridden because very large numbers of these objects are created, and the
  363. //following two members currently cause 8 bytes to be wasted. Refactoring the contents of AttrMap into this
  364. //class would allow the fields to pack cleanly.
  365. AttrMap attributes; // this has 2 "extra" bytes - which could pack into the space following the count
  366. byte flags; // this could also pack into the space following the count.
  367. };
  368. #ifdef __64BIT__
  369. #pragma pack(pop)
  370. #endif
  371. jlib_decl IPropertyTree *createPropBranch(IPropertyTree *tree, const char *xpath, bool createIntermediates=false, IPropertyTree **created=NULL, IPropertyTree **createdParent=NULL);
  372. class LocalPTree : public PTree
  373. {
  374. public:
  375. LocalPTree(const char *name=NULL, byte flags=ipt_none, IPTArrayValue *value=NULL, ChildMap *children=NULL)
  376. : PTree(name, flags, value, children) { }
  377. virtual bool isEquivalent(IPropertyTree *tree) { return (NULL != QUERYINTERFACE(tree, LocalPTree)); }
  378. virtual IPropertyTree *create(const char *name=NULL, IPTArrayValue *value=NULL, ChildMap *children=NULL, bool existing=false)
  379. {
  380. return new LocalPTree(name, flags, value, children);
  381. }
  382. virtual IPropertyTree *create(MemoryBuffer &mb)
  383. {
  384. IPropertyTree *tree = new LocalPTree();
  385. tree->deserialize(mb);
  386. return tree;
  387. }
  388. };
  389. class PTree;
  390. class SingleIdIterator : public CInterfaceOf<IPropertyTreeIterator>
  391. {
  392. public:
  393. SingleIdIterator(const PTree &_tree, unsigned pos=1, unsigned _many=(unsigned)-1);
  394. ~SingleIdIterator();
  395. void setCurrent(unsigned pos);
  396. // IPropertyTreeIterator
  397. virtual bool first();
  398. virtual bool next();
  399. virtual bool isValid();
  400. virtual IPropertyTree & query() { return * current; }
  401. private:
  402. unsigned many, count, whichNext, start;
  403. IPropertyTree *current;
  404. const PTree &tree;
  405. };
  406. class PTLocalIteratorBase : public CInterfaceOf<IPropertyTreeIterator>
  407. {
  408. public:
  409. PTLocalIteratorBase(const PTree *tree, const char *_id, bool _nocase, bool sort);
  410. ~PTLocalIteratorBase();
  411. virtual bool match() = 0;
  412. // IPropertyTreeIterator
  413. virtual bool first();
  414. virtual bool next();
  415. virtual bool isValid();
  416. virtual IPropertyTree & query() { return iter->query(); }
  417. protected:
  418. bool nocase, sort; // pack with the link count
  419. IPropertyTreeIterator *baseIter;
  420. StringAttr id;
  421. private:
  422. const PTree *tree;
  423. IPropertyTreeIterator *iter;
  424. IPropertyTree *current;
  425. bool _next();
  426. };
  427. class PTIdMatchIterator : public PTLocalIteratorBase
  428. {
  429. public:
  430. PTIdMatchIterator(const PTree *tree, const char *id, bool nocase, bool sort) : PTLocalIteratorBase(tree, id, nocase, sort) { }
  431. virtual bool match();
  432. };
  433. class StackElement;
  434. class PTStackIterator : public CInterfaceOf<IPropertyTreeIterator>
  435. {
  436. public:
  437. PTStackIterator(IPropertyTreeIterator *_iter, const char *_xpath);
  438. ~PTStackIterator();
  439. // IPropertyTreeIterator
  440. virtual bool first();
  441. virtual bool isValid();
  442. virtual bool next();
  443. virtual IPropertyTree & query();
  444. private:
  445. void setIterator(IPropertyTreeIterator *iter);
  446. void pushToStack(IPropertyTreeIterator *iter, const char *xpath);
  447. IPropertyTreeIterator *popFromStack(StringAttr &path);
  448. private: // data
  449. IPropertyTreeIterator *rootIter, *iter;
  450. const char *xxpath;
  451. IPropertyTree *current;
  452. StringAttr xpath, stackPath;
  453. unsigned stacklen;
  454. unsigned stackmax;
  455. StackElement *stack;
  456. };
  457. class CPTreeMaker : public CInterfaceOf<IPTreeMaker>
  458. {
  459. bool rootProvided, noRoot; // pack into the space following the link count
  460. IPropertyTree *root;
  461. ICopyArrayOf<IPropertyTree> ptreeStack;
  462. IPTreeNodeCreator *nodeCreator;
  463. class CDefaultNodeCreator : implements IPTreeNodeCreator, public CInterface
  464. {
  465. byte flags;
  466. public:
  467. IMPLEMENT_IINTERFACE;
  468. CDefaultNodeCreator(byte _flags) : flags(_flags) { }
  469. virtual IPropertyTree *create(const char *tag) { return createPTree(tag, flags); }
  470. };
  471. protected:
  472. IPropertyTree *currentNode;
  473. public:
  474. CPTreeMaker(byte flags=ipt_none, IPTreeNodeCreator *_nodeCreator=NULL, IPropertyTree *_root=NULL, bool _noRoot=false) : noRoot(_noRoot)
  475. {
  476. if (_nodeCreator)
  477. nodeCreator = LINK(_nodeCreator);
  478. else
  479. nodeCreator = new CDefaultNodeCreator(flags);
  480. if (_root)
  481. {
  482. root = LINK(_root);
  483. rootProvided = true;
  484. }
  485. else
  486. {
  487. root = NULL;
  488. rootProvided = false;
  489. }
  490. reset();
  491. }
  492. ~CPTreeMaker()
  493. {
  494. ::Release(nodeCreator);
  495. ::Release(root);
  496. }
  497. // IPTreeMaker
  498. virtual void beginNode(const char *tag, offset_t startOffset)
  499. {
  500. if (rootProvided)
  501. {
  502. currentNode = root;
  503. rootProvided = false;
  504. }
  505. else
  506. {
  507. IPropertyTree *parent = currentNode;
  508. if (!root)
  509. {
  510. currentNode = nodeCreator->create(tag);
  511. root = currentNode;
  512. }
  513. else
  514. currentNode = nodeCreator->create(NULL);
  515. if (parent)
  516. parent->addPropTree(tag, currentNode);
  517. else if (noRoot)
  518. root->addPropTree(tag, currentNode);
  519. }
  520. ptreeStack.append(*currentNode);
  521. }
  522. virtual void newAttribute(const char *name, const char *value)
  523. {
  524. currentNode->setProp(name, value);
  525. }
  526. virtual void beginNodeContent(const char *name) { }
  527. virtual void endNode(const char *tag, unsigned length, const void *value, bool binary, offset_t endOffset)
  528. {
  529. if (binary)
  530. currentNode->setPropBin(NULL, length, value);
  531. else
  532. currentNode->setProp(NULL, (const char *)value);
  533. unsigned c = ptreeStack.ordinality();
  534. if (c==1 && !noRoot && currentNode != root)
  535. ::Release(currentNode);
  536. ptreeStack.pop();
  537. currentNode = (c>1) ? &ptreeStack.tos() : NULL;
  538. }
  539. virtual IPropertyTree *queryRoot() { return root; }
  540. virtual IPropertyTree *queryCurrentNode() { return currentNode; }
  541. virtual void reset()
  542. {
  543. if (!rootProvided)
  544. {
  545. ::Release(root);
  546. if (noRoot)
  547. root = nodeCreator->create("__NoRoot__");
  548. else
  549. root = NULL;
  550. }
  551. currentNode = NULL;
  552. }
  553. virtual IPropertyTree *create(const char *tag)
  554. {
  555. return nodeCreator->create(tag);
  556. }
  557. };
  558. #endif