Major Update:
- Update printing: Do not use '\n' if indent = 0
- Implement refilling of buffer (from fd) while parsing
- No longer use LineMark, but keep track of char position with CharNo
- Use Mark to reference point for shifting buffer on refill
- SkipWhiteSpace no longer inline method
- Refill buffer if required, change Mark & CharNo on line break
- CreateBuffer(), RefillBuffer() & FreeBuffer() now public methods
- Make Loading and Saving more flexible:
- Refactor from LoadFromFile():
ReadFromFile(), ReadFromHandle(), ReadFromBuffer()
- Refactor from SaveToFile() & PrintToScreen:
WriteToFile(), WriteToScreen, WriteToHandle()
This commit is contained in:
@@ -688,16 +688,16 @@ int CShiftBuffer::Clear( int ClearLen )
|
|||||||
if ((ClearLen == -1) || (ClearLen >= BufLen))
|
if ((ClearLen == -1) || (ClearLen >= BufLen))
|
||||||
{
|
{
|
||||||
// Clear all data
|
// Clear all data
|
||||||
BytesCleared = BufLen;
|
|
||||||
BufLen = 0;
|
BufLen = 0;
|
||||||
Buffer[0] = 0;
|
Buffer[0] = 0;
|
||||||
|
BytesCleared = BufLen;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Shift remaining data
|
// Shift remaining data
|
||||||
BytesCleared = ClearLen;
|
|
||||||
memmove( Buffer, &Buffer[ClearLen], BufLen-ClearLen ); // Shift remaining old data left
|
memmove( Buffer, &Buffer[ClearLen], BufLen-ClearLen ); // Shift remaining old data left
|
||||||
BufLen -= ClearLen;
|
BufLen -= ClearLen;
|
||||||
Buffer[BufLen] = 0;
|
Buffer[BufLen] = 0;
|
||||||
|
BytesCleared = ClearLen;
|
||||||
}
|
}
|
||||||
|
|
||||||
return BytesCleared;
|
return BytesCleared;
|
||||||
|
|||||||
@@ -27,12 +27,13 @@ CJSONparse::CJSONparse( CDataTree * pDataTree )
|
|||||||
OutputHandle = -1;
|
OutputHandle = -1;
|
||||||
|
|
||||||
Buffer = NULL;
|
Buffer = NULL;
|
||||||
BufEnd = NULL;
|
|
||||||
|
|
||||||
// Parsing operation
|
// Parsing operation
|
||||||
BufPos = NULL;
|
BufPos = NULL;
|
||||||
LineMark = NULL;
|
Mark = NULL;
|
||||||
LineNo = 0;
|
LineNo = 0;
|
||||||
|
CharNo = 0;
|
||||||
|
RefillBuffer = false;
|
||||||
|
|
||||||
// Printing operation
|
// Printing operation
|
||||||
Spacer[0] = 0;
|
Spacer[0] = 0;
|
||||||
@@ -53,53 +54,31 @@ CJSONparse::~CJSONparse()
|
|||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
bool CJSONparse::PrintToScreen( const char * RootPath, const int Indent )
|
bool CJSONparse::WriteToScreen( const char * RootPath, const int Indent )
|
||||||
{
|
{
|
||||||
TDataMember * RootObject;
|
|
||||||
|
|
||||||
// Validate
|
|
||||||
if (!DataTree) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set to StdOut
|
|
||||||
OutputHandle = 1;
|
|
||||||
|
|
||||||
// Get Root object
|
|
||||||
if (!RootPath || !*RootPath) {
|
|
||||||
RootObject = DataTree->GetRootMember();
|
|
||||||
}
|
|
||||||
else if (!(RootObject = DataTree->GetMember( NULL, RootPath ))) {
|
|
||||||
Error = true;
|
|
||||||
sprintf( ErrorText, "Invalid root object path" );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print key name
|
|
||||||
if (RootObject->Name) {
|
|
||||||
write( OutputHandle, "\"", 1 );
|
|
||||||
write( OutputHandle, RootObject->Name, strlen(RootObject->Name) );
|
|
||||||
write( OutputHandle, "\" : ", 4 );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print to screen
|
// Print to screen
|
||||||
PrintObject( RootObject, Indent );
|
WriteToHandle( RootPath, 1, Indent );
|
||||||
|
|
||||||
// Close file
|
|
||||||
close( OutputHandle );
|
|
||||||
OutputHandle = -1;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
bool CJSONparse::SaveToFile( const char * RootPath, const char * FilePath, const int Indent )
|
bool CJSONparse::WriteToFile( const char * RootPath, const char * Path, const char * FileName, const int Indent )
|
||||||
{
|
{
|
||||||
TDataMember * RootObject;
|
char FilePath[250] = "";
|
||||||
|
|
||||||
// Validate
|
// Build file name
|
||||||
if (!DataTree) {
|
strcpy( FilePath, Path );
|
||||||
return false;
|
strcat( FilePath, FileName );
|
||||||
|
|
||||||
|
// Read file
|
||||||
|
return WriteToFile( RootPath, FilePath, Indent );
|
||||||
}
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool CJSONparse::WriteToFile( const char * RootPath, const char * FilePath, const int Indent )
|
||||||
|
{
|
||||||
|
int Handle = -1;
|
||||||
|
|
||||||
// Clear Error
|
// Clear Error
|
||||||
Error = false;
|
Error = false;
|
||||||
@@ -112,12 +91,38 @@ bool CJSONparse::SaveToFile( const char * RootPath, const char * FilePath, const
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Open file
|
// Open file
|
||||||
if (!(OutputHandle = open( FilePath, O_CREAT|O_WRONLY|O_TRUNC ))) {
|
if ((Handle = open( FilePath, O_CREAT|O_WRONLY|O_TRUNC )) < 0) {
|
||||||
Error = true;
|
Error = true;
|
||||||
sprintf( ErrorText, "Could not open file" );
|
sprintf( ErrorText, "Could not open file" );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Save to file
|
||||||
|
WriteToHandle( RootPath, Handle, Indent );
|
||||||
|
|
||||||
|
// Close file
|
||||||
|
close( Handle );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool CJSONparse::WriteToHandle( const char * RootPath, const int Handle, const int Indent )
|
||||||
|
{
|
||||||
|
TDataMember * RootObject;
|
||||||
|
|
||||||
|
// Validate
|
||||||
|
if (!DataTree) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open file
|
||||||
|
if (Handle < 0) {
|
||||||
|
Error = true;
|
||||||
|
sprintf( ErrorText, "Could not write to invalid handle" );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
OutputHandle = Handle;
|
||||||
|
|
||||||
// Get Root object
|
// Get Root object
|
||||||
if (!RootPath || !*RootPath) {
|
if (!RootPath || !*RootPath) {
|
||||||
RootObject = DataTree->GetRootMember();
|
RootObject = DataTree->GetRootMember();
|
||||||
@@ -130,17 +135,29 @@ bool CJSONparse::SaveToFile( const char * RootPath, const char * FilePath, const
|
|||||||
|
|
||||||
// Print to file
|
// Print to file
|
||||||
PrintObject( RootObject, Indent );
|
PrintObject( RootObject, Indent );
|
||||||
|
write( OutputHandle, "\n", 1 );
|
||||||
|
|
||||||
// Close file
|
|
||||||
close( OutputHandle );
|
|
||||||
OutputHandle = -1;
|
OutputHandle = -1;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
bool CJSONparse::LoadFromFile( const char * RootPath, const char * FilePath, int pBufLen )
|
bool CJSONparse::ReadFromFile( const char * RootPath, const char * Path, const char * FileName )
|
||||||
{
|
{
|
||||||
TDataMember * RootObject = NULL;
|
char FilePath[250] = "";
|
||||||
|
|
||||||
|
// Build file name
|
||||||
|
strcpy( FilePath, Path );
|
||||||
|
strcat( FilePath, FileName );
|
||||||
|
|
||||||
|
// Read file
|
||||||
|
return ReadFromFile( RootPath, FilePath );
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool CJSONparse::ReadFromFile( const char * RootPath, const char * FilePath )
|
||||||
|
{
|
||||||
|
int Handle = -1;
|
||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
if (!DataTree) {
|
if (!DataTree) {
|
||||||
@@ -158,14 +175,36 @@ bool CJSONparse::LoadFromFile( const char * RootPath, const char * FilePath, int
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Open file
|
// Open file
|
||||||
if (!(InputHandle = open( FilePath, O_RDONLY ))) {
|
if ((Handle = open( FilePath, O_RDONLY )) < 0) {
|
||||||
Error = true;
|
Error = true;
|
||||||
sprintf( ErrorText, "Could not open file" );
|
sprintf( ErrorText, "Could not open file" );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Continuously refill buffer while loading
|
||||||
|
ReadFromHandle( RootPath, Handle, true );
|
||||||
|
|
||||||
|
// Close File
|
||||||
|
close( Handle );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool CJSONparse::ReadFromHandle( const char * RootPath, int Handle, bool pRefillBuffer )
|
||||||
|
{
|
||||||
|
// Clear Error
|
||||||
|
Error = false;
|
||||||
|
|
||||||
|
// Validate
|
||||||
|
if (Handle < 0) {
|
||||||
|
Error = true;
|
||||||
|
sprintf( ErrorText, "Cannot read from invalid handle" );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
InputHandle = Handle;
|
||||||
|
|
||||||
// Load Buffer
|
// Load Buffer
|
||||||
CreateBuffer( pBufLen );
|
CreateBuffer( 50 );
|
||||||
if (!FillBuffer()) {
|
if (!FillBuffer()) {
|
||||||
Error = true;
|
Error = true;
|
||||||
sprintf( ErrorText, "Could not read from file" );
|
sprintf( ErrorText, "Could not read from file" );
|
||||||
@@ -173,6 +212,31 @@ bool CJSONparse::LoadFromFile( const char * RootPath, const char * FilePath, int
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Continuously refill buffer while loading
|
||||||
|
RefillBuffer = pRefillBuffer;
|
||||||
|
ReadFromBuffer( RootPath );
|
||||||
|
RefillBuffer = false;
|
||||||
|
|
||||||
|
// Destroy buffer
|
||||||
|
FreeBuffer();
|
||||||
|
|
||||||
|
InputHandle = -1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool CJSONparse::ReadFromBuffer( const char * RootPath )
|
||||||
|
{
|
||||||
|
TDataMember * RootObject = NULL;
|
||||||
|
|
||||||
|
// Validate
|
||||||
|
if (!DataTree || !Buffer) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear Error
|
||||||
|
Error = false;
|
||||||
|
|
||||||
// Get/Create Root object
|
// Get/Create Root object
|
||||||
if (!RootPath || !*RootPath) {
|
if (!RootPath || !*RootPath) {
|
||||||
RootObject = DataTree->GetRootMember();
|
RootObject = DataTree->GetRootMember();
|
||||||
@@ -183,16 +247,20 @@ bool CJSONparse::LoadFromFile( const char * RootPath, const char * FilePath, int
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset values
|
// Delete existing object contents
|
||||||
LineNo = 1;
|
|
||||||
DataTree->Delete( RootObject, NULL );
|
DataTree->Delete( RootObject, NULL );
|
||||||
|
|
||||||
|
// Position Counters
|
||||||
|
LineNo = 1;
|
||||||
|
CharNo = 0;
|
||||||
|
|
||||||
// Parse Root Object
|
// Parse Root Object
|
||||||
SkipWhiteSpace();
|
SkipWhiteSpace();
|
||||||
if (!ParseObject( RootObject )) {
|
if (!ParseObject( RootObject )) {
|
||||||
if (!Error) {
|
if (!Error) {
|
||||||
Error = true;
|
Error = true;
|
||||||
sprintf( ErrorText, "First entry in file must be an Object on line %d:%ld", LineNo, BufPos-LineMark );
|
CharNo += BufPos-Mark;
|
||||||
|
sprintf( ErrorText, "First entry in file must be an Object on line %d:%d", LineNo, CharNo );
|
||||||
}
|
}
|
||||||
FreeBuffer();
|
FreeBuffer();
|
||||||
return false;
|
return false;
|
||||||
@@ -202,15 +270,13 @@ bool CJSONparse::LoadFromFile( const char * RootPath, const char * FilePath, int
|
|||||||
SkipWhiteSpace();
|
SkipWhiteSpace();
|
||||||
if (*BufPos != 0) {
|
if (*BufPos != 0) {
|
||||||
Error = true;
|
Error = true;
|
||||||
sprintf( ErrorText, "No content expected after Root object on line %d:%ld", LineNo, BufPos-LineMark );
|
CharNo += BufPos-Mark;
|
||||||
|
sprintf( ErrorText, "No content expected after Root object on line %d:%d", LineNo, CharNo );
|
||||||
FreeBuffer();
|
FreeBuffer();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Success
|
// Success
|
||||||
close( InputHandle );
|
|
||||||
InputHandle = -1;
|
|
||||||
FreeBuffer();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@@ -226,8 +292,7 @@ bool CJSONparse::CreateBuffer( int pBufLen )
|
|||||||
|
|
||||||
// Reset markers
|
// Reset markers
|
||||||
Buffer->PeekDirect( &BufPos, 0 );
|
Buffer->PeekDirect( &BufPos, 0 );
|
||||||
BufEnd = BufPos;
|
Mark = BufPos;
|
||||||
LineMark = BufPos;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -235,13 +300,19 @@ bool CJSONparse::CreateBuffer( int pBufLen )
|
|||||||
|
|
||||||
bool CJSONparse::FillBuffer()
|
bool CJSONparse::FillBuffer()
|
||||||
{
|
{
|
||||||
|
char * BufStart;
|
||||||
|
int PosShift = BufPos - Mark;
|
||||||
|
|
||||||
|
// Remove all bytes up to Mark
|
||||||
|
Buffer->PeekDirect( &BufStart, 0 );
|
||||||
|
Buffer->Clear( Mark-BufStart );
|
||||||
|
|
||||||
// Read from file
|
// Read from file
|
||||||
Buffer->ReadFromFD( InputHandle );
|
Buffer->ReadFromFD( InputHandle );
|
||||||
|
|
||||||
// Update Markers
|
// Reset Mark to start of buffer
|
||||||
Buffer->PeekDirect( &BufEnd, Buffer->Len() );
|
Mark = BufStart;
|
||||||
Buffer->PeekDirect( &BufPos, 0 );
|
BufPos = Mark + PosShift;
|
||||||
LineMark = BufPos;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -255,18 +326,40 @@ void CJSONparse::FreeBuffer()
|
|||||||
Buffer = NULL;
|
Buffer = NULL;
|
||||||
|
|
||||||
// Update Markers
|
// Update Markers
|
||||||
BufEnd = NULL;
|
|
||||||
BufPos = NULL;
|
BufPos = NULL;
|
||||||
LineMark = NULL;
|
Mark = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
bool CJSONparse::ParseString( char ** Value, int &pLen )
|
void CJSONparse::SkipWhiteSpace()
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
// Append buffer if required
|
||||||
|
if (!*BufPos && RefillBuffer)
|
||||||
|
FillBuffer();
|
||||||
|
|
||||||
|
// Skip whitespace
|
||||||
|
if (!isspace(*BufPos)) {
|
||||||
|
CharNo += BufPos-Mark;
|
||||||
|
Mark = BufPos;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*BufPos == '\n') {
|
||||||
|
Mark = BufPos;
|
||||||
|
LineNo++;
|
||||||
|
CharNo = 0;
|
||||||
|
}
|
||||||
|
BufPos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool CJSONparse::ParseString( char ** Value, int &Len )
|
||||||
{
|
{
|
||||||
char * Mark;
|
|
||||||
char * EndMark;
|
char * EndMark;
|
||||||
int Len;
|
|
||||||
|
|
||||||
// Check for opening quote
|
// Check for opening quote
|
||||||
if (*BufPos != '"') {
|
if (*BufPos != '"') {
|
||||||
@@ -278,12 +371,19 @@ bool CJSONparse::ParseString( char ** Value, int &pLen )
|
|||||||
Len = 0;
|
Len = 0;
|
||||||
|
|
||||||
// Mark start of quote
|
// Mark start of quote
|
||||||
Mark = BufPos;
|
|
||||||
BufPos++;
|
BufPos++;
|
||||||
|
|
||||||
// Check for closing quote
|
// Check for closing quote
|
||||||
while ((BufPos = strpbrk( BufPos, "\"/\\\n\t\b\f\n\r" )))
|
while (true)
|
||||||
{
|
{
|
||||||
|
// Check for special characters
|
||||||
|
if ((EndMark = strpbrk( BufPos, "\"/\\\n\t\b\f\n\r" ))) {
|
||||||
|
BufPos = EndMark;
|
||||||
|
} else if (RefillBuffer) {
|
||||||
|
FillBuffer();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (*BufPos == '"') {
|
if (*BufPos == '"') {
|
||||||
// End of string found
|
// End of string found
|
||||||
BufPos++;
|
BufPos++;
|
||||||
@@ -291,15 +391,25 @@ bool CJSONparse::ParseString( char ** Value, int &pLen )
|
|||||||
}
|
}
|
||||||
else if (!*BufPos) {
|
else if (!*BufPos) {
|
||||||
Error = true;
|
Error = true;
|
||||||
sprintf( ErrorText, "Expect closing '\"' for string on line %d:%ld", LineNo, Mark-LineMark );
|
sprintf( ErrorText, "Expect closing '\"' for string on line %d:%d", LineNo, CharNo+1 );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (*BufPos == '\\') {
|
else if (*BufPos == '\\') {
|
||||||
|
if (!*(BufPos+1) && RefillBuffer) {
|
||||||
|
if (FillBuffer()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (*(BufPos+1) == 'u') {
|
if (*(BufPos+1) == 'u') {
|
||||||
for (EndMark = BufPos+2; EndMark < BufPos+6; EndMark++) {
|
for (EndMark = BufPos+2; EndMark < BufPos+6; EndMark++) {
|
||||||
|
if (!*BufPos && RefillBuffer) {
|
||||||
|
FillBuffer();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (!isxdigit( *EndMark )) {
|
if (!isxdigit( *EndMark )) {
|
||||||
Error = true;
|
Error = true;
|
||||||
sprintf( ErrorText, "Expect 4-digit hex value for escape value on line %d:%ld", LineNo, Mark-LineMark );
|
CharNo += BufPos-EndMark;
|
||||||
|
sprintf( ErrorText, "Expect 4-digit hex value for escape value on line %d:%d", LineNo, CharNo );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -310,18 +420,20 @@ bool CJSONparse::ParseString( char ** Value, int &pLen )
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Error = true;
|
Error = true;
|
||||||
sprintf( ErrorText, "Invalid escape sequence on line %d:%ld", LineNo, Mark-LineMark );
|
CharNo += BufPos-Mark+1;
|
||||||
|
sprintf( ErrorText, "Invalid escape sequence on line %d:%d", LineNo, CharNo );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Error = true;
|
Error = true;
|
||||||
sprintf( ErrorText, "Un-escaped special character in string on line %d:%ld", LineNo, BufPos-LineMark );
|
CharNo += BufPos-Mark+1;
|
||||||
|
sprintf( ErrorText, "Un-escaped special character in string on line %d:%d", LineNo, CharNo );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate size of name
|
// Get size of name
|
||||||
Len = BufPos-Mark-2;
|
Len = BufPos-Mark-2;
|
||||||
|
|
||||||
// Create Return value pointer
|
// Create Return value pointer
|
||||||
@@ -329,9 +441,6 @@ bool CJSONparse::ParseString( char ** Value, int &pLen )
|
|||||||
memcpy( *Value, Mark+1, Len );
|
memcpy( *Value, Mark+1, Len );
|
||||||
(*Value)[Len] = 0;
|
(*Value)[Len] = 0;
|
||||||
|
|
||||||
// Set other parameters
|
|
||||||
pLen = Len;
|
|
||||||
|
|
||||||
// Success
|
// Success
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -354,21 +463,22 @@ bool CJSONparse::ParseObject( TDataMember * Object )
|
|||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
// Look for Member Name
|
// Evaluate key name
|
||||||
SkipWhiteSpace();
|
SkipWhiteSpace();
|
||||||
if (*BufPos == '}') {
|
if (*BufPos == '}') {
|
||||||
|
// End of Object
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (!ParseString( &MemberName, Len )) {
|
else if (!ParseString( &MemberName, Len )) {
|
||||||
if (!Error) {
|
if (!Error) {
|
||||||
Error = true;
|
Error = true;
|
||||||
sprintf( ErrorText, "Expect quoted key name on line %d:%ld", LineNo, BufPos-LineMark );
|
sprintf( ErrorText, "Expect quoted key name on line %d:%d", LineNo, CharNo );
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (!Len) {
|
else if (!Len) {
|
||||||
Error = true;
|
Error = true;
|
||||||
sprintf( ErrorText, "Empty parameter name on line %d:%ld", LineNo, BufPos-LineMark );
|
sprintf( ErrorText, "Empty parameter name on line %d:%d", LineNo, CharNo );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -379,7 +489,7 @@ bool CJSONparse::ParseObject( TDataMember * Object )
|
|||||||
SkipWhiteSpace();
|
SkipWhiteSpace();
|
||||||
if (*BufPos != ':') {
|
if (*BufPos != ':') {
|
||||||
Error = true;
|
Error = true;
|
||||||
sprintf( ErrorText, "Expected ':' delimiter on line %d:%ld", LineNo, BufPos-LineMark );
|
sprintf( ErrorText, "Expected ':' delimiter on line %d:%d", LineNo, CharNo );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
BufPos++;
|
BufPos++;
|
||||||
@@ -394,6 +504,7 @@ bool CJSONparse::ParseObject( TDataMember * Object )
|
|||||||
!Error &&
|
!Error &&
|
||||||
!ParsePrimitive( Member ))
|
!ParsePrimitive( Member ))
|
||||||
{
|
{
|
||||||
|
// Destroy member
|
||||||
DataTree->Delete( Object, MemberName );
|
DataTree->Delete( Object, MemberName );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -413,7 +524,7 @@ bool CJSONparse::ParseObject( TDataMember * Object )
|
|||||||
// Expect end of object
|
// Expect end of object
|
||||||
if (*BufPos != '}') {
|
if (*BufPos != '}') {
|
||||||
Error = true;
|
Error = true;
|
||||||
sprintf( ErrorText, "Closing brace for object '}' expected on line %d:%ld", LineNo, BufPos-LineMark );
|
sprintf( ErrorText, "Closing brace for object '}' expected on line %d:%d", LineNo, CharNo );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
BufPos++;
|
BufPos++;
|
||||||
@@ -476,7 +587,7 @@ bool CJSONparse::ParseArray( TDataMember * Array )
|
|||||||
// Expect end of object
|
// Expect end of object
|
||||||
if (*BufPos != ']') {
|
if (*BufPos != ']') {
|
||||||
Error = true;
|
Error = true;
|
||||||
sprintf( ErrorText, "Closing brace for array ']' expected on line %d:%ld", LineNo, BufPos-LineMark );
|
sprintf( ErrorText, "Closing brace for array ']' expected on line %d:%d", LineNo, CharNo );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
BufPos++;
|
BufPos++;
|
||||||
@@ -507,14 +618,14 @@ bool CJSONparse::ParsePrimitive( TDataMember * Member )
|
|||||||
{
|
{
|
||||||
char * Value = NULL;
|
char * Value = NULL;
|
||||||
int Len = 0;
|
int Len = 0;
|
||||||
char * Mark;
|
|
||||||
char * EndMark;
|
char * EndMark;
|
||||||
|
|
||||||
// Mark start of value
|
|
||||||
Mark = BufPos;
|
|
||||||
|
|
||||||
// Get end of value
|
// Get end of value
|
||||||
while ((*BufPos != 0) && !isspace(*BufPos) && (*BufPos != ',')) {
|
while (true) {
|
||||||
|
if (!*BufPos && RefillBuffer)
|
||||||
|
FillBuffer();
|
||||||
|
if (!*BufPos || isspace(*BufPos) || (*BufPos == ',') || (*BufPos == '}') || (*BufPos == ']'))
|
||||||
|
break;
|
||||||
BufPos++;
|
BufPos++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -522,7 +633,7 @@ bool CJSONparse::ParsePrimitive( TDataMember * Member )
|
|||||||
Len = BufPos - Mark;
|
Len = BufPos - Mark;
|
||||||
if (!Len) {
|
if (!Len) {
|
||||||
Error = true;
|
Error = true;
|
||||||
sprintf( ErrorText, "Missing param value on line %d:%ld", LineNo, Mark-LineMark );
|
sprintf( ErrorText, "Missing param value on line %d:%d", LineNo, CharNo );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -556,7 +667,7 @@ bool CJSONparse::ParsePrimitive( TDataMember * Member )
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Error = true;
|
Error = true;
|
||||||
sprintf( ErrorText, "Invalid primitive param value on line %d:%ld", LineNo, Mark-LineMark );
|
sprintf( ErrorText, "Invalid primitive param value on line %d:%d", LineNo, CharNo );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -578,14 +689,17 @@ bool CJSONparse::PrintObject( TDataMember * Object, const int Indent )
|
|||||||
write( OutputHandle, "{", 1 );
|
write( OutputHandle, "{", 1 );
|
||||||
|
|
||||||
// Extend spacer
|
// Extend spacer
|
||||||
|
if (Indent) {
|
||||||
memset( &Spacer[SpacerLen], ' ', 2 );
|
memset( &Spacer[SpacerLen], ' ', 2 );
|
||||||
SpacerLen += 2;
|
SpacerLen += 2;
|
||||||
Spacer[SpacerLen] = 0;
|
Spacer[SpacerLen] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Save parameters
|
// Save parameters
|
||||||
for (Member = Object->FirstChild; Member != NULL; (Member = Member->Next))
|
for (Member = Object->FirstChild; Member != NULL; (Member = Member->Next))
|
||||||
{
|
{
|
||||||
// Write parameter name
|
// Whitespace around first bracket
|
||||||
|
if (Indent) {
|
||||||
if (First) {
|
if (First) {
|
||||||
First = false;
|
First = false;
|
||||||
if (Object->Name) {
|
if (Object->Name) {
|
||||||
@@ -599,11 +713,16 @@ bool CJSONparse::PrintObject( TDataMember * Object, const int Indent )
|
|||||||
else {
|
else {
|
||||||
write( OutputHandle, Spacer, SpacerLen );
|
write( OutputHandle, Spacer, SpacerLen );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Print key name
|
// Print key name
|
||||||
write( OutputHandle, "\"", 1 );
|
write( OutputHandle, "\"", 1 );
|
||||||
write( OutputHandle, Member->Name, strlen(Member->Name) );
|
write( OutputHandle, Member->Name, strlen(Member->Name) );
|
||||||
|
if (Indent) {
|
||||||
write( OutputHandle,"\" : ", 4 );
|
write( OutputHandle,"\" : ", 4 );
|
||||||
|
} else {
|
||||||
|
write( OutputHandle, "\":", 2 );
|
||||||
|
}
|
||||||
|
|
||||||
// Print value
|
// Print value
|
||||||
Last = (++Count >= Object->Len);
|
Last = (++Count >= Object->Len);
|
||||||
@@ -633,15 +752,17 @@ bool CJSONparse::PrintObject( TDataMember * Object, const int Indent )
|
|||||||
PrintObject( Member, Indent );
|
PrintObject( Member, Indent );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!Last) {
|
if (!Last)
|
||||||
write( OutputHandle, ",", 1 );
|
write( OutputHandle, ",", 1 );
|
||||||
}
|
if (Indent)
|
||||||
write( OutputHandle, "\n", 1 );
|
write( OutputHandle, "\n", 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shorten spacer
|
// Shorten spacer
|
||||||
|
if (Indent) {
|
||||||
SpacerLen -= 2;
|
SpacerLen -= 2;
|
||||||
Spacer[SpacerLen] = 0;
|
Spacer[SpacerLen] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Closing brace
|
// Closing brace
|
||||||
if (Object->Len) {
|
if (Object->Len) {
|
||||||
@@ -663,19 +784,23 @@ bool CJSONparse::PrintArray( TDataMember * Array, const int Indent )
|
|||||||
write( OutputHandle, "[", 1 );
|
write( OutputHandle, "[", 1 );
|
||||||
|
|
||||||
// Extend spacer
|
// Extend spacer
|
||||||
|
if (Indent) {
|
||||||
memset( &Spacer[SpacerLen], ' ', 2 );
|
memset( &Spacer[SpacerLen], ' ', 2 );
|
||||||
SpacerLen += 2;
|
SpacerLen += 2;
|
||||||
Spacer[SpacerLen] = 0;
|
Spacer[SpacerLen] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Save parameters
|
// Save parameters
|
||||||
for (Member = Array->FirstChild; Member != NULL; (Member = Member->Next))
|
for (Member = Array->FirstChild; Member != NULL; (Member = Member->Next))
|
||||||
{
|
{
|
||||||
// Write parameter name
|
// Whitespace around brace
|
||||||
|
if (Indent) {
|
||||||
if (First) {
|
if (First) {
|
||||||
First = false;
|
First = false;
|
||||||
write( OutputHandle, "\n", 1 );
|
write( OutputHandle, "\n", 1 );
|
||||||
}
|
}
|
||||||
write( OutputHandle, Spacer, SpacerLen );
|
write( OutputHandle, Spacer, SpacerLen );
|
||||||
|
}
|
||||||
|
|
||||||
Last = (++Count >= Array->Len);
|
Last = (++Count >= Array->Len);
|
||||||
switch (Member->Type)
|
switch (Member->Type)
|
||||||
@@ -704,15 +829,17 @@ bool CJSONparse::PrintArray( TDataMember * Array, const int Indent )
|
|||||||
PrintObject( Member, Indent );
|
PrintObject( Member, Indent );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!Last) {
|
if (!Last)
|
||||||
write( OutputHandle, ",", 1 );
|
write( OutputHandle, ",", 1 );
|
||||||
}
|
if (Indent)
|
||||||
write( OutputHandle, "\n", 1 );
|
write( OutputHandle, "\n", 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shorten spacer
|
// Shorten spacer
|
||||||
|
if (Indent) {
|
||||||
SpacerLen -= 2;
|
SpacerLen -= 2;
|
||||||
Spacer[SpacerLen] = 0;
|
Spacer[SpacerLen] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Closing brace
|
// Closing brace
|
||||||
if (Array->Len) {
|
if (Array->Len) {
|
||||||
|
|||||||
@@ -32,10 +32,11 @@ private:
|
|||||||
CShiftBuffer * Buffer;
|
CShiftBuffer * Buffer;
|
||||||
|
|
||||||
// Parsing operation
|
// Parsing operation
|
||||||
char * BufEnd;
|
|
||||||
char * BufPos;
|
char * BufPos;
|
||||||
char * LineMark;
|
char * Mark;
|
||||||
int LineNo;
|
int LineNo;
|
||||||
|
int CharNo;
|
||||||
|
bool RefillBuffer;
|
||||||
|
|
||||||
// Printing Operation
|
// Printing Operation
|
||||||
char Spacer[100];
|
char Spacer[100];
|
||||||
@@ -45,21 +46,8 @@ private:
|
|||||||
bool Error;
|
bool Error;
|
||||||
char ErrorText[100];
|
char ErrorText[100];
|
||||||
|
|
||||||
// File Buffer operation
|
|
||||||
bool CreateBuffer( int pBufLen );
|
|
||||||
bool FillBuffer();
|
|
||||||
void FreeBuffer();
|
|
||||||
|
|
||||||
// Parsing functions
|
// Parsing functions
|
||||||
inline void SkipWhiteSpace() {
|
void SkipWhiteSpace();
|
||||||
while (isspace(*BufPos)) {
|
|
||||||
if (*BufPos == '\n') {
|
|
||||||
LineMark = BufPos;
|
|
||||||
LineNo++;
|
|
||||||
}
|
|
||||||
BufPos++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bool ParseString( char ** Value, int &pLen );
|
bool ParseString( char ** Value, int &pLen );
|
||||||
bool ParseObject( TDataMember * Object );
|
bool ParseObject( TDataMember * Object );
|
||||||
bool ParseArray( TDataMember * Array );
|
bool ParseArray( TDataMember * Array );
|
||||||
@@ -73,10 +61,22 @@ public:
|
|||||||
CJSONparse( CDataTree * pDataTree );
|
CJSONparse( CDataTree * pDataTree );
|
||||||
~CJSONparse();
|
~CJSONparse();
|
||||||
|
|
||||||
bool PrintToScreen( const char * Path, const int Indent );
|
// Buffer operation
|
||||||
|
bool CreateBuffer( int pBufLen );
|
||||||
|
bool FillBuffer();
|
||||||
|
void FreeBuffer();
|
||||||
|
bool ReadFromBuffer( const char * RootPath );
|
||||||
|
|
||||||
bool LoadFromFile( const char * Path, const char * FilePath, int pBufLen = 500 );
|
// Input
|
||||||
bool SaveToFile( const char * Path, const char * FilePath, const int Indent = 2 );
|
bool ReadFromHandle( const char * RootPath, const int Handle, bool pRefillBuffer );
|
||||||
|
bool ReadFromFile( const char * RootPath, const char * Path, const char * FileName );
|
||||||
|
bool ReadFromFile( const char * RootPath, const char * FilePath );
|
||||||
|
|
||||||
|
// Output
|
||||||
|
bool WriteToHandle( const char * RootPath, const int Handle, const int Indent = 2 );
|
||||||
|
bool WriteToScreen( const char * RootPath, const int Indent = 2 );
|
||||||
|
bool WriteToFile( const char * RootPath, const char * Path, const char * FileName, const int Indent = 2 );
|
||||||
|
bool WriteToFile( const char * RootPath, const char * FilePath, const int Indent = 2 );
|
||||||
|
|
||||||
const char * GetError() { return ((Error)? ErrorText : "Success"); };
|
const char * GetError() { return ((Error)? ErrorText : "Success"); };
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user