2020-12-09 00:55:06 +01:00
|
|
|
/*************** bson CPP Declares Source Code File (.H) ***************/
|
|
|
|
/* Name: bson.cpp Version 1.0 */
|
2020-11-21 21:52:48 +01:00
|
|
|
/* */
|
2020-12-09 00:55:06 +01:00
|
|
|
/* (C) Copyright to the author Olivier BERTRAND 2020 */
|
2020-11-21 21:52:48 +01:00
|
|
|
/* */
|
2020-12-09 00:55:06 +01:00
|
|
|
/* This file contains the BJSON classes functions. */
|
2020-11-21 21:52:48 +01:00
|
|
|
/***********************************************************************/
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* Include relevant sections of the MariaDB header file. */
|
|
|
|
/***********************************************************************/
|
|
|
|
#include <my_global.h>
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* Include application header files: */
|
|
|
|
/* global.h is header containing all global declarations. */
|
|
|
|
/* plgdbsem.h is header containing the DB application declarations. */
|
2020-12-09 00:55:06 +01:00
|
|
|
/* bson.h is header containing the BSON classes declarations. */
|
2020-11-21 21:52:48 +01:00
|
|
|
/***********************************************************************/
|
|
|
|
#include "global.h"
|
|
|
|
#include "plgdbsem.h"
|
|
|
|
#include "bson.h"
|
|
|
|
|
2020-12-04 23:21:59 +01:00
|
|
|
/***********************************************************************/
|
|
|
|
/* Check macro. */
|
|
|
|
/***********************************************************************/
|
|
|
|
#if defined(_DEBUG)
|
|
|
|
#define CheckType(X,Y) if (!X || X ->Type != Y) throw MSG(VALTYPE_NOMATCH);
|
|
|
|
#else
|
2020-12-17 13:58:13 +01:00
|
|
|
#define CheckType(X,Y)
|
2020-12-04 23:21:59 +01:00
|
|
|
#endif
|
|
|
|
|
2021-06-08 17:44:43 +02:00
|
|
|
#if defined(_WIN32)
|
2020-11-21 21:52:48 +01:00
|
|
|
#define EL "\r\n"
|
|
|
|
#else
|
|
|
|
#define EL "\n"
|
|
|
|
#undef SE_CATCH // Does not work for Linux
|
|
|
|
#endif
|
|
|
|
|
2021-01-28 01:02:29 +01:00
|
|
|
int GetJsonDefPrec(void);
|
|
|
|
|
2020-11-21 21:52:48 +01:00
|
|
|
#if defined(SE_CATCH)
|
|
|
|
/**************************************************************************/
|
|
|
|
/* This is the support of catching C interrupts to prevent crashes. */
|
|
|
|
/**************************************************************************/
|
|
|
|
#include <eh.h>
|
|
|
|
|
|
|
|
class SE_Exception {
|
|
|
|
public:
|
|
|
|
SE_Exception(unsigned int n, PEXCEPTION_RECORD p) : nSE(n), eRec(p) {}
|
|
|
|
~SE_Exception() {}
|
|
|
|
|
|
|
|
unsigned int nSE;
|
|
|
|
PEXCEPTION_RECORD eRec;
|
|
|
|
}; // end of class SE_Exception
|
|
|
|
|
|
|
|
void trans_func(unsigned int u, _EXCEPTION_POINTERS* pExp) {
|
|
|
|
throw SE_Exception(u, pExp->ExceptionRecord);
|
|
|
|
} // end of trans_func
|
|
|
|
|
|
|
|
char* GetExceptionDesc(PGLOBAL g, unsigned int e);
|
|
|
|
#endif // SE_CATCH
|
|
|
|
|
|
|
|
/* --------------------------- Class BDOC ---------------------------- */
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* BDOC constructor. */
|
|
|
|
/***********************************************************************/
|
2020-12-01 19:30:56 +01:00
|
|
|
BDOC::BDOC(PGLOBAL G) : BJSON(G, NULL)
|
2020-11-21 21:52:48 +01:00
|
|
|
{
|
2020-11-25 12:56:45 +01:00
|
|
|
jp = NULL;
|
|
|
|
s = NULL;
|
|
|
|
len = 0;
|
2020-12-22 22:50:12 +01:00
|
|
|
pretty = 3;
|
2020-11-21 21:52:48 +01:00
|
|
|
pty[0] = pty[1] = pty[2] = true;
|
2020-12-22 22:50:12 +01:00
|
|
|
comma = false;
|
2020-11-21 21:52:48 +01:00
|
|
|
} // end of BDOC constructor
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* Parse a json string. */
|
|
|
|
/* Note: when pretty is not known, the caller set pretty to 3. */
|
|
|
|
/***********************************************************************/
|
2020-12-22 22:50:12 +01:00
|
|
|
PBVAL BDOC::ParseJson(PGLOBAL g, char* js, size_t lng)
|
2020-12-08 01:15:40 +01:00
|
|
|
{
|
2021-02-03 15:35:32 +01:00
|
|
|
size_t i;
|
2020-12-22 22:50:12 +01:00
|
|
|
bool b = false, ptyp = (bool *)pty;
|
2020-12-09 00:55:06 +01:00
|
|
|
PBVAL bvp = NULL;
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2020-11-25 12:56:45 +01:00
|
|
|
s = js;
|
|
|
|
len = lng;
|
|
|
|
xtrc(1, "BDOC::ParseJson: s=%.10s len=%zd\n", s, len);
|
2020-11-21 21:52:48 +01:00
|
|
|
|
|
|
|
if (!s || !len) {
|
|
|
|
strcpy(g->Message, "Void JSON object");
|
|
|
|
return NULL;
|
2020-12-22 22:50:12 +01:00
|
|
|
} // endif s
|
2020-11-21 21:52:48 +01:00
|
|
|
|
|
|
|
// Trying to guess the pretty format
|
|
|
|
if (s[0] == '[' && (s[1] == '\n' || (s[1] == '\r' && s[2] == '\n')))
|
|
|
|
pty[0] = false;
|
|
|
|
|
|
|
|
try {
|
2020-12-09 00:55:06 +01:00
|
|
|
bvp = NewVal();
|
|
|
|
bvp->Type = TYPE_UNKNOWN;
|
2020-11-21 21:52:48 +01:00
|
|
|
|
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
switch (s[i]) {
|
|
|
|
case '[':
|
2020-12-09 00:55:06 +01:00
|
|
|
if (bvp->Type != TYPE_UNKNOWN)
|
2020-12-22 22:50:12 +01:00
|
|
|
bvp->To_Val = ParseAsArray(i);
|
2020-11-21 21:52:48 +01:00
|
|
|
else
|
2020-12-09 00:55:06 +01:00
|
|
|
bvp->To_Val = ParseArray(++i);
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2020-12-09 00:55:06 +01:00
|
|
|
bvp->Type = TYPE_JAR;
|
2020-11-21 21:52:48 +01:00
|
|
|
break;
|
|
|
|
case '{':
|
2020-12-09 00:55:06 +01:00
|
|
|
if (bvp->Type != TYPE_UNKNOWN) {
|
2020-12-22 22:50:12 +01:00
|
|
|
bvp->To_Val = ParseAsArray(i);
|
2020-12-09 00:55:06 +01:00
|
|
|
bvp->Type = TYPE_JAR;
|
2020-11-25 17:42:01 +01:00
|
|
|
} else {
|
2020-12-09 00:55:06 +01:00
|
|
|
bvp->To_Val = ParseObject(++i);
|
|
|
|
bvp->Type = TYPE_JOB;
|
2020-11-25 17:42:01 +01:00
|
|
|
} // endif Type
|
2020-11-21 21:52:48 +01:00
|
|
|
|
|
|
|
break;
|
|
|
|
case ' ':
|
|
|
|
case '\t':
|
|
|
|
case '\n':
|
|
|
|
case '\r':
|
|
|
|
break;
|
|
|
|
case ',':
|
2020-12-09 00:55:06 +01:00
|
|
|
if (bvp->Type != TYPE_UNKNOWN && (pretty == 1 || pretty == 3)) {
|
2020-12-22 22:50:12 +01:00
|
|
|
comma = true;
|
2020-11-21 21:52:48 +01:00
|
|
|
pty[0] = pty[2] = false;
|
|
|
|
break;
|
|
|
|
} // endif pretty
|
|
|
|
|
2022-07-19 21:06:55 +02:00
|
|
|
snprintf(g->Message, sizeof(g->Message), "Unexpected ',' (pretty=%d)", pretty);
|
2020-11-21 21:52:48 +01:00
|
|
|
throw 3;
|
|
|
|
case '(':
|
|
|
|
b = true;
|
|
|
|
break;
|
|
|
|
case ')':
|
|
|
|
if (b) {
|
|
|
|
b = false;
|
|
|
|
break;
|
|
|
|
} // endif b
|
|
|
|
|
|
|
|
default:
|
2020-12-09 00:55:06 +01:00
|
|
|
if (bvp->Type != TYPE_UNKNOWN) {
|
2020-12-22 22:50:12 +01:00
|
|
|
bvp->To_Val = ParseAsArray(i);
|
2020-12-09 00:55:06 +01:00
|
|
|
bvp->Type = TYPE_JAR;
|
2020-12-26 19:44:38 +01:00
|
|
|
} else if ((bvp->To_Val = MOF(ParseValue(i, NewVal()))))
|
2020-12-09 00:55:06 +01:00
|
|
|
bvp->Type = TYPE_JVAL;
|
2020-11-21 21:52:48 +01:00
|
|
|
else
|
|
|
|
throw 4;
|
|
|
|
|
|
|
|
break;
|
|
|
|
}; // endswitch s[i]
|
|
|
|
|
2020-12-09 00:55:06 +01:00
|
|
|
if (bvp->Type == TYPE_UNKNOWN)
|
2022-07-19 21:06:55 +02:00
|
|
|
snprintf(g->Message, sizeof(g->Message), "Invalid Json string '%.*s'", MY_MIN((int)len, 50), s);
|
2020-12-22 22:50:12 +01:00
|
|
|
else if (pretty == 3) {
|
2020-11-21 21:52:48 +01:00
|
|
|
for (i = 0; i < 3; i++)
|
|
|
|
if (pty[i]) {
|
2020-12-22 22:50:12 +01:00
|
|
|
pretty = i;
|
2020-11-21 21:52:48 +01:00
|
|
|
break;
|
|
|
|
} // endif pty
|
|
|
|
|
|
|
|
} // endif ptyp
|
|
|
|
|
|
|
|
} catch (int n) {
|
|
|
|
if (trace(1))
|
2020-12-01 19:30:56 +01:00
|
|
|
htrc("Exception %d: %s\n", n, G->Message);
|
|
|
|
GetMsg(g);
|
2020-12-09 00:55:06 +01:00
|
|
|
bvp = NULL;
|
2020-11-21 21:52:48 +01:00
|
|
|
} catch (const char* msg) {
|
|
|
|
strcpy(g->Message, msg);
|
2020-12-09 00:55:06 +01:00
|
|
|
bvp = NULL;
|
2020-11-21 21:52:48 +01:00
|
|
|
} // end catch
|
|
|
|
|
2020-12-09 00:55:06 +01:00
|
|
|
return bvp;
|
2020-11-21 21:52:48 +01:00
|
|
|
} // end of ParseJson
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* Parse several items as being in an array. */
|
|
|
|
/***********************************************************************/
|
2021-02-03 15:35:32 +01:00
|
|
|
OFFSET BDOC::ParseAsArray(size_t& i) {
|
2020-11-21 21:52:48 +01:00
|
|
|
if (pty[0] && (!pretty || pretty > 2)) {
|
|
|
|
OFFSET jsp;
|
|
|
|
|
2020-12-22 22:50:12 +01:00
|
|
|
if ((jsp = ParseArray((i = 0))) && pretty == 3)
|
|
|
|
pretty = (pty[0]) ? 0 : 3;
|
2020-11-21 21:52:48 +01:00
|
|
|
|
|
|
|
return jsp;
|
|
|
|
} else
|
2020-12-01 19:30:56 +01:00
|
|
|
strcpy(G->Message, "More than one item in file");
|
2020-11-21 21:52:48 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
} // end of ParseAsArray
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* Parse a JSON Array. */
|
|
|
|
/***********************************************************************/
|
2021-02-03 15:35:32 +01:00
|
|
|
OFFSET BDOC::ParseArray(size_t& i)
|
2020-12-08 01:15:40 +01:00
|
|
|
{
|
2020-11-21 21:52:48 +01:00
|
|
|
int level = 0;
|
|
|
|
bool b = (!i);
|
|
|
|
PBVAL vlp, firstvlp, lastvlp;
|
|
|
|
|
|
|
|
vlp = firstvlp = lastvlp = NULL;
|
|
|
|
|
|
|
|
for (; i < len; i++)
|
|
|
|
switch (s[i]) {
|
|
|
|
case ',':
|
|
|
|
if (level < 2) {
|
2021-02-03 15:35:32 +01:00
|
|
|
sprintf(G->Message, "Unexpected ',' near %.*s", (int) ARGS);
|
2020-11-21 21:52:48 +01:00
|
|
|
throw 1;
|
|
|
|
} else
|
|
|
|
level = 1;
|
|
|
|
|
|
|
|
break;
|
|
|
|
case ']':
|
|
|
|
if (level == 1) {
|
2021-02-03 15:35:32 +01:00
|
|
|
sprintf(G->Message, "Unexpected ',]' near %.*s", (int) ARGS);
|
2020-11-21 21:52:48 +01:00
|
|
|
throw 1;
|
|
|
|
} // endif level
|
|
|
|
|
2020-11-25 12:56:45 +01:00
|
|
|
return MOF(firstvlp);
|
2020-11-21 21:52:48 +01:00
|
|
|
case '\n':
|
|
|
|
if (!b)
|
|
|
|
pty[0] = pty[1] = false;
|
|
|
|
case '\r':
|
|
|
|
case ' ':
|
|
|
|
case '\t':
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if (level == 2) {
|
2021-02-03 15:35:32 +01:00
|
|
|
sprintf(G->Message, "Unexpected value near %.*s", (int) ARGS);
|
2020-11-21 21:52:48 +01:00
|
|
|
throw 1;
|
|
|
|
} else if (lastvlp) {
|
2020-12-26 19:44:38 +01:00
|
|
|
vlp = ParseValue(i, NewVal());
|
2020-11-25 12:56:45 +01:00
|
|
|
lastvlp->Next = MOF(vlp);
|
2020-11-21 21:52:48 +01:00
|
|
|
lastvlp = vlp;
|
|
|
|
} else
|
2020-12-26 19:44:38 +01:00
|
|
|
firstvlp = lastvlp = ParseValue(i, NewVal());
|
2020-11-21 21:52:48 +01:00
|
|
|
|
|
|
|
level = (b) ? 1 : 2;
|
|
|
|
break;
|
|
|
|
}; // endswitch s[i]
|
|
|
|
|
|
|
|
if (b) {
|
|
|
|
// Case of Pretty == 0
|
2020-11-25 12:56:45 +01:00
|
|
|
return MOF(firstvlp);
|
2020-11-21 21:52:48 +01:00
|
|
|
} // endif b
|
|
|
|
|
|
|
|
throw ("Unexpected EOF in array");
|
|
|
|
} // end of ParseArray
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* Parse a JSON Object. */
|
|
|
|
/***********************************************************************/
|
2021-02-03 15:35:32 +01:00
|
|
|
OFFSET BDOC::ParseObject(size_t& i)
|
2020-12-08 01:15:40 +01:00
|
|
|
{
|
2020-11-21 21:52:48 +01:00
|
|
|
OFFSET key;
|
|
|
|
int level = 0;
|
|
|
|
PBPR bpp, firstbpp, lastbpp;
|
|
|
|
|
|
|
|
bpp = firstbpp = lastbpp = NULL;
|
|
|
|
|
|
|
|
for (; i < len; i++)
|
|
|
|
switch (s[i]) {
|
|
|
|
case '"':
|
|
|
|
if (level < 2) {
|
2020-12-01 19:30:56 +01:00
|
|
|
key = ParseString(++i);
|
2020-12-26 19:44:38 +01:00
|
|
|
bpp = NewPair(key);
|
2020-11-21 21:52:48 +01:00
|
|
|
|
|
|
|
if (lastbpp) {
|
2020-12-26 19:44:38 +01:00
|
|
|
lastbpp->Vlp.Next = MOF(bpp);
|
2020-11-21 21:52:48 +01:00
|
|
|
lastbpp = bpp;
|
|
|
|
} else
|
|
|
|
firstbpp = lastbpp = bpp;
|
|
|
|
|
2020-11-25 17:42:01 +01:00
|
|
|
level = 2;
|
2020-11-21 21:52:48 +01:00
|
|
|
} else {
|
2021-02-03 15:35:32 +01:00
|
|
|
sprintf(G->Message, "misplaced string near %.*s", (int) ARGS);
|
2020-11-21 21:52:48 +01:00
|
|
|
throw 2;
|
|
|
|
} // endif level
|
|
|
|
|
|
|
|
break;
|
|
|
|
case ':':
|
2020-11-25 17:42:01 +01:00
|
|
|
if (level == 2) {
|
2020-12-26 19:44:38 +01:00
|
|
|
ParseValue(++i, GetVlp(lastbpp));
|
2020-11-25 17:42:01 +01:00
|
|
|
level = 3;
|
2020-11-21 21:52:48 +01:00
|
|
|
} else {
|
2021-02-03 15:35:32 +01:00
|
|
|
sprintf(G->Message, "Unexpected ':' near %.*s", (int) ARGS);
|
2020-11-21 21:52:48 +01:00
|
|
|
throw 2;
|
|
|
|
} // endif level
|
|
|
|
|
|
|
|
break;
|
|
|
|
case ',':
|
2020-11-25 17:42:01 +01:00
|
|
|
if (level < 3) {
|
2021-02-03 15:35:32 +01:00
|
|
|
sprintf(G->Message, "Unexpected ',' near %.*s", (int) ARGS);
|
2020-11-21 21:52:48 +01:00
|
|
|
throw 2;
|
|
|
|
} else
|
2020-11-25 17:42:01 +01:00
|
|
|
level = 1;
|
2020-11-21 21:52:48 +01:00
|
|
|
|
|
|
|
break;
|
|
|
|
case '}':
|
2020-11-25 17:42:01 +01:00
|
|
|
if (!(level == 0 || level == 3)) {
|
2021-02-03 15:35:32 +01:00
|
|
|
sprintf(G->Message, "Unexpected '}' near %.*s", (int) ARGS);
|
2020-11-21 21:52:48 +01:00
|
|
|
throw 2;
|
|
|
|
} // endif level
|
|
|
|
|
2020-11-25 12:56:45 +01:00
|
|
|
return MOF(firstbpp);
|
2020-11-21 21:52:48 +01:00
|
|
|
case '\n':
|
|
|
|
pty[0] = pty[1] = false;
|
|
|
|
case '\r':
|
|
|
|
case ' ':
|
|
|
|
case '\t':
|
|
|
|
break;
|
|
|
|
default:
|
2020-12-01 19:30:56 +01:00
|
|
|
sprintf(G->Message, "Unexpected character '%c' near %.*s",
|
2021-02-03 15:35:32 +01:00
|
|
|
s[i], (int) ARGS);
|
2020-11-21 21:52:48 +01:00
|
|
|
throw 2;
|
|
|
|
}; // endswitch s[i]
|
|
|
|
|
2020-12-01 19:30:56 +01:00
|
|
|
strcpy(G->Message, "Unexpected EOF in Object");
|
2020-11-21 21:52:48 +01:00
|
|
|
throw 2;
|
|
|
|
} // end of ParseObject
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* Parse a JSON Value. */
|
|
|
|
/***********************************************************************/
|
2021-02-03 15:35:32 +01:00
|
|
|
PBVAL BDOC::ParseValue(size_t& i, PBVAL bvp)
|
2020-12-01 19:30:56 +01:00
|
|
|
{
|
2020-11-21 21:52:48 +01:00
|
|
|
for (; i < len; i++)
|
|
|
|
switch (s[i]) {
|
|
|
|
case '\n':
|
|
|
|
pty[0] = pty[1] = false;
|
|
|
|
case '\r':
|
|
|
|
case ' ':
|
|
|
|
case '\t':
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
goto suite;
|
|
|
|
} // endswitch
|
|
|
|
|
|
|
|
suite:
|
|
|
|
switch (s[i]) {
|
|
|
|
case '[':
|
2020-12-01 19:30:56 +01:00
|
|
|
bvp->To_Val = ParseArray(++i);
|
2020-11-21 21:52:48 +01:00
|
|
|
bvp->Type = TYPE_JAR;
|
|
|
|
break;
|
|
|
|
case '{':
|
2020-12-01 19:30:56 +01:00
|
|
|
bvp->To_Val = ParseObject(++i);
|
2020-11-21 21:52:48 +01:00
|
|
|
bvp->Type = TYPE_JOB;
|
|
|
|
break;
|
|
|
|
case '"':
|
2020-12-01 19:30:56 +01:00
|
|
|
bvp->To_Val = ParseString(++i);
|
2020-11-21 21:52:48 +01:00
|
|
|
bvp->Type = TYPE_STRG;
|
|
|
|
break;
|
|
|
|
case 't':
|
|
|
|
if (!strncmp(s + i, "true", 4)) {
|
|
|
|
bvp->B = true;
|
|
|
|
bvp->Type = TYPE_BOOL;
|
|
|
|
i += 3;
|
|
|
|
} else
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
break;
|
|
|
|
case 'f':
|
|
|
|
if (!strncmp(s + i, "false", 5)) {
|
|
|
|
bvp->B = false;
|
|
|
|
bvp->Type = TYPE_BOOL;
|
|
|
|
i += 4;
|
|
|
|
} else
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
break;
|
|
|
|
case 'n':
|
|
|
|
if (!strncmp(s + i, "null", 4)) {
|
|
|
|
bvp->Type = TYPE_NULL;
|
|
|
|
i += 3;
|
|
|
|
} else
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
break;
|
|
|
|
case '-':
|
|
|
|
default:
|
|
|
|
if (s[i] == '-' || isdigit(s[i]))
|
2020-12-01 19:30:56 +01:00
|
|
|
ParseNumeric(i, bvp);
|
2020-11-21 21:52:48 +01:00
|
|
|
else
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
}; // endswitch s[i]
|
|
|
|
|
|
|
|
return bvp;
|
|
|
|
|
|
|
|
err:
|
2021-02-03 15:35:32 +01:00
|
|
|
sprintf(G->Message, "Unexpected character '%c' near %.*s", s[i], (int) ARGS);
|
2020-11-21 21:52:48 +01:00
|
|
|
throw 3;
|
|
|
|
} // end of ParseValue
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* Unescape and parse a JSON string. */
|
|
|
|
/***********************************************************************/
|
2021-02-03 15:35:32 +01:00
|
|
|
OFFSET BDOC::ParseString(size_t& i)
|
2020-12-08 01:15:40 +01:00
|
|
|
{
|
2020-11-21 21:52:48 +01:00
|
|
|
uchar* p;
|
|
|
|
int n = 0;
|
|
|
|
|
|
|
|
// Be sure of memory availability
|
2020-12-01 19:30:56 +01:00
|
|
|
if (((size_t)len + 1 - i) > ((PPOOLHEADER)G->Sarea)->FreeBlk)
|
2020-11-21 21:52:48 +01:00
|
|
|
throw("ParseString: Out of memory");
|
|
|
|
|
|
|
|
// The size to allocate is not known yet
|
2020-12-08 01:15:40 +01:00
|
|
|
p = (uchar*)BsonSubAlloc(0);
|
2020-11-21 21:52:48 +01:00
|
|
|
|
|
|
|
for (; i < len; i++)
|
|
|
|
switch (s[i]) {
|
|
|
|
case '"':
|
|
|
|
p[n++] = 0;
|
2020-12-08 01:15:40 +01:00
|
|
|
BsonSubAlloc(n);
|
2020-11-25 12:56:45 +01:00
|
|
|
return MOF(p);
|
2020-11-21 21:52:48 +01:00
|
|
|
case '\\':
|
|
|
|
if (++i < len) {
|
|
|
|
if (s[i] == 'u') {
|
|
|
|
if (len - i > 5) {
|
|
|
|
// if (charset == utf8) {
|
|
|
|
char xs[5];
|
|
|
|
uint hex;
|
|
|
|
|
|
|
|
xs[0] = s[++i];
|
|
|
|
xs[1] = s[++i];
|
|
|
|
xs[2] = s[++i];
|
|
|
|
xs[3] = s[++i];
|
|
|
|
xs[4] = 0;
|
|
|
|
hex = strtoul(xs, NULL, 16);
|
|
|
|
|
|
|
|
if (hex < 0x80) {
|
|
|
|
p[n] = (uchar)hex;
|
|
|
|
} else if (hex < 0x800) {
|
|
|
|
p[n++] = (uchar)(0xC0 | (hex >> 6));
|
|
|
|
p[n] = (uchar)(0x80 | (hex & 0x3F));
|
|
|
|
} else if (hex < 0x10000) {
|
|
|
|
p[n++] = (uchar)(0xE0 | (hex >> 12));
|
|
|
|
p[n++] = (uchar)(0x80 | ((hex >> 6) & 0x3f));
|
|
|
|
p[n] = (uchar)(0x80 | (hex & 0x3f));
|
|
|
|
} else
|
|
|
|
p[n] = '?';
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
} else {
|
|
|
|
char xs[3];
|
|
|
|
UINT hex;
|
|
|
|
|
|
|
|
i += 2;
|
|
|
|
xs[0] = s[++i];
|
|
|
|
xs[1] = s[++i];
|
|
|
|
xs[2] = 0;
|
|
|
|
hex = strtoul(xs, NULL, 16);
|
|
|
|
p[n] = (char)hex;
|
|
|
|
} // endif charset
|
|
|
|
#endif // 0
|
|
|
|
} else
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
} else switch (s[i]) {
|
|
|
|
case 't': p[n] = '\t'; break;
|
|
|
|
case 'n': p[n] = '\n'; break;
|
|
|
|
case 'r': p[n] = '\r'; break;
|
|
|
|
case 'b': p[n] = '\b'; break;
|
|
|
|
case 'f': p[n] = '\f'; break;
|
|
|
|
default: p[n] = s[i]; break;
|
|
|
|
} // endswitch
|
|
|
|
|
|
|
|
n++;
|
|
|
|
} else
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
p[n++] = s[i];
|
|
|
|
break;
|
|
|
|
}; // endswitch s[i]
|
|
|
|
|
|
|
|
err:
|
|
|
|
throw("Unexpected EOF in String");
|
|
|
|
} // end of ParseString
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* Parse a JSON numeric value. */
|
|
|
|
/***********************************************************************/
|
2021-02-03 15:35:32 +01:00
|
|
|
void BDOC::ParseNumeric(size_t& i, PBVAL vlp)
|
2020-12-08 01:15:40 +01:00
|
|
|
{
|
2020-11-21 21:52:48 +01:00
|
|
|
char buf[50];
|
|
|
|
int n = 0;
|
|
|
|
short nd = 0;
|
|
|
|
bool has_dot = false;
|
|
|
|
bool has_e = false;
|
|
|
|
bool found_digit = false;
|
|
|
|
|
|
|
|
for (; i < len; i++) {
|
|
|
|
switch (s[i]) {
|
|
|
|
case '.':
|
|
|
|
if (!found_digit || has_dot || has_e)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
has_dot = true;
|
|
|
|
break;
|
|
|
|
case 'e':
|
|
|
|
case 'E':
|
|
|
|
if (!found_digit || has_e)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
has_e = true;
|
|
|
|
found_digit = false;
|
|
|
|
break;
|
|
|
|
case '+':
|
|
|
|
if (!has_e)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
// fall through
|
|
|
|
case '-':
|
|
|
|
if (found_digit)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if (isdigit(s[i])) {
|
|
|
|
if (has_dot && !has_e)
|
|
|
|
nd++; // Number of decimals
|
|
|
|
|
|
|
|
found_digit = true;
|
|
|
|
} else
|
|
|
|
goto fin;
|
|
|
|
|
|
|
|
}; // endswitch s[i]
|
|
|
|
|
|
|
|
buf[n++] = s[i];
|
|
|
|
} // endfor i
|
|
|
|
|
|
|
|
fin:
|
|
|
|
if (found_digit) {
|
|
|
|
buf[n] = 0;
|
|
|
|
|
|
|
|
if (has_dot || has_e) {
|
2021-01-08 22:18:52 +01:00
|
|
|
double dv = atof(buf);
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2021-01-08 22:18:52 +01:00
|
|
|
if (nd >= 6 || dv > FLT_MAX || dv < FLT_MIN) {
|
2020-12-01 19:30:56 +01:00
|
|
|
double* dvp = (double*)PlugSubAlloc(G, NULL, sizeof(double));
|
2020-11-21 21:52:48 +01:00
|
|
|
|
|
|
|
*dvp = dv;
|
2020-11-25 12:56:45 +01:00
|
|
|
vlp->To_Val = MOF(dvp);
|
2020-11-21 21:52:48 +01:00
|
|
|
vlp->Type = TYPE_DBL;
|
|
|
|
} else {
|
|
|
|
vlp->F = (float)dv;
|
|
|
|
vlp->Type = TYPE_FLOAT;
|
|
|
|
} // endif nd
|
|
|
|
|
2021-01-08 22:18:52 +01:00
|
|
|
vlp->Nd = MY_MIN(nd, 16);
|
2020-11-21 21:52:48 +01:00
|
|
|
} else {
|
2020-11-25 12:56:45 +01:00
|
|
|
longlong iv = strtoll(buf, NULL, 10);
|
2020-11-21 21:52:48 +01:00
|
|
|
|
|
|
|
if (iv > INT_MAX32 || iv < INT_MIN32) {
|
2020-12-01 19:30:56 +01:00
|
|
|
longlong *llp = (longlong*)PlugSubAlloc(G, NULL, sizeof(longlong));
|
2020-11-21 21:52:48 +01:00
|
|
|
|
|
|
|
*llp = iv;
|
2020-11-25 12:56:45 +01:00
|
|
|
vlp->To_Val = MOF(llp);
|
2020-11-21 21:52:48 +01:00
|
|
|
vlp->Type = TYPE_BINT;
|
|
|
|
} else {
|
|
|
|
vlp->N = (int)iv;
|
|
|
|
vlp->Type = TYPE_INTG;
|
|
|
|
} // endif iv
|
|
|
|
|
|
|
|
} // endif has
|
|
|
|
|
|
|
|
i--; // Unstack following character
|
|
|
|
return;
|
|
|
|
} else
|
|
|
|
throw("No digit found");
|
|
|
|
|
|
|
|
err:
|
|
|
|
throw("Unexpected EOF in number");
|
|
|
|
} // end of ParseNumeric
|
|
|
|
|
|
|
|
/***********************************************************************/
|
2020-11-25 12:56:45 +01:00
|
|
|
/* Serialize a BJSON document tree: */
|
2020-11-21 21:52:48 +01:00
|
|
|
/***********************************************************************/
|
2020-12-08 01:15:40 +01:00
|
|
|
PSZ BDOC::Serialize(PGLOBAL g, PBVAL bvp, char* fn, int pretty)
|
|
|
|
{
|
2020-11-21 21:52:48 +01:00
|
|
|
PSZ str = NULL;
|
|
|
|
bool b = false, err = true;
|
|
|
|
FILE* fs = NULL;
|
|
|
|
|
2020-12-01 19:30:56 +01:00
|
|
|
G->Message[0] = 0;
|
2020-11-21 21:52:48 +01:00
|
|
|
|
|
|
|
try {
|
|
|
|
if (!bvp) {
|
|
|
|
strcpy(g->Message, "Null json tree");
|
|
|
|
throw 1;
|
|
|
|
} else if (!fn) {
|
|
|
|
// Serialize to a string
|
|
|
|
jp = new(g) JOUTSTR(g);
|
|
|
|
b = pretty == 1;
|
|
|
|
} else {
|
|
|
|
if (!(fs = fopen(fn, "wb"))) {
|
2022-07-19 21:06:55 +02:00
|
|
|
snprintf(g->Message, sizeof(g->Message), MSG(OPEN_MODE_ERROR),
|
2020-11-21 21:52:48 +01:00
|
|
|
"w", (int)errno, fn);
|
|
|
|
strcat(strcat(g->Message, ": "), strerror(errno));
|
|
|
|
throw 2;
|
|
|
|
} else if (pretty >= 2) {
|
|
|
|
// Serialize to a pretty file
|
|
|
|
jp = new(g)JOUTPRT(g, fs);
|
|
|
|
} else {
|
|
|
|
// Serialize to a flat file
|
|
|
|
b = true;
|
|
|
|
jp = new(g)JOUTFILE(g, fs, pretty);
|
|
|
|
} // endif's
|
|
|
|
|
|
|
|
} // endif's
|
|
|
|
|
|
|
|
switch (bvp->Type) {
|
|
|
|
case TYPE_JAR:
|
|
|
|
err = SerializeArray(bvp->To_Val, b);
|
|
|
|
break;
|
|
|
|
case TYPE_JOB:
|
|
|
|
err = ((b && jp->Prty()) && jp->WriteChr('\t'));
|
|
|
|
err |= SerializeObject(bvp->To_Val);
|
|
|
|
break;
|
|
|
|
case TYPE_JVAL:
|
2020-11-25 12:56:45 +01:00
|
|
|
err = SerializeValue(MVP(bvp->To_Val));
|
2020-11-21 21:52:48 +01:00
|
|
|
break;
|
|
|
|
default:
|
2021-01-12 18:25:41 +01:00
|
|
|
err = SerializeValue(bvp, true);
|
2020-11-21 21:52:48 +01:00
|
|
|
} // endswitch Type
|
|
|
|
|
|
|
|
if (fs) {
|
|
|
|
fputs(EL, fs);
|
|
|
|
fclose(fs);
|
|
|
|
str = (err) ? NULL : strcpy(g->Message, "Ok");
|
|
|
|
} else if (!err) {
|
|
|
|
str = ((JOUTSTR*)jp)->Strp;
|
|
|
|
jp->WriteChr('\0');
|
|
|
|
PlugSubAlloc(g, NULL, ((JOUTSTR*)jp)->N);
|
2020-12-01 19:30:56 +01:00
|
|
|
} else if (G->Message[0])
|
2020-11-21 21:52:48 +01:00
|
|
|
strcpy(g->Message, "Error in Serialize");
|
2020-12-01 19:30:56 +01:00
|
|
|
else
|
|
|
|
GetMsg(g);
|
2020-11-21 21:52:48 +01:00
|
|
|
|
|
|
|
} catch (int n) {
|
|
|
|
if (trace(1))
|
2020-12-01 19:30:56 +01:00
|
|
|
htrc("Exception %d: %s\n", n, G->Message);
|
|
|
|
GetMsg(g);
|
2020-11-21 21:52:48 +01:00
|
|
|
str = NULL;
|
|
|
|
} catch (const char* msg) {
|
|
|
|
strcpy(g->Message, msg);
|
|
|
|
str = NULL;
|
|
|
|
} // end catch
|
|
|
|
|
|
|
|
return str;
|
|
|
|
} // end of Serialize
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* Serialize a JSON Array. */
|
|
|
|
/***********************************************************************/
|
2020-12-08 01:15:40 +01:00
|
|
|
bool BDOC::SerializeArray(OFFSET arp, bool b)
|
|
|
|
{
|
2020-11-21 21:52:48 +01:00
|
|
|
bool first = true;
|
2020-11-25 12:56:45 +01:00
|
|
|
PBVAL vp = MVP(arp);
|
2020-11-21 21:52:48 +01:00
|
|
|
|
|
|
|
if (b) {
|
|
|
|
if (jp->Prty()) {
|
|
|
|
if (jp->WriteChr('['))
|
|
|
|
return true;
|
|
|
|
else if (jp->Prty() == 1 && (jp->WriteStr(EL) || jp->WriteChr('\t')))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
} // endif Prty
|
|
|
|
|
|
|
|
} else if (jp->WriteChr('['))
|
|
|
|
return true;
|
|
|
|
|
2020-11-25 12:56:45 +01:00
|
|
|
for (vp; vp; vp = MVP(vp->Next)) {
|
2020-11-21 21:52:48 +01:00
|
|
|
if (first)
|
|
|
|
first = false;
|
|
|
|
else if ((!b || jp->Prty()) && jp->WriteChr(','))
|
|
|
|
return true;
|
|
|
|
else if (b) {
|
|
|
|
if (jp->Prty() < 2 && jp->WriteStr(EL))
|
|
|
|
return true;
|
|
|
|
else if (jp->Prty() == 1 && jp->WriteChr('\t'))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
} // endif b
|
|
|
|
|
|
|
|
if (SerializeValue(vp))
|
|
|
|
return true;
|
|
|
|
|
2020-11-25 12:56:45 +01:00
|
|
|
} // endfor vp
|
2020-11-21 21:52:48 +01:00
|
|
|
|
|
|
|
if (b && jp->Prty() == 1 && jp->WriteStr(EL))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return ((!b || jp->Prty()) && jp->WriteChr(']'));
|
|
|
|
} // end of SerializeArray
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* Serialize a JSON Object. */
|
|
|
|
/***********************************************************************/
|
2020-12-08 01:15:40 +01:00
|
|
|
bool BDOC::SerializeObject(OFFSET obp)
|
|
|
|
{
|
2020-11-21 21:52:48 +01:00
|
|
|
bool first = true;
|
2020-11-25 12:56:45 +01:00
|
|
|
PBPR prp = MPP(obp);
|
2020-11-21 21:52:48 +01:00
|
|
|
|
|
|
|
if (jp->WriteChr('{'))
|
|
|
|
return true;
|
|
|
|
|
2020-12-26 19:44:38 +01:00
|
|
|
for (prp; prp; prp = GetNext(prp)) {
|
2020-11-21 21:52:48 +01:00
|
|
|
if (first)
|
|
|
|
first = false;
|
|
|
|
else if (jp->WriteChr(','))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (jp->WriteChr('"') ||
|
2020-11-25 12:56:45 +01:00
|
|
|
jp->WriteStr(MZP(prp->Key)) ||
|
2020-11-21 21:52:48 +01:00
|
|
|
jp->WriteChr('"') ||
|
|
|
|
jp->WriteChr(':') ||
|
2020-12-26 19:44:38 +01:00
|
|
|
SerializeValue(GetVlp(prp)))
|
2020-11-21 21:52:48 +01:00
|
|
|
return true;
|
|
|
|
|
|
|
|
} // endfor i
|
|
|
|
|
|
|
|
return jp->WriteChr('}');
|
|
|
|
} // end of SerializeObject
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* Serialize a JSON Value. */
|
|
|
|
/***********************************************************************/
|
2021-01-12 18:25:41 +01:00
|
|
|
bool BDOC::SerializeValue(PBVAL jvp, bool b)
|
2020-12-08 01:15:40 +01:00
|
|
|
{
|
2020-11-21 21:52:48 +01:00
|
|
|
char buf[64];
|
|
|
|
|
2020-11-27 10:25:47 +01:00
|
|
|
if (jvp) switch (jvp->Type) {
|
2020-11-21 21:52:48 +01:00
|
|
|
case TYPE_JAR:
|
|
|
|
return SerializeArray(jvp->To_Val, false);
|
|
|
|
case TYPE_JOB:
|
|
|
|
return SerializeObject(jvp->To_Val);
|
|
|
|
case TYPE_BOOL:
|
|
|
|
return jp->WriteStr(jvp->B ? "true" : "false");
|
|
|
|
case TYPE_STRG:
|
|
|
|
case TYPE_DTM:
|
2021-01-12 18:25:41 +01:00
|
|
|
if (b) {
|
|
|
|
return jp->WriteStr(MZP(jvp->To_Val));
|
|
|
|
} else
|
|
|
|
return jp->Escape(MZP(jvp->To_Val));
|
|
|
|
|
2020-11-21 21:52:48 +01:00
|
|
|
case TYPE_INTG:
|
|
|
|
sprintf(buf, "%d", jvp->N);
|
|
|
|
return jp->WriteStr(buf);
|
|
|
|
case TYPE_BINT:
|
2020-11-25 12:56:45 +01:00
|
|
|
sprintf(buf, "%lld", *(longlong*)MakePtr(Base, jvp->To_Val));
|
2020-11-21 21:52:48 +01:00
|
|
|
return jp->WriteStr(buf);
|
|
|
|
case TYPE_FLOAT:
|
|
|
|
sprintf(buf, "%.*f", jvp->Nd, jvp->F);
|
|
|
|
return jp->WriteStr(buf);
|
|
|
|
case TYPE_DBL:
|
2020-11-25 12:56:45 +01:00
|
|
|
sprintf(buf, "%.*lf", jvp->Nd, *(double*)MakePtr(Base, jvp->To_Val));
|
2020-11-21 21:52:48 +01:00
|
|
|
return jp->WriteStr(buf);
|
|
|
|
case TYPE_NULL:
|
|
|
|
return jp->WriteStr("null");
|
2021-01-08 22:18:52 +01:00
|
|
|
case TYPE_JVAL:
|
|
|
|
return SerializeValue(MVP(jvp->To_Val));
|
2020-11-21 21:52:48 +01:00
|
|
|
default:
|
|
|
|
return jp->WriteStr("???"); // TODO
|
|
|
|
} // endswitch Type
|
|
|
|
|
2020-11-27 10:25:47 +01:00
|
|
|
return jp->WriteStr("null");
|
2020-11-21 21:52:48 +01:00
|
|
|
} // end of SerializeValue
|
|
|
|
|
2020-11-25 12:56:45 +01:00
|
|
|
/* --------------------------- Class BJSON --------------------------- */
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* Program for sub-allocating Bjson structures. */
|
|
|
|
/***********************************************************************/
|
2020-12-01 19:30:56 +01:00
|
|
|
void* BJSON::BsonSubAlloc(size_t size)
|
2020-11-25 12:56:45 +01:00
|
|
|
{
|
|
|
|
PPOOLHEADER pph; /* Points on area header. */
|
2020-12-01 19:30:56 +01:00
|
|
|
void* memp = G->Sarea;
|
2020-11-25 12:56:45 +01:00
|
|
|
|
|
|
|
size = ((size + 3) / 4) * 4; /* Round up size to multiple of 4 */
|
|
|
|
pph = (PPOOLHEADER)memp;
|
|
|
|
|
|
|
|
xtrc(16, "SubAlloc in %p size=%zd used=%zd free=%zd\n",
|
|
|
|
memp, size, pph->To_Free, pph->FreeBlk);
|
|
|
|
|
|
|
|
if (size > pph->FreeBlk) { /* Not enough memory left in pool */
|
2020-12-01 19:30:56 +01:00
|
|
|
sprintf(G->Message,
|
2020-11-25 12:56:45 +01:00
|
|
|
"Not enough memory for request of %zd (used=%zd free=%zd)",
|
|
|
|
size, pph->To_Free, pph->FreeBlk);
|
2020-12-01 19:30:56 +01:00
|
|
|
xtrc(1, "BsonSubAlloc: %s\n", G->Message);
|
2021-01-08 22:18:52 +01:00
|
|
|
|
|
|
|
if (Throw)
|
|
|
|
throw(1234);
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
|
2020-11-25 12:56:45 +01:00
|
|
|
} /* endif size OS32 code */
|
|
|
|
|
|
|
|
// Do the suballocation the simplest way
|
|
|
|
memp = MakePtr(memp, pph->To_Free); /* Points to suballocated block */
|
|
|
|
pph->To_Free += size; /* New offset of pool free block */
|
|
|
|
pph->FreeBlk -= size; /* New size of pool free block */
|
|
|
|
xtrc(16, "Done memp=%p used=%zd free=%zd\n",
|
|
|
|
memp, pph->To_Free, pph->FreeBlk);
|
|
|
|
return memp;
|
2020-12-08 01:15:40 +01:00
|
|
|
} // end of BsonSubAlloc
|
|
|
|
|
|
|
|
/*********************************************************************************/
|
|
|
|
/* Program for SubSet re-initialization of the memory pool. */
|
|
|
|
/*********************************************************************************/
|
2020-12-31 15:43:52 +01:00
|
|
|
PSZ BJSON::NewStr(PSZ str)
|
2020-12-08 01:15:40 +01:00
|
|
|
{
|
|
|
|
if (str) {
|
|
|
|
PSZ sm = (PSZ)BsonSubAlloc(strlen(str) + 1);
|
|
|
|
|
|
|
|
strcpy(sm, str);
|
2020-12-31 15:43:52 +01:00
|
|
|
return sm;
|
2020-12-08 01:15:40 +01:00
|
|
|
} else
|
|
|
|
return NULL;
|
|
|
|
|
2020-12-31 15:43:52 +01:00
|
|
|
} // end of NewStr
|
2020-11-25 12:56:45 +01:00
|
|
|
|
2020-12-01 19:30:56 +01:00
|
|
|
/*********************************************************************************/
|
|
|
|
/* Program for SubSet re-initialization of the memory pool. */
|
|
|
|
/*********************************************************************************/
|
|
|
|
void BJSON::SubSet(bool b)
|
|
|
|
{
|
|
|
|
PPOOLHEADER pph = (PPOOLHEADER)G->Sarea;
|
|
|
|
|
|
|
|
pph->To_Free = (G->Saved_Size) ? G->Saved_Size : sizeof(POOLHEADER);
|
|
|
|
pph->FreeBlk = G->Sarea_Size - pph->To_Free;
|
|
|
|
|
|
|
|
if (b)
|
|
|
|
G->Saved_Size = 0;
|
|
|
|
|
2020-12-09 00:55:06 +01:00
|
|
|
} // end of SubSet
|
2020-12-01 19:30:56 +01:00
|
|
|
|
2020-12-15 12:28:03 +01:00
|
|
|
/*********************************************************************************/
|
|
|
|
/* Set the beginning of suballocations. */
|
|
|
|
/*********************************************************************************/
|
|
|
|
void BJSON::MemSet(size_t size)
|
|
|
|
{
|
|
|
|
PPOOLHEADER pph = (PPOOLHEADER)G->Sarea;
|
|
|
|
|
|
|
|
pph->To_Free = size + sizeof(POOLHEADER);
|
|
|
|
pph->FreeBlk = G->Sarea_Size - pph->To_Free;
|
|
|
|
} // end of MemSet
|
|
|
|
|
|
|
|
/* ------------------------ Bobject functions ------------------------ */
|
2020-11-25 12:56:45 +01:00
|
|
|
|
|
|
|
/***********************************************************************/
|
2020-12-26 19:44:38 +01:00
|
|
|
/* Set a pair vlp to some PVAL values. */
|
|
|
|
/***********************************************************************/
|
|
|
|
void BJSON::SetPairValue(PBPR brp, PBVAL bvp)
|
|
|
|
{
|
|
|
|
if (bvp) {
|
|
|
|
brp->Vlp.To_Val = bvp->To_Val;
|
|
|
|
brp->Vlp.Nd = bvp->Nd;
|
|
|
|
brp->Vlp.Type = bvp->Type;
|
|
|
|
} else {
|
|
|
|
brp->Vlp.To_Val = 0;
|
|
|
|
brp->Vlp.Nd = 0;
|
|
|
|
brp->Vlp.Type = TYPE_NULL;
|
|
|
|
} // endif bvp
|
|
|
|
|
|
|
|
} // end of SetPairValue
|
|
|
|
|
|
|
|
/***********************************************************************/
|
2020-11-25 12:56:45 +01:00
|
|
|
/* Sub-allocate and initialize a BPAIR. */
|
|
|
|
/***********************************************************************/
|
2020-12-26 19:44:38 +01:00
|
|
|
PBPR BJSON::NewPair(OFFSET key, int type)
|
2020-11-25 12:56:45 +01:00
|
|
|
{
|
2020-12-01 19:30:56 +01:00
|
|
|
PBPR bpp = (PBPR)BsonSubAlloc(sizeof(BPAIR));
|
2020-11-25 12:56:45 +01:00
|
|
|
|
|
|
|
bpp->Key = key;
|
2020-12-26 19:44:38 +01:00
|
|
|
bpp->Vlp.Type = type;
|
|
|
|
bpp->Vlp.To_Val = 0;
|
|
|
|
bpp->Vlp.Nd = 0;
|
|
|
|
bpp->Vlp.Next = 0;
|
2020-11-25 12:56:45 +01:00
|
|
|
return bpp;
|
|
|
|
} // end of SubAllocPair
|
2020-11-21 21:52:48 +01:00
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* Return the number of pairs in this object. */
|
|
|
|
/***********************************************************************/
|
2020-12-04 23:21:59 +01:00
|
|
|
int BJSON::GetObjectSize(PBVAL bop, bool b)
|
2020-11-25 12:56:45 +01:00
|
|
|
{
|
2020-12-04 23:21:59 +01:00
|
|
|
CheckType(bop, TYPE_JOB);
|
2020-11-21 21:52:48 +01:00
|
|
|
int n = 0;
|
|
|
|
|
2020-12-04 23:21:59 +01:00
|
|
|
for (PBPR brp = GetObject(bop); brp; brp = GetNext(brp))
|
2020-11-21 21:52:48 +01:00
|
|
|
// If b return only non null pairs
|
2020-12-26 19:44:38 +01:00
|
|
|
if (!b || (brp->Vlp.To_Val && brp->Vlp.Type != TYPE_NULL))
|
2020-11-21 21:52:48 +01:00
|
|
|
n++;
|
|
|
|
|
|
|
|
return n;
|
2020-11-25 12:56:45 +01:00
|
|
|
} // end of GetObjectSize
|
2020-11-21 21:52:48 +01:00
|
|
|
|
|
|
|
/***********************************************************************/
|
2020-11-25 12:56:45 +01:00
|
|
|
/* Add a new pair to an Object and return it. */
|
2020-11-21 21:52:48 +01:00
|
|
|
/***********************************************************************/
|
2020-12-26 19:44:38 +01:00
|
|
|
PBVAL BJSON::AddPair(PBVAL bop, PSZ key, int type)
|
2020-11-25 12:56:45 +01:00
|
|
|
{
|
2020-12-04 23:21:59 +01:00
|
|
|
CheckType(bop, TYPE_JOB);
|
|
|
|
PBPR brp;
|
2020-12-26 19:44:38 +01:00
|
|
|
OFFSET nrp = NewPair(key, type);
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2020-12-04 23:21:59 +01:00
|
|
|
if (bop->To_Val) {
|
2020-12-26 19:44:38 +01:00
|
|
|
for (brp = GetObject(bop); brp->Vlp.Next; brp = GetNext(brp));
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2020-12-26 19:44:38 +01:00
|
|
|
brp->Vlp.Next = nrp;
|
2020-11-25 12:56:45 +01:00
|
|
|
} else
|
2020-12-04 23:21:59 +01:00
|
|
|
bop->To_Val = nrp;
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2020-12-04 23:21:59 +01:00
|
|
|
bop->Nd++;
|
2020-12-26 19:44:38 +01:00
|
|
|
return GetVlp(MPP(nrp));
|
2020-11-21 21:52:48 +01:00
|
|
|
} // end of AddPair
|
|
|
|
|
|
|
|
/***********************************************************************/
|
2020-11-25 12:56:45 +01:00
|
|
|
/* Return all object keys as an array. */
|
2020-11-21 21:52:48 +01:00
|
|
|
/***********************************************************************/
|
2020-12-04 23:21:59 +01:00
|
|
|
PBVAL BJSON::GetKeyList(PBVAL bop)
|
2020-11-25 12:56:45 +01:00
|
|
|
{
|
2020-12-04 23:21:59 +01:00
|
|
|
CheckType(bop, TYPE_JOB);
|
|
|
|
PBVAL arp = NewVal(TYPE_JAR);
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2020-12-04 23:21:59 +01:00
|
|
|
for (PBPR brp = GetObject(bop); brp; brp = GetNext(brp))
|
|
|
|
AddArrayValue(arp, MOF(SubAllocVal(brp->Key, TYPE_STRG)));
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2020-12-04 23:21:59 +01:00
|
|
|
return arp;
|
2020-11-21 21:52:48 +01:00
|
|
|
} // end of GetKeyList
|
|
|
|
|
|
|
|
/***********************************************************************/
|
2020-11-25 12:56:45 +01:00
|
|
|
/* Return all object values as an array. */
|
2020-11-21 21:52:48 +01:00
|
|
|
/***********************************************************************/
|
2020-12-04 23:21:59 +01:00
|
|
|
PBVAL BJSON::GetObjectValList(PBVAL bop)
|
2020-11-25 12:56:45 +01:00
|
|
|
{
|
2020-12-04 23:21:59 +01:00
|
|
|
CheckType(bop, TYPE_JOB);
|
|
|
|
PBVAL arp = NewVal(TYPE_JAR);
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2020-12-04 23:21:59 +01:00
|
|
|
for (PBPR brp = GetObject(bop); brp; brp = GetNext(brp))
|
2020-12-31 15:43:52 +01:00
|
|
|
AddArrayValue(arp, DupVal(GetVlp(brp)));
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2020-12-04 23:21:59 +01:00
|
|
|
return arp;
|
2020-11-25 12:56:45 +01:00
|
|
|
} // end of GetObjectValList
|
2020-11-21 21:52:48 +01:00
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* Get the value corresponding to the given key. */
|
|
|
|
/***********************************************************************/
|
2020-12-04 23:21:59 +01:00
|
|
|
PBVAL BJSON::GetKeyValue(PBVAL bop, PSZ key)
|
2020-11-25 12:56:45 +01:00
|
|
|
{
|
2020-12-04 23:21:59 +01:00
|
|
|
CheckType(bop, TYPE_JOB);
|
|
|
|
|
|
|
|
for (PBPR brp = GetObject(bop); brp; brp = GetNext(brp))
|
|
|
|
if (!strcmp(GetKey(brp), key))
|
2020-12-26 19:44:38 +01:00
|
|
|
return GetVlp(brp);
|
2020-11-21 21:52:48 +01:00
|
|
|
|
|
|
|
return NULL;
|
2020-11-25 12:56:45 +01:00
|
|
|
} // end of GetKeyValue;
|
2020-11-21 21:52:48 +01:00
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* Return the text corresponding to all keys (XML like). */
|
|
|
|
/***********************************************************************/
|
2020-12-04 23:21:59 +01:00
|
|
|
PSZ BJSON::GetObjectText(PGLOBAL g, PBVAL bop, PSTRG text)
|
|
|
|
{
|
|
|
|
CheckType(bop, TYPE_JOB);
|
2020-12-08 01:15:40 +01:00
|
|
|
PBPR brp = GetObject(bop);
|
2020-12-04 23:21:59 +01:00
|
|
|
|
2020-12-08 01:15:40 +01:00
|
|
|
if (brp) {
|
2020-11-21 21:52:48 +01:00
|
|
|
bool b;
|
|
|
|
|
|
|
|
if (!text) {
|
|
|
|
text = new(g) STRING(g, 256);
|
|
|
|
b = true;
|
|
|
|
} else {
|
|
|
|
if (text->GetLastChar() != ' ')
|
|
|
|
text->Append(' ');
|
|
|
|
|
|
|
|
b = false;
|
|
|
|
} // endif text
|
|
|
|
|
2020-12-26 19:44:38 +01:00
|
|
|
if (b && !brp->Vlp.Next && !strcmp(MZP(brp->Key), "$date")) {
|
2020-11-21 21:52:48 +01:00
|
|
|
int i;
|
|
|
|
PSZ s;
|
|
|
|
|
2020-12-26 19:44:38 +01:00
|
|
|
GetValueText(g, GetVlp(brp), text);
|
2020-11-21 21:52:48 +01:00
|
|
|
s = text->GetStr();
|
|
|
|
i = (s[1] == '-' ? 2 : 1);
|
|
|
|
|
|
|
|
if (IsNum(s + i)) {
|
|
|
|
// Date is in milliseconds
|
|
|
|
int j = text->GetLength();
|
|
|
|
|
|
|
|
if (j >= 4 + i) {
|
|
|
|
s[j - 3] = 0; // Change it to seconds
|
|
|
|
text->SetLength((uint)strlen(s));
|
|
|
|
} else
|
|
|
|
text->Set(" 0");
|
|
|
|
|
|
|
|
} // endif text
|
|
|
|
|
2020-12-26 19:44:38 +01:00
|
|
|
} else for (; brp; brp = GetNext(brp)) {
|
|
|
|
GetValueText(g, GetVlp(brp), text);
|
2020-11-25 12:56:45 +01:00
|
|
|
|
2020-12-26 19:44:38 +01:00
|
|
|
if (brp->Vlp.Next)
|
2020-11-21 21:52:48 +01:00
|
|
|
text->Append(' ');
|
|
|
|
|
2020-11-25 12:56:45 +01:00
|
|
|
} // endfor brp
|
2020-11-21 21:52:48 +01:00
|
|
|
|
|
|
|
if (b) {
|
|
|
|
text->Trim();
|
|
|
|
return text->GetStr();
|
|
|
|
} // endif b
|
|
|
|
|
2020-11-25 12:56:45 +01:00
|
|
|
} // endif bop
|
2020-11-21 21:52:48 +01:00
|
|
|
|
|
|
|
return NULL;
|
2020-11-25 12:56:45 +01:00
|
|
|
} // end of GetObjectText;
|
2020-11-21 21:52:48 +01:00
|
|
|
|
|
|
|
/***********************************************************************/
|
2020-11-25 12:56:45 +01:00
|
|
|
/* Set or add a value corresponding to the given key. */
|
2020-11-21 21:52:48 +01:00
|
|
|
/***********************************************************************/
|
2020-12-04 23:21:59 +01:00
|
|
|
void BJSON::SetKeyValue(PBVAL bop, OFFSET bvp, PSZ key)
|
2020-11-25 12:56:45 +01:00
|
|
|
{
|
2020-12-04 23:21:59 +01:00
|
|
|
CheckType(bop, TYPE_JOB);
|
|
|
|
PBPR brp, prp = NULL;
|
2020-11-25 12:56:45 +01:00
|
|
|
|
2020-12-04 23:21:59 +01:00
|
|
|
if (bop->To_Val) {
|
|
|
|
for (brp = GetObject(bop); brp; brp = GetNext(brp))
|
2020-12-26 19:44:38 +01:00
|
|
|
if (!strcmp(GetKey(brp), key))
|
|
|
|
break;
|
|
|
|
else
|
2020-11-25 12:56:45 +01:00
|
|
|
prp = brp;
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2020-11-25 12:56:45 +01:00
|
|
|
if (!brp)
|
2020-12-26 19:44:38 +01:00
|
|
|
brp = MPP(prp->Vlp.Next = NewPair(key));
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2020-11-25 12:56:45 +01:00
|
|
|
} else
|
2020-12-26 19:44:38 +01:00
|
|
|
brp = MPP(bop->To_Val = NewPair(key));
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2020-12-26 19:44:38 +01:00
|
|
|
SetPairValue(brp, MVP(bvp));
|
2020-12-04 23:21:59 +01:00
|
|
|
bop->Nd++;
|
2020-11-25 12:56:45 +01:00
|
|
|
} // end of SetKeyValue
|
2020-11-21 21:52:48 +01:00
|
|
|
|
|
|
|
/***********************************************************************/
|
2020-11-25 12:56:45 +01:00
|
|
|
/* Merge two objects. */
|
2020-11-21 21:52:48 +01:00
|
|
|
/***********************************************************************/
|
2020-12-04 23:21:59 +01:00
|
|
|
PBVAL BJSON::MergeObject(PBVAL bop1, PBVAL bop2)
|
2020-11-25 12:56:45 +01:00
|
|
|
{
|
2020-12-04 23:21:59 +01:00
|
|
|
CheckType(bop1, TYPE_JOB);
|
|
|
|
CheckType(bop2, TYPE_JOB);
|
|
|
|
|
|
|
|
if (bop1->To_Val)
|
|
|
|
for (PBPR brp = GetObject(bop2); brp; brp = GetNext(brp))
|
2020-12-26 19:44:38 +01:00
|
|
|
SetKeyValue(bop1, GetVlp(brp), GetKey(brp));
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2020-12-04 23:21:59 +01:00
|
|
|
else {
|
|
|
|
bop1->To_Val = bop2->To_Val;
|
|
|
|
bop1->Nd = bop2->Nd;
|
|
|
|
} // endelse To_Val
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2020-11-25 12:56:45 +01:00
|
|
|
return bop1;
|
|
|
|
} // end of MergeObject;
|
2020-11-21 21:52:48 +01:00
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* Delete a value corresponding to the given key. */
|
|
|
|
/***********************************************************************/
|
2021-01-08 22:18:52 +01:00
|
|
|
bool BJSON::DeleteKey(PBVAL bop, PCSZ key)
|
2020-11-25 12:56:45 +01:00
|
|
|
{
|
2020-12-04 23:21:59 +01:00
|
|
|
CheckType(bop, TYPE_JOB);
|
2020-11-25 12:56:45 +01:00
|
|
|
PBPR brp, pbrp = NULL;
|
|
|
|
|
2020-12-04 23:21:59 +01:00
|
|
|
for (brp = GetObject(bop); brp; brp = GetNext(brp))
|
2020-11-25 12:56:45 +01:00
|
|
|
if (!strcmp(MZP(brp->Key), key)) {
|
|
|
|
if (pbrp) {
|
2020-12-26 19:44:38 +01:00
|
|
|
pbrp->Vlp.Next = brp->Vlp.Next;
|
2020-11-25 12:56:45 +01:00
|
|
|
} else
|
2020-12-26 19:44:38 +01:00
|
|
|
bop->To_Val = brp->Vlp.Next;
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2020-12-04 23:21:59 +01:00
|
|
|
bop->Nd--;
|
2021-01-08 22:18:52 +01:00
|
|
|
return true;;
|
2020-11-21 21:52:48 +01:00
|
|
|
} else
|
2020-11-25 12:56:45 +01:00
|
|
|
pbrp = brp;
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2021-01-08 22:18:52 +01:00
|
|
|
return false;
|
2020-11-21 21:52:48 +01:00
|
|
|
} // end of DeleteKey
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* True if void or if all members are nulls. */
|
|
|
|
/***********************************************************************/
|
2020-12-04 23:21:59 +01:00
|
|
|
bool BJSON::IsObjectNull(PBVAL bop)
|
2020-11-25 12:56:45 +01:00
|
|
|
{
|
2020-12-04 23:21:59 +01:00
|
|
|
CheckType(bop, TYPE_JOB);
|
|
|
|
|
|
|
|
for (PBPR brp = GetObject(bop); brp; brp = GetNext(brp))
|
2020-12-26 19:44:38 +01:00
|
|
|
if (brp->Vlp.To_Val && brp->Vlp.Type != TYPE_NULL)
|
2020-11-21 21:52:48 +01:00
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
2020-11-25 12:56:45 +01:00
|
|
|
} // end of IsObjectNull
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2020-11-25 12:56:45 +01:00
|
|
|
/* ------------------------- Barray functions ------------------------ */
|
2020-11-21 21:52:48 +01:00
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* Return the number of values in this object. */
|
|
|
|
/***********************************************************************/
|
2020-11-25 12:56:45 +01:00
|
|
|
int BJSON::GetArraySize(PBVAL bap, bool b)
|
|
|
|
{
|
2020-12-04 23:21:59 +01:00
|
|
|
CheckType(bap, TYPE_JAR);
|
2020-11-25 12:56:45 +01:00
|
|
|
int n = 0;
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2020-12-04 23:21:59 +01:00
|
|
|
for (PBVAL bvp = GetArray(bap); bvp; bvp = GetNext(bvp))
|
2020-11-25 12:56:45 +01:00
|
|
|
// If b, return only non null values
|
|
|
|
if (!b || bvp->Type != TYPE_NULL)
|
|
|
|
n++;
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2020-11-25 12:56:45 +01:00
|
|
|
return n;
|
|
|
|
} // end of GetArraySize
|
2020-11-21 21:52:48 +01:00
|
|
|
|
|
|
|
/***********************************************************************/
|
2020-11-25 12:56:45 +01:00
|
|
|
/* Get the Nth value of an Array. */
|
2020-11-21 21:52:48 +01:00
|
|
|
/***********************************************************************/
|
2020-11-25 12:56:45 +01:00
|
|
|
PBVAL BJSON::GetArrayValue(PBVAL bap, int n)
|
|
|
|
{
|
2020-12-04 23:21:59 +01:00
|
|
|
CheckType(bap, TYPE_JAR);
|
2020-11-25 12:56:45 +01:00
|
|
|
int i = 0;
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2021-02-05 11:55:47 +01:00
|
|
|
if (n < 0)
|
|
|
|
n += GetArraySize(bap);
|
|
|
|
|
2020-12-04 23:21:59 +01:00
|
|
|
for (PBVAL bvp = GetArray(bap); bvp; bvp = GetNext(bvp), i++)
|
2020-11-25 12:56:45 +01:00
|
|
|
if (i == n)
|
|
|
|
return bvp;
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2020-11-25 12:56:45 +01:00
|
|
|
return NULL;
|
|
|
|
} // end of GetArrayValue
|
2020-11-21 21:52:48 +01:00
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* Add a Value to the Array Value list. */
|
|
|
|
/***********************************************************************/
|
2020-12-31 15:43:52 +01:00
|
|
|
void BJSON::AddArrayValue(PBVAL bap, OFFSET nbv, int* x)
|
2020-11-25 12:56:45 +01:00
|
|
|
{
|
2020-12-04 23:21:59 +01:00
|
|
|
CheckType(bap, TYPE_JAR);
|
2020-12-31 15:43:52 +01:00
|
|
|
int i = 0;
|
|
|
|
PBVAL bvp, lbp = NULL;
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2020-12-31 15:43:52 +01:00
|
|
|
if (!nbv)
|
|
|
|
nbv = MOF(NewVal());
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2020-12-31 15:43:52 +01:00
|
|
|
for (bvp = GetArray(bap); bvp; bvp = GetNext(bvp), i++)
|
|
|
|
if (x && i == *x)
|
|
|
|
break;
|
|
|
|
else
|
|
|
|
lbp = bvp;
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2020-12-31 15:43:52 +01:00
|
|
|
if (lbp) {
|
|
|
|
MVP(nbv)->Next = lbp->Next;
|
|
|
|
lbp->Next = nbv;
|
|
|
|
} else {
|
|
|
|
MVP(nbv)->Next = bap->To_Val;
|
|
|
|
bap->To_Val = nbv;
|
|
|
|
} // endif lbp
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2020-12-04 23:21:59 +01:00
|
|
|
bap->Nd++;
|
2020-11-25 12:56:45 +01:00
|
|
|
} // end of AddArrayValue
|
2020-11-21 21:52:48 +01:00
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* Merge two arrays. */
|
|
|
|
/***********************************************************************/
|
2020-12-04 23:21:59 +01:00
|
|
|
void BJSON::MergeArray(PBVAL bap1, PBVAL bap2)
|
2020-11-25 12:56:45 +01:00
|
|
|
{
|
2020-12-04 23:21:59 +01:00
|
|
|
CheckType(bap1, TYPE_JAR);
|
|
|
|
CheckType(bap2, TYPE_JAR);
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2020-12-04 23:21:59 +01:00
|
|
|
if (bap1->To_Val) {
|
|
|
|
for (PBVAL bvp = GetArray(bap2); bvp; bvp = GetNext(bvp))
|
|
|
|
AddArrayValue(bap1, MOF(DupVal(bvp)));
|
|
|
|
|
|
|
|
} else {
|
|
|
|
bap1->To_Val = bap2->To_Val;
|
|
|
|
bap1->Nd = bap2->Nd;
|
|
|
|
} // endif To_Val
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2020-11-25 12:56:45 +01:00
|
|
|
} // end of MergeArray
|
2020-11-21 21:52:48 +01:00
|
|
|
|
|
|
|
/***********************************************************************/
|
2020-12-04 23:21:59 +01:00
|
|
|
/* Set the nth Value of the Array Value list or add it. */
|
2020-11-21 21:52:48 +01:00
|
|
|
/***********************************************************************/
|
2020-12-04 23:21:59 +01:00
|
|
|
void BJSON::SetArrayValue(PBVAL bap, PBVAL nvp, int n)
|
2020-11-25 12:56:45 +01:00
|
|
|
{
|
2020-12-04 23:21:59 +01:00
|
|
|
CheckType(bap, TYPE_JAR);
|
2020-12-15 12:28:03 +01:00
|
|
|
int i = 0;
|
2021-01-28 18:30:32 +01:00
|
|
|
PBVAL bvp = NULL;
|
2020-11-25 12:56:45 +01:00
|
|
|
|
2021-05-01 22:29:38 +02:00
|
|
|
for (bvp = GetArray(bap); i < n; i++, bvp = bvp ? GetNext(bvp) : NULL)
|
|
|
|
if (!bvp)
|
|
|
|
AddArrayValue(bap, NewVal());
|
2020-11-25 12:56:45 +01:00
|
|
|
|
2020-12-04 23:21:59 +01:00
|
|
|
if (!bvp)
|
|
|
|
AddArrayValue(bap, MOF(nvp));
|
2021-05-01 22:29:38 +02:00
|
|
|
else
|
|
|
|
SetValueVal(bvp, nvp);
|
2020-11-21 21:52:48 +01:00
|
|
|
|
|
|
|
} // end of SetValue
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* Return the text corresponding to all values. */
|
|
|
|
/***********************************************************************/
|
2020-12-04 23:21:59 +01:00
|
|
|
PSZ BJSON::GetArrayText(PGLOBAL g, PBVAL bap, PSTRG text)
|
|
|
|
{
|
|
|
|
CheckType(bap, TYPE_JAR);
|
|
|
|
|
|
|
|
if (bap->To_Val) {
|
2020-11-21 21:52:48 +01:00
|
|
|
bool b;
|
|
|
|
|
|
|
|
if (!text) {
|
|
|
|
text = new(g) STRING(g, 256);
|
|
|
|
b = true;
|
|
|
|
} else {
|
|
|
|
if (text->GetLastChar() != ' ')
|
|
|
|
text->Append(" (");
|
|
|
|
else
|
|
|
|
text->Append('(');
|
|
|
|
|
|
|
|
b = false;
|
2020-11-25 12:56:45 +01:00
|
|
|
} // endif text
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2020-12-04 23:21:59 +01:00
|
|
|
for (PBVAL bvp = GetArray(bap); bvp; bvp = GetNext(bvp)) {
|
2020-11-25 12:56:45 +01:00
|
|
|
GetValueText(g, bvp, text);
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2020-11-25 12:56:45 +01:00
|
|
|
if (bvp->Next)
|
2020-11-21 21:52:48 +01:00
|
|
|
text->Append(", ");
|
|
|
|
else if (!b)
|
|
|
|
text->Append(')');
|
|
|
|
|
2020-12-04 23:21:59 +01:00
|
|
|
} // endfor bvp
|
2020-11-21 21:52:48 +01:00
|
|
|
|
|
|
|
if (b) {
|
|
|
|
text->Trim();
|
|
|
|
return text->GetStr();
|
|
|
|
} // endif b
|
|
|
|
|
2020-12-04 23:21:59 +01:00
|
|
|
} // endif To_Val
|
2020-11-21 21:52:48 +01:00
|
|
|
|
|
|
|
return NULL;
|
|
|
|
} // end of GetText;
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* Delete a Value from the Arrays Value list. */
|
|
|
|
/***********************************************************************/
|
2021-01-08 22:18:52 +01:00
|
|
|
bool BJSON::DeleteValue(PBVAL bap, int n)
|
2020-11-25 12:56:45 +01:00
|
|
|
{
|
2020-12-04 23:21:59 +01:00
|
|
|
CheckType(bap, TYPE_JAR);
|
|
|
|
int i = 0;
|
|
|
|
PBVAL bvp, pvp = NULL;
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2021-01-08 22:18:52 +01:00
|
|
|
for (bvp = GetArray(bap); bvp; i++, bvp = GetNext(bvp))
|
|
|
|
if (i == n) {
|
|
|
|
if (pvp)
|
|
|
|
pvp->Next = bvp->Next;
|
|
|
|
else
|
|
|
|
bap->To_Val = bvp->Next;
|
2020-11-25 12:56:45 +01:00
|
|
|
|
2021-01-08 22:18:52 +01:00
|
|
|
bap->Nd--;
|
|
|
|
return true;;
|
|
|
|
} else
|
|
|
|
pvp = bvp;
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2021-01-08 22:18:52 +01:00
|
|
|
return false;
|
2020-11-21 21:52:48 +01:00
|
|
|
} // end of DeleteValue
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* True if void or if all members are nulls. */
|
|
|
|
/***********************************************************************/
|
2020-11-25 12:56:45 +01:00
|
|
|
bool BJSON::IsArrayNull(PBVAL bap)
|
|
|
|
{
|
2020-12-04 23:21:59 +01:00
|
|
|
CheckType(bap, TYPE_JAR);
|
|
|
|
|
|
|
|
for (PBVAL bvp = GetArray(bap); bvp; bvp = GetNext(bvp))
|
2020-11-25 12:56:45 +01:00
|
|
|
if (bvp->Type != TYPE_NULL)
|
2020-11-21 21:52:48 +01:00
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
} // end of IsNull
|
|
|
|
|
2020-11-25 12:56:45 +01:00
|
|
|
/* ------------------------- Bvalue functions ------------------------ */
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* Sub-allocate and clear a BVAL. */
|
|
|
|
/***********************************************************************/
|
2020-12-01 19:30:56 +01:00
|
|
|
PBVAL BJSON::NewVal(int type)
|
2020-11-25 12:56:45 +01:00
|
|
|
{
|
2020-12-01 19:30:56 +01:00
|
|
|
PBVAL bvp = (PBVAL)BsonSubAlloc(sizeof(BVAL));
|
2020-11-25 12:56:45 +01:00
|
|
|
|
|
|
|
bvp->To_Val = 0;
|
|
|
|
bvp->Nd = 0;
|
2020-12-01 19:30:56 +01:00
|
|
|
bvp->Type = type;
|
2020-11-25 12:56:45 +01:00
|
|
|
bvp->Next = 0;
|
|
|
|
return bvp;
|
|
|
|
} // end of SubAllocVal
|
|
|
|
|
2020-12-01 19:30:56 +01:00
|
|
|
/***********************************************************************/
|
|
|
|
/* Sub-allocate and initialize a BVAL as type. */
|
|
|
|
/***********************************************************************/
|
|
|
|
PBVAL BJSON::SubAllocVal(OFFSET toval, int type, short nd)
|
|
|
|
{
|
|
|
|
PBVAL bvp = NewVal(type);
|
|
|
|
|
|
|
|
bvp->To_Val = toval;
|
|
|
|
bvp->Nd = nd;
|
|
|
|
return bvp;
|
|
|
|
} // end of SubAllocVal
|
|
|
|
|
2020-11-25 12:56:45 +01:00
|
|
|
/***********************************************************************/
|
|
|
|
/* Sub-allocate and initialize a BVAL as string. */
|
|
|
|
/***********************************************************************/
|
2020-12-01 19:30:56 +01:00
|
|
|
PBVAL BJSON::SubAllocStr(OFFSET toval, short nd)
|
2020-11-25 12:56:45 +01:00
|
|
|
{
|
2020-12-01 19:30:56 +01:00
|
|
|
PBVAL bvp = NewVal(TYPE_STRG);
|
2020-11-25 12:56:45 +01:00
|
|
|
|
|
|
|
bvp->To_Val = toval;
|
|
|
|
bvp->Nd = nd;
|
|
|
|
return bvp;
|
2020-12-08 01:15:40 +01:00
|
|
|
} // end of SubAllocStr
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2020-11-25 12:56:45 +01:00
|
|
|
/***********************************************************************/
|
|
|
|
/* Allocate a BVALUE with a given string or numeric value. */
|
|
|
|
/***********************************************************************/
|
2020-12-04 23:21:59 +01:00
|
|
|
PBVAL BJSON::NewVal(PVAL valp)
|
2020-11-25 12:56:45 +01:00
|
|
|
{
|
2020-12-01 19:30:56 +01:00
|
|
|
PBVAL vlp = NewVal();
|
2020-12-04 23:21:59 +01:00
|
|
|
|
2020-12-01 19:30:56 +01:00
|
|
|
SetValue(vlp, valp);
|
2020-11-25 12:56:45 +01:00
|
|
|
return vlp;
|
|
|
|
} // end of SubAllocVal
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* Sub-allocate and initialize a BVAL from another BVAL. */
|
|
|
|
/***********************************************************************/
|
2021-02-16 00:31:27 +01:00
|
|
|
PBVAL BJSON::DupVal(PBVAL bvlp)
|
|
|
|
{
|
|
|
|
if (bvlp) {
|
|
|
|
PBVAL bvp = NewVal();
|
|
|
|
|
|
|
|
*bvp = *bvlp;
|
|
|
|
bvp->Next = 0;
|
|
|
|
return bvp;
|
|
|
|
} else
|
|
|
|
return NULL;
|
2020-11-25 12:56:45 +01:00
|
|
|
|
|
|
|
} // end of DupVal
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* Return the size of value's value. */
|
|
|
|
/***********************************************************************/
|
|
|
|
int BJSON::GetSize(PBVAL vlp, bool b)
|
|
|
|
{
|
|
|
|
switch (vlp->Type) {
|
|
|
|
case TYPE_JAR:
|
2020-12-04 23:21:59 +01:00
|
|
|
return GetArraySize(vlp);
|
2020-11-25 12:56:45 +01:00
|
|
|
case TYPE_JOB:
|
2020-12-04 23:21:59 +01:00
|
|
|
return GetObjectSize(vlp);
|
2020-11-25 12:56:45 +01:00
|
|
|
default:
|
|
|
|
return 1;
|
|
|
|
} // enswitch Type
|
|
|
|
|
|
|
|
} // end of GetSize
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2020-12-26 19:44:38 +01:00
|
|
|
PBVAL BJSON::GetBson(PBVAL bvp)
|
|
|
|
{
|
|
|
|
PBVAL bp = NULL;
|
|
|
|
|
|
|
|
switch (bvp->Type) {
|
|
|
|
case TYPE_JAR:
|
|
|
|
bp = MVP(bvp->To_Val);
|
|
|
|
break;
|
|
|
|
case TYPE_JOB:
|
|
|
|
bp = GetVlp(MPP(bvp->To_Val));
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
bp = bvp;
|
|
|
|
break;
|
|
|
|
} // endswitch Type
|
|
|
|
|
|
|
|
return bp;
|
|
|
|
} // end of GetBson
|
|
|
|
|
2020-11-21 21:52:48 +01:00
|
|
|
/***********************************************************************/
|
2020-11-25 12:56:45 +01:00
|
|
|
/* Return the Value's as a Value struct. */
|
2020-11-21 21:52:48 +01:00
|
|
|
/***********************************************************************/
|
2020-11-25 12:56:45 +01:00
|
|
|
PVAL BJSON::GetValue(PGLOBAL g, PBVAL vp)
|
|
|
|
{
|
|
|
|
double d;
|
|
|
|
PVAL valp;
|
|
|
|
PBVAL vlp = vp->Type == TYPE_JVAL ? MVP(vp->To_Val) : vp;
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2020-11-25 12:56:45 +01:00
|
|
|
switch (vlp->Type) {
|
2020-12-26 19:44:38 +01:00
|
|
|
case TYPE_STRG:
|
|
|
|
case TYPE_DBL:
|
|
|
|
case TYPE_BINT:
|
|
|
|
valp = AllocateValue(g, MP(vlp->To_Val), vlp->Type, vlp->Nd);
|
|
|
|
break;
|
|
|
|
case TYPE_INTG:
|
|
|
|
case TYPE_BOOL:
|
|
|
|
valp = AllocateValue(g, vlp, vlp->Type);
|
|
|
|
break;
|
|
|
|
case TYPE_FLOAT:
|
|
|
|
d = (double)vlp->F;
|
|
|
|
valp = AllocateValue(g, &d, TYPE_DOUBLE, vlp->Nd);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
valp = NULL;
|
|
|
|
break;
|
2020-11-25 12:56:45 +01:00
|
|
|
} // endswitch Type
|
2020-11-21 21:52:48 +01:00
|
|
|
|
|
|
|
return valp;
|
|
|
|
} // end of GetValue
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* Return the Value's Integer value. */
|
|
|
|
/***********************************************************************/
|
2020-11-25 12:56:45 +01:00
|
|
|
int BJSON::GetInteger(PBVAL vp) {
|
|
|
|
int n;
|
|
|
|
PBVAL vlp = (vp->Type == TYPE_JVAL) ? MVP(vp->To_Val) : vp;
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2020-11-25 12:56:45 +01:00
|
|
|
switch (vlp->Type) {
|
|
|
|
case TYPE_INTG:
|
|
|
|
n = vlp->N;
|
|
|
|
break;
|
|
|
|
case TYPE_FLOAT:
|
|
|
|
n = (int)vlp->F;
|
|
|
|
break;
|
2020-11-21 21:52:48 +01:00
|
|
|
case TYPE_DTM:
|
2020-11-25 12:56:45 +01:00
|
|
|
case TYPE_STRG:
|
|
|
|
n = atoi(MZP(vlp->To_Val));
|
|
|
|
break;
|
|
|
|
case TYPE_BOOL:
|
|
|
|
n = (vlp->B) ? 1 : 0;
|
|
|
|
break;
|
|
|
|
case TYPE_BINT:
|
|
|
|
n = (int)*(longlong*)MP(vlp->To_Val);
|
|
|
|
break;
|
|
|
|
case TYPE_DBL:
|
|
|
|
n = (int)*(double*)MP(vlp->To_Val);
|
|
|
|
break;
|
2020-11-21 21:52:48 +01:00
|
|
|
default:
|
|
|
|
n = 0;
|
|
|
|
} // endswitch Type
|
|
|
|
|
|
|
|
return n;
|
|
|
|
} // end of GetInteger
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* Return the Value's Big integer value. */
|
|
|
|
/***********************************************************************/
|
2020-11-25 12:56:45 +01:00
|
|
|
longlong BJSON::GetBigint(PBVAL vp) {
|
|
|
|
longlong lln;
|
|
|
|
PBVAL vlp = (vp->Type == TYPE_JVAL) ? MVP(vp->To_Val) : vp;
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2020-11-25 12:56:45 +01:00
|
|
|
switch (vlp->Type) {
|
|
|
|
case TYPE_BINT:
|
|
|
|
lln = *(longlong*)MP(vlp->To_Val);
|
|
|
|
break;
|
|
|
|
case TYPE_INTG:
|
|
|
|
lln = (longlong)vlp->N;
|
|
|
|
break;
|
|
|
|
case TYPE_FLOAT:
|
|
|
|
lln = (longlong)vlp->F;
|
|
|
|
break;
|
|
|
|
case TYPE_DBL:
|
|
|
|
lln = (longlong)*(double*)MP(vlp->To_Val);
|
|
|
|
break;
|
2020-11-21 21:52:48 +01:00
|
|
|
case TYPE_DTM:
|
2020-11-25 12:56:45 +01:00
|
|
|
case TYPE_STRG:
|
|
|
|
lln = atoll(MZP(vlp->To_Val));
|
|
|
|
break;
|
|
|
|
case TYPE_BOOL:
|
|
|
|
lln = (vlp->B) ? 1 : 0;
|
|
|
|
break;
|
2020-11-21 21:52:48 +01:00
|
|
|
default:
|
|
|
|
lln = 0;
|
|
|
|
} // endswitch Type
|
|
|
|
|
|
|
|
return lln;
|
|
|
|
} // end of GetBigint
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* Return the Value's Double value. */
|
|
|
|
/***********************************************************************/
|
2020-11-25 12:56:45 +01:00
|
|
|
double BJSON::GetDouble(PBVAL vp)
|
|
|
|
{
|
2020-11-21 21:52:48 +01:00
|
|
|
double d;
|
2020-11-25 12:56:45 +01:00
|
|
|
PBVAL vlp = (vp->Type == TYPE_JVAL) ? MVP(vp->To_Val) : vp;
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2020-11-25 12:56:45 +01:00
|
|
|
switch (vlp->Type) {
|
2021-01-28 19:54:24 +01:00
|
|
|
case TYPE_DBL:
|
|
|
|
d = *(double*)MP(vlp->To_Val);
|
|
|
|
break;
|
|
|
|
case TYPE_BINT:
|
|
|
|
d = (double)*(longlong*)MP(vlp->To_Val);
|
|
|
|
break;
|
|
|
|
case TYPE_INTG:
|
|
|
|
d = (double)vlp->N;
|
|
|
|
break;
|
|
|
|
case TYPE_FLOAT:
|
|
|
|
d = (double)vlp->F;
|
|
|
|
break;
|
|
|
|
case TYPE_DTM:
|
|
|
|
case TYPE_STRG:
|
|
|
|
d = atof(MZP(vlp->To_Val));
|
|
|
|
break;
|
|
|
|
case TYPE_BOOL:
|
|
|
|
d = (vlp->B) ? 1.0 : 0.0;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
d = 0.0;
|
2020-11-21 21:52:48 +01:00
|
|
|
} // endswitch Type
|
|
|
|
|
|
|
|
return d;
|
2021-01-08 22:18:52 +01:00
|
|
|
} // end of GetDouble
|
2020-11-21 21:52:48 +01:00
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* Return the Value's String value. */
|
|
|
|
/***********************************************************************/
|
2020-12-01 19:30:56 +01:00
|
|
|
PSZ BJSON::GetString(PBVAL vp, char* buff)
|
2020-11-25 12:56:45 +01:00
|
|
|
{
|
2020-11-21 21:52:48 +01:00
|
|
|
char buf[32];
|
|
|
|
char* p = (buff) ? buff : buf;
|
2020-11-25 12:56:45 +01:00
|
|
|
PBVAL vlp = (vp->Type == TYPE_JVAL) ? MVP(vp->To_Val) : vp;
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2020-11-25 12:56:45 +01:00
|
|
|
switch (vlp->Type) {
|
2020-11-21 21:52:48 +01:00
|
|
|
case TYPE_DTM:
|
|
|
|
case TYPE_STRG:
|
2020-11-25 12:56:45 +01:00
|
|
|
p = MZP(vlp->To_Val);
|
2020-11-21 21:52:48 +01:00
|
|
|
break;
|
|
|
|
case TYPE_INTG:
|
2020-11-25 12:56:45 +01:00
|
|
|
sprintf(p, "%d", vlp->N);
|
|
|
|
break;
|
|
|
|
case TYPE_FLOAT:
|
|
|
|
sprintf(p, "%.*f", vlp->Nd, vlp->F);
|
2020-11-21 21:52:48 +01:00
|
|
|
break;
|
|
|
|
case TYPE_BINT:
|
2020-11-25 12:56:45 +01:00
|
|
|
sprintf(p, "%lld", *(longlong*)MP(vlp->To_Val));
|
2020-11-21 21:52:48 +01:00
|
|
|
break;
|
|
|
|
case TYPE_DBL:
|
2020-11-25 12:56:45 +01:00
|
|
|
sprintf(p, "%.*lf", vlp->Nd, *(double*)MP(vlp->To_Val));
|
2020-11-21 21:52:48 +01:00
|
|
|
break;
|
|
|
|
case TYPE_BOOL:
|
2020-11-25 12:56:45 +01:00
|
|
|
p = (PSZ)((vlp->B) ? "true" : "false");
|
2020-11-21 21:52:48 +01:00
|
|
|
break;
|
|
|
|
case TYPE_NULL:
|
2020-11-25 12:56:45 +01:00
|
|
|
p = (PSZ)"null";
|
2020-11-21 21:52:48 +01:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
p = NULL;
|
|
|
|
} // endswitch Type
|
|
|
|
|
2020-12-01 19:30:56 +01:00
|
|
|
return (p == buf) ? (PSZ)PlugDup(G, buf) : p;
|
2020-11-21 21:52:48 +01:00
|
|
|
} // end of GetString
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* Return the Value's String value. */
|
|
|
|
/***********************************************************************/
|
2020-12-04 23:21:59 +01:00
|
|
|
PSZ BJSON::GetValueText(PGLOBAL g, PBVAL vlp, PSTRG text)
|
|
|
|
{
|
2020-11-25 12:56:45 +01:00
|
|
|
if (vlp->Type == TYPE_JOB)
|
2020-12-04 23:21:59 +01:00
|
|
|
return GetObjectText(g, vlp, text);
|
2020-11-25 12:56:45 +01:00
|
|
|
else if (vlp->Type == TYPE_JAR)
|
2020-12-04 23:21:59 +01:00
|
|
|
return GetArrayText(g, vlp, text);
|
2020-11-21 21:52:48 +01:00
|
|
|
|
|
|
|
char buff[32];
|
2020-12-01 19:30:56 +01:00
|
|
|
PSZ s = (vlp->Type == TYPE_NULL) ? NULL : GetString(vlp, buff);
|
2020-11-21 21:52:48 +01:00
|
|
|
|
|
|
|
if (s)
|
|
|
|
text->Append(s);
|
|
|
|
else if (GetJsonNull())
|
|
|
|
text->Append(GetJsonNull());
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
} // end of GetText
|
|
|
|
|
2020-12-04 23:21:59 +01:00
|
|
|
void BJSON::SetValueObj(PBVAL vlp, PBVAL bop)
|
2020-11-25 12:56:45 +01:00
|
|
|
{
|
2020-12-04 23:21:59 +01:00
|
|
|
CheckType(bop, TYPE_JOB);
|
|
|
|
vlp->To_Val = bop->To_Val;
|
|
|
|
vlp->Nd = bop->Nd;
|
2020-11-25 12:56:45 +01:00
|
|
|
vlp->Type = TYPE_JOB;
|
|
|
|
} // end of SetValueObj;
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2020-11-25 12:56:45 +01:00
|
|
|
void BJSON::SetValueArr(PBVAL vlp, PBVAL bap)
|
|
|
|
{
|
2020-12-04 23:21:59 +01:00
|
|
|
CheckType(bap, TYPE_JAR);
|
|
|
|
vlp->To_Val = bap->To_Val;
|
|
|
|
vlp->Nd = bap->Nd;
|
2020-11-25 12:56:45 +01:00
|
|
|
vlp->Type = TYPE_JAR;
|
2020-11-21 21:52:48 +01:00
|
|
|
} // end of SetValue;
|
|
|
|
|
2020-11-25 12:56:45 +01:00
|
|
|
void BJSON::SetValueVal(PBVAL vlp, PBVAL vp)
|
|
|
|
{
|
|
|
|
vlp->To_Val = vp->To_Val;
|
|
|
|
vlp->Nd = vp->Nd;
|
|
|
|
vlp->Type = vp->Type;
|
|
|
|
} // end of SetValue;
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2020-12-04 23:21:59 +01:00
|
|
|
PBVAL BJSON::SetValue(PBVAL vlp, PVAL valp)
|
2020-11-25 12:56:45 +01:00
|
|
|
{
|
2020-12-04 23:21:59 +01:00
|
|
|
if (!vlp)
|
|
|
|
vlp = NewVal();
|
|
|
|
|
2020-11-21 21:52:48 +01:00
|
|
|
if (!valp || valp->IsNull()) {
|
2020-11-25 12:56:45 +01:00
|
|
|
vlp->Type = TYPE_NULL;
|
2020-11-21 21:52:48 +01:00
|
|
|
} else switch (valp->GetType()) {
|
2021-01-08 22:18:52 +01:00
|
|
|
case TYPE_DATE:
|
|
|
|
if (((DTVAL*)valp)->IsFormatted())
|
|
|
|
vlp->To_Val = DupStr(valp->GetCharValue());
|
|
|
|
else {
|
|
|
|
char buf[32];
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2021-01-08 22:18:52 +01:00
|
|
|
vlp->To_Val = DupStr(valp->GetCharString(buf));
|
|
|
|
} // endif Formatted
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2021-01-08 22:18:52 +01:00
|
|
|
vlp->Type = TYPE_DTM;
|
|
|
|
break;
|
|
|
|
case TYPE_STRING:
|
|
|
|
vlp->To_Val = DupStr(valp->GetCharValue());
|
|
|
|
vlp->Type = TYPE_STRG;
|
|
|
|
break;
|
|
|
|
case TYPE_DOUBLE:
|
|
|
|
case TYPE_DECIM:
|
|
|
|
{ double d = valp->GetFloatValue();
|
|
|
|
int nd = (IsTypeNum(valp->GetType())) ? valp->GetValPrec() : 0;
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2021-01-12 18:25:41 +01:00
|
|
|
if (nd > 0 && nd <= 6 && d >= FLT_MIN && d <= FLT_MAX) {
|
2021-01-08 22:18:52 +01:00
|
|
|
vlp->F = (float)valp->GetFloatValue();
|
|
|
|
vlp->Type = TYPE_FLOAT;
|
|
|
|
} else {
|
|
|
|
double* dp = (double*)BsonSubAlloc(sizeof(double));
|
2020-11-25 12:56:45 +01:00
|
|
|
|
2021-01-08 22:18:52 +01:00
|
|
|
*dp = d;
|
|
|
|
vlp->To_Val = MOF(dp);
|
|
|
|
vlp->Type = TYPE_DBL;
|
|
|
|
} // endif Nd
|
2020-11-21 21:52:48 +01:00
|
|
|
|
2021-01-08 22:18:52 +01:00
|
|
|
vlp->Nd = MY_MIN(nd, 16);
|
|
|
|
} break;
|
|
|
|
case TYPE_TINY:
|
|
|
|
vlp->B = valp->GetTinyValue() != 0;
|
|
|
|
vlp->Type = TYPE_BOOL;
|
|
|
|
break;
|
|
|
|
case TYPE_INT:
|
2020-11-25 12:56:45 +01:00
|
|
|
vlp->N = valp->GetIntValue();
|
|
|
|
vlp->Type = TYPE_INTG;
|
2021-01-08 22:18:52 +01:00
|
|
|
break;
|
|
|
|
case TYPE_BIGINT:
|
|
|
|
if (valp->GetBigintValue() >= INT_MIN32 &&
|
|
|
|
valp->GetBigintValue() <= INT_MAX32) {
|
|
|
|
vlp->N = valp->GetIntValue();
|
|
|
|
vlp->Type = TYPE_INTG;
|
|
|
|
} else {
|
|
|
|
longlong* llp = (longlong*)BsonSubAlloc(sizeof(longlong));
|
2020-11-25 12:56:45 +01:00
|
|
|
|
2021-01-08 22:18:52 +01:00
|
|
|
*llp = valp->GetBigintValue();
|
|
|
|
vlp->To_Val = MOF(llp);
|
|
|
|
vlp->Type = TYPE_BINT;
|
|
|
|
} // endif BigintValue
|
2020-11-25 12:56:45 +01:00
|
|
|
|
2021-01-08 22:18:52 +01:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
sprintf(G->Message, "Unsupported typ %d\n", valp->GetType());
|
|
|
|
throw(777);
|
2020-11-21 21:52:48 +01:00
|
|
|
} // endswitch Type
|
|
|
|
|
2020-12-04 23:21:59 +01:00
|
|
|
return vlp;
|
2020-11-21 21:52:48 +01:00
|
|
|
} // end of SetValue
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* Set the Value's value as the given integer. */
|
|
|
|
/***********************************************************************/
|
2020-11-25 12:56:45 +01:00
|
|
|
void BJSON::SetInteger(PBVAL vlp, int n)
|
|
|
|
{
|
|
|
|
vlp->N = n;
|
|
|
|
vlp->Type = TYPE_INTG;
|
2020-11-21 21:52:48 +01:00
|
|
|
} // end of SetInteger
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* Set the Value's Boolean value as a tiny integer. */
|
|
|
|
/***********************************************************************/
|
2020-11-25 12:56:45 +01:00
|
|
|
void BJSON::SetBool(PBVAL vlp, bool b)
|
|
|
|
{
|
|
|
|
vlp->B = b;
|
|
|
|
vlp->Type = TYPE_BOOL;
|
2020-11-21 21:52:48 +01:00
|
|
|
} // end of SetTiny
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* Set the Value's value as the given big integer. */
|
|
|
|
/***********************************************************************/
|
2020-12-01 19:30:56 +01:00
|
|
|
void BJSON::SetBigint(PBVAL vlp, longlong ll)
|
2020-11-25 12:56:45 +01:00
|
|
|
{
|
|
|
|
if (ll >= INT_MIN32 && ll <= INT_MAX32) {
|
|
|
|
vlp->N = (int)ll;
|
|
|
|
vlp->Type = TYPE_INTG;
|
|
|
|
} else {
|
2020-12-01 19:30:56 +01:00
|
|
|
longlong* llp = (longlong*)PlugSubAlloc(G, NULL, sizeof(longlong));
|
2020-11-25 12:56:45 +01:00
|
|
|
|
|
|
|
*llp = ll;
|
|
|
|
vlp->To_Val = MOF(llp);
|
|
|
|
vlp->Type = TYPE_BINT;
|
|
|
|
} // endif ll
|
|
|
|
|
2020-11-21 21:52:48 +01:00
|
|
|
} // end of SetBigint
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* Set the Value's value as the given DOUBLE. */
|
|
|
|
/***********************************************************************/
|
2021-01-28 01:02:29 +01:00
|
|
|
void BJSON::SetFloat(PBVAL vlp, double d, int prec)
|
2021-01-08 22:18:52 +01:00
|
|
|
{
|
2021-01-28 01:02:29 +01:00
|
|
|
int nd = MY_MIN((prec < 0) ? GetJsonDefPrec() : prec, 16);
|
|
|
|
|
|
|
|
if (nd < 6 && d >= FLT_MIN && d <= FLT_MAX) {
|
|
|
|
vlp->F = (float)d;
|
|
|
|
vlp->Type = TYPE_FLOAT;
|
|
|
|
} else {
|
|
|
|
double* dp = (double*)BsonSubAlloc(sizeof(double));
|
2021-01-08 22:18:52 +01:00
|
|
|
|
2021-01-28 01:02:29 +01:00
|
|
|
*dp = d;
|
|
|
|
vlp->To_Val = MOF(dp);
|
|
|
|
vlp->Type = TYPE_DBL;
|
|
|
|
} // endif nd
|
|
|
|
|
|
|
|
vlp->Nd = nd;
|
2020-11-21 21:52:48 +01:00
|
|
|
} // end of SetFloat
|
|
|
|
|
|
|
|
/***********************************************************************/
|
2021-01-08 22:18:52 +01:00
|
|
|
/* Set the Value's value as the given DOUBLE representation. */
|
|
|
|
/***********************************************************************/
|
|
|
|
void BJSON::SetFloat(PBVAL vlp, PSZ s)
|
|
|
|
{
|
|
|
|
char *p = strchr(s, '.');
|
|
|
|
int nd = 0;
|
|
|
|
double d = atof(s);
|
|
|
|
|
|
|
|
if (p) {
|
|
|
|
for (++p; isdigit(*p); nd++, p++);
|
|
|
|
for (--p; *p == '0'; nd--, p--);
|
|
|
|
} // endif p
|
|
|
|
|
2021-01-28 01:02:29 +01:00
|
|
|
SetFloat(vlp, d, nd);
|
2021-01-08 22:18:52 +01:00
|
|
|
} // end of SetFloat
|
|
|
|
|
|
|
|
/***********************************************************************/
|
2020-11-21 21:52:48 +01:00
|
|
|
/* Set the Value's value as the given string. */
|
|
|
|
/***********************************************************************/
|
2021-01-08 22:18:52 +01:00
|
|
|
void BJSON::SetString(PBVAL vlp, PSZ s, int ci)
|
|
|
|
{
|
2020-11-25 12:56:45 +01:00
|
|
|
vlp->To_Val = MOF(s);
|
|
|
|
vlp->Nd = ci;
|
|
|
|
vlp->Type = TYPE_STRG;
|
2020-11-21 21:52:48 +01:00
|
|
|
} // end of SetString
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* True when its JSON or normal value is null. */
|
|
|
|
/***********************************************************************/
|
2021-01-08 22:18:52 +01:00
|
|
|
bool BJSON::IsValueNull(PBVAL vlp)
|
|
|
|
{
|
2020-11-25 12:56:45 +01:00
|
|
|
bool b;
|
|
|
|
|
|
|
|
switch (vlp->Type) {
|
|
|
|
case TYPE_NULL:
|
|
|
|
b = true;
|
|
|
|
break;
|
|
|
|
case TYPE_JOB:
|
2020-12-04 23:21:59 +01:00
|
|
|
b = IsObjectNull(vlp);
|
2020-11-25 12:56:45 +01:00
|
|
|
break;
|
|
|
|
case TYPE_JAR:
|
2020-12-04 23:21:59 +01:00
|
|
|
b = IsArrayNull(vlp);
|
2020-11-25 12:56:45 +01:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
b = false;
|
|
|
|
} // endswitch Type
|
|
|
|
|
|
|
|
return b;
|
|
|
|
} // end of IsNull
|