/* * JX9_INT_MAX * Expand the largest integer supported. * Note that JX9 deals with 64-bit integer for all platforms. */ static void JX9_INTMAX_Const(jx9_value *pVal, void *pUnused) { SXUNUSED(pUnused); jx9_value_int64(pVal, SXI64_HIGH); }
/* * JX9_INT_SIZE * Expand the size in bytes of a 64-bit integer. */ static void JX9_INTSIZE_Const(jx9_value *pVal, void *pUnused) { SXUNUSED(pUnused); jx9_value_int64(pVal, sizeof(sxi64)); }
/* * Decode a FastJSON binary blob. */ UNQLITE_PRIVATE sxi32 FastJsonDecode( const void *pIn, /* Binary JSON */ sxu32 nByte, /* Chunk delimiter */ jx9_value *pOut, /* Decoded value */ const unsigned char **pzPtr, int iNest /* Nesting limit */ ) { const unsigned char *zIn = (const unsigned char *)pIn; const unsigned char *zEnd = &zIn[nByte]; sxi32 rc = SXRET_OK; int c; if( iNest >= UNQLITE_FAST_JSON_NEST_LIMIT ){ /* Nesting limit reached */ return SXERR_LIMIT; } c = zIn[0]; /* Advance the stream cursor */ zIn++; /* Process the binary token */ switch(c){ case FJSON_NULL: /* null */ jx9_value_null(pOut); break; case FJSON_FALSE: /* Boolean FALSE */ jx9_value_bool(pOut,0); break; case FJSON_TRUE: /* Boolean TRUE */ jx9_value_bool(pOut,1); break; case FJSON_INT64: { /* 64Bit integer */ sxu64 iVal; /* Sanity check */ if( &zIn[8] >= zEnd ){ /* Corrupt chunk */ rc = SXERR_CORRUPT; break; } SyBigEndianUnpack64(zIn,&iVal); /* Advance the pointer */ zIn += 8; jx9_value_int64(pOut,(jx9_int64)iVal); break; } case FJSON_REAL: { /* Real number */ double iVal = 0; /* cc warning */ sxu16 iLen; /* Sanity check */ if( &zIn[2] >= zEnd ){ /* Corrupt chunk */ rc = SXERR_CORRUPT; break; } SyBigEndianUnpack16(zIn,&iLen); if( &zIn[iLen] >= zEnd ){ /* Corrupt chunk */ rc = SXERR_CORRUPT; break; } zIn += 2; SyStrToReal((const char *)zIn,(sxu32)iLen,&iVal,0); /* Advance the pointer */ zIn += iLen; jx9_value_double(pOut,iVal); break; } case FJSON_STRING: { /* UTF-8/Binary chunk */ sxu32 iLength; /* Sanity check */ if( &zIn[4] >= zEnd ){ /* Corrupt chunk */ rc = SXERR_CORRUPT; break; } SyBigEndianUnpack32(zIn,&iLength); if( &zIn[iLength] >= zEnd ){ /* Corrupt chunk */ rc = SXERR_CORRUPT; break; } zIn += 4; /* Invalidate any prior representation */ if( pOut->iFlags & MEMOBJ_STRING ){ /* Reset the string cursor */ SyBlobReset(&pOut->sBlob); } rc = jx9MemObjStringAppend(pOut,(const char *)zIn,iLength); /* Update pointer */ zIn += iLength; break; } case FJSON_ARRAY_START: { /* Binary JSON array */ jx9_hashmap *pMap; jx9_value sVal; /* Allocate a new hashmap */ pMap = (jx9_hashmap *)jx9NewHashmap(pOut->pVm,0,0); if( pMap == 0 ){ rc = SXERR_MEM; break; } jx9MemObjInit(pOut->pVm,&sVal); jx9MemObjRelease(pOut); MemObjSetType(pOut,MEMOBJ_HASHMAP); pOut->x.pOther = pMap; rc = SXRET_OK; for(;;){ /* Jump leading binary commas */ while (zIn < zEnd && zIn[0] == FJSON_COMMA ){ zIn++; } if( zIn >= zEnd || zIn[0] == FJSON_ARRAY_END ){ if( zIn < zEnd ){ zIn++; /* Jump the trailing binary ] */ } break; } /* Decode the value */ rc = FastJsonDecode((const void *)zIn,(sxu32)(zEnd-zIn),&sVal,&zIn,iNest+1); if( rc != SXRET_OK ){ break; } /* Insert the decoded value */ rc = jx9HashmapInsert(pMap,0,&sVal); if( rc != UNQLITE_OK ){ break; } } if( rc != SXRET_OK ){ jx9MemObjRelease(pOut); } jx9MemObjRelease(&sVal); break; } case FJSON_DOC_START: { /* Binary JSON object */ jx9_value sVal,sKey; jx9_hashmap *pMap; /* Allocate a new hashmap */ pMap = (jx9_hashmap *)jx9NewHashmap(pOut->pVm,0,0); if( pMap == 0 ){ rc = SXERR_MEM; break; } jx9MemObjInit(pOut->pVm,&sVal); jx9MemObjInit(pOut->pVm,&sKey); jx9MemObjRelease(pOut); MemObjSetType(pOut,MEMOBJ_HASHMAP); pOut->x.pOther = pMap; rc = SXRET_OK; for(;;){ /* Jump leading binary commas */ while (zIn < zEnd && zIn[0] == FJSON_COMMA ){ zIn++; } if( zIn >= zEnd || zIn[0] == FJSON_DOC_END ){ if( zIn < zEnd ){ zIn++; /* Jump the trailing binary } */ } break; } /* Extract the key */ rc = FastJsonDecode((const void *)zIn,(sxu32)(zEnd-zIn),&sKey,&zIn,iNest+1); if( rc != UNQLITE_OK ){ break; } if( zIn >= zEnd || zIn[0] != FJSON_COLON ){ rc = UNQLITE_CORRUPT; break; } zIn++; /* Jump the binary colon ':' */ if( zIn >= zEnd ){ rc = UNQLITE_CORRUPT; break; } /* Decode the value */ rc = FastJsonDecode((const void *)zIn,(sxu32)(zEnd-zIn),&sVal,&zIn,iNest+1); if( rc != SXRET_OK ){ break; } /* Insert the key and its associated value */ rc = jx9HashmapInsert(pMap,&sKey,&sVal); if( rc != UNQLITE_OK ){ break; } } if( rc != SXRET_OK ){ jx9MemObjRelease(pOut); } jx9MemObjRelease(&sVal); jx9MemObjRelease(&sKey); break; } default: /* Corrupt data */ rc = SXERR_CORRUPT; break; } if( pzPtr ){ *pzPtr = zIn; } return rc; }