BinaryPropertyList.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825
  1. /*
  2. * Copyright (C) 2009 Apple Inc. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. * 1. Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * 2. Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. *
  13. * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
  14. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  15. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  16. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
  17. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  18. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  19. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  20. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  21. * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  22. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  23. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. */
  25. #include "BinaryPropertyList.h"
  26. #include <limits>
  27. #include <wtf/HashMap.h>
  28. #include <wtf/HashSet.h>
  29. #include <wtf/text/StringHash.h>
  30. static const size_t headerSize = 8;
  31. static const size_t trailerSize = 32;
  32. static const UInt8 booleanTrueMarkerByte = 0x09;
  33. static const UInt8 oneByteIntegerMarkerByte = 0x10;
  34. static const UInt8 twoByteIntegerMarkerByte = 0x11;
  35. static const UInt8 fourByteIntegerMarkerByte = 0x12;
  36. static const UInt8 eightByteIntegerMarkerByte = 0x13;
  37. static const UInt8 asciiStringMarkerByte = 0x50;
  38. static const UInt8 asciiStringWithSeparateLengthMarkerByte = 0x5F;
  39. static const UInt8 unicodeStringMarkerByte = 0x60;
  40. static const UInt8 unicodeStringWithSeparateLengthMarkerByte = 0x6F;
  41. static const UInt8 arrayMarkerByte = 0xA0;
  42. static const UInt8 arrayWithSeparateLengthMarkerByte = 0xAF;
  43. static const UInt8 dictionaryMarkerByte = 0xD0;
  44. static const UInt8 dictionaryWithSeparateLengthMarkerByte = 0xDF;
  45. static const size_t maxLengthInMarkerByte = 0xE;
  46. class IntegerArray {
  47. public:
  48. IntegerArray() : m_integers(0), m_size(0) { }
  49. IntegerArray(const int* integers, size_t size) : m_integers(integers), m_size(size) { ASSERT(integers); ASSERT(size); }
  50. void markDeleted() { m_integers = 0; m_size = deletedValueSize(); }
  51. bool isDeletedValue() const { return m_size == deletedValueSize(); }
  52. const int* integers() const { ASSERT(!isDeletedValue()); return m_integers; }
  53. size_t size() const { ASSERT(!isDeletedValue()); return m_size; }
  54. private:
  55. static size_t deletedValueSize() { return std::numeric_limits<size_t>::max(); }
  56. friend bool operator==(const IntegerArray&, const IntegerArray&);
  57. const int* m_integers;
  58. size_t m_size;
  59. };
  60. inline bool operator==(const IntegerArray& a, const IntegerArray& b)
  61. {
  62. return a.m_integers == b.m_integers && a.m_size == b.m_size;
  63. }
  64. struct IntegerArrayHashTraits : WTF::GenericHashTraits<IntegerArray> {
  65. static const bool needsDestruction = false;
  66. static void constructDeletedValue(IntegerArray& slot) { slot.markDeleted(); }
  67. static bool isDeletedValue(const IntegerArray& array) { return array.isDeletedValue(); }
  68. };
  69. struct IntegerArrayHash {
  70. static unsigned hash(const IntegerArray&);
  71. static bool equal(const IntegerArray&, const IntegerArray&);
  72. static const bool safeToCompareToEmptyOrDeleted = true;
  73. };
  74. unsigned IntegerArrayHash::hash(const IntegerArray& array)
  75. {
  76. return StringHasher::hashMemory(array.integers(), array.size() * sizeof(int));
  77. }
  78. bool IntegerArrayHash::equal(const IntegerArray& a, const IntegerArray& b)
  79. {
  80. if (a.isDeletedValue() || b.isDeletedValue())
  81. return a.isDeletedValue() == b.isDeletedValue();
  82. if (a.size() != b.size())
  83. return false;
  84. for (size_t i = 0; i < a.size(); ++i) {
  85. if (a.integers()[i] != b.integers()[i])
  86. return false;
  87. }
  88. return true;
  89. }
  90. typedef size_t ObjectReference;
  91. class BinaryPropertyListPlan : private BinaryPropertyListObjectStream {
  92. public:
  93. BinaryPropertyListPlan(BinaryPropertyListWriter&);
  94. ObjectReference booleanTrueObjectReference() const;
  95. ObjectReference integerObjectReference(int) const;
  96. ObjectReference stringObjectReference(const String&) const;
  97. ObjectReference integerArrayObjectReference(const int*, size_t) const;
  98. ObjectReference objectCount() const { return m_currentObjectReference; }
  99. ObjectReference byteCount() const { return m_byteCount; }
  100. ObjectReference objectReferenceCount() const { return m_objectReferenceCount; }
  101. private:
  102. virtual void writeBooleanTrue();
  103. virtual void writeInteger(int);
  104. virtual void writeString(const String&);
  105. virtual void writeIntegerArray(const int*, size_t);
  106. virtual void writeUniqueString(const String&);
  107. virtual void writeUniqueString(const char*);
  108. virtual size_t writeArrayStart();
  109. virtual void writeArrayEnd(size_t);
  110. virtual size_t writeDictionaryStart();
  111. virtual void writeDictionaryEnd(size_t);
  112. void writeArrayObject(size_t);
  113. void writeDictionaryObject(size_t);
  114. void writeStringObject(const String&);
  115. void writeStringObject(const char*);
  116. static ObjectReference invalidObjectReference() { return std::numeric_limits<ObjectReference>::max(); }
  117. typedef HashMap<IntegerArray, ObjectReference, IntegerArrayHash, IntegerArrayHashTraits> IntegerArrayMap;
  118. ObjectReference m_booleanTrueObjectReference;
  119. ObjectReference m_integerZeroObjectReference;
  120. HashMap<int, ObjectReference> m_integers;
  121. HashMap<String, ObjectReference> m_strings;
  122. IntegerArrayMap m_integerArrays;
  123. ObjectReference m_currentObjectReference;
  124. size_t m_currentAggregateSize;
  125. size_t m_byteCount;
  126. size_t m_objectReferenceCount;
  127. };
  128. BinaryPropertyListPlan::BinaryPropertyListPlan(BinaryPropertyListWriter& client)
  129. : m_booleanTrueObjectReference(invalidObjectReference())
  130. , m_integerZeroObjectReference(invalidObjectReference())
  131. , m_currentObjectReference(0)
  132. , m_currentAggregateSize(0)
  133. , m_byteCount(0)
  134. , m_objectReferenceCount(0)
  135. {
  136. client.writeObjects(*this);
  137. ASSERT(m_currentAggregateSize == 1);
  138. }
  139. void BinaryPropertyListPlan::writeBooleanTrue()
  140. {
  141. ++m_currentAggregateSize;
  142. if (m_booleanTrueObjectReference != invalidObjectReference())
  143. return;
  144. m_booleanTrueObjectReference = m_currentObjectReference++;
  145. ++m_byteCount;
  146. }
  147. static inline int integerByteCount(size_t integer)
  148. {
  149. if (integer <= 0xFF)
  150. return 2;
  151. if (integer <= 0xFFFF)
  152. return 3;
  153. #ifdef __LP64__
  154. if (integer <= 0xFFFFFFFFULL)
  155. return 5;
  156. return 9;
  157. #else
  158. return 5;
  159. #endif
  160. }
  161. void BinaryPropertyListPlan::writeInteger(int integer)
  162. {
  163. ASSERT(integer >= 0);
  164. ++m_currentAggregateSize;
  165. if (!integer) {
  166. if (m_integerZeroObjectReference != invalidObjectReference())
  167. return;
  168. m_integerZeroObjectReference = m_currentObjectReference;
  169. } else {
  170. if (!m_integers.add(integer, m_currentObjectReference).isNewEntry)
  171. return;
  172. }
  173. ++m_currentObjectReference;
  174. m_byteCount += integerByteCount(integer);
  175. }
  176. void BinaryPropertyListPlan::writeString(const String& string)
  177. {
  178. ++m_currentAggregateSize;
  179. if (!m_strings.add(string, m_currentObjectReference).isNewEntry)
  180. return;
  181. ++m_currentObjectReference;
  182. writeStringObject(string);
  183. }
  184. void BinaryPropertyListPlan::writeIntegerArray(const int* integers, size_t size)
  185. {
  186. size_t savedAggregateSize = ++m_currentAggregateSize;
  187. ASSERT(size);
  188. IntegerArrayMap::AddResult addResult = m_integerArrays.add(IntegerArray(integers, size), 0);
  189. if (!addResult.isNewEntry)
  190. return;
  191. for (size_t i = 0; i < size; ++i)
  192. writeInteger(integers[i]);
  193. addResult.iterator->value = m_currentObjectReference++;
  194. writeArrayObject(size);
  195. m_currentAggregateSize = savedAggregateSize;
  196. }
  197. void BinaryPropertyListPlan::writeUniqueString(const String& string)
  198. {
  199. ++m_currentAggregateSize;
  200. ++m_currentObjectReference;
  201. writeStringObject(string);
  202. }
  203. void BinaryPropertyListPlan::writeUniqueString(const char* string)
  204. {
  205. ++m_currentAggregateSize;
  206. ++m_currentObjectReference;
  207. writeStringObject(string);
  208. }
  209. size_t BinaryPropertyListPlan::writeArrayStart()
  210. {
  211. size_t savedAggregateSize = m_currentAggregateSize;
  212. m_currentAggregateSize = 0;
  213. return savedAggregateSize;
  214. }
  215. void BinaryPropertyListPlan::writeArrayEnd(size_t savedAggregateSize)
  216. {
  217. ++m_currentObjectReference;
  218. writeArrayObject(m_currentAggregateSize);
  219. m_currentAggregateSize = savedAggregateSize + 1;
  220. }
  221. size_t BinaryPropertyListPlan::writeDictionaryStart()
  222. {
  223. size_t savedAggregateSize = m_currentAggregateSize;
  224. m_currentAggregateSize = 0;
  225. return savedAggregateSize;
  226. }
  227. void BinaryPropertyListPlan::writeDictionaryEnd(size_t savedAggregateSize)
  228. {
  229. ++m_currentObjectReference;
  230. writeDictionaryObject(m_currentAggregateSize);
  231. m_currentAggregateSize = savedAggregateSize + 1;
  232. }
  233. static size_t markerPlusLengthByteCount(size_t length)
  234. {
  235. if (length <= maxLengthInMarkerByte)
  236. return 1;
  237. return 1 + integerByteCount(length);
  238. }
  239. void BinaryPropertyListPlan::writeStringObject(const String& string)
  240. {
  241. unsigned length = string.length();
  242. m_byteCount += markerPlusLengthByteCount(length) + length;
  243. if (!string.containsOnlyASCII())
  244. m_byteCount += length;
  245. }
  246. void BinaryPropertyListPlan::writeStringObject(const char* string)
  247. {
  248. unsigned length = strlen(string);
  249. m_byteCount += markerPlusLengthByteCount(length) + length;
  250. }
  251. void BinaryPropertyListPlan::writeArrayObject(size_t size)
  252. {
  253. ASSERT(size);
  254. m_byteCount += markerPlusLengthByteCount(size);
  255. m_objectReferenceCount += size;
  256. }
  257. void BinaryPropertyListPlan::writeDictionaryObject(size_t size)
  258. {
  259. ASSERT(size);
  260. ASSERT(!(size & 1));
  261. m_byteCount += markerPlusLengthByteCount(size / 2);
  262. m_objectReferenceCount += size;
  263. }
  264. ObjectReference BinaryPropertyListPlan::booleanTrueObjectReference() const
  265. {
  266. ASSERT(m_booleanTrueObjectReference != invalidObjectReference());
  267. return m_booleanTrueObjectReference;
  268. }
  269. ObjectReference BinaryPropertyListPlan::integerObjectReference(int integer) const
  270. {
  271. ASSERT(integer >= 0);
  272. if (!integer) {
  273. ASSERT(m_integerZeroObjectReference != invalidObjectReference());
  274. return m_integerZeroObjectReference;
  275. }
  276. ASSERT(m_integers.contains(integer));
  277. return m_integers.get(integer);
  278. }
  279. ObjectReference BinaryPropertyListPlan::stringObjectReference(const String& string) const
  280. {
  281. ASSERT(m_strings.contains(string));
  282. return m_strings.get(string);
  283. }
  284. ObjectReference BinaryPropertyListPlan::integerArrayObjectReference(const int* integers, size_t size) const
  285. {
  286. ASSERT(m_integerArrays.contains(IntegerArray(integers, size)));
  287. return m_integerArrays.get(IntegerArray(integers, size));
  288. }
  289. class BinaryPropertyListSerializer : private BinaryPropertyListObjectStream {
  290. public:
  291. BinaryPropertyListSerializer(BinaryPropertyListWriter&);
  292. private:
  293. virtual void writeBooleanTrue();
  294. virtual void writeInteger(int);
  295. virtual void writeString(const String&);
  296. virtual void writeIntegerArray(const int*, size_t);
  297. virtual void writeUniqueString(const String&);
  298. virtual void writeUniqueString(const char*);
  299. virtual size_t writeArrayStart();
  300. virtual void writeArrayEnd(size_t);
  301. virtual size_t writeDictionaryStart();
  302. virtual void writeDictionaryEnd(size_t);
  303. ObjectReference writeIntegerWithoutAddingAggregateObjectReference(int);
  304. void appendIntegerObject(int);
  305. void appendStringObject(const String&);
  306. void appendStringObject(const char*);
  307. void appendIntegerArrayObject(const int*, size_t);
  308. void appendByte(unsigned char);
  309. void appendByte(unsigned);
  310. void appendByte(unsigned long);
  311. void appendByte(int);
  312. void appendInteger(size_t);
  313. void appendObjectReference(ObjectReference);
  314. void addAggregateObjectReference(ObjectReference);
  315. void startObject();
  316. const BinaryPropertyListPlan m_plan;
  317. const int m_objectReferenceSize;
  318. const size_t m_offsetTableStart;
  319. const int m_offsetSize;
  320. const size_t m_bufferSize;
  321. UInt8* const m_buffer;
  322. UInt8* m_currentByte;
  323. ObjectReference m_currentObjectReference;
  324. UInt8* m_currentAggregateBufferByte;
  325. };
  326. inline void BinaryPropertyListSerializer::appendByte(unsigned char byte)
  327. {
  328. *m_currentByte++ = byte;
  329. ASSERT(m_currentByte <= m_currentAggregateBufferByte);
  330. }
  331. inline void BinaryPropertyListSerializer::appendByte(unsigned byte)
  332. {
  333. *m_currentByte++ = byte;
  334. ASSERT(m_currentByte <= m_currentAggregateBufferByte);
  335. }
  336. inline void BinaryPropertyListSerializer::appendByte(unsigned long byte)
  337. {
  338. *m_currentByte++ = byte;
  339. ASSERT(m_currentByte <= m_currentAggregateBufferByte);
  340. }
  341. inline void BinaryPropertyListSerializer::appendByte(int byte)
  342. {
  343. *m_currentByte++ = byte;
  344. ASSERT(m_currentByte <= m_currentAggregateBufferByte);
  345. }
  346. static int bytesNeeded(size_t count)
  347. {
  348. ASSERT(count);
  349. int bytesNeeded = 1;
  350. for (size_t mask = std::numeric_limits<size_t>::max() << 8; count & mask; mask <<= 8)
  351. ++bytesNeeded;
  352. return bytesNeeded;
  353. }
  354. static inline void storeLength(UInt8* destination, size_t length)
  355. {
  356. #ifdef __LP64__
  357. destination[0] = length >> 56;
  358. destination[1] = length >> 48;
  359. destination[2] = length >> 40;
  360. destination[3] = length >> 32;
  361. #else
  362. destination[0] = 0;
  363. destination[1] = 0;
  364. destination[2] = 0;
  365. destination[3] = 0;
  366. #endif
  367. destination[4] = length >> 24;
  368. destination[5] = length >> 16;
  369. destination[6] = length >> 8;
  370. destination[7] = length;
  371. }
  372. // Like memmove, but reverses the bytes.
  373. static void moveAndReverseBytes(UInt8* destination, const UInt8* source, size_t length)
  374. {
  375. ASSERT(length);
  376. memmove(destination, source, length);
  377. UInt8* start = destination;
  378. UInt8* end = destination + length;
  379. while (end - start > 1)
  380. std::swap(*start++, *--end);
  381. }
  382. // The serializer uses a single buffer for the property list.
  383. // The buffer contains:
  384. //
  385. // 8-byte header
  386. // object data
  387. // offset table
  388. // 32-byte trailer
  389. //
  390. // While serializing object, the offset table entry for each object is written just before
  391. // the object data for that object is written. Aggregates, arrays and dictionaries, are a
  392. // special case. The objects that go into an aggregate are written before the aggregate is.
  393. // As each object is written, the object reference is put in the aggregate buffer. Then,
  394. // when the aggregate is written, the aggregate buffer is copied into place in the object
  395. // data. Finally, the header and trailer are written.
  396. //
  397. // The aggregate buffer shares space with the object data, like this:
  398. //
  399. // 8-byte header
  400. // object data
  401. // >>> aggregate buffer <<<
  402. // offset table
  403. // 32-byte trailer
  404. //
  405. // To make it easy to build it incrementally, the buffer starts at the end of the object
  406. // data space, and grows backwards. We're guaranteed the aggregate buffer will never collide
  407. // with the object data pointer because we know that the object data is correctly sized
  408. // based on our plan, and all the data in the aggregate buffer will be used to create the
  409. // actual aggregate objects; in the worst case the aggregate buffer will already be in
  410. // exactly the right place, but backwards.
  411. BinaryPropertyListSerializer::BinaryPropertyListSerializer(BinaryPropertyListWriter& client)
  412. : m_plan(client)
  413. , m_objectReferenceSize(bytesNeeded(m_plan.objectCount()))
  414. , m_offsetTableStart(headerSize + m_plan.byteCount() + m_plan.objectReferenceCount() * m_objectReferenceSize)
  415. , m_offsetSize(bytesNeeded(m_offsetTableStart))
  416. , m_bufferSize(m_offsetTableStart + m_plan.objectCount() * m_offsetSize + trailerSize)
  417. , m_buffer(client.buffer(m_bufferSize))
  418. , m_currentObjectReference(0)
  419. {
  420. ASSERT(m_objectReferenceSize > 0);
  421. ASSERT(m_offsetSize > 0);
  422. #ifdef __LP64__
  423. ASSERT(m_objectReferenceSize <= 8);
  424. ASSERT(m_offsetSize <= 8);
  425. #else
  426. ASSERT(m_objectReferenceSize <= 4);
  427. ASSERT(m_offsetSize <= 4);
  428. #endif
  429. if (!m_buffer)
  430. return;
  431. // Write objects and offset table.
  432. m_currentByte = m_buffer + headerSize;
  433. m_currentAggregateBufferByte = m_buffer + m_offsetTableStart;
  434. client.writeObjects(*this);
  435. ASSERT(m_currentObjectReference == m_plan.objectCount());
  436. ASSERT(m_currentAggregateBufferByte == m_buffer + m_offsetTableStart);
  437. ASSERT(m_currentByte == m_buffer + m_offsetTableStart);
  438. // Write header.
  439. memcpy(m_buffer, "bplist00", headerSize);
  440. // Write trailer.
  441. UInt8* trailer = m_buffer + m_bufferSize - trailerSize;
  442. memset(trailer, 0, 6);
  443. trailer[6] = m_offsetSize;
  444. trailer[7] = m_objectReferenceSize;
  445. storeLength(trailer + 8, m_plan.objectCount());
  446. storeLength(trailer + 16, m_plan.objectCount() - 1);
  447. storeLength(trailer + 24, m_offsetTableStart);
  448. }
  449. void BinaryPropertyListSerializer::writeBooleanTrue()
  450. {
  451. ObjectReference reference = m_plan.booleanTrueObjectReference();
  452. if (m_currentObjectReference != reference)
  453. ASSERT(reference < m_currentObjectReference);
  454. else {
  455. startObject();
  456. appendByte(booleanTrueMarkerByte);
  457. }
  458. addAggregateObjectReference(reference);
  459. }
  460. inline ObjectReference BinaryPropertyListSerializer::writeIntegerWithoutAddingAggregateObjectReference(int integer)
  461. {
  462. ObjectReference reference = m_plan.integerObjectReference(integer);
  463. if (m_currentObjectReference != reference)
  464. ASSERT(reference < m_currentObjectReference);
  465. else
  466. appendIntegerObject(integer);
  467. return reference;
  468. }
  469. void BinaryPropertyListSerializer::writeInteger(int integer)
  470. {
  471. addAggregateObjectReference(writeIntegerWithoutAddingAggregateObjectReference(integer));
  472. }
  473. void BinaryPropertyListSerializer::writeString(const String& string)
  474. {
  475. ObjectReference reference = m_plan.stringObjectReference(string);
  476. if (m_currentObjectReference != reference)
  477. ASSERT(reference < m_currentObjectReference);
  478. else
  479. appendStringObject(string);
  480. addAggregateObjectReference(reference);
  481. }
  482. void BinaryPropertyListSerializer::writeIntegerArray(const int* integers, size_t size)
  483. {
  484. ObjectReference reference = m_plan.integerArrayObjectReference(integers, size);
  485. for (size_t i = 0; i < size; ++i)
  486. writeIntegerWithoutAddingAggregateObjectReference(integers[i]);
  487. if (m_currentObjectReference != reference)
  488. ASSERT(reference < m_currentObjectReference);
  489. else
  490. appendIntegerArrayObject(integers, size);
  491. addAggregateObjectReference(reference);
  492. }
  493. void BinaryPropertyListSerializer::writeUniqueString(const char* string)
  494. {
  495. addAggregateObjectReference(m_currentObjectReference);
  496. appendStringObject(string);
  497. }
  498. void BinaryPropertyListSerializer::writeUniqueString(const String& string)
  499. {
  500. addAggregateObjectReference(m_currentObjectReference);
  501. appendStringObject(string);
  502. }
  503. size_t BinaryPropertyListSerializer::writeArrayStart()
  504. {
  505. return m_currentAggregateBufferByte - m_buffer;
  506. }
  507. void BinaryPropertyListSerializer::writeArrayEnd(size_t savedAggregateBufferOffset)
  508. {
  509. ObjectReference reference = m_currentObjectReference;
  510. startObject();
  511. size_t aggregateBufferByteCount = savedAggregateBufferOffset - (m_currentAggregateBufferByte - m_buffer);
  512. ASSERT(aggregateBufferByteCount);
  513. ASSERT(!(aggregateBufferByteCount % m_objectReferenceSize));
  514. size_t size = aggregateBufferByteCount / m_objectReferenceSize;
  515. if (size <= maxLengthInMarkerByte)
  516. appendByte(arrayMarkerByte | size);
  517. else {
  518. appendByte(arrayWithSeparateLengthMarkerByte);
  519. appendInteger(size);
  520. }
  521. m_currentAggregateBufferByte = m_buffer + savedAggregateBufferOffset;
  522. ASSERT(m_currentByte <= m_currentAggregateBufferByte);
  523. moveAndReverseBytes(m_currentByte, m_currentAggregateBufferByte - aggregateBufferByteCount, aggregateBufferByteCount);
  524. m_currentByte += aggregateBufferByteCount;
  525. ASSERT(m_currentByte <= m_currentAggregateBufferByte);
  526. if (m_currentObjectReference < m_plan.objectCount())
  527. addAggregateObjectReference(reference);
  528. else
  529. ASSERT(m_currentObjectReference == m_plan.objectCount());
  530. }
  531. size_t BinaryPropertyListSerializer::writeDictionaryStart()
  532. {
  533. return m_currentAggregateBufferByte - m_buffer;
  534. }
  535. void BinaryPropertyListSerializer::writeDictionaryEnd(size_t savedAggregateBufferOffset)
  536. {
  537. ObjectReference reference = m_currentObjectReference;
  538. startObject();
  539. size_t aggregateBufferByteCount = savedAggregateBufferOffset - (m_currentAggregateBufferByte - m_buffer);
  540. ASSERT(aggregateBufferByteCount);
  541. ASSERT(!(aggregateBufferByteCount % (m_objectReferenceSize * 2)));
  542. size_t size = aggregateBufferByteCount / (m_objectReferenceSize * 2);
  543. if (size <= maxLengthInMarkerByte)
  544. appendByte(dictionaryMarkerByte | size);
  545. else {
  546. appendByte(dictionaryWithSeparateLengthMarkerByte);
  547. appendInteger(size);
  548. }
  549. m_currentAggregateBufferByte = m_buffer + savedAggregateBufferOffset;
  550. ASSERT(m_currentByte <= m_currentAggregateBufferByte);
  551. moveAndReverseBytes(m_currentByte, m_currentAggregateBufferByte - aggregateBufferByteCount, aggregateBufferByteCount);
  552. m_currentByte += aggregateBufferByteCount;
  553. ASSERT(m_currentByte <= m_currentAggregateBufferByte);
  554. if (m_currentObjectReference != m_plan.objectCount())
  555. addAggregateObjectReference(reference);
  556. else
  557. ASSERT(m_currentObjectReference == m_plan.objectCount());
  558. }
  559. void BinaryPropertyListSerializer::appendIntegerObject(int integer)
  560. {
  561. startObject();
  562. ASSERT(integer >= 0);
  563. appendInteger(integer);
  564. }
  565. void BinaryPropertyListSerializer::appendInteger(size_t integer)
  566. {
  567. if (integer <= 0xFF) {
  568. appendByte(oneByteIntegerMarkerByte);
  569. appendByte(integer);
  570. return;
  571. }
  572. if (integer <= 0xFFFF) {
  573. appendByte(twoByteIntegerMarkerByte);
  574. appendByte(integer >> 8);
  575. appendByte(integer);
  576. return;
  577. }
  578. #ifdef __LP64__
  579. if (integer <= 0xFFFFFFFFULL) {
  580. #endif
  581. appendByte(fourByteIntegerMarkerByte);
  582. appendByte(integer >> 24);
  583. appendByte(integer >> 16);
  584. appendByte(integer >> 8);
  585. appendByte(integer);
  586. #ifdef __LP64__
  587. return;
  588. }
  589. appendByte(eightByteIntegerMarkerByte);
  590. appendByte(integer >> 56);
  591. appendByte(integer >> 48);
  592. appendByte(integer >> 40);
  593. appendByte(integer >> 32);
  594. appendByte(integer >> 24);
  595. appendByte(integer >> 16);
  596. appendByte(integer >> 8);
  597. appendByte(integer);
  598. #endif
  599. }
  600. void BinaryPropertyListSerializer::appendStringObject(const String& string)
  601. {
  602. startObject();
  603. const UChar* characters = string.characters();
  604. unsigned length = string.length();
  605. if (charactersAreAllASCII(characters, length)) {
  606. if (length <= maxLengthInMarkerByte)
  607. appendByte(static_cast<unsigned char>(asciiStringMarkerByte | length));
  608. else {
  609. appendByte(asciiStringWithSeparateLengthMarkerByte);
  610. appendInteger(length);
  611. }
  612. for (unsigned i = 0; i < length; ++i)
  613. appendByte(characters[i]);
  614. } else {
  615. if (length <= maxLengthInMarkerByte)
  616. appendByte(static_cast<unsigned char>(unicodeStringMarkerByte | length));
  617. else {
  618. appendByte(unicodeStringWithSeparateLengthMarkerByte);
  619. appendInteger(length);
  620. }
  621. for (unsigned i = 0; i < length; ++i) {
  622. appendByte(characters[i] >> 8);
  623. appendByte(characters[i]);
  624. }
  625. }
  626. }
  627. void BinaryPropertyListSerializer::appendStringObject(const char* string)
  628. {
  629. startObject();
  630. unsigned length = strlen(string);
  631. if (length <= maxLengthInMarkerByte)
  632. appendByte(static_cast<unsigned char>(asciiStringMarkerByte | length));
  633. else {
  634. appendByte(asciiStringWithSeparateLengthMarkerByte);
  635. appendInteger(length);
  636. }
  637. for (unsigned i = 0; i < length; ++i)
  638. appendByte(string[i]);
  639. }
  640. void BinaryPropertyListSerializer::appendIntegerArrayObject(const int* integers, size_t size)
  641. {
  642. startObject();
  643. if (size <= maxLengthInMarkerByte)
  644. appendByte(arrayMarkerByte | size);
  645. else {
  646. appendByte(arrayWithSeparateLengthMarkerByte);
  647. appendInteger(size);
  648. }
  649. for (unsigned i = 0; i < size; ++i)
  650. appendObjectReference(m_plan.integerObjectReference(integers[i]));
  651. }
  652. void BinaryPropertyListSerializer::appendObjectReference(ObjectReference reference)
  653. {
  654. switch (m_objectReferenceSize) {
  655. #ifdef __LP64__
  656. case 8:
  657. appendByte(reference >> 56);
  658. case 7:
  659. appendByte(reference >> 48);
  660. case 6:
  661. appendByte(reference >> 40);
  662. case 5:
  663. appendByte(reference >> 32);
  664. #endif
  665. case 4:
  666. appendByte(reference >> 24);
  667. case 3:
  668. appendByte(reference >> 16);
  669. case 2:
  670. appendByte(reference >> 8);
  671. case 1:
  672. appendByte(reference);
  673. }
  674. }
  675. void BinaryPropertyListSerializer::startObject()
  676. {
  677. ObjectReference reference = m_currentObjectReference++;
  678. size_t offset = m_currentByte - m_buffer;
  679. UInt8* offsetTableEntry = m_buffer + m_offsetTableStart + reference * m_offsetSize + m_offsetSize;
  680. switch (m_offsetSize) {
  681. #ifdef __LP64__
  682. case 8:
  683. offsetTableEntry[-8] = offset >> 56;
  684. case 7:
  685. offsetTableEntry[-7] = offset >> 48;
  686. case 6:
  687. offsetTableEntry[-6] = offset >> 40;
  688. case 5:
  689. offsetTableEntry[-5] = offset >> 32;
  690. #endif
  691. case 4:
  692. offsetTableEntry[-4] = offset >> 24;
  693. case 3:
  694. offsetTableEntry[-3] = offset >> 16;
  695. case 2:
  696. offsetTableEntry[-2] = offset >> 8;
  697. case 1:
  698. offsetTableEntry[-1] = offset;
  699. }
  700. }
  701. void BinaryPropertyListSerializer::addAggregateObjectReference(ObjectReference reference)
  702. {
  703. switch (m_objectReferenceSize) {
  704. #ifdef __LP64__
  705. case 8:
  706. *--m_currentAggregateBufferByte = reference >> 56;
  707. case 7:
  708. *--m_currentAggregateBufferByte = reference >> 48;
  709. case 6:
  710. *--m_currentAggregateBufferByte = reference >> 40;
  711. case 5:
  712. *--m_currentAggregateBufferByte = reference >> 32;
  713. #endif
  714. case 4:
  715. *--m_currentAggregateBufferByte = reference >> 24;
  716. case 3:
  717. *--m_currentAggregateBufferByte = reference >> 16;
  718. case 2:
  719. *--m_currentAggregateBufferByte = reference >> 8;
  720. case 1:
  721. *--m_currentAggregateBufferByte = reference;
  722. }
  723. ASSERT(m_currentByte <= m_currentAggregateBufferByte);
  724. }
  725. void BinaryPropertyListWriter::writePropertyList()
  726. {
  727. BinaryPropertyListSerializer serializer(*this);
  728. }