blob: 89a6bfc570b930cff6fc245fa18ab7acf159119f [file]
//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
#pragma once
#if ENABLE_TTD
#define TTD_SERIALIZATION_BUFFER_SIZE 2097152
#define TTD_SERIALIZATION_MAX_FORMATTED_DATA_SIZE 128
//forward decl
//
//TODO: This is not cool but we need it for the trace logger decls.
// Split that class out into a seperate file and then include it later in Runtime.h
//
namespace Js
{
class JavascriptFunction;
}
namespace TTD
{
namespace NSTokens
{
//Seperator tokens for records
enum class Separator : byte
{
NoSeparator = 0x0,
CommaSeparator = 0x1,
BigSpaceSeparator = 0x2,
CommaAndBigSpaceSeparator = (CommaSeparator | BigSpaceSeparator)
};
DEFINE_ENUM_FLAG_OPERATORS(Separator);
enum class ParseTokenKind
{
Error = 0x0,
Comma,
Colon,
LBrack,
RBrack,
LCurly,
RCurly,
Null,
True,
False,
NaN,
PosInfty,
NegInfty,
UpperBound,
LowerBound,
Epsilon,
Number,
Address,
LogTag,
EnumTag,
WellKnownToken,
String
};
//Key values for records
//WARNING - note the byte size on the enum type so be careful when adding new keys to the enumeration
enum class Key : byte
{
Invalid = 0x0,
#define ENTRY_SERIALIZE_ENUM(X) X,
#include "TTSerializeEnum.h"
Count
};
void InitKeyNamesArray(const char16*** names, size_t** lengths);
void CleanupKeyNamesArray(const char16*** names, size_t** lengths);
}
////
//A virtual class that handles the actual write (and format) of a value to a stream
class FileWriter
{
private:
//The file that we are writing into
JsTTDStreamHandle m_hfile;
TTDWriteBytesToStreamCallback m_pfWrite;
TTDFlushAndCloseStreamCallback m_pfClose;
size_t m_cursor;
byte* m_buffer;
//flush the buffer contents to disk
void WriteBlock(const byte* buff, size_t bufflen);
template <size_t requestedSpace>
byte* ReserveSpaceForSmallData()
{
TTDAssert(requestedSpace < TTD_SERIALIZATION_BUFFER_SIZE, "Must be small data element!");
if(this->m_cursor + requestedSpace >= TTD_SERIALIZATION_BUFFER_SIZE)
{
this->WriteBlock(this->m_buffer, this->m_cursor);
this->m_cursor = 0;
}
return (this->m_buffer + this->m_cursor);
}
void CommitSpaceForSmallData(size_t usedSpace)
{
TTDAssert(this->m_cursor + usedSpace < TTD_SERIALIZATION_BUFFER_SIZE, "Must have already reserved the space!");
this->m_cursor += usedSpace;
}
protected:
template <typename T>
void WriteRawByteBuff_Fixed(const T& data)
{
byte* trgt = this->ReserveSpaceForSmallData<sizeof(T)>();
js_memcpy_s(trgt, sizeof(T), (const byte*)(&data), sizeof(T));
this->CommitSpaceForSmallData(sizeof(T));
}
void WriteRawByteBuff(const byte* buff, size_t bufflen)
{
if(this->m_cursor + bufflen < TTD_SERIALIZATION_BUFFER_SIZE)
{
size_t sizeAvailable = (TTD_SERIALIZATION_BUFFER_SIZE - this->m_cursor);
TTDAssert(sizeAvailable >= bufflen, "Our size computation is off somewhere.");
js_memcpy_s(this->m_buffer + this->m_cursor, sizeAvailable, buff, bufflen);
this->m_cursor += bufflen;
}
else
{
this->WriteBlock(this->m_buffer, this->m_cursor);
this->m_cursor = 0;
const byte* remainingBuff = buff;
size_t remainingBytes = bufflen;
while(remainingBytes > TTD_SERIALIZATION_BUFFER_SIZE)
{
TTDAssert(this->m_cursor == 0, "Should be empty.");
this->WriteBlock(remainingBuff, TTD_SERIALIZATION_BUFFER_SIZE);
remainingBuff += TTD_SERIALIZATION_BUFFER_SIZE;
remainingBytes -= TTD_SERIALIZATION_BUFFER_SIZE;
}
if(remainingBytes > 0)
{
js_memcpy_s(this->m_buffer, TTD_SERIALIZATION_BUFFER_SIZE, remainingBuff, remainingBytes);
this->m_cursor += remainingBytes;
}
}
}
void WriteRawCharBuff(const char16* buff, size_t bufflen)
{
this->WriteRawByteBuff((const byte*)buff, bufflen * sizeof(char16));
}
void WriteRawChar(char16 c)
{
this->WriteRawByteBuff_Fixed<char16>(c);
}
template <size_t N, typename T>
void WriteFormattedCharData(const char16(&formatString)[N], T data)
{
byte* trgtBuff = this->ReserveSpaceForSmallData<TTD_SERIALIZATION_MAX_FORMATTED_DATA_SIZE>();
int addedChars = swprintf_s((char16*)trgtBuff, (TTD_SERIALIZATION_MAX_FORMATTED_DATA_SIZE / sizeof(char16)), formatString, data);
TTDAssert(addedChars != -1 && addedChars < (TTD_SERIALIZATION_MAX_FORMATTED_DATA_SIZE / sizeof(char16)), "Formatting failed or result is too big.");
int addedBytes = (addedChars != -1) ? (addedChars * sizeof(char16)) : 0;
this->CommitSpaceForSmallData(addedBytes);
}
public:
FileWriter(JsTTDStreamHandle handle, TTDWriteBytesToStreamCallback pfWrite, TTDFlushAndCloseStreamCallback pfClose);
virtual ~FileWriter();
void FlushAndClose();
////
virtual void WriteSeperator(NSTokens::Separator separator) = 0;
virtual void WriteKey(NSTokens::Key key, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) = 0;
void WriteLengthValue(uint32 length, NSTokens::Separator separator = NSTokens::Separator::NoSeparator);
void WriteSequenceStart_DefaultKey(NSTokens::Separator separator = NSTokens::Separator::NoSeparator);
virtual void WriteSequenceStart(NSTokens::Separator separator = NSTokens::Separator::NoSeparator) = 0;
virtual void WriteSequenceEnd(NSTokens::Separator separator = NSTokens::Separator::NoSeparator) = 0;
void WriteRecordStart_DefaultKey(NSTokens::Separator separator = NSTokens::Separator::NoSeparator);
virtual void WriteRecordStart(NSTokens::Separator separator = NSTokens::Separator::NoSeparator) = 0;
virtual void WriteRecordEnd(NSTokens::Separator separator = NSTokens::Separator::NoSeparator) = 0;
virtual void AdjustIndent(int32 delta) = 0;
virtual void SetIndent(uint32 depth) = 0;
////
virtual void WriteNakedNull(NSTokens::Separator separator = NSTokens::Separator::NoSeparator) = 0;
void WriteNull(NSTokens::Key key, NSTokens::Separator separator = NSTokens::Separator::NoSeparator);
virtual void WriteNakedByte(byte val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) = 0;
virtual void WriteBool(NSTokens::Key key, bool val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) = 0;
virtual void WriteNakedInt32(int32 val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) = 0;
void WriteInt32(NSTokens::Key key, int32 val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator);
virtual void WriteNakedUInt32(uint32 val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) = 0;
void WriteUInt32(NSTokens::Key key, uint32 val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator);
virtual void WriteNakedInt64(int64 val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) = 0;
void WriteInt64(NSTokens::Key key, int64 val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator);
virtual void WriteNakedUInt64(uint64 val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) = 0;
void WriteUInt64(NSTokens::Key key, uint64 val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator);
virtual void WriteNakedDouble(double val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) = 0;
void WriteDouble(NSTokens::Key key, double val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator);
virtual void WriteNakedAddr(TTD_PTR_ID val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) = 0;
void WriteAddr(NSTokens::Key key, TTD_PTR_ID val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator);
virtual void WriteNakedLogTag(TTD_LOG_PTR_ID val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) = 0;
void WriteLogTag(NSTokens::Key key, TTD_LOG_PTR_ID val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator);
virtual void WriteNakedTag(uint32 tagvalue, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) = 0;
template <typename T>
void WriteTag(NSTokens::Key key, T tag, NSTokens::Separator separator = NSTokens::Separator::NoSeparator)
{
this->WriteKey(key, separator);
this->WriteNakedTag((uint32)tag);
}
////
virtual void WriteNakedString(const TTString& val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) = 0;
void WriteString(NSTokens::Key key, const TTString& val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator);
virtual void WriteNakedWellKnownToken(TTD_WELLKNOWN_TOKEN val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) = 0;
void WriteWellKnownToken(NSTokens::Key key, TTD_WELLKNOWN_TOKEN val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator);
virtual void WriteInlineCode(_In_reads_(length) const char16* code, uint32 length, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) = 0;
virtual void WriteInlinePropertyRecordName(_In_reads_(length) const char16* pname, uint32 length, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) = 0;
};
//A implements the writer for verbose text formatted output
class TextFormatWriter : public FileWriter
{
private:
//Array of key names and their lengths
const char16** m_keyNameArray;
size_t* m_keyNameLengthArray;
//indent size for formatting
uint32 m_indentSize;
public:
TextFormatWriter(JsTTDStreamHandle handle, TTDWriteBytesToStreamCallback pfWrite, TTDFlushAndCloseStreamCallback pfClose);
virtual ~TextFormatWriter();
////
virtual void WriteSeperator(NSTokens::Separator separator) override;
virtual void WriteKey(NSTokens::Key key, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
virtual void WriteSequenceStart(NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
virtual void WriteSequenceEnd(NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
virtual void WriteRecordStart(NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
virtual void WriteRecordEnd(NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
virtual void AdjustIndent(int32 delta) override;
virtual void SetIndent(uint32 depth) override;
////
virtual void WriteNakedNull(NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
virtual void WriteNakedByte(byte val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
virtual void WriteBool(NSTokens::Key key, bool val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
virtual void WriteNakedInt32(int32 val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
virtual void WriteNakedUInt32(uint32 val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
virtual void WriteNakedInt64(int64 val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
virtual void WriteNakedUInt64(uint64 val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
virtual void WriteNakedDouble(double val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
virtual void WriteNakedAddr(TTD_PTR_ID val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
virtual void WriteNakedLogTag(TTD_LOG_PTR_ID val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
virtual void WriteNakedTag(uint32 tagvalue, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
////
virtual void WriteNakedString(const TTString& val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
virtual void WriteNakedWellKnownToken(TTD_WELLKNOWN_TOKEN val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
virtual void WriteInlineCode(_In_reads_(length) const char16* code, uint32 length, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
virtual void WriteInlinePropertyRecordName(_In_reads_(length) const char16* pname, uint32 length, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
};
//A implements the writer for a compact binary formatted output
class BinaryFormatWriter : public FileWriter
{
public:
BinaryFormatWriter(JsTTDStreamHandle handle, TTDWriteBytesToStreamCallback pfWrite, TTDFlushAndCloseStreamCallback pfClose);
virtual ~BinaryFormatWriter();
////
virtual void WriteSeperator(NSTokens::Separator separator) override;
virtual void WriteKey(NSTokens::Key key, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
virtual void WriteSequenceStart(NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
virtual void WriteSequenceEnd(NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
virtual void WriteRecordStart(NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
virtual void WriteRecordEnd(NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
virtual void AdjustIndent(int32 delta) override;
virtual void SetIndent(uint32 depth) override;
////
virtual void WriteNakedNull(NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
virtual void WriteNakedByte(byte val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
virtual void WriteBool(NSTokens::Key key, bool val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
virtual void WriteNakedInt32(int32 val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
virtual void WriteNakedUInt32(uint32 val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
virtual void WriteNakedInt64(int64 val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
virtual void WriteNakedUInt64(uint64 val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
virtual void WriteNakedDouble(double val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
virtual void WriteNakedAddr(TTD_PTR_ID val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
virtual void WriteNakedLogTag(TTD_LOG_PTR_ID val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
virtual void WriteNakedTag(uint32 tagvalue, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
////
virtual void WriteNakedString(const TTString& val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
virtual void WriteNakedWellKnownToken(TTD_WELLKNOWN_TOKEN val, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
virtual void WriteInlineCode(_In_reads_(length) const char16* code, uint32 length, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
virtual void WriteInlinePropertyRecordName(_In_reads_(length) const char16* pname, uint32 length, NSTokens::Separator separator = NSTokens::Separator::NoSeparator) override;
};
//////////////////
//A virtual class that handles the actual read of values from a stream
class FileReader
{
private:
JsTTDStreamHandle m_hfile;
TTDReadBytesFromStreamCallback m_pfRead;
TTDFlushAndCloseStreamCallback m_pfClose;
int32 m_peekChar;
size_t m_cursor;
size_t m_buffCount;
byte* m_buffer;
void ReadBlock(byte* buff, size_t* readSize);
protected:
template <typename T>
void ReadBytesInto_Fixed(T& data)
{
size_t sizeAvailable = (this->m_buffCount - this->m_cursor);
byte* buff = (byte*)&data;
if(sizeAvailable >= sizeof(T))
{
js_memcpy_s(buff, sizeAvailable, this->m_buffer + this->m_cursor, sizeof(T));
this->m_cursor += sizeof(T);
}
else
{
if(sizeAvailable > 0)
{
js_memcpy_s(buff, sizeAvailable, this->m_buffer + this->m_cursor, sizeAvailable);
this->m_cursor += sizeAvailable;
}
byte* remainingBuff = (buff + sizeAvailable);
size_t remainingBytes = (sizeof(T) - sizeAvailable);
if(remainingBytes > 0)
{
this->ReadBlock(this->m_buffer, &this->m_buffCount);
this->m_cursor = 0;
TTDAssert(this->m_buffCount >= remainingBytes, "Not sure what happened");
js_memcpy_s(remainingBuff, this->m_buffCount, this->m_buffer, remainingBytes);
this->m_cursor += remainingBytes;
}
}
}
void ReadBytesInto(byte* buff, size_t requiredBytes)
{
size_t sizeAvailable = (this->m_buffCount - this->m_cursor);
if(sizeAvailable >= requiredBytes)
{
js_memcpy_s(buff, sizeAvailable, this->m_buffer + this->m_cursor, requiredBytes);
this->m_cursor += requiredBytes;
}
else
{
if(sizeAvailable > 0)
{
js_memcpy_s(buff, sizeAvailable, this->m_buffer + this->m_cursor, sizeAvailable);
this->m_cursor += sizeAvailable;
}
byte* remainingBuff = (buff + sizeAvailable);
size_t remainingBytes = (requiredBytes - sizeAvailable);
while(remainingBytes > TTD_SERIALIZATION_BUFFER_SIZE)
{
size_t readCount = 0;
this->ReadBlock(remainingBuff, &readCount);
remainingBuff += readCount;
remainingBytes -= readCount;
}
if(remainingBytes > 0)
{
this->ReadBlock(this->m_buffer, &this->m_buffCount);
this->m_cursor = 0;
TTDAssert(this->m_buffCount >= remainingBytes, "Not sure what happened");
js_memcpy_s(remainingBuff, this->m_buffCount, this->m_buffer, remainingBytes);
this->m_cursor += remainingBytes;
}
}
}
bool PeekRawChar(_Out_ char16* c)
{
if(this->m_peekChar != -1)
{
*c = (char16)this->m_peekChar;
return true;
}
else
{
bool success = this->ReadRawChar(c);
if(success)
{
this->m_peekChar = *c;
}
return success;
}
}
bool ReadRawChar(_Out_ char16* c)
{
if(this->m_peekChar != -1)
{
*c = (char16)this->m_peekChar;
this->m_peekChar = -1;
return true;
}
else
{
if(this->m_cursor == this->m_buffCount)
{
this->ReadBlock(this->m_buffer, &this->m_buffCount);
this->m_cursor = 0;
}
if(this->m_cursor == this->m_buffCount)
{
// Make sure to set a value before we return.
*c = _u('\0');
return false;
}
else
{
*c = *((char16*)(this->m_buffer + this->m_cursor));
this->m_cursor += sizeof(char16);
return true;
}
}
}
public:
FileReader(JsTTDStreamHandle handle, TTDReadBytesFromStreamCallback pfRead, TTDFlushAndCloseStreamCallback pfClose);
virtual ~FileReader();
virtual void ReadSeperator(bool readSeparator) = 0;
virtual void ReadKey(NSTokens::Key keyCheck, bool readSeparator = false) = 0;
uint32 ReadLengthValue(bool readSeparator = false);
void ReadSequenceStart_WDefaultKey(bool readSeparator = false);
virtual void ReadSequenceStart(bool readSeparator = false) = 0;
virtual void ReadSequenceEnd() = 0;
void ReadRecordStart_WDefaultKey(bool readSeparator = false);
virtual void ReadRecordStart(bool readSeparator = false) = 0;
virtual void ReadRecordEnd() = 0;
////
virtual void ReadNakedNull(bool readSeparator = false) = 0;
void ReadNull(NSTokens::Key keyCheck, bool readSeparator = false);
virtual byte ReadNakedByte(bool readSeparator = false) = 0;
virtual bool ReadBool(NSTokens::Key keyCheck, bool readSeparator = false) = 0;
virtual int32 ReadNakedInt32(bool readSeparator = false) = 0;
int32 ReadInt32(NSTokens::Key keyCheck, bool readSeparator = false);
virtual uint32 ReadNakedUInt32(bool readSeparator = false) = 0;
uint32 ReadUInt32(NSTokens::Key keyCheck, bool readSeparator = false);
virtual int64 ReadNakedInt64(bool readSeparator = false) = 0;
int64 ReadInt64(NSTokens::Key keyCheck, bool readSeparator = false);
virtual uint64 ReadNakedUInt64(bool readSeparator = false) = 0;
uint64 ReadUInt64(NSTokens::Key keyCheck, bool readSeparator = false);
virtual double ReadNakedDouble(bool readSeparator = false) = 0;
double ReadDouble(NSTokens::Key keyCheck, bool readSeparator = false);
virtual TTD_PTR_ID ReadNakedAddr(bool readSeparator = false) = 0;
TTD_PTR_ID ReadAddr(NSTokens::Key keyCheck, bool readSeparator = false);
virtual TTD_LOG_PTR_ID ReadNakedLogTag(bool readSeparator = false) = 0;
TTD_LOG_PTR_ID ReadLogTag(NSTokens::Key keyCheck, bool readSeparator = false);
virtual uint32 ReadNakedTag(bool readSeparator = false) = 0;
template <typename T>
T ReadTag(NSTokens::Key keyCheck, bool readSeparator = false)
{
this->ReadKey(keyCheck, readSeparator);
uint32 tval = this->ReadNakedTag();
return (T)tval;
}
////
virtual void ReadNakedString(SlabAllocator& alloc, TTString& into, bool readSeparator = false) = 0;
virtual void ReadNakedString(UnlinkableSlabAllocator& alloc, TTString& into, bool readSeparator = false) = 0;
template <typename Allocator>
void ReadString(NSTokens::Key keyCheck, Allocator& alloc, TTString& into, bool readSeparator = false)
{
this->ReadKey(keyCheck, readSeparator);
return this->ReadNakedString(alloc, into);
}
virtual TTD_WELLKNOWN_TOKEN ReadNakedWellKnownToken(SlabAllocator& alloc, bool readSeparator = false) = 0;
virtual TTD_WELLKNOWN_TOKEN ReadNakedWellKnownToken(UnlinkableSlabAllocator& alloc, bool readSeparator = false) = 0;
template <typename Allocator>
TTD_WELLKNOWN_TOKEN ReadWellKnownToken(NSTokens::Key keyCheck, Allocator& alloc, bool readSeparator = false)
{
this->ReadKey(keyCheck, readSeparator);
return this->ReadNakedWellKnownToken(alloc);
}
virtual void ReadInlineCode(_Out_writes_(length) char16* code, uint32 length, bool readSeparator = false) = 0;
};
//////////////////
//A serialization class that reads a verbose text data format
class TextFormatReader : public FileReader
{
private:
JsUtil::List<char16, HeapAllocator> m_charListPrimary;
JsUtil::List<char16, HeapAllocator> m_charListOpt;
JsUtil::List<char16, HeapAllocator> m_charListDiscard;
//Array of key names and their lengths
const char16** m_keyNameArray;
size_t* m_keyNameLengthArray;
NSTokens::ParseTokenKind Scan(JsUtil::List<char16, HeapAllocator>& charList);
NSTokens::ParseTokenKind ScanKey(JsUtil::List<char16, HeapAllocator>& charList);
NSTokens::ParseTokenKind ScanSpecialNumber();
NSTokens::ParseTokenKind ScanNumber(JsUtil::List<char16, HeapAllocator>& charList);
NSTokens::ParseTokenKind ScanAddress(JsUtil::List<char16, HeapAllocator>& charList);
NSTokens::ParseTokenKind ScanLogTag(JsUtil::List<char16, HeapAllocator>& charList);
NSTokens::ParseTokenKind ScanEnumTag(JsUtil::List<char16, HeapAllocator>& charList);
NSTokens::ParseTokenKind ScanWellKnownToken(JsUtil::List<char16, HeapAllocator>& charList);
NSTokens::ParseTokenKind ScanString(JsUtil::List<char16, HeapAllocator>& charList);
NSTokens::ParseTokenKind ScanNakedString(char16 leadChar);
int64 ReadIntFromCharArray(const char16* buff);
uint64 ReadUIntFromCharArray(const char16* buff);
double ReadDoubleFromCharArray(const char16* buff);
public:
TextFormatReader(JsTTDStreamHandle handle, TTDReadBytesFromStreamCallback pfRead, TTDFlushAndCloseStreamCallback pfClose);
virtual ~TextFormatReader();
virtual void ReadSeperator(bool readSeparator) override;
virtual void ReadKey(NSTokens::Key keyCheck, bool readSeparator = false) override;
virtual void ReadSequenceStart(bool readSeparator = false) override;
virtual void ReadSequenceEnd() override;
virtual void ReadRecordStart(bool readSeparator = false) override;
virtual void ReadRecordEnd() override;
////
virtual void ReadNakedNull(bool readSeparator = false) override;
virtual byte ReadNakedByte(bool readSeparator = false) override;
virtual bool ReadBool(NSTokens::Key keyCheck, bool readSeparator = false) override;
virtual int32 ReadNakedInt32(bool readSeparator = false) override;
virtual uint32 ReadNakedUInt32(bool readSeparator = false) override;
virtual int64 ReadNakedInt64(bool readSeparator = false) override;
virtual uint64 ReadNakedUInt64(bool readSeparator = false) override;
virtual double ReadNakedDouble(bool readSeparator = false) override;
virtual TTD_PTR_ID ReadNakedAddr(bool readSeparator = false) override;
virtual TTD_LOG_PTR_ID ReadNakedLogTag(bool readSeparator = false) override;
virtual uint32 ReadNakedTag(bool readSeparator = false) override;
////
virtual void ReadNakedString(SlabAllocator& alloc, TTString& into, bool readSeparator = false) override;
virtual void ReadNakedString(UnlinkableSlabAllocator& alloc, TTString& into, bool readSeparator = false) override;
virtual TTD_WELLKNOWN_TOKEN ReadNakedWellKnownToken(SlabAllocator& alloc, bool readSeparator = false) override;
virtual TTD_WELLKNOWN_TOKEN ReadNakedWellKnownToken(UnlinkableSlabAllocator& alloc, bool readSeparator = false) override;
virtual void ReadInlineCode(_Out_writes_(length) char16* code, uint32 length, bool readSeparator = false) override;
};
//A serialization class that reads a compact binary format
class BinaryFormatReader : public FileReader
{
public:
BinaryFormatReader(JsTTDStreamHandle handle, TTDReadBytesFromStreamCallback pfRead, TTDFlushAndCloseStreamCallback pfClose);
virtual ~BinaryFormatReader();
virtual void ReadSeperator(bool readSeparator) override;
virtual void ReadKey(NSTokens::Key keyCheck, bool readSeparator = false) override;
virtual void ReadSequenceStart(bool readSeparator = false) override;
virtual void ReadSequenceEnd() override;
virtual void ReadRecordStart(bool readSeparator = false) override;
virtual void ReadRecordEnd() override;
////
virtual void ReadNakedNull(bool readSeparator = false) override;
virtual byte ReadNakedByte(bool readSeparator = false) override;
virtual bool ReadBool(NSTokens::Key keyCheck, bool readSeparator = false) override;
virtual int32 ReadNakedInt32(bool readSeparator = false) override;
virtual uint32 ReadNakedUInt32(bool readSeparator = false) override;
virtual int64 ReadNakedInt64(bool readSeparator = false) override;
virtual uint64 ReadNakedUInt64(bool readSeparator = false) override;
virtual double ReadNakedDouble(bool readSeparator = false) override;
virtual TTD_PTR_ID ReadNakedAddr(bool readSeparator = false) override;
virtual TTD_LOG_PTR_ID ReadNakedLogTag(bool readSeparator = false) override;
virtual uint32 ReadNakedTag(bool readSeparator = false) override;
////
virtual void ReadNakedString(SlabAllocator& alloc, TTString& into, bool readSeparator = false) override;
virtual void ReadNakedString(UnlinkableSlabAllocator& alloc, TTString& into, bool readSeparator = false) override;
virtual TTD_WELLKNOWN_TOKEN ReadNakedWellKnownToken(SlabAllocator& alloc, bool readSeparator = false) override;
virtual TTD_WELLKNOWN_TOKEN ReadNakedWellKnownToken(UnlinkableSlabAllocator& alloc, bool readSeparator = false) override;
virtual void ReadInlineCode(_Out_writes_(length) char16* code, uint32 length, bool readSeparator = false) override;
};
//////////////////
#if ENABLE_OBJECT_SOURCE_TRACKING
//A struct that we use for tracking where objects have been allocated
struct DiagnosticOrigin
{
int32 SourceLine;
uint32 EventTime;
uint64 TimeHash;
};
bool IsDiagnosticOriginInformationValid(const DiagnosticOrigin& info);
void InitializeDiagnosticOriginInformation(DiagnosticOrigin& info);
void CopyDiagnosticOriginInformation(DiagnosticOrigin& infoInto, const DiagnosticOrigin& infoFrom);
void SetDiagnosticOriginInformation(DiagnosticOrigin& info, uint32 sourceLine, uint64 eTime, uint64 fTime, uint64 lTime);
void EmitDiagnosticOriginInformation(const DiagnosticOrigin& info, FileWriter* writer, NSTokens::Separator separator);
void ParseDiagnosticOriginInformation(DiagnosticOrigin& info, bool readSeperator, FileReader* reader);
#endif
#if ENABLE_BASIC_TRACE || ENABLE_FULL_BC_TRACE
#define TRACE_LOGGER_BUFFER_SIZE 4096
#define TRACE_LOGGER_INDENT_BUFFER_SIZE 64
//Class that provides all of the trace output functionality we want
class TraceLogger
{
private:
char* m_buffer;
char* m_indentBuffer;
int32 m_currLength;
int32 m_indentSize;
FILE* m_outfile;
void EnsureSpace(uint32 length)
{
if(this->m_currLength + length >= TRACE_LOGGER_BUFFER_SIZE)
{
fwrite(this->m_buffer, sizeof(char), this->m_currLength, this->m_outfile);
fflush(this->m_outfile);
this->m_currLength = 0;
}
}
void AppendRaw(const char* str, uint32 length)
{
if(length >= TRACE_LOGGER_BUFFER_SIZE)
{
const char* msg = "Oversize string ... omitting from output";
fwrite(msg, sizeof(char), strlen(msg), this->m_outfile);
}
else
{
TTDAssert(this->m_currLength + length < TRACE_LOGGER_BUFFER_SIZE, "We are going to overrun!");
memcpy(this->m_buffer + this->m_currLength, str, length);
this->m_currLength += length;
}
}
void AppendRaw(const char16* str, uint32 length)
{
if(length >= TRACE_LOGGER_BUFFER_SIZE)
{
const char* msg = "Oversize string ... omitting from output";
fwrite(msg, sizeof(char), strlen(msg), this->m_outfile);
}
else
{
TTDAssert(this->m_currLength + length < TRACE_LOGGER_BUFFER_SIZE, "We are going to overrun!");
char* currs = (this->m_buffer + this->m_currLength);
const char16* currw = str;
for(uint32 i = 0; i < length; ++i)
{
*currs = (char)(*currw);
++currs;
++currw;
}
this->m_currLength += length;
}
}
template<size_t N>
void AppendLiteral(const char(&str)[N])
{
this->EnsureSpace(N - 1);
this->AppendRaw(str, N - 1);
}
void AppendText(char* text, uint32 length);
void AppendText(const char16* text, uint32 length);
void AppendIndent();
void AppendString(char* text);
void AppendBool(bool bval);
void AppendInteger(int64 ival);
void AppendUnsignedInteger(uint64 ival);
void AppendIntegerHex(int64 ival);
void AppendDouble(double dval);
public:
TraceLogger(FILE* outfile = stderr);
~TraceLogger();
void ForceFlush();
template<size_t N>
void WriteLiteralMsg(const char(&str)[N])
{
this->AppendIndent();
this->AppendLiteral(str);
this->ForceFlush();
}
void WriteEnumAction(int64 eTime, BOOL returnCode, Js::PropertyId pid, Js::PropertyAttributes attrib, Js::JavascriptString* pname);
void WriteVar(Js::Var var, bool skipStringContents=false);
void WriteCall(Js::JavascriptFunction* function, bool isExternal, uint32 argc, Js::Var* argv, int64 etime);
void WriteReturn(Js::JavascriptFunction* function, Js::Var res, int64 etime);
void WriteReturnException(Js::JavascriptFunction* function, int64 etime);
void WriteStmtIndex(uint32 line, uint32 column);
void WriteTraceValue(Js::Var var);
};
#endif
}
#endif