deffield.cpp 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  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. #include "jlib.hpp"
  14. #include "jstream.hpp"
  15. #include "jmisc.hpp"
  16. #include "defvalue.hpp"
  17. #include "jexcept.hpp"
  18. #include "jlzw.hpp"
  19. #include "deffield.ipp"
  20. //------------------------------------------------------------------------------------------------
  21. CDefRecordElement::CDefRecordElement(DefElemKind _kind, IAtom * _name, ITypeInfo * _type, size32_t _maxSize)
  22. {
  23. kind = _kind;
  24. name = _name;
  25. type.set(_type);
  26. maxSize = _maxSize;
  27. closed = false;
  28. }
  29. bool CDefRecordElement::operator==(IDefRecordElement const & other) const
  30. {
  31. if((kind != other.getKind()) || (name != other.queryName()) || (maxSize != other.getMaxSize()) || (queryCompareValue() != other.queryCompareValue()) || (children.ordinality() != other.numChildren()))
  32. return false;
  33. if(type)
  34. {
  35. if((!other.queryType()) || !isSameBasicType(type, other.queryType()))
  36. return false;
  37. }
  38. else
  39. {
  40. if(other.queryType())
  41. return false;
  42. }
  43. ForEachItemIn(idx, children)
  44. if(!(children.item(idx) == *other.queryChild(idx)))
  45. return false;
  46. return true;
  47. }
  48. void CDefRecordElement::appendChild(IDefRecordElement * elem)
  49. {
  50. assertex(!closed);
  51. CDefRecordElement * cast = dynamic_cast<CDefRecordElement *>(elem);
  52. children.append(*LINK(cast));
  53. }
  54. IDefRecordElement * CDefRecordElement::close()
  55. {
  56. assertex(!closed);
  57. closed = true;
  58. return this;
  59. }
  60. //------------------------------------------------------------------------------------------------
  61. CDefRecordBuilder::CDefRecordBuilder(unsigned maxSize)
  62. {
  63. Owned<ITypeInfo> type = makeRecordType();
  64. elem.setown(new CDefRecordElement(DEKrecord, NULL, type, maxSize));
  65. }
  66. void CDefRecordBuilder::addChild(IDefRecordElement * element)
  67. {
  68. elem->appendChild(element);
  69. }
  70. void CDefRecordBuilder::addChildOwn(IDefRecordElement * element)
  71. {
  72. elem->appendChild(element);
  73. element->Release();
  74. }
  75. IDefRecordElement * CDefRecordBuilder::close()
  76. {
  77. return elem.getClear()->close();
  78. }
  79. //------------------------------------------------------------------------------------------------
  80. CDefRecordMeta::CDefRecordMeta(IDefRecordElement * _record, unsigned _numKeyed) : record(_record), numKeyed(_numKeyed)
  81. {
  82. }
  83. //------------------------------------------------------------------------------------------------
  84. IDefRecordElement * createDEfield(IAtom * name, ITypeInfo * type, IDefRecordElement * record, size32_t maxSize)
  85. {
  86. CDefRecordElement * elem = new CDefRecordElement(DEKfield, name, type, maxSize);
  87. if (record)
  88. elem->appendChild(record);
  89. return elem->close();
  90. }
  91. IDefRecordBuilder * createDErecord(size32_t maxSize)
  92. {
  93. return new CDefRecordBuilder(maxSize);
  94. }
  95. IDefRecordElement * createDEifblock(IDefRecordElement * field, IValue * value, IDefRecordElement * record)
  96. {
  97. CDefRecordElement * elem = new CDefIfBlock(value);
  98. elem->appendChild(field);
  99. elem->appendChild(record);
  100. return elem->close();
  101. }
  102. IDefRecordMeta * createDefRecordMeta(IDefRecordElement * record, unsigned numKeyed)
  103. {
  104. return new CDefRecordMeta(record, numKeyed);
  105. }
  106. //------------------------------------------------------------------------------------------------
  107. static void serializeElement(MemoryBuffer & target, IDefRecordElement * elem)
  108. {
  109. byte kind = elem ? elem->getKind() : DEKnone;
  110. target.append(kind);
  111. switch (kind)
  112. {
  113. case DEKnone:
  114. break;
  115. case DEKrecord:
  116. {
  117. size32_t maxSize = elem->getMaxSize();
  118. unsigned numChildren = elem->numChildren();
  119. target.append(maxSize).append(numChildren);
  120. for (unsigned i=0; i < numChildren; i++)
  121. serializeElement(target, elem->queryChild(i));
  122. break;
  123. }
  124. case DEKifblock:
  125. {
  126. IValue * value = elem->queryCompareValue();
  127. serializeValue(target, value);
  128. serializeElement(target, elem->queryChild(0));
  129. serializeElement(target, elem->queryChild(1));
  130. break;
  131. }
  132. case DEKfield:
  133. {
  134. IAtom * name = elem->queryName();
  135. ITypeInfo * type = elem->queryType();
  136. size32_t maxSize = elem->getMaxSize();
  137. serializeAtom(target, name);
  138. type->serialize(target);
  139. serializeElement(target, elem->queryChild(0));
  140. target.append(maxSize);
  141. break;
  142. }
  143. default:
  144. throwUnexpected();
  145. }
  146. }
  147. static void doSerializeRecordMeta(MemoryBuffer & target, IDefRecordMeta * meta)
  148. {
  149. serializeElement(target, meta->queryRecord());
  150. target.append(meta->numKeyedFields());
  151. }
  152. extern DEFTYPE_API void serializeRecordMeta(MemoryBuffer & target, IDefRecordMeta * meta, bool compress)
  153. {
  154. if (compress)
  155. {
  156. MemoryBuffer temp;
  157. doSerializeRecordMeta(temp, meta);
  158. compressToBuffer(target, temp.length(), temp.toByteArray());
  159. }
  160. else
  161. doSerializeRecordMeta(target, meta);
  162. }
  163. static IDefRecordElement * deserializeElement(MemoryBuffer & source)
  164. {
  165. byte kind;
  166. source.read(kind);
  167. switch (kind)
  168. {
  169. case DEKnone:
  170. return NULL;
  171. case DEKrecord:
  172. {
  173. size32_t maxSize;
  174. unsigned numChildren;
  175. source.read(maxSize).read(numChildren);
  176. Owned<IDefRecordBuilder> builder = createDErecord(maxSize);
  177. for (unsigned i=0; i < numChildren; i++)
  178. builder->addChildOwn(deserializeElement(source));
  179. return builder->close();
  180. }
  181. case DEKifblock:
  182. {
  183. Owned<IValue> value = deserializeValue(source);
  184. Owned<IDefRecordElement> field = deserializeElement(source);
  185. Owned<IDefRecordElement> record = deserializeElement(source);
  186. return createDEifblock(field, value, record);
  187. }
  188. case DEKfield:
  189. {
  190. IAtom * name = deserializeAtom(source);
  191. Owned<ITypeInfo> type = deserializeType(source);
  192. Owned<IDefRecordElement> record = deserializeElement(source);
  193. size32_t maxSize;
  194. source.read(maxSize);
  195. return createDEfield(name, type, record, maxSize);
  196. }
  197. default:
  198. throwUnexpected();
  199. }
  200. }
  201. static IDefRecordMeta * doDeserializeRecordMeta(MemoryBuffer & source)
  202. {
  203. Owned<IDefRecordElement> record = deserializeElement(source);
  204. unsigned numKeyed;
  205. source.read(numKeyed);
  206. return createDefRecordMeta(record, numKeyed);
  207. }
  208. extern DEFTYPE_API IDefRecordMeta * deserializeRecordMeta(MemoryBuffer & source, bool compress)
  209. {
  210. if (compress)
  211. {
  212. MemoryBuffer temp;
  213. decompressToBuffer(temp, source);
  214. return doDeserializeRecordMeta(temp);
  215. }
  216. else
  217. return doDeserializeRecordMeta(source);
  218. }
  219. extern DEFTYPE_API void serializeRecordMeta(IPropertyTree * target, IDefRecordMeta * meta);
  220. extern DEFTYPE_API IDefRecordMeta * deserializeRecordMeta(const IPropertyTree * source);
  221. static void addElementToPTree(IPropertyTree * root, IDefRecordElement * elem)
  222. {
  223. byte kind = elem ? elem->getKind() : DEKnone;
  224. Owned<IPTree> branch = createPTree();
  225. StringAttr branchName;
  226. switch (kind)
  227. {
  228. case DEKnone:
  229. branchName.set("None");
  230. if (elem)
  231. assertex(elem->numChildren() == 0);
  232. break;
  233. case DEKrecord:
  234. {
  235. branchName.set("Record");
  236. branch->setPropInt("@maxSize", elem->getMaxSize());
  237. unsigned numChildren = elem->numChildren();
  238. for (unsigned i=0; i < numChildren; i++)
  239. addElementToPTree(branch, elem->queryChild(i));
  240. break;
  241. }
  242. case DEKifblock:
  243. {
  244. branchName.set("IfBlock");
  245. StringBuffer value;
  246. elem->queryCompareValue()->getStringValue(value);
  247. branch->setProp("@compareValue", value.str());
  248. assertex(elem->numChildren() == 2);
  249. addElementToPTree(branch, elem->queryChild(0));
  250. addElementToPTree(branch, elem->queryChild(0));
  251. break;
  252. }
  253. case DEKfield:
  254. {
  255. branchName.set("Field");
  256. branch->setProp("@name", str(elem->queryName()));
  257. branch->setPropInt("@maxSize", elem->getMaxSize());
  258. StringBuffer type;
  259. elem->queryType()->getDescriptiveType(type);
  260. branch->setProp("@type", type.str());
  261. assertex(elem->numChildren() <= 1);
  262. if(elem->numChildren())
  263. addElementToPTree(branch, elem->queryChild(0));
  264. break;
  265. }
  266. default:
  267. throwUnexpected();
  268. }
  269. root->addPropTree(branchName.get(), branch.getClear());
  270. }
  271. extern DEFTYPE_API StringBuffer & getRecordMetaAsString(StringBuffer & out, IDefRecordMeta const * meta)
  272. {
  273. Owned<IPropertyTree> tree = createPTree("RecordMeta");
  274. tree->setPropInt("@numKeyedFields", meta->numKeyedFields());
  275. addElementToPTree(tree, meta->queryRecord());
  276. toXML(tree, out);
  277. return out;
  278. }