2
0

TTSerialize.h 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #pragma once
  6. #if ENABLE_TTD
  7. #define TTD_SERIALIZATION_BUFFER_SIZE 2097152
  8. #define TTD_SERIALIZATION_MAX_FORMATTED_DATA_SIZE 128
  9. //forward decl
  10. //
  11. //TODO: This is not cool but we need it for the trace logger decls.
  12. // Split that class out into a seperate file and then include it later in Runtime.h
  13. //
  14. namespace Js
  15. {
  16. class JavascriptFunction;
  17. }
  18. namespace TTD
  19. {
  20. namespace NSTokens
  21. {
  22. //Seperator tokens for records
  23. enum class Separator : byte
  24. {
  25. NoSeparator = 0x0,
  26. CommaSeparator = 0x1,
  27. BigSpaceSeparator = 0x2,
  28. CommaAndBigSpaceSeparator = (CommaSeparator | BigSpaceSeparator)
  29. };
  30. DEFINE_ENUM_FLAG_OPERATORS(Separator);
  31. enum class ParseTokenKind
  32. {
  33. Error = 0x0,
  34. Comma,
  35. Colon,
  36. LBrack,
  37. RBrack,
  38. LCurly,
  39. RCurly,
  40. Null,
  41. True,
  42. False,
  43. NaN,
  44. PosInfty,
  45. NegInfty,
  46. UpperBound,
  47. LowerBound,
  48. Epsilon,
  49. Number,
  50. Address,
  51. LogTag,
  52. EnumTag,
  53. WellKnownToken,
  54. String
  55. };
  56. //Key values for records
  57. //WARNING - note the byte size on the enum type so be careful when adding new keys to the enumeration
  58. enum class Key : byte
  59. {
  60. Invalid = 0x0,
  61. #define ENTRY_SERIALIZE_ENUM(X) X,
  62. #include "TTSerializeEnum.h"
  63. Count
  64. };
  65. void InitKeyNamesArray(const char16*** names, size_t** lengths);
  66. void CleanupKeyNamesArray(const char16*** names, size_t** lengths);
  67. }
  68. ////
  69. //A virtual class that handles the actual write (and format) of a value to a stream
  70. class FileWriter
  71. {
  72. private:
  73. //The file that we are writing into
  74. JsTTDStreamHandle m_hfile;
  75. TTDWriteBytesToStreamCallback m_pfWrite;
  76. TTDFlushAndCloseStreamCallback m_pfClose;
  77. size_t m_cursor;
  78. byte* m_buffer;
  79. //flush the buffer contents to disk
  80. void WriteBlock(const byte* buff, size_t bufflen);
  81. template <size_t requestedSpace>
  82. byte* ReserveSpaceForSmallData()
  83. {
  84. TTDAssert(requestedSpace < TTD_SERIALIZATION_BUFFER_SIZE, "Must be small data element!");
  85. if(this->m_cursor + requestedSpace >= TTD_SERIALIZATION_BUFFER_SIZE)
  86. {
  87. this->WriteBlock(this->m_buffer, this->m_cursor);
  88. this->m_cursor = 0;
  89. }
  90. return (this->m_buffer + this->m_cursor);
  91. }
  92. void CommitSpaceForSmallData(size_t usedSpace)
  93. {
  94. TTDAssert(this->m_cursor + usedSpace < TTD_SERIALIZATION_BUFFER_SIZE, "Must have already reserved the space!");
  95. this->m_cursor += usedSpace;
  96. }
  97. protected:
  98. template <typename T>
  99. void WriteRawByteBuff_Fixed(const T& data)
  100. {
  101. byte* trgt = this->ReserveSpaceForSmallData<sizeof(T)>();
  102. js_memcpy_s(trgt, sizeof(T), (const byte*)(&data), sizeof(T));
  103. this->CommitSpaceForSmallData(sizeof(T));
  104. }
  105. void WriteRawByteBuff(const byte* buff, size_t bufflen)
  106. {
  107. if(this->m_cursor + bufflen < TTD_SERIALIZATION_BUFFER_SIZE)
  108. {
  109. size_t sizeAvailable = (TTD_SERIALIZATION_BUFFER_SIZE - this->m_cursor);
  110. TTDAssert(sizeAvailable >= bufflen, "Our size computation is off somewhere.");
  111. js_memcpy_s(this->m_buffer + this->m_cursor, sizeAvailable, buff, bufflen);
  112. this->m_cursor += bufflen;
  113. }
  114. else
  115. {
  116. this->WriteBlock(this->m_buffer, this->m_cursor);
  117. this->m_cursor = 0;
  118. const byte* remainingBuff = buff;
  119. size_t remainingBytes = bufflen;
  120. while(remainingBytes > TTD_SERIALIZATION_BUFFER_SIZE)
  121. {
  122. TTDAssert(this->m_cursor == 0, "Should be empty.");
  123. this->WriteBlock(remainingBuff, TTD_SERIALIZATION_BUFFER_SIZE);
  124. remainingBuff += TTD_SERIALIZATION_BUFFER_SIZE;
  125. remainingBytes -= TTD_SERIALIZATION_BUFFER_SIZE;
  126. }
  127. if(remainingBytes > 0)
  128. {
  129. js_memcpy_s(this->m_buffer, TTD_SERIALIZATION_BUFFER_SIZE, remainingBuff, remainingBytes);
  130. this->m_cursor += remainingBytes;
  131. }
  132. }
  133. }
  134. void WriteRawCharBuff(const char16* buff, size_t bufflen)
  135. {
  136. this->WriteRawByteBuff((const byte*)buff, bufflen * sizeof(char16));
  137. }
  138. void WriteRawChar(char16 c)
  139. {
  140. this->WriteRawByteBuff_Fixed<char16>(c);
  141. }
  142. template <size_t N, typename T>
  143. void WriteFormattedCharData(const char16(&formatString)[N], T data)
  144. {
  145. byte* trgtBuff = this->ReserveSpaceForSmallData<TTD_SERIALIZATION_MAX_FORMATTED_DATA_SIZE>();
  146. int addedChars = swprintf_s((char16*)trgtBuff, (TTD_SERIALIZATION_MAX_FORMATTED_DATA_SIZE / sizeof(char16)), formatString, data);
  147. TTDAssert(addedChars != -1 && addedChars < (TTD_SERIALIZATION_MAX_FORMATTED_DATA_SIZE / sizeof(char16)), "Formatting failed or result is too big.");
  148. int addedBytes = (addedChars != -1) ? (addedChars * sizeof(char16)) : 0;
  149. this->CommitSpaceForSmallData(addedBytes);
  150. }
  151. public:
  152. FileWriter(JsTTDStreamHandle handle, TTDWriteBytesToStreamCallback pfWrite, TTDFlushAndCloseStreamCallback pfClose);
  153. virtual ~FileWriter();
  154. void FlushAndClose();
  155. ////
  156. virtual void WriteSeperator(NSTokens::Separator separator) = 0;
  157. virtual void WriteKey(NSTokens::Key key, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) = 0;
  158. void WriteLengthValue(uint32 length, NSTokens::Separator separator = NSTokens::Separator::NoSeparator);
  159. void WriteSequenceStart_DefaultKey(NSTokens::Separator separator = NSTokens::Separator::NoSeparator);
  160. virtual void WriteSequenceStart(NSTokens::Separator separator = NSTokens::Separator::NoSeparator) = 0;
  161. virtual void WriteSequenceEnd(NSTokens::Separator separator = NSTokens::Separator::NoSeparator) = 0;
  162. void WriteRecordStart_DefaultKey(NSTokens::Separator separator = NSTokens::Separator::NoSeparator);
  163. virtual void WriteRecordStart(NSTokens::Separator separator = NSTokens::Separator::NoSeparator) = 0;
  164. virtual void WriteRecordEnd(NSTokens::Separator separator = NSTokens::Separator::NoSeparator) = 0;
  165. virtual void AdjustIndent(int32 delta) = 0;
  166. virtual void SetIndent(uint32 depth) = 0;
  167. ////
  168. virtual void WriteNakedNull(NSTokens::Separator separator = NSTokens::Separator::NoSeparator) = 0;
  169. void WriteNull(NSTokens::Key key, NSTokens::Separator separator = NSTokens::Separator::NoSeparator);
  170. virtual void WriteNakedByte(byte val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) = 0;
  171. virtual void WriteBool(NSTokens::Key key, bool val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) = 0;
  172. virtual void WriteNakedInt32(int32 val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) = 0;
  173. void WriteInt32(NSTokens::Key key, int32 val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator);
  174. virtual void WriteNakedUInt32(uint32 val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) = 0;
  175. void WriteUInt32(NSTokens::Key key, uint32 val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator);
  176. virtual void WriteNakedInt64(int64 val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) = 0;
  177. void WriteInt64(NSTokens::Key key, int64 val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator);
  178. virtual void WriteNakedUInt64(uint64 val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) = 0;
  179. void WriteUInt64(NSTokens::Key key, uint64 val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator);
  180. virtual void WriteNakedDouble(double val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) = 0;
  181. void WriteDouble(NSTokens::Key key, double val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator);
  182. virtual void WriteNakedAddr(TTD_PTR_ID val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) = 0;
  183. void WriteAddr(NSTokens::Key key, TTD_PTR_ID val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator);
  184. virtual void WriteNakedLogTag(TTD_LOG_PTR_ID val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) = 0;
  185. void WriteLogTag(NSTokens::Key key, TTD_LOG_PTR_ID val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator);
  186. virtual void WriteNakedTag(uint32 tagvalue, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) = 0;
  187. template <typename T>
  188. void WriteTag(NSTokens::Key key, T tag, NSTokens::Separator separator = NSTokens::Separator::NoSeparator)
  189. {
  190. this->WriteKey(key, separator);
  191. this->WriteNakedTag((uint32)tag);
  192. }
  193. ////
  194. virtual void WriteNakedString(const TTString& val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) = 0;
  195. void WriteString(NSTokens::Key key, const TTString& val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator);
  196. virtual void WriteNakedWellKnownToken(TTD_WELLKNOWN_TOKEN val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) = 0;
  197. void WriteWellKnownToken(NSTokens::Key key, TTD_WELLKNOWN_TOKEN val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator);
  198. virtual void WriteInlineCode(_In_reads_(length) const char16* code, uint32 length, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) = 0;
  199. virtual void WriteInlinePropertyRecordName(_In_reads_(length) const char16* pname, uint32 length, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) = 0;
  200. };
  201. //A implements the writer for verbose text formatted output
  202. class TextFormatWriter : public FileWriter
  203. {
  204. private:
  205. //Array of key names and their lengths
  206. const char16** m_keyNameArray;
  207. size_t* m_keyNameLengthArray;
  208. //indent size for formatting
  209. uint32 m_indentSize;
  210. public:
  211. TextFormatWriter(JsTTDStreamHandle handle, TTDWriteBytesToStreamCallback pfWrite, TTDFlushAndCloseStreamCallback pfClose);
  212. virtual ~TextFormatWriter();
  213. ////
  214. virtual void WriteSeperator(NSTokens::Separator separator) override;
  215. virtual void WriteKey(NSTokens::Key key, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
  216. virtual void WriteSequenceStart(NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
  217. virtual void WriteSequenceEnd(NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
  218. virtual void WriteRecordStart(NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
  219. virtual void WriteRecordEnd(NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
  220. virtual void AdjustIndent(int32 delta) override;
  221. virtual void SetIndent(uint32 depth) override;
  222. ////
  223. virtual void WriteNakedNull(NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
  224. virtual void WriteNakedByte(byte val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
  225. virtual void WriteBool(NSTokens::Key key, bool val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
  226. virtual void WriteNakedInt32(int32 val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
  227. virtual void WriteNakedUInt32(uint32 val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
  228. virtual void WriteNakedInt64(int64 val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
  229. virtual void WriteNakedUInt64(uint64 val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
  230. virtual void WriteNakedDouble(double val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
  231. virtual void WriteNakedAddr(TTD_PTR_ID val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
  232. virtual void WriteNakedLogTag(TTD_LOG_PTR_ID val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
  233. virtual void WriteNakedTag(uint32 tagvalue, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
  234. ////
  235. virtual void WriteNakedString(const TTString& val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
  236. virtual void WriteNakedWellKnownToken(TTD_WELLKNOWN_TOKEN val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
  237. virtual void WriteInlineCode(_In_reads_(length) const char16* code, uint32 length, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
  238. virtual void WriteInlinePropertyRecordName(_In_reads_(length) const char16* pname, uint32 length, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
  239. };
  240. //A implements the writer for a compact binary formatted output
  241. class BinaryFormatWriter : public FileWriter
  242. {
  243. public:
  244. BinaryFormatWriter(JsTTDStreamHandle handle, TTDWriteBytesToStreamCallback pfWrite, TTDFlushAndCloseStreamCallback pfClose);
  245. virtual ~BinaryFormatWriter();
  246. ////
  247. virtual void WriteSeperator(NSTokens::Separator separator) override;
  248. virtual void WriteKey(NSTokens::Key key, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
  249. virtual void WriteSequenceStart(NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
  250. virtual void WriteSequenceEnd(NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
  251. virtual void WriteRecordStart(NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
  252. virtual void WriteRecordEnd(NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
  253. virtual void AdjustIndent(int32 delta) override;
  254. virtual void SetIndent(uint32 depth) override;
  255. ////
  256. virtual void WriteNakedNull(NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
  257. virtual void WriteNakedByte(byte val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
  258. virtual void WriteBool(NSTokens::Key key, bool val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
  259. virtual void WriteNakedInt32(int32 val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
  260. virtual void WriteNakedUInt32(uint32 val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
  261. virtual void WriteNakedInt64(int64 val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
  262. virtual void WriteNakedUInt64(uint64 val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
  263. virtual void WriteNakedDouble(double val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
  264. virtual void WriteNakedAddr(TTD_PTR_ID val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
  265. virtual void WriteNakedLogTag(TTD_LOG_PTR_ID val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
  266. virtual void WriteNakedTag(uint32 tagvalue, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
  267. ////
  268. virtual void WriteNakedString(const TTString& val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
  269. virtual void WriteNakedWellKnownToken(TTD_WELLKNOWN_TOKEN val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
  270. virtual void WriteInlineCode(_In_reads_(length) const char16* code, uint32 length, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
  271. virtual void WriteInlinePropertyRecordName(_In_reads_(length) const char16* pname, uint32 length, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
  272. };
  273. //////////////////
  274. //A virtual class that handles the actual read of values from a stream
  275. class FileReader
  276. {
  277. private:
  278. JsTTDStreamHandle m_hfile;
  279. TTDReadBytesFromStreamCallback m_pfRead;
  280. TTDFlushAndCloseStreamCallback m_pfClose;
  281. int32 m_peekChar;
  282. size_t m_cursor;
  283. size_t m_buffCount;
  284. byte* m_buffer;
  285. void ReadBlock(byte* buff, size_t* readSize);
  286. protected:
  287. template <typename T>
  288. void ReadBytesInto_Fixed(T& data)
  289. {
  290. size_t sizeAvailable = (this->m_buffCount - this->m_cursor);
  291. byte* buff = (byte*)&data;
  292. if(sizeAvailable >= sizeof(T))
  293. {
  294. js_memcpy_s(buff, sizeAvailable, this->m_buffer + this->m_cursor, sizeof(T));
  295. this->m_cursor += sizeof(T);
  296. }
  297. else
  298. {
  299. if(sizeAvailable > 0)
  300. {
  301. js_memcpy_s(buff, sizeAvailable, this->m_buffer + this->m_cursor, sizeAvailable);
  302. this->m_cursor += sizeAvailable;
  303. }
  304. byte* remainingBuff = (buff + sizeAvailable);
  305. size_t remainingBytes = (sizeof(T) - sizeAvailable);
  306. if(remainingBytes > 0)
  307. {
  308. this->ReadBlock(this->m_buffer, &this->m_buffCount);
  309. this->m_cursor = 0;
  310. TTDAssert(this->m_buffCount >= remainingBytes, "Not sure what happened");
  311. js_memcpy_s(remainingBuff, this->m_buffCount, this->m_buffer, remainingBytes);
  312. this->m_cursor += remainingBytes;
  313. }
  314. }
  315. }
  316. void ReadBytesInto(byte* buff, size_t requiredBytes)
  317. {
  318. size_t sizeAvailable = (this->m_buffCount - this->m_cursor);
  319. if(sizeAvailable >= requiredBytes)
  320. {
  321. js_memcpy_s(buff, sizeAvailable, this->m_buffer + this->m_cursor, requiredBytes);
  322. this->m_cursor += requiredBytes;
  323. }
  324. else
  325. {
  326. if(sizeAvailable > 0)
  327. {
  328. js_memcpy_s(buff, sizeAvailable, this->m_buffer + this->m_cursor, sizeAvailable);
  329. this->m_cursor += sizeAvailable;
  330. }
  331. byte* remainingBuff = (buff + sizeAvailable);
  332. size_t remainingBytes = (requiredBytes - sizeAvailable);
  333. while(remainingBytes > TTD_SERIALIZATION_BUFFER_SIZE)
  334. {
  335. size_t readCount = 0;
  336. this->ReadBlock(remainingBuff, &readCount);
  337. TTDAssert(readCount > 0, "We are out of data but still need more");
  338. remainingBuff += readCount;
  339. remainingBytes -= readCount;
  340. }
  341. if(remainingBytes > 0)
  342. {
  343. this->ReadBlock(this->m_buffer, &this->m_buffCount);
  344. this->m_cursor = 0;
  345. TTDAssert(this->m_buffCount >= remainingBytes, "Not sure what happened");
  346. js_memcpy_s(remainingBuff, this->m_buffCount, this->m_buffer, remainingBytes);
  347. this->m_cursor += remainingBytes;
  348. }
  349. }
  350. }
  351. bool PeekRawChar(_Out_ char16* c)
  352. {
  353. if(this->m_peekChar != -1)
  354. {
  355. *c = (char16)this->m_peekChar;
  356. return true;
  357. }
  358. else
  359. {
  360. bool success = this->ReadRawChar(c);
  361. if(success)
  362. {
  363. this->m_peekChar = *c;
  364. }
  365. return success;
  366. }
  367. }
  368. bool ReadRawChar(_Out_ char16* c)
  369. {
  370. if(this->m_peekChar != -1)
  371. {
  372. *c = (char16)this->m_peekChar;
  373. this->m_peekChar = -1;
  374. return true;
  375. }
  376. else
  377. {
  378. if(this->m_cursor == this->m_buffCount)
  379. {
  380. this->ReadBlock(this->m_buffer, &this->m_buffCount);
  381. this->m_cursor = 0;
  382. }
  383. if(this->m_cursor == this->m_buffCount)
  384. {
  385. // Make sure to set a value before we return.
  386. *c = _u('\0');
  387. return false;
  388. }
  389. else
  390. {
  391. *c = *((char16*)(this->m_buffer + this->m_cursor));
  392. this->m_cursor += sizeof(char16);
  393. return true;
  394. }
  395. }
  396. }
  397. public:
  398. FileReader(JsTTDStreamHandle handle, TTDReadBytesFromStreamCallback pfRead, TTDFlushAndCloseStreamCallback pfClose);
  399. virtual ~FileReader();
  400. virtual void ReadSeperator(bool readSeparator) = 0;
  401. virtual void ReadKey(NSTokens::Key keyCheck, bool readSeparator = false) = 0;
  402. uint32 ReadLengthValue(bool readSeparator = false);
  403. void ReadSequenceStart_WDefaultKey(bool readSeparator = false);
  404. virtual void ReadSequenceStart(bool readSeparator = false) = 0;
  405. virtual void ReadSequenceEnd() = 0;
  406. void ReadRecordStart_WDefaultKey(bool readSeparator = false);
  407. virtual void ReadRecordStart(bool readSeparator = false) = 0;
  408. virtual void ReadRecordEnd() = 0;
  409. ////
  410. virtual void ReadNakedNull(bool readSeparator = false) = 0;
  411. void ReadNull(NSTokens::Key keyCheck, bool readSeparator = false);
  412. virtual byte ReadNakedByte(bool readSeparator = false) = 0;
  413. virtual bool ReadBool(NSTokens::Key keyCheck, bool readSeparator = false) = 0;
  414. virtual int32 ReadNakedInt32(bool readSeparator = false) = 0;
  415. int32 ReadInt32(NSTokens::Key keyCheck, bool readSeparator = false);
  416. virtual uint32 ReadNakedUInt32(bool readSeparator = false) = 0;
  417. uint32 ReadUInt32(NSTokens::Key keyCheck, bool readSeparator = false);
  418. virtual int64 ReadNakedInt64(bool readSeparator = false) = 0;
  419. int64 ReadInt64(NSTokens::Key keyCheck, bool readSeparator = false);
  420. virtual uint64 ReadNakedUInt64(bool readSeparator = false) = 0;
  421. uint64 ReadUInt64(NSTokens::Key keyCheck, bool readSeparator = false);
  422. virtual double ReadNakedDouble(bool readSeparator = false) = 0;
  423. double ReadDouble(NSTokens::Key keyCheck, bool readSeparator = false);
  424. virtual TTD_PTR_ID ReadNakedAddr(bool readSeparator = false) = 0;
  425. TTD_PTR_ID ReadAddr(NSTokens::Key keyCheck, bool readSeparator = false);
  426. virtual TTD_LOG_PTR_ID ReadNakedLogTag(bool readSeparator = false) = 0;
  427. TTD_LOG_PTR_ID ReadLogTag(NSTokens::Key keyCheck, bool readSeparator = false);
  428. virtual uint32 ReadNakedTag(bool readSeparator = false) = 0;
  429. template <typename T>
  430. T ReadTag(NSTokens::Key keyCheck, bool readSeparator = false)
  431. {
  432. this->ReadKey(keyCheck, readSeparator);
  433. uint32 tval = this->ReadNakedTag();
  434. return (T)tval;
  435. }
  436. ////
  437. virtual void ReadNakedString(SlabAllocator& alloc, TTString& into, bool readSeparator = false) = 0;
  438. virtual void ReadNakedString(UnlinkableSlabAllocator& alloc, TTString& into, bool readSeparator = false) = 0;
  439. template <typename Allocator>
  440. void ReadString(NSTokens::Key keyCheck, Allocator& alloc, TTString& into, bool readSeparator = false)
  441. {
  442. this->ReadKey(keyCheck, readSeparator);
  443. return this->ReadNakedString(alloc, into);
  444. }
  445. virtual TTD_WELLKNOWN_TOKEN ReadNakedWellKnownToken(SlabAllocator& alloc, bool readSeparator = false) = 0;
  446. virtual TTD_WELLKNOWN_TOKEN ReadNakedWellKnownToken(UnlinkableSlabAllocator& alloc, bool readSeparator = false) = 0;
  447. template <typename Allocator>
  448. TTD_WELLKNOWN_TOKEN ReadWellKnownToken(NSTokens::Key keyCheck, Allocator& alloc, bool readSeparator = false)
  449. {
  450. this->ReadKey(keyCheck, readSeparator);
  451. return this->ReadNakedWellKnownToken(alloc);
  452. }
  453. virtual void ReadInlineCode(_Out_writes_(length) char16* code, uint32 length, bool readSeparator = false) = 0;
  454. };
  455. //////////////////
  456. //A serialization class that reads a verbose text data format
  457. class TextFormatReader : public FileReader
  458. {
  459. private:
  460. JsUtil::List<char16, HeapAllocator> m_charListPrimary;
  461. JsUtil::List<char16, HeapAllocator> m_charListOpt;
  462. JsUtil::List<char16, HeapAllocator> m_charListDiscard;
  463. //Array of key names and their lengths
  464. const char16** m_keyNameArray;
  465. size_t* m_keyNameLengthArray;
  466. NSTokens::ParseTokenKind Scan(JsUtil::List<char16, HeapAllocator>& charList);
  467. NSTokens::ParseTokenKind ScanKey(JsUtil::List<char16, HeapAllocator>& charList);
  468. NSTokens::ParseTokenKind ScanSpecialNumber();
  469. NSTokens::ParseTokenKind ScanNumber(JsUtil::List<char16, HeapAllocator>& charList);
  470. NSTokens::ParseTokenKind ScanAddress(JsUtil::List<char16, HeapAllocator>& charList);
  471. NSTokens::ParseTokenKind ScanLogTag(JsUtil::List<char16, HeapAllocator>& charList);
  472. NSTokens::ParseTokenKind ScanEnumTag(JsUtil::List<char16, HeapAllocator>& charList);
  473. NSTokens::ParseTokenKind ScanWellKnownToken(JsUtil::List<char16, HeapAllocator>& charList);
  474. NSTokens::ParseTokenKind ScanString(JsUtil::List<char16, HeapAllocator>& charList);
  475. NSTokens::ParseTokenKind ScanNakedString(char16 leadChar);
  476. int64 ReadIntFromCharArray(const char16* buff);
  477. uint64 ReadUIntFromCharArray(const char16* buff);
  478. double ReadDoubleFromCharArray(const char16* buff);
  479. public:
  480. TextFormatReader(JsTTDStreamHandle handle, TTDReadBytesFromStreamCallback pfRead, TTDFlushAndCloseStreamCallback pfClose);
  481. virtual ~TextFormatReader();
  482. virtual void ReadSeperator(bool readSeparator) override;
  483. virtual void ReadKey(NSTokens::Key keyCheck, bool readSeparator = false) override;
  484. virtual void ReadSequenceStart(bool readSeparator = false) override;
  485. virtual void ReadSequenceEnd() override;
  486. virtual void ReadRecordStart(bool readSeparator = false) override;
  487. virtual void ReadRecordEnd() override;
  488. ////
  489. virtual void ReadNakedNull(bool readSeparator = false) override;
  490. virtual byte ReadNakedByte(bool readSeparator = false) override;
  491. virtual bool ReadBool(NSTokens::Key keyCheck, bool readSeparator = false) override;
  492. virtual int32 ReadNakedInt32(bool readSeparator = false) override;
  493. virtual uint32 ReadNakedUInt32(bool readSeparator = false) override;
  494. virtual int64 ReadNakedInt64(bool readSeparator = false) override;
  495. virtual uint64 ReadNakedUInt64(bool readSeparator = false) override;
  496. virtual double ReadNakedDouble(bool readSeparator = false) override;
  497. virtual TTD_PTR_ID ReadNakedAddr(bool readSeparator = false) override;
  498. virtual TTD_LOG_PTR_ID ReadNakedLogTag(bool readSeparator = false) override;
  499. virtual uint32 ReadNakedTag(bool readSeparator = false) override;
  500. ////
  501. virtual void ReadNakedString(SlabAllocator& alloc, TTString& into, bool readSeparator = false) override;
  502. virtual void ReadNakedString(UnlinkableSlabAllocator& alloc, TTString& into, bool readSeparator = false) override;
  503. virtual TTD_WELLKNOWN_TOKEN ReadNakedWellKnownToken(SlabAllocator& alloc, bool readSeparator = false) override;
  504. virtual TTD_WELLKNOWN_TOKEN ReadNakedWellKnownToken(UnlinkableSlabAllocator& alloc, bool readSeparator = false) override;
  505. virtual void ReadInlineCode(_Out_writes_(length) char16* code, uint32 length, bool readSeparator = false) override;
  506. };
  507. //A serialization class that reads a compact binary format
  508. class BinaryFormatReader : public FileReader
  509. {
  510. public:
  511. BinaryFormatReader(JsTTDStreamHandle handle, TTDReadBytesFromStreamCallback pfRead, TTDFlushAndCloseStreamCallback pfClose);
  512. virtual ~BinaryFormatReader();
  513. virtual void ReadSeperator(bool readSeparator) override;
  514. virtual void ReadKey(NSTokens::Key keyCheck, bool readSeparator = false) override;
  515. virtual void ReadSequenceStart(bool readSeparator = false) override;
  516. virtual void ReadSequenceEnd() override;
  517. virtual void ReadRecordStart(bool readSeparator = false) override;
  518. virtual void ReadRecordEnd() override;
  519. ////
  520. virtual void ReadNakedNull(bool readSeparator = false) override;
  521. virtual byte ReadNakedByte(bool readSeparator = false) override;
  522. virtual bool ReadBool(NSTokens::Key keyCheck, bool readSeparator = false) override;
  523. virtual int32 ReadNakedInt32(bool readSeparator = false) override;
  524. virtual uint32 ReadNakedUInt32(bool readSeparator = false) override;
  525. virtual int64 ReadNakedInt64(bool readSeparator = false) override;
  526. virtual uint64 ReadNakedUInt64(bool readSeparator = false) override;
  527. virtual double ReadNakedDouble(bool readSeparator = false) override;
  528. virtual TTD_PTR_ID ReadNakedAddr(bool readSeparator = false) override;
  529. virtual TTD_LOG_PTR_ID ReadNakedLogTag(bool readSeparator = false) override;
  530. virtual uint32 ReadNakedTag(bool readSeparator = false) override;
  531. ////
  532. virtual void ReadNakedString(SlabAllocator& alloc, TTString& into, bool readSeparator = false) override;
  533. virtual void ReadNakedString(UnlinkableSlabAllocator& alloc, TTString& into, bool readSeparator = false) override;
  534. virtual TTD_WELLKNOWN_TOKEN ReadNakedWellKnownToken(SlabAllocator& alloc, bool readSeparator = false) override;
  535. virtual TTD_WELLKNOWN_TOKEN ReadNakedWellKnownToken(UnlinkableSlabAllocator& alloc, bool readSeparator = false) override;
  536. virtual void ReadInlineCode(_Out_writes_(length) char16* code, uint32 length, bool readSeparator = false) override;
  537. };
  538. //////////////////
  539. #if ENABLE_OBJECT_SOURCE_TRACKING
  540. //A struct that we use for tracking where objects have been allocated
  541. struct DiagnosticOrigin
  542. {
  543. int32 SourceLine;
  544. uint32 EventTime;
  545. uint64 TimeHash;
  546. };
  547. bool IsDiagnosticOriginInformationValid(const DiagnosticOrigin& info);
  548. void InitializeDiagnosticOriginInformation(DiagnosticOrigin& info);
  549. void CopyDiagnosticOriginInformation(DiagnosticOrigin& infoInto, const DiagnosticOrigin& infoFrom);
  550. void SetDiagnosticOriginInformation(DiagnosticOrigin& info, uint32 sourceLine, uint64 eTime, uint64 fTime, uint64 lTime);
  551. void EmitDiagnosticOriginInformation(const DiagnosticOrigin& info, FileWriter* writer, NSTokens::Separator separator);
  552. void ParseDiagnosticOriginInformation(DiagnosticOrigin& info, bool readSeperator, FileReader* reader);
  553. #endif
  554. #if ENABLE_BASIC_TRACE || ENABLE_FULL_BC_TRACE
  555. #define TRACE_LOGGER_BUFFER_SIZE 4096
  556. #define TRACE_LOGGER_INDENT_BUFFER_SIZE 64
  557. //Class that provides all of the trace output functionality we want
  558. class TraceLogger
  559. {
  560. private:
  561. char* m_buffer;
  562. char* m_indentBuffer;
  563. int32 m_currLength;
  564. int32 m_indentSize;
  565. FILE* m_outfile;
  566. void EnsureSpace(uint32 length)
  567. {
  568. if(this->m_currLength + length >= TRACE_LOGGER_BUFFER_SIZE)
  569. {
  570. fwrite(this->m_buffer, sizeof(char), this->m_currLength, this->m_outfile);
  571. fflush(this->m_outfile);
  572. this->m_currLength = 0;
  573. }
  574. }
  575. void AppendRaw(const char* str, uint32 length)
  576. {
  577. if(length >= TRACE_LOGGER_BUFFER_SIZE)
  578. {
  579. const char* msg = "Oversize string ... omitting from output";
  580. fwrite(msg, sizeof(char), strlen(msg), this->m_outfile);
  581. }
  582. else
  583. {
  584. TTDAssert(this->m_currLength + length < TRACE_LOGGER_BUFFER_SIZE, "We are going to overrun!");
  585. memcpy(this->m_buffer + this->m_currLength, str, length);
  586. this->m_currLength += length;
  587. }
  588. }
  589. void AppendRaw(const char16* str, uint32 length)
  590. {
  591. if(length >= TRACE_LOGGER_BUFFER_SIZE)
  592. {
  593. const char* msg = "Oversize string ... omitting from output";
  594. fwrite(msg, sizeof(char), strlen(msg), this->m_outfile);
  595. }
  596. else
  597. {
  598. TTDAssert(this->m_currLength + length < TRACE_LOGGER_BUFFER_SIZE, "We are going to overrun!");
  599. char* currs = (this->m_buffer + this->m_currLength);
  600. const char16* currw = str;
  601. for(uint32 i = 0; i < length; ++i)
  602. {
  603. *currs = (char)(*currw);
  604. ++currs;
  605. ++currw;
  606. }
  607. this->m_currLength += length;
  608. }
  609. }
  610. template<size_t N>
  611. void AppendLiteral(const char(&str)[N])
  612. {
  613. this->EnsureSpace(N - 1);
  614. this->AppendRaw(str, N - 1);
  615. }
  616. void AppendText(char* text, uint32 length);
  617. void AppendText(const char16* text, uint32 length);
  618. void AppendIndent();
  619. void AppendString(char* text);
  620. void AppendBool(bool bval);
  621. void AppendInteger(int64 ival);
  622. void AppendUnsignedInteger(uint64 ival);
  623. void AppendIntegerHex(int64 ival);
  624. void AppendDouble(double dval);
  625. public:
  626. TraceLogger(FILE* outfile = stderr);
  627. ~TraceLogger();
  628. void ForceFlush();
  629. template<size_t N>
  630. void WriteLiteralMsg(const char(&str)[N])
  631. {
  632. this->AppendIndent();
  633. this->AppendLiteral(str);
  634. this->ForceFlush();
  635. }
  636. void WriteEnumAction(int64 eTime, BOOL returnCode, Js::PropertyId pid, Js::PropertyAttributes attrib, Js::JavascriptString* pname);
  637. void WriteVar(Js::Var var, bool skipStringContents=false);
  638. void WriteCall(Js::JavascriptFunction* function, bool isExternal, uint32 argc, Js::Var* argv, int64 etime);
  639. void WriteReturn(Js::JavascriptFunction* function, Js::Var res, int64 etime);
  640. void WriteReturnException(Js::JavascriptFunction* function, int64 etime);
  641. void WriteStmtIndex(uint32 line, uint32 column);
  642. void WriteTraceValue(Js::Var var);
  643. };
  644. #endif
  645. }
  646. #endif