Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
MariaDB
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
477b5256
Commit
477b5256
authored
Nov 21, 2020
by
Olivier Bertrand
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix some test failure
parent
038381e1
Changes
10
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
2323 additions
and
33 deletions
+2323
-33
storage/connect/Header.h
storage/connect/Header.h
+395
-0
storage/connect/bson.cpp
storage/connect/bson.cpp
+1601
-0
storage/connect/bson.h
storage/connect/bson.h
+291
-0
storage/connect/json.h
storage/connect/json.h
+16
-12
storage/connect/jsonudf.cpp
storage/connect/jsonudf.cpp
+4
-4
storage/connect/jsonudf.h
storage/connect/jsonudf.h
+1
-1
storage/connect/myutil.cpp
storage/connect/myutil.cpp
+1
-2
storage/connect/tabfmt.cpp
storage/connect/tabfmt.cpp
+1
-1
storage/connect/tabjson.cpp
storage/connect/tabjson.cpp
+12
-12
storage/connect/tabjson.h
storage/connect/tabjson.h
+1
-1
No files found.
storage/connect/Header.h
0 → 100644
View file @
477b5256
#pragma once
/**************** json H Declares Source Code File (.H) ****************/
/* Name: json.h Version 1.2 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 2014 - 2020 */
/* */
/* This file contains the JSON classes declares. */
/***********************************************************************/
#include <mysql_com.h>
#include "value.h"
#include "xobject.h"
#if defined(_DEBUG)
#define X assert(false);
#else
#define X
#endif
enum
JTYP
{
TYPE_NULL
=
TYPE_VOID
,
TYPE_STRG
=
TYPE_STRING
,
TYPE_DBL
=
TYPE_DOUBLE
,
TYPE_BOOL
=
TYPE_TINY
,
TYPE_BINT
=
TYPE_BIGINT
,
TYPE_DTM
=
TYPE_DATE
,
TYPE_INTG
=
TYPE_INT
,
TYPE_VAL
=
12
,
TYPE_JSON
,
TYPE_JAR
,
TYPE_JOB
,
TYPE_JVAL
};
class
JDOC
;
class
JOUT
;
class
JSON
;
class
JVALUE
;
class
JOBJECT
;
class
JARRAY
;
typedef
class
JDOC
*
PJDOC
;
typedef
class
JSON
*
PJSON
;
typedef
class
JVALUE
*
PJVAL
;
typedef
class
JOBJECT
*
PJOB
;
typedef
class
JARRAY
*
PJAR
;
// BSON size should be equal on Linux and Windows
#define BMX 255
typedef
struct
BSON
*
PBSON
;
typedef
struct
JPAIR
*
PJPR
;
//typedef struct VAL *PVL;
/***********************************************************************/
/* Structure JPAIR. The pairs of a json Object. */
/***********************************************************************/
struct
JPAIR
{
PCSZ
Key
;
// This pair key name
PJVAL
Val
;
// To the value of the pair
PJPR
Next
;
// To the next pair
};
// end of struct JPAIR
#if 0
/***********************************************************************/
/* Structure VAL (string, int, float, bool or null) */
/***********************************************************************/
struct VAL {
union {
char* Strp; // Ptr to a string
int N; // An integer value
long long LLn; // A big integer value
double F; // A float value
bool B; // True or false
};
int Nd; // Decimal number
JTYP Type; // The value type
}; // end of struct VAL
#endif // 0
/***********************************************************************/
/* Structure used to return binary json to Json UDF functions. */
/***********************************************************************/
struct
BSON
{
char
Msg
[
BMX
+
1
];
char
*
Filename
;
PGLOBAL
G
;
int
Pretty
;
ulong
Reslen
;
my_bool
Changed
;
PJSON
Top
;
PJSON
Jsp
;
PBSON
Bsp
;
};
// end of struct BSON
PBSON
JbinAlloc
(
PGLOBAL
g
,
UDF_ARGS
*
args
,
ulong
len
,
PJSON
jsp
);
//PVL AllocVal(PGLOBAL g, JTYP type);
char
*
NextChr
(
PSZ
s
,
char
sep
);
char
*
GetJsonNull
(
void
);
const
char
*
GetFmt
(
int
type
,
bool
un
);
PJSON
ParseJson
(
PGLOBAL
g
,
char
*
s
,
size_t
n
,
int
*
prty
=
NULL
,
bool
*
b
=
NULL
);
PSZ
Serialize
(
PGLOBAL
g
,
PJSON
jsp
,
char
*
fn
,
int
pretty
);
DllExport
bool
IsNum
(
PSZ
s
);
/***********************************************************************/
/* Class JDOC. The class for parsing and serializing json documents. */
/***********************************************************************/
class
JDOC
:
public
BLOCK
{
friend
PJSON
ParseJson
(
PGLOBAL
,
char
*
,
size_t
,
int
*
,
bool
*
);
friend
PSZ
Serialize
(
PGLOBAL
,
PJSON
,
char
*
,
int
);
public:
JDOC
(
void
)
:
js
(
NULL
),
s
(
NULL
),
len
(
0
),
pty
(
NULL
)
{}
void
SetJp
(
JOUT
*
jp
)
{
js
=
jp
;
}
protected:
PJAR
ParseArray
(
PGLOBAL
g
,
int
&
i
);
PJOB
ParseObject
(
PGLOBAL
g
,
int
&
i
);
PJVAL
ParseValue
(
PGLOBAL
g
,
int
&
i
);
char
*
ParseString
(
PGLOBAL
g
,
int
&
i
);
void
ParseNumeric
(
PGLOBAL
g
,
int
&
i
,
PJVAL
jvp
);
PJAR
ParseAsArray
(
PGLOBAL
g
,
int
&
i
,
int
pretty
,
int
*
ptyp
);
bool
SerializeArray
(
PJAR
jarp
,
bool
b
);
bool
SerializeObject
(
PJOB
jobp
);
bool
SerializeValue
(
PJVAL
jvp
);
// Members used when parsing and serializing
private:
JOUT
*
js
;
char
*
s
;
int
len
;
bool
*
pty
;
};
// end of class JDOC
/***********************************************************************/
/* Class JSON. The base class for all other json classes. */
/***********************************************************************/
class
JSON
:
public
BLOCK
{
public:
// Constructor
JSON
(
void
)
{
Type
=
TYPE_JSON
;
}
JSON
(
int
)
{}
// Implementation
inline
JTYP
GetType
(
void
)
{
return
Type
;
}
// Methods
virtual
int
size
(
void
)
{
return
1
;
}
virtual
void
Clear
(
void
)
{
X
}
virtual
PJOB
GetObject
(
void
)
{
return
NULL
;
}
virtual
PJAR
GetArray
(
void
)
{
return
NULL
;
}
virtual
PJVAL
GetArrayValue
(
int
i
)
{
X
return
NULL
;
}
virtual
int
GetSize
(
bool
b
)
{
X
return
0
;
}
virtual
PJSON
GetJsp
(
void
)
{
X
return
NULL
;
}
virtual
PJPR
GetFirst
(
void
)
{
X
return
NULL
;
}
virtual
PSZ
GetText
(
PGLOBAL
g
,
PSTRG
text
)
{
X
return
NULL
;
}
virtual
bool
Merge
(
PGLOBAL
g
,
PJSON
jsp
)
{
X
return
true
;
}
virtual
void
SetValue
(
PJSON
jsp
)
{
X
}
virtual
bool
DeleteValue
(
int
i
)
{
X
return
true
;
}
virtual
bool
IsNull
(
void
)
{
X
return
true
;
}
// Members
JTYP
Type
;
};
// end of class JSON
/***********************************************************************/
/* Class JOBJECT: contains a list of value pairs. */
/***********************************************************************/
class
JOBJECT
:
public
JSON
{
friend
class
JDOC
;
friend
class
JSNX
;
friend
class
SWAP
;
public:
JOBJECT
(
void
)
:
JSON
()
{
Type
=
TYPE_JOB
;
First
=
Last
=
NULL
;
}
JOBJECT
(
int
i
)
:
JSON
(
i
)
{}
// Methods
virtual
void
Clear
(
void
)
{
First
=
Last
=
NULL
;
}
//virtual JTYP GetValType(void) {return TYPE_JOB;}
virtual
PJPR
GetFirst
(
void
)
{
return
First
;
}
virtual
int
GetSize
(
bool
b
);
virtual
PJOB
GetObject
(
void
)
{
return
this
;
}
virtual
PSZ
GetText
(
PGLOBAL
g
,
PSTRG
text
);
virtual
bool
Merge
(
PGLOBAL
g
,
PJSON
jsp
);
virtual
bool
IsNull
(
void
);
// Specific
PJPR
AddPair
(
PGLOBAL
g
,
PCSZ
key
);
PJVAL
GetKeyValue
(
const
char
*
key
);
PJAR
GetKeyList
(
PGLOBAL
g
);
PJAR
GetValList
(
PGLOBAL
g
);
void
SetKeyValue
(
PGLOBAL
g
,
PJVAL
jvp
,
PCSZ
key
);
void
DeleteKey
(
PCSZ
k
);
protected:
PJPR
First
;
PJPR
Last
;
};
// end of class JOBJECT
/***********************************************************************/
/* Class JARRAY. */
/***********************************************************************/
class
JARRAY
:
public
JSON
{
friend
class
SWAP
;
public:
JARRAY
(
void
);
JARRAY
(
int
i
)
:
JSON
(
i
)
{}
// Methods
virtual
void
Clear
(
void
)
{
First
=
Last
=
NULL
;
Size
=
0
;
}
virtual
int
size
(
void
)
{
return
Size
;
}
virtual
PJAR
GetArray
(
void
)
{
return
this
;
}
virtual
int
GetSize
(
bool
b
);
virtual
PJVAL
GetArrayValue
(
int
i
);
virtual
PSZ
GetText
(
PGLOBAL
g
,
PSTRG
text
);
virtual
bool
Merge
(
PGLOBAL
g
,
PJSON
jsp
);
virtual
bool
DeleteValue
(
int
n
);
virtual
bool
IsNull
(
void
);
// Specific
PJVAL
AddArrayValue
(
PGLOBAL
g
,
PJVAL
jvp
=
NULL
,
int
*
x
=
NULL
);
bool
SetArrayValue
(
PGLOBAL
g
,
PJVAL
jvp
,
int
i
);
void
InitArray
(
PGLOBAL
g
);
protected:
// Members
int
Size
;
// The number of items in the array
int
Alloc
;
// The Mvals allocated size
PJVAL
First
;
// Used when constructing
PJVAL
Last
;
// Last constructed value
PJVAL
*
Mvals
;
// Allocated when finished
};
// end of class JARRAY
/***********************************************************************/
/* Class JVALUE. */
/***********************************************************************/
class
JVALUE
:
public
JSON
{
friend
class
JARRAY
;
friend
class
JSNX
;
friend
class
JSONDISC
;
friend
class
JSONCOL
;
friend
class
JSON
;
friend
class
JDOC
;
friend
class
SWAP
;
public:
JVALUE
(
void
)
:
JSON
()
{
Type
=
TYPE_JVAL
;
Clear
();
}
JVALUE
(
PJSON
jsp
);
//JVALUE(PGLOBAL g, PVL vlp);
JVALUE
(
PGLOBAL
g
,
PVAL
valp
);
JVALUE
(
PGLOBAL
g
,
PCSZ
strp
);
JVALUE
(
int
i
)
:
JSON
(
i
)
{}
//using JSON::GetVal;
//using JSON::SetVal;
// Methods
virtual
void
Clear
(
void
);
//virtual JTYP GetType(void) {return TYPE_JVAL;}
virtual
JTYP
GetValType
(
void
);
virtual
PJOB
GetObject
(
void
);
virtual
PJAR
GetArray
(
void
);
virtual
PJSON
GetJsp
(
void
)
{
return
(
DataType
==
TYPE_JSON
?
Jsp
:
NULL
);
}
virtual
PSZ
GetText
(
PGLOBAL
g
,
PSTRG
text
);
virtual
bool
IsNull
(
void
);
// Specific
//inline PVL GetVal(void) { return Val; }
//inline void SetVal(PVL vlp) { Val = vlp; }
inline
PJSON
GetJson
(
void
)
{
return
(
DataType
==
TYPE_JSON
?
Jsp
:
this
);
}
PSZ
GetString
(
PGLOBAL
g
,
char
*
buff
=
NULL
);
int
GetInteger
(
void
);
long
long
GetBigint
(
void
);
double
GetFloat
(
void
);
PVAL
GetValue
(
PGLOBAL
g
);
void
SetValue
(
PJSON
jsp
);
void
SetValue
(
PGLOBAL
g
,
PVAL
valp
);
void
SetString
(
PGLOBAL
g
,
PSZ
s
,
int
ci
=
0
);
void
SetInteger
(
PGLOBAL
g
,
int
n
);
void
SetBigint
(
PGLOBAL
g
,
longlong
ll
);
void
SetFloat
(
PGLOBAL
g
,
double
f
);
void
SetBool
(
PGLOBAL
g
,
bool
b
);
protected:
union
{
PJSON
Jsp
;
// To the json value
char
*
Strp
;
// Ptr to a string
int
N
;
// An integer value
long
long
LLn
;
// A big integer value
double
F
;
// A (double) float value
bool
B
;
// True or false
};
//PVL Val; // To the string or numeric value
PJVAL
Next
;
// Next value in array
JTYP
DataType
;
// The data value type
int
Nd
;
// Decimal number
bool
Del
;
// True when deleted
};
// end of class JVALUE
/***********************************************************************/
/* Class JOUT. Used by Serialize. */
/***********************************************************************/
class
JOUT
:
public
BLOCK
{
public:
JOUT
(
PGLOBAL
gp
)
:
BLOCK
()
{
g
=
gp
;
Pretty
=
3
;
}
virtual
bool
WriteStr
(
const
char
*
s
)
=
0
;
virtual
bool
WriteChr
(
const
char
c
)
=
0
;
virtual
bool
Escape
(
const
char
*
s
)
=
0
;
int
Prty
(
void
)
{
return
Pretty
;
}
// Member
PGLOBAL
g
;
int
Pretty
;
};
// end of class JOUT
/***********************************************************************/
/* Class JOUTSTR. Used to Serialize to a string. */
/***********************************************************************/
class
JOUTSTR
:
public
JOUT
{
public:
JOUTSTR
(
PGLOBAL
g
);
virtual
bool
WriteStr
(
const
char
*
s
);
virtual
bool
WriteChr
(
const
char
c
);
virtual
bool
Escape
(
const
char
*
s
);
// Member
char
*
Strp
;
// The serialized string
size_t
N
;
// Position of next char
size_t
Max
;
// String max size
};
// end of class JOUTSTR
/***********************************************************************/
/* Class JOUTFILE. Used to Serialize to a file. */
/***********************************************************************/
class
JOUTFILE
:
public
JOUT
{
public:
JOUTFILE
(
PGLOBAL
g
,
FILE
*
str
,
int
pty
)
:
JOUT
(
g
)
{
Stream
=
str
;
Pretty
=
pty
;
}
virtual
bool
WriteStr
(
const
char
*
s
);
virtual
bool
WriteChr
(
const
char
c
);
virtual
bool
Escape
(
const
char
*
s
);
// Member
FILE
*
Stream
;
};
// end of class JOUTFILE
/***********************************************************************/
/* Class JOUTPRT. Used to Serialize to a pretty file. */
/***********************************************************************/
class
JOUTPRT
:
public
JOUTFILE
{
public:
JOUTPRT
(
PGLOBAL
g
,
FILE
*
str
)
:
JOUTFILE
(
g
,
str
,
2
)
{
M
=
0
;
B
=
false
;
}
virtual
bool
WriteStr
(
const
char
*
s
);
virtual
bool
WriteChr
(
const
char
c
);
// Member
int
M
;
bool
B
;
};
// end of class JOUTPRT
/***********************************************************************/
/* Class SWAP. Used to make or unmake a JSON tree movable. */
/* This is done by making all pointers to offsets. */
/***********************************************************************/
class
SWAP
:
public
BLOCK
{
public:
// Constructor
SWAP
(
PGLOBAL
g
,
PJSON
jsp
)
{
G
=
g
,
Base
=
(
char
*
)
jsp
-
8
;
}
// Methods
void
SwapJson
(
PJSON
jsp
,
bool
move
);
protected:
size_t
MoffJson
(
PJSON
jnp
);
size_t
MoffArray
(
PJAR
jarp
);
size_t
MoffObject
(
PJOB
jobp
);
size_t
MoffJValue
(
PJVAL
jvp
);
size_t
MoffPair
(
PJPR
jpp
);
//size_t MoffVal(PVL vlp);
PJSON
MptrJson
(
PJSON
jnp
);
PJAR
MptrArray
(
PJAR
jarp
);
PJOB
MptrObject
(
PJOB
jobp
);
PJVAL
MptrJValue
(
PJVAL
jvp
);
PJPR
MptrPair
(
PJPR
jpp
);
//PVL MptrVal(PVL vlp);
// Member
PGLOBAL
G
;
void
*
Base
;
};
// end of class SWAP
storage/connect/bson.cpp
0 → 100644
View file @
477b5256
/*************** json CPP Declares Source Code File (.H) ***************/
/* Name: json.cpp Version 1.5 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 2014 - 2020 */
/* */
/* This file contains the JSON classes functions. */
/***********************************************************************/
/***********************************************************************/
/* 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. */
/* xjson.h is header containing the JSON classes declarations. */
/***********************************************************************/
#include "global.h"
#include "plgdbsem.h"
#include "bson.h"
#define ARGS MY_MIN(24,(int)len-i),s+MY_MAX(i-3,0)
#if defined(__WIN__)
#define EL "\r\n"
#else
#define EL "\n"
#undef SE_CATCH // Does not work for Linux
#endif
#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
#if 0
char* GetJsonNull(void);
/***********************************************************************/
/* IsNum: check whether this string is all digits. */
/***********************************************************************/
bool IsNum(PSZ s) {
for (char* p = s; *p; p++)
if (*p == ']')
break;
else if (!isdigit(*p) || *p == '-')
return false;
return true;
} // end of IsNum
/***********************************************************************/
/* NextChr: return the first found '[' or Sep pointer. */
/***********************************************************************/
char* NextChr(PSZ s, char sep) {
char* p1 = strchr(s, '[');
char* p2 = strchr(s, sep);
if (!p2)
return p1;
else if (p1)
return MY_MIN(p1, p2);
return p2;
} // end of NextChr
#endif // 0
/* --------------------------- Class BDOC ---------------------------- */
/***********************************************************************/
/* BDOC constructor. */
/***********************************************************************/
BDOC
::
BDOC
(
void
)
:
jp
(
NULL
),
base
(
NULL
),
s
(
NULL
),
len
(
0
)
{
pty
[
0
]
=
pty
[
1
]
=
pty
[
2
]
=
true
;
}
// end of BDOC constructor
/***********************************************************************/
/* Program for sub-allocating Bson structures. */
/***********************************************************************/
void
*
BDOC
::
BsonSubAlloc
(
PGLOBAL
g
,
size_t
size
)
{
PPOOLHEADER
pph
;
/* Points on area header. */
void
*
memp
=
g
->
Sarea
;
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 */
sprintf
(
g
->
Message
,
"Not enough memory for request of %zd (used=%zd free=%zd)"
,
size
,
pph
->
To_Free
,
pph
->
FreeBlk
);
xtrc
(
1
,
"BsonSubAlloc: %s
\n
"
,
g
->
Message
);
throw
(
1234
);
}
/* 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
;
}
/* end of BsonSubAlloc */
/***********************************************************************/
/* Parse a json string. */
/* Note: when pretty is not known, the caller set pretty to 3. */
/***********************************************************************/
PBVAL
BDOC
::
ParseJson
(
PGLOBAL
g
,
char
*
js
,
size_t
lng
,
int
*
ptyp
,
bool
*
comma
)
{
int
i
,
pretty
=
(
ptyp
)
?
*
ptyp
:
3
;
bool
b
=
false
;
PBVAL
bvp
=
NULL
;
xtrc
(
1
,
"ParseJson: s=%.10s len=%zd
\n
"
,
s
,
len
);
if
(
!
s
||
!
len
)
{
strcpy
(
g
->
Message
,
"Void JSON object"
);
return
NULL
;
}
else
if
(
comma
)
*
comma
=
false
;
// Trying to guess the pretty format
if
(
s
[
0
]
==
'['
&&
(
s
[
1
]
==
'\n'
||
(
s
[
1
]
==
'\r'
&&
s
[
2
]
==
'\n'
)))
pty
[
0
]
=
false
;
s
=
js
;
len
=
lng
;
try
{
bvp
=
(
PBVAL
)
PlugSubAlloc
(
g
,
NULL
,
sizeof
(
BVAL
));
bvp
->
Type
=
TYPE_UNKNOWN
;
base
=
bvp
;
for
(
i
=
0
;
i
<
len
;
i
++
)
switch
(
s
[
i
])
{
case
'['
:
if
(
bvp
->
Type
!=
TYPE_UNKNOWN
)
bvp
->
To_Val
=
ParseAsArray
(
g
,
i
,
pretty
,
ptyp
);
else
bvp
->
To_Val
=
ParseArray
(
g
,
++
i
);
bvp
->
Type
=
TYPE_JAR
;
break
;
case
'{'
:
if
(
bvp
->
Type
!=
TYPE_UNKNOWN
)
{
bvp
->
To_Val
=
ParseAsArray
(
g
,
i
,
pretty
,
ptyp
);
bvp
->
Type
=
TYPE_JAR
;
}
else
if
((
bvp
->
To_Val
=
ParseObject
(
g
,
++
i
)))
bvp
->
Type
=
TYPE_JOB
;
else
throw
2
;
break
;
case
' '
:
case
'\t'
:
case
'\n'
:
case
'\r'
:
break
;
case
','
:
if
(
bvp
->
Type
!=
TYPE_UNKNOWN
&&
(
pretty
==
1
||
pretty
==
3
))
{
if
(
comma
)
*
comma
=
true
;
pty
[
0
]
=
pty
[
2
]
=
false
;
break
;
}
// endif pretty
sprintf
(
g
->
Message
,
"Unexpected ',' (pretty=%d)"
,
pretty
);
throw
3
;
case
'('
:
b
=
true
;
break
;
case
')'
:
if
(
b
)
{
b
=
false
;
break
;
}
// endif b
default:
if
(
bvp
->
Type
!=
TYPE_UNKNOWN
)
{
bvp
->
To_Val
=
ParseAsArray
(
g
,
i
,
pretty
,
ptyp
);
bvp
->
Type
=
TYPE_JAR
;
}
else
if
((
bvp
->
To_Val
=
MakeOff
(
base
,
ParseValue
(
g
,
i
))))
bvp
->
Type
=
TYPE_JVAL
;
else
throw
4
;
break
;
};
// endswitch s[i]
if
(
bvp
->
Type
==
TYPE_UNKNOWN
)
sprintf
(
g
->
Message
,
"Invalid Json string '%.*s'"
,
MY_MIN
((
int
)
len
,
50
),
s
);
else
if
(
ptyp
&&
pretty
==
3
)
{
*
ptyp
=
3
;
// Not recognized pretty
for
(
i
=
0
;
i
<
3
;
i
++
)
if
(
pty
[
i
])
{
*
ptyp
=
i
;
break
;
}
// endif pty
}
// endif ptyp
}
catch
(
int
n
)
{
if
(
trace
(
1
))
htrc
(
"Exception %d: %s
\n
"
,
n
,
g
->
Message
);
bvp
=
NULL
;
}
catch
(
const
char
*
msg
)
{
strcpy
(
g
->
Message
,
msg
);
bvp
=
NULL
;
}
// end catch
return
bvp
;
}
// end of ParseJson
/***********************************************************************/
/* Parse several items as being in an array. */
/***********************************************************************/
OFFSET
BDOC
::
ParseAsArray
(
PGLOBAL
g
,
int
&
i
,
int
pretty
,
int
*
ptyp
)
{
if
(
pty
[
0
]
&&
(
!
pretty
||
pretty
>
2
))
{
OFFSET
jsp
;
if
((
jsp
=
ParseArray
(
g
,
(
i
=
0
)))
&&
ptyp
&&
pretty
==
3
)
*
ptyp
=
(
pty
[
0
])
?
0
:
3
;
return
jsp
;
}
else
strcpy
(
g
->
Message
,
"More than one item in file"
);
return
0
;
}
// end of ParseAsArray
/***********************************************************************/
/* Parse a JSON Array. */
/***********************************************************************/
OFFSET
BDOC
::
ParseArray
(
PGLOBAL
g
,
int
&
i
)
{
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
)
{
sprintf
(
g
->
Message
,
"Unexpected ',' near %.*s"
,
ARGS
);
throw
1
;
}
else
level
=
1
;
break
;
case
']'
:
if
(
level
==
1
)
{
sprintf
(
g
->
Message
,
"Unexpected ',]' near %.*s"
,
ARGS
);
throw
1
;
}
// endif level
return
MakeOff
(
base
,
vlp
);
case
'\n'
:
if
(
!
b
)
pty
[
0
]
=
pty
[
1
]
=
false
;
case
'\r'
:
case
' '
:
case
'\t'
:
break
;
default:
if
(
level
==
2
)
{
sprintf
(
g
->
Message
,
"Unexpected value near %.*s"
,
ARGS
);
throw
1
;
}
else
if
(
lastvlp
)
{
vlp
=
ParseValue
(
g
,
i
);
lastvlp
->
Next
=
MakeOff
(
base
,
vlp
);
lastvlp
=
vlp
;
}
else
firstvlp
=
lastvlp
=
ParseValue
(
g
,
i
);
level
=
(
b
)
?
1
:
2
;
break
;
};
// endswitch s[i]
if
(
b
)
{
// Case of Pretty == 0
return
MakeOff
(
base
,
vlp
);
}
// endif b
throw
(
"Unexpected EOF in array"
);
}
// end of ParseArray
/***********************************************************************/
/* Sub-allocate and initialize a BPAIR. */
/***********************************************************************/
PBPR
BDOC
::
SubAllocPair
(
PGLOBAL
g
,
OFFSET
key
)
{
PBPR
bpp
=
(
PBPR
)
BsonSubAlloc
(
g
,
sizeof
(
BPAIR
));
bpp
->
Key
=
key
;
bpp
->
Vlp
=
0
;
bpp
->
Next
=
0
;
return
bpp
;
}
// end of SubAllocPair
/***********************************************************************/
/* Parse a JSON Object. */
/***********************************************************************/
OFFSET
BDOC
::
ParseObject
(
PGLOBAL
g
,
int
&
i
)
{
OFFSET
key
;
int
level
=
0
;
PBPR
bpp
,
firstbpp
,
lastbpp
;
bpp
=
firstbpp
=
lastbpp
=
NULL
;
for
(;
i
<
len
;
i
++
)
switch
(
s
[
i
])
{
case
'"'
:
if
(
level
<
2
)
{
key
=
ParseString
(
g
,
++
i
);
bpp
=
SubAllocPair
(
g
,
key
);
if
(
lastbpp
)
{
lastbpp
->
Next
=
MakeOff
(
base
,
bpp
);
lastbpp
=
bpp
;
}
else
firstbpp
=
lastbpp
=
bpp
;
level
=
1
;
}
else
{
sprintf
(
g
->
Message
,
"misplaced string near %.*s"
,
ARGS
);
throw
2
;
}
// endif level
break
;
case
':'
:
if
(
level
==
1
)
{
lastbpp
->
Vlp
=
MakeOff
(
base
,
ParseValue
(
g
,
++
i
));
level
=
2
;
}
else
{
sprintf
(
g
->
Message
,
"Unexpected ':' near %.*s"
,
ARGS
);
throw
2
;
}
// endif level
break
;
case
','
:
if
(
level
<
2
)
{
sprintf
(
g
->
Message
,
"Unexpected ',' near %.*s"
,
ARGS
);
throw
2
;
}
else
level
=
0
;
break
;
case
'}'
:
if
(
level
<
2
)
{
sprintf
(
g
->
Message
,
"Unexpected '}' near %.*s"
,
ARGS
);
throw
2
;
}
// endif level
return
MakeOff
(
base
,
firstbpp
);
case
'\n'
:
pty
[
0
]
=
pty
[
1
]
=
false
;
case
'\r'
:
case
' '
:
case
'\t'
:
break
;
default:
sprintf
(
g
->
Message
,
"Unexpected character '%c' near %.*s"
,
s
[
i
],
ARGS
);
throw
2
;
};
// endswitch s[i]
strcpy
(
g
->
Message
,
"Unexpected EOF in Object"
);
throw
2
;
}
// end of ParseObject
/***********************************************************************/
/* Sub-allocate and initialize a BVAL. */
/***********************************************************************/
PBVAL
BDOC
::
SubAllocVal
(
PGLOBAL
g
)
{
PBVAL
bvp
=
(
PBVAL
)
BsonSubAlloc
(
g
,
sizeof
(
BVAL
));
bvp
->
To_Val
=
0
;
bvp
->
Nd
=
0
;
bvp
->
Type
=
TYPE_UNKNOWN
;
bvp
->
Next
=
0
;
return
bvp
;
}
// end of SubAllocVal
/***********************************************************************/
/* Parse a JSON Value. */
/***********************************************************************/
PBVAL
BDOC
::
ParseValue
(
PGLOBAL
g
,
int
&
i
)
{
PBVAL
bvp
=
SubAllocVal
(
g
);
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
'['
:
bvp
->
To_Val
=
ParseArray
(
g
,
++
i
);
bvp
->
Type
=
TYPE_JAR
;
break
;
case
'{'
:
bvp
->
To_Val
=
ParseObject
(
g
,
++
i
);
bvp
->
Type
=
TYPE_JOB
;
break
;
case
'"'
:
// jvp->Val = AllocVal(g, TYPE_STRG);
bvp
->
To_Val
=
ParseString
(
g
,
++
i
);
bvp
->
Type
=
TYPE_STRG
;
break
;
case
't'
:
if
(
!
strncmp
(
s
+
i
,
"true"
,
4
))
{
// jvp->Val = AllocVal(g, TYPE_BOOL);
bvp
->
B
=
true
;
bvp
->
Type
=
TYPE_BOOL
;
i
+=
3
;
}
else
goto
err
;
break
;
case
'f'
:
if
(
!
strncmp
(
s
+
i
,
"false"
,
5
))
{
// jvp->Val = AllocVal(g, TYPE_BOOL);
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
]))
ParseNumeric
(
g
,
i
,
bvp
);
else
goto
err
;
};
// endswitch s[i]
return
bvp
;
err:
sprintf
(
g
->
Message
,
"Unexpected character '%c' near %.*s"
,
s
[
i
],
ARGS
);
throw
3
;
}
// end of ParseValue
/***********************************************************************/
/* Unescape and parse a JSON string. */
/***********************************************************************/
OFFSET
BDOC
::
ParseString
(
PGLOBAL
g
,
int
&
i
)
{
uchar
*
p
;
int
n
=
0
;
// Be sure of memory availability
if
(((
size_t
)
len
+
1
-
i
)
>
((
PPOOLHEADER
)
g
->
Sarea
)
->
FreeBlk
)
throw
(
"ParseString: Out of memory"
);
// The size to allocate is not known yet
p
=
(
uchar
*
)
PlugSubAlloc
(
g
,
NULL
,
0
);
for
(;
i
<
len
;
i
++
)
switch
(
s
[
i
])
{
case
'"'
:
p
[
n
++
]
=
0
;
PlugSubAlloc
(
g
,
NULL
,
n
);
return
MakeOff
(
base
,
p
);
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. */
/***********************************************************************/
void
BDOC
::
ParseNumeric
(
PGLOBAL
g
,
int
&
i
,
PBVAL
vlp
)
{
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
)
{
double
dv
=
strtod
(
buf
,
NULL
);
if
(
nd
>
6
)
{
double
*
dvp
=
(
double
*
)
PlugSubAlloc
(
g
,
NULL
,
sizeof
(
double
));
*
dvp
=
dv
;
vlp
->
To_Val
=
MakeOff
(
base
,
dvp
);
vlp
->
Type
=
TYPE_DBL
;
}
else
{
vlp
->
F
=
(
float
)
dv
;
vlp
->
Type
=
TYPE_FLOAT
;
}
// endif nd
vlp
->
Nd
=
nd
;
}
else
{
long
long
iv
=
strtoll
(
buf
,
NULL
,
10
);
if
(
iv
>
INT_MAX32
||
iv
<
INT_MIN32
)
{
long
long
*
llp
=
(
long
long
*
)
PlugSubAlloc
(
g
,
NULL
,
sizeof
(
long
long
));
*
llp
=
iv
;
vlp
->
To_Val
=
MakeOff
(
base
,
llp
);
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
/***********************************************************************/
/* Serialize a JSON document tree: */
/***********************************************************************/
PSZ
BDOC
::
Serialize
(
PGLOBAL
g
,
PBVAL
bvp
,
char
*
fn
,
int
pretty
)
{
PSZ
str
=
NULL
;
bool
b
=
false
,
err
=
true
;
JOUT
*
jp
;
FILE
*
fs
=
NULL
;
g
->
Message
[
0
]
=
0
;
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"
)))
{
sprintf
(
g
->
Message
,
MSG
(
OPEN_MODE_ERROR
),
"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
:
err
=
SerializeValue
((
PBVAL
)
MakePtr
(
base
,
bvp
->
To_Val
));
break
;
default:
strcpy
(
g
->
Message
,
"Invalid json tree"
);
}
// 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
);
}
else
{
if
(
!
g
->
Message
[
0
])
strcpy
(
g
->
Message
,
"Error in Serialize"
);
}
// endif's
}
catch
(
int
n
)
{
if
(
trace
(
1
))
htrc
(
"Exception %d: %s
\n
"
,
n
,
g
->
Message
);
str
=
NULL
;
}
catch
(
const
char
*
msg
)
{
strcpy
(
g
->
Message
,
msg
);
str
=
NULL
;
}
// end catch
return
str
;
}
// end of Serialize
/***********************************************************************/
/* Serialize a JSON Array. */
/***********************************************************************/
bool
BDOC
::
SerializeArray
(
OFFSET
arp
,
bool
b
)
{
bool
first
=
true
;
PBVAL
vp
=
(
PBVAL
)
MakePtr
(
base
,
arp
);
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
;
for
(
vp
;
vp
;
vp
=
(
PBVAL
)
MakePtr
(
base
,
vp
->
Next
))
{
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
;
}
// endfor i
if
(
b
&&
jp
->
Prty
()
==
1
&&
jp
->
WriteStr
(
EL
))
return
true
;
return
((
!
b
||
jp
->
Prty
())
&&
jp
->
WriteChr
(
']'
));
}
// end of SerializeArray
/***********************************************************************/
/* Serialize a JSON Object. */
/***********************************************************************/
bool
BDOC
::
SerializeObject
(
OFFSET
obp
)
{
bool
first
=
true
;
PBPR
prp
=
(
PBPR
)
MakePtr
(
base
,
obp
);
if
(
jp
->
WriteChr
(
'{'
))
return
true
;
for
(
prp
;
prp
;
prp
=
(
PBPR
)
MakePtr
(
base
,
prp
->
Next
))
{
if
(
first
)
first
=
false
;
else
if
(
jp
->
WriteChr
(
','
))
return
true
;
if
(
jp
->
WriteChr
(
'"'
)
||
jp
->
WriteStr
((
const
char
*
)
MakePtr
(
base
,
prp
->
Key
))
||
jp
->
WriteChr
(
'"'
)
||
jp
->
WriteChr
(
':'
)
||
SerializeValue
((
PBVAL
)
MakePtr
(
base
,
prp
->
Vlp
)))
return
true
;
}
// endfor i
return
jp
->
WriteChr
(
'}'
);
}
// end of SerializeObject
/***********************************************************************/
/* Serialize a JSON Value. */
/***********************************************************************/
bool
BDOC
::
SerializeValue
(
PBVAL
jvp
)
{
char
buf
[
64
];
switch
(
jvp
->
Type
)
{
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
:
return
jp
->
Escape
((
const
char
*
)
MakePtr
(
base
,
jvp
->
To_Val
));
case
TYPE_INTG
:
sprintf
(
buf
,
"%d"
,
jvp
->
N
);
return
jp
->
WriteStr
(
buf
);
case
TYPE_BINT
:
sprintf
(
buf
,
"%lld"
,
*
(
long
long
*
)
MakePtr
(
base
,
jvp
->
To_Val
));
return
jp
->
WriteStr
(
buf
);
case
TYPE_FLOAT
:
sprintf
(
buf
,
"%.*f"
,
jvp
->
Nd
,
jvp
->
F
);
return
jp
->
WriteStr
(
buf
);
case
TYPE_DBL
:
sprintf
(
buf
,
"%.*lf"
,
jvp
->
Nd
,
*
(
double
*
)
MakePtr
(
base
,
jvp
->
To_Val
));
return
jp
->
WriteStr
(
buf
);
case
TYPE_NULL
:
return
jp
->
WriteStr
(
"null"
);
default:
return
jp
->
WriteStr
(
"???"
);
// TODO
}
// endswitch Type
strcpy
(
jp
->
g
->
Message
,
"Unrecognized value"
);
return
true
;
}
// end of SerializeValue
#if 0
/* -------------------------- Class JOBJECT -------------------------- */
/***********************************************************************/
/* Return the number of pairs in this object. */
/***********************************************************************/
int JOBJECT::GetSize(bool b) {
int n = 0;
for (PJPR jpp = First; jpp; jpp = jpp->Next)
// If b return only non null pairs
if (!b || jpp->Val && !jpp->Val->IsNull())
n++;
return n;
} // end of GetSize
/***********************************************************************/
/* Add a new pair to an Object. */
/***********************************************************************/
PJPR JOBJECT::AddPair(PGLOBAL g, PCSZ key) {
PJPR jpp = (PJPR)PlugSubAlloc(g, NULL, sizeof(JPAIR));
jpp->Key = key;
jpp->Next = NULL;
jpp->Val = NULL;
if (Last)
Last->Next = jpp;
else
First = jpp;
Last = jpp;
return jpp;
} // end of AddPair
/***********************************************************************/
/* Return all keys as an array. */
/***********************************************************************/
PJAR JOBJECT::GetKeyList(PGLOBAL g) {
PJAR jarp = new(g) JARRAY();
for (PJPR jpp = First; jpp; jpp = jpp->Next)
jarp->AddArrayValue(g, new(g) JVALUE(g, jpp->Key));
jarp->InitArray(g);
return jarp;
} // end of GetKeyList
/***********************************************************************/
/* Return all values as an array. */
/***********************************************************************/
PJAR JOBJECT::GetValList(PGLOBAL g) {
PJAR jarp = new(g) JARRAY();
for (PJPR jpp = First; jpp; jpp = jpp->Next)
jarp->AddArrayValue(g, jpp->Val);
jarp->InitArray(g);
return jarp;
} // end of GetValList
/***********************************************************************/
/* Get the value corresponding to the given key. */
/***********************************************************************/
PJVAL JOBJECT::GetKeyValue(const char* key) {
for (PJPR jp = First; jp; jp = jp->Next)
if (!strcmp(jp->Key, key))
return jp->Val;
return NULL;
} // end of GetValue;
/***********************************************************************/
/* Return the text corresponding to all keys (XML like). */
/***********************************************************************/
PSZ JOBJECT::GetText(PGLOBAL g, PSTRG text) {
if (First) {
bool b;
if (!text) {
text = new(g) STRING(g, 256);
b = true;
} else {
if (text->GetLastChar() != ' ')
text->Append(' ');
b = false;
} // endif text
if (b && !First->Next && !strcmp(First->Key, "$date")) {
int i;
PSZ s;
First->Val->GetText(g, text);
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
} else for (PJPR jp = First; jp; jp = jp->Next) {
jp->Val->GetText(g, text);
if (jp->Next)
text->Append(' ');
} // endfor jp
if (b) {
text->Trim();
return text->GetStr();
} // endif b
} // endif First
return NULL;
} // end of GetText;
/***********************************************************************/
/* Merge two objects. */
/***********************************************************************/
bool JOBJECT::Merge(PGLOBAL g, PJSON jsp) {
if (jsp->GetType() != TYPE_JOB) {
strcpy(g->Message, "Second argument is not an object");
return true;
} // endif Type
PJOB jobp = (PJOB)jsp;
for (PJPR jpp = jobp->First; jpp; jpp = jpp->Next)
SetKeyValue(g, jpp->Val, jpp->Key);
return false;
} // end of Marge;
/***********************************************************************/
/* Set or add a value corresponding to the given key. */
/***********************************************************************/
void JOBJECT::SetKeyValue(PGLOBAL g, PJVAL jvp, PCSZ key) {
PJPR jp;
for (jp = First; jp; jp = jp->Next)
if (!strcmp(jp->Key, key)) {
jp->Val = jvp;
break;
} // endif key
if (!jp) {
jp = AddPair(g, key);
jp->Val = jvp;
} // endif jp
} // end of SetValue
/***********************************************************************/
/* Delete a value corresponding to the given key. */
/***********************************************************************/
void JOBJECT::DeleteKey(PCSZ key) {
PJPR jp, * pjp = &First;
for (jp = First; jp; jp = jp->Next)
if (!strcmp(jp->Key, key)) {
*pjp = jp->Next;
break;
} else
pjp = &jp->Next;
} // end of DeleteKey
/***********************************************************************/
/* True if void or if all members are nulls. */
/***********************************************************************/
bool JOBJECT::IsNull(void) {
for (PJPR jp = First; jp; jp = jp->Next)
if (!jp->Val->IsNull())
return false;
return true;
} // end of IsNull
/* -------------------------- Class JARRAY --------------------------- */
/***********************************************************************/
/* JARRAY constructor. */
/***********************************************************************/
JARRAY::JARRAY(void) : JSON() {
Type = TYPE_JAR;
Size = 0;
Alloc = 0;
First = Last = NULL;
Mvals = NULL;
} // end of JARRAY constructor
/***********************************************************************/
/* Return the number of values in this object. */
/***********************************************************************/
int JARRAY::GetSize(bool b) {
if (b) {
// Return only non null values
int n = 0;
for (PJVAL jvp = First; jvp; jvp = jvp->Next)
if (!jvp->IsNull())
n++;
return n;
} else
return Size;
} // end of GetSize
/***********************************************************************/
/* Make the array of values from the values list. */
/***********************************************************************/
void JARRAY::InitArray(PGLOBAL g) {
int i;
PJVAL jvp, * pjvp = &First;
for (Size = 0, jvp = First; jvp; jvp = jvp->Next)
if (!jvp->Del)
Size++;
if (Size > Alloc) {
// No need to realloc after deleting values
Mvals = (PJVAL*)PlugSubAlloc(g, NULL, Size * sizeof(PJVAL));
Alloc = Size;
} // endif Size
for (i = 0, jvp = First; jvp; jvp = jvp->Next)
if (!jvp->Del) {
Mvals[i++] = jvp;
pjvp = &jvp->Next;
Last = jvp;
} else
*pjvp = jvp->Next;
} // end of InitArray
/***********************************************************************/
/* Get the Nth value of an Array. */
/***********************************************************************/
PJVAL JARRAY::GetArrayValue(int i) {
if (Mvals && i >= 0 && i < Size)
return Mvals[i];
else
return NULL;
} // end of GetValue
/***********************************************************************/
/* Add a Value to the Array Value list. */
/***********************************************************************/
PJVAL JARRAY::AddArrayValue(PGLOBAL g, PJVAL jvp, int* x) {
if (!jvp)
jvp = new(g) JVALUE;
if (x) {
int i = 0, n = *x;
PJVAL jp, * jpp = &First;
for (jp = First; jp && i < n; i++, jp = *(jpp = &jp->Next));
(*jpp) = jvp;
if (!(jvp->Next = jp))
Last = jvp;
} else {
if (!First)
First = jvp;
else if (Last == First)
First->Next = Last = jvp;
else
Last->Next = jvp;
Last = jvp;
Last->Next = NULL;
} // endif x
return jvp;
} // end of AddValue
/***********************************************************************/
/* Merge two arrays. */
/***********************************************************************/
bool JARRAY::Merge(PGLOBAL g, PJSON jsp) {
if (jsp->GetType() != TYPE_JAR) {
strcpy(g->Message, "Second argument is not an array");
return true;
} // endif Type
PJAR arp = (PJAR)jsp;
for (int i = 0; i < arp->size(); i++)
AddArrayValue(g, arp->GetArrayValue(i));
InitArray(g);
return false;
} // end of Merge
/***********************************************************************/
/* Set the nth Value of the Array Value list. */
/***********************************************************************/
bool JARRAY::SetArrayValue(PGLOBAL g, PJVAL jvp, int n) {
int i = 0;
PJVAL jp, * jpp = &First;
for (jp = First; i < n; i++, jp = *(jpp = &jp->Next))
if (!jp)
*jpp = jp = new(g) JVALUE;
*jpp = jvp;
jvp->Next = (jp ? jp->Next : NULL);
return false;
} // end of SetValue
/***********************************************************************/
/* Return the text corresponding to all values. */
/***********************************************************************/
PSZ JARRAY::GetText(PGLOBAL g, PSTRG text) {
if (First) {
bool b;
PJVAL jp;
if (!text) {
text = new(g) STRING(g, 256);
b = true;
} else {
if (text->GetLastChar() != ' ')
text->Append(" (");
else
text->Append('(');
b = false;
}
for (jp = First; jp; jp = jp->Next) {
jp->GetText(g, text);
if (jp->Next)
text->Append(", ");
else if (!b)
text->Append(')');
} // endfor jp
if (b) {
text->Trim();
return text->GetStr();
} // endif b
} // endif First
return NULL;
} // end of GetText;
/***********************************************************************/
/* Delete a Value from the Arrays Value list. */
/***********************************************************************/
bool JARRAY::DeleteValue(int n) {
PJVAL jvp = GetArrayValue(n);
if (jvp) {
jvp->Del = true;
return false;
} else
return true;
} // end of DeleteValue
/***********************************************************************/
/* True if void or if all members are nulls. */
/***********************************************************************/
bool JARRAY::IsNull(void) {
for (int i = 0; i < Size; i++)
if (!Mvals[i]->IsNull())
return false;
return true;
} // end of IsNull
/* -------------------------- Class JVALUE- -------------------------- */
/***********************************************************************/
/* Constructor for a JVALUE. */
/***********************************************************************/
JVALUE::JVALUE(PJSON jsp) : JSON() {
if (jsp->GetType() == TYPE_JVAL) {
PJVAL jvp = (PJVAL)jsp;
// Val = ((PJVAL)jsp)->GetVal();
if (jvp->DataType == TYPE_JSON) {
Jsp = jvp->GetJsp();
DataType = TYPE_JSON;
Nd = 0;
} else {
LLn = jvp->LLn; // Must be LLn on 32 bit machines
Nd = jvp->Nd;
DataType = jvp->DataType;
} // endelse Jsp
} else {
Jsp = jsp;
// Val = NULL;
DataType = TYPE_JSON;
Nd = 0;
} // endif Type
Next = NULL;
Del = false;
Type = TYPE_JVAL;
} // end of JVALUE constructor
#if 0
/***********************************************************************/
/* Constructor for a JVALUE with a given string or numeric value. */
/***********************************************************************/
JVALUE::JVALUE(PGLOBAL g, PVL vlp) : JSON() {
Jsp = NULL;
Val = vlp;
Next = NULL;
Del = false;
Type = TYPE_JVAL;
} // end of JVALUE constructor
#endif // 0
/***********************************************************************/
/* Constructor for a JVALUE with a given string or numeric value. */
/***********************************************************************/
JVALUE::JVALUE(PGLOBAL g, PVAL valp) : JSON() {
Jsp = NULL;
//Val = NULL;
SetValue(g, valp);
Next = NULL;
Del = false;
Type = TYPE_JVAL;
} // end of JVALUE constructor
/***********************************************************************/
/* Constructor for a given string. */
/***********************************************************************/
JVALUE::JVALUE(PGLOBAL g, PCSZ strp) : JSON() {
Jsp = NULL;
//Val = AllocVal(g, TYPE_STRG);
Strp = (char*)strp;
DataType = TYPE_STRG;
Nd = 0;
Next = NULL;
Del = false;
Type = TYPE_JVAL;
} // end of JVALUE constructor
/***********************************************************************/
/* Set or reset all Jvalue members. */
/***********************************************************************/
void JVALUE::Clear(void) {
Jsp = NULL;
Next = NULL;
Type = TYPE_JVAL;
Del = false;
Nd = 0;
DataType = TYPE_NULL;
} // end of Clear
/***********************************************************************/
/* Returns the type of the Value's value. */
/***********************************************************************/
JTYP JVALUE::GetValType(void) {
if (DataType == TYPE_JSON)
return Jsp->GetType();
//else if (Val)
// return Val->Type;
else
return DataType;
} // end of GetValType
/***********************************************************************/
/* Return the Value's Object value. */
/***********************************************************************/
PJOB JVALUE::GetObject(void) {
if (DataType == TYPE_JSON && Jsp->GetType() == TYPE_JOB)
return (PJOB)Jsp;
return NULL;
} // end of GetObject
/***********************************************************************/
/* Return the Value's Array value. */
/***********************************************************************/
PJAR JVALUE::GetArray(void) {
if (DataType == TYPE_JSON && Jsp->GetType() == TYPE_JAR)
return (PJAR)Jsp;
return NULL;
} // end of GetArray
/***********************************************************************/
/* Return the Value's as a Value class. */
/***********************************************************************/
PVAL JVALUE::GetValue(PGLOBAL g) {
PVAL valp = NULL;
if (DataType != TYPE_JSON)
if (DataType == TYPE_STRG)
valp = AllocateValue(g, Strp, DataType, Nd);
else
valp = AllocateValue(g, &LLn, DataType, Nd);
return valp;
} // end of GetValue
/***********************************************************************/
/* Return the Value's Integer value. */
/***********************************************************************/
int JVALUE::GetInteger(void) {
int n;
switch (DataType) {
case TYPE_INTG: n = N; break;
case TYPE_DBL: n = (int)F; break;
case TYPE_DTM:
case TYPE_STRG: n = atoi(Strp); break;
case TYPE_BOOL: n = (B) ? 1 : 0; break;
case TYPE_BINT: n = (int)LLn; break;
default:
n = 0;
} // endswitch Type
return n;
} // end of GetInteger
/***********************************************************************/
/* Return the Value's Big integer value. */
/***********************************************************************/
long long JVALUE::GetBigint(void) {
long long lln;
switch (DataType) {
case TYPE_BINT: lln = LLn; break;
case TYPE_INTG: lln = (long long)N; break;
case TYPE_DBL: lln = (long long)F; break;
case TYPE_DTM:
case TYPE_STRG: lln = atoll(Strp); break;
case TYPE_BOOL: lln = (B) ? 1 : 0; break;
default:
lln = 0;
} // endswitch Type
return lln;
} // end of GetBigint
/***********************************************************************/
/* Return the Value's Double value. */
/***********************************************************************/
double JVALUE::GetFloat(void) {
double d;
switch (DataType) {
case TYPE_DBL: d = F; break;
case TYPE_BINT: d = (double)LLn; break;
case TYPE_INTG: d = (double)N; break;
case TYPE_DTM:
case TYPE_STRG: d = atof(Strp); break;
case TYPE_BOOL: d = (B) ? 1.0 : 0.0; break;
default:
d = 0.0;
} // endswitch Type
return d;
} // end of GetFloat
/***********************************************************************/
/* Return the Value's String value. */
/***********************************************************************/
PSZ JVALUE::GetString(PGLOBAL g, char* buff) {
char buf[32];
char* p = (buff) ? buff : buf;
switch (DataType) {
case TYPE_DTM:
case TYPE_STRG:
p = Strp;
break;
case TYPE_INTG:
sprintf(p, "%d", N);
break;
case TYPE_BINT:
sprintf(p, "%lld", LLn);
break;
case TYPE_DBL:
sprintf(p, "%.*lf", Nd, F);
break;
case TYPE_BOOL:
p = (char*)((B) ? "true" : "false");
break;
case TYPE_NULL:
p = (char*)"null";
break;
default:
p = NULL;
} // endswitch Type
return (p == buf) ? (char*)PlugDup(g, buf) : p;
} // end of GetString
/***********************************************************************/
/* Return the Value's String value. */
/***********************************************************************/
PSZ JVALUE::GetText(PGLOBAL g, PSTRG text) {
if (DataType == TYPE_JSON)
return Jsp->GetText(g, text);
char buff[32];
PSZ s = (DataType == TYPE_NULL) ? NULL : GetString(g, buff);
if (s)
text->Append(s);
else if (GetJsonNull())
text->Append(GetJsonNull());
return NULL;
} // end of GetText
void JVALUE::SetValue(PJSON jsp) {
if (DataType == TYPE_JSON && jsp->GetType() == TYPE_JVAL) {
Jsp = jsp->GetJsp();
Nd = ((PJVAL)jsp)->Nd;
DataType = ((PJVAL)jsp)->DataType;
// Val = ((PJVAL)jsp)->GetVal();
} else {
Jsp = jsp;
DataType = TYPE_JSON;
} // endif Type
} // end of SetValue;
void JVALUE::SetValue(PGLOBAL g, PVAL valp) {
//if (!Val)
// Val = AllocVal(g, TYPE_VAL);
if (!valp || valp->IsNull()) {
DataType = TYPE_NULL;
} else switch (valp->GetType()) {
case TYPE_DATE:
if (((DTVAL*)valp)->IsFormatted())
Strp = valp->GetCharValue();
else {
char buf[32];
Strp = PlugDup(g, valp->GetCharString(buf));
} // endif Formatted
DataType = TYPE_DTM;
break;
case TYPE_STRING:
Strp = valp->GetCharValue();
DataType = TYPE_STRG;
break;
case TYPE_DOUBLE:
case TYPE_DECIM:
F = valp->GetFloatValue();
if (IsTypeNum(valp->GetType()))
Nd = valp->GetValPrec();
DataType = TYPE_DBL;
break;
case TYPE_TINY:
B = valp->GetTinyValue() != 0;
DataType = TYPE_BOOL;
case TYPE_INT:
N = valp->GetIntValue();
DataType = TYPE_INTG;
break;
case TYPE_BIGINT:
LLn = valp->GetBigintValue();
DataType = TYPE_BINT;
break;
default:
sprintf(g->Message, "Unsupported typ %d\n", valp->GetType());
throw(777);
} // endswitch Type
} // end of SetValue
/***********************************************************************/
/* Set the Value's value as the given integer. */
/***********************************************************************/
void JVALUE::SetInteger(PGLOBAL g, int n) {
N = n;
DataType = TYPE_INTG;
} // end of SetInteger
/***********************************************************************/
/* Set the Value's Boolean value as a tiny integer. */
/***********************************************************************/
void JVALUE::SetBool(PGLOBAL g, bool b) {
B = b;
DataType = TYPE_BOOL;
} // end of SetTiny
/***********************************************************************/
/* Set the Value's value as the given big integer. */
/***********************************************************************/
void JVALUE::SetBigint(PGLOBAL g, long long ll) {
LLn = ll;
DataType = TYPE_BINT;
} // end of SetBigint
/***********************************************************************/
/* Set the Value's value as the given DOUBLE. */
/***********************************************************************/
void JVALUE::SetFloat(PGLOBAL g, double f) {
F = f;
Nd = 6;
DataType = TYPE_DBL;
} // end of SetFloat
/***********************************************************************/
/* Set the Value's value as the given string. */
/***********************************************************************/
void JVALUE::SetString(PGLOBAL g, PSZ s, int ci) {
Strp = s;
Nd = ci;
DataType = TYPE_STRG;
} // end of SetString
/***********************************************************************/
/* True when its JSON or normal value is null. */
/***********************************************************************/
bool JVALUE::IsNull(void) {
return (DataType == TYPE_JSON) ? Jsp->IsNull() : DataType == TYPE_NULL;
} // end of IsNull
#endif // 0
storage/connect/bson.h
0 → 100644
View file @
477b5256
#pragma once
/**************** bson H Declares Source Code File (.H) ****************/
/* Name: bson.h Version 1.0 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 2020 */
/* */
/* This file contains the BSON classe declares. */
/***********************************************************************/
#include <mysql_com.h>
#include "json.h"
#include "xobject.h"
#if defined(_DEBUG)
#define X assert(false);
#else
#define X
#endif
class
BDOC
;
class
BOUT
;
//class JSON;
typedef
class
BDOC
*
PBDOC
;
//typedef class BJSON* PBSON;
// BSON size should be equal on Linux and Windows
#define BMX 255
typedef
uint
OFFSET
;
/***********************************************************************/
/* Structure JVALUE. */
/***********************************************************************/
typedef
struct
_jvalue
{
union
{
OFFSET
To_Val
;
// Offset to a value
int
N
;
// An integer value
float
F
;
// A float value
bool
B
;
// A boolean value True or false (0)
};
short
Nd
;
// Number of decimals
JTYP
Type
;
// The value type
OFFSET
Next
;
// Offset to the next value in array
}
BVAL
,
*
PBVAL
;
// end of struct BVALUE
/***********************************************************************/
/* Structure JPAIR. The pairs of a json Object. */
/***********************************************************************/
typedef
struct
_jpair
{
OFFSET
Key
;
// Offset to this pair key name
OFFSET
Vlp
;
// To the value of the pair
OFFSET
Next
;
// Offset to the next pair in object
}
BPAIR
,
*
PBPR
;
// end of struct BPAIR
#if 0
/***********************************************************************/
/* Structure used to return binary json to Json UDF functions. */
/* (should be moved to jsonudf.h). */
/***********************************************************************/
typedef struct _JsonBin {
char Msg[BMX + 1];
char *Filename;
PGLOBAL G;
int Pretty;
ulong Reslen;
my_bool Changed;
PBSON Top;
PBSON Jsp;
PBJN Bsp;
} BJSON, *PBJN ; // end of struct BJSON
PBJN JbinAlloc(PGLOBAL g, UDF_ARGS* args, ulong len, PJSON jsp);
#endif // 0
char
*
NextChr
(
PSZ
s
,
char
sep
);
char
*
GetJsonNull
(
void
);
const
char
*
GetFmt
(
int
type
,
bool
un
);
DllExport
bool
IsNum
(
PSZ
s
);
/***********************************************************************/
/* Class JDOC. The class for parsing and serializing json documents. */
/***********************************************************************/
class
BDOC
:
public
BLOCK
{
public:
BDOC
(
void
);
void
*
BsonSubAlloc
(
PGLOBAL
g
,
size_t
size
);
PBPR
SubAllocPair
(
PGLOBAL
g
,
OFFSET
key
);
PBVAL
SubAllocVal
(
PGLOBAL
g
);
PBVAL
ParseJson
(
PGLOBAL
g
,
char
*
s
,
size_t
n
,
int
*
prty
=
NULL
,
bool
*
b
=
NULL
);
PSZ
Serialize
(
PGLOBAL
g
,
PBVAL
bvp
,
char
*
fn
,
int
pretty
);
protected:
OFFSET
ParseArray
(
PGLOBAL
g
,
int
&
i
);
OFFSET
ParseObject
(
PGLOBAL
g
,
int
&
i
);
PBVAL
ParseValue
(
PGLOBAL
g
,
int
&
i
);
OFFSET
ParseString
(
PGLOBAL
g
,
int
&
i
);
void
ParseNumeric
(
PGLOBAL
g
,
int
&
i
,
PBVAL
bvp
);
OFFSET
ParseAsArray
(
PGLOBAL
g
,
int
&
i
,
int
pretty
,
int
*
ptyp
);
bool
SerializeArray
(
OFFSET
arp
,
bool
b
);
bool
SerializeObject
(
OFFSET
obp
);
bool
SerializeValue
(
PBVAL
vp
);
// Members used when parsing and serializing
private:
JOUT
*
jp
;
// Used with serialize
void
*
base
;
// The base for making offsets or pointers
char
*
s
;
// The Json string to parse
int
len
;
// The Json string length
bool
pty
[
3
];
// Used to guess what pretty is
};
// end of class BDOC
#if 0
/***********************************************************************/
/* Class BJSON. The class handling all BSON operations. */
/***********************************************************************/
class BJSON : public BLOCK {
public:
// Constructor
BJSON(PBVAL vp, void* base) { Vlp = vp; Base = base; }
// Array functions
int GetSize(bool b);
PBVAL GetArrayValue(int i);
PSZ GetText(PGLOBAL g, PSTRG text);
bool Merge(PGLOBAL g, PBVAL jsp);
bool DeleteValue(int n);
PBVAL AddArrayValue(PGLOBAL g, PBVAL jvp = NULL, int* x = NULL);
bool SetArrayValue(PGLOBAL g, PBVAL jvp, int i);
// Object functions
int GetObjectSize(PBPR prp, bool b);
PSZ GetObjectText(PGLOBAL g, PBPR prp, PSTRG text);
bool MergeObject(PGLOBAL g, PBPR prp);
PJPR AddPair(PGLOBAL g, PCSZ key);
PJVAL GetKeyValue(const char* key);
PJAR GetKeyList(PGLOBAL g);
PJAR GetValList(PGLOBAL g);
void SetKeyValue(PGLOBAL g, PBVAL jvp, PCSZ key);
void DeleteKey(PCSZ k);
// Value functions
PBPR GetObject(void);
PBVAL GetArray(void);
PJSON GetJsp(void) { return (DataType == TYPE_JSON ? Jsp : NULL); }
PSZ GetValueText(PGLOBAL g, PSTRG text);
inline PJSON GetJson(void) { return (DataType == TYPE_JSON ? Jsp : this); }
PSZ GetString(PGLOBAL g, char* buff = NULL);
int GetInteger(void);
long long GetBigint(void);
double GetFloat(void);
PVAL GetValue(PGLOBAL g);
void SetValue(PJSON jsp);
void SetValue(PGLOBAL g, PVAL valp);
void SetString(PGLOBAL g, PSZ s, int ci = 0);
void SetInteger(PGLOBAL g, int n);
void SetBigint(PGLOBAL g, longlong ll);
void SetFloat(PGLOBAL g, double f);
void SetBool(PGLOBAL g, bool b);
// Members
PBVAL Vlp;
void* Base;
}; // end of class BJSON
/***********************************************************************/
/* Class JOBJECT: contains a list of value pairs. */
/***********************************************************************/
class JOBJECT : public JSON {
friend class JDOC;
friend class JSNX;
friend class SWAP;
public:
JOBJECT(void) : JSON() { Type = TYPE_JOB; First = Last = NULL; }
JOBJECT(int i) : JSON(i) {}
// Methods
virtual void Clear(void) { First = Last = NULL; }
virtual PJPR GetFirst(void) { return First; }
virtual int GetSize(PBPR prp, bool b);
virtual PJOB GetObject(void) { return this; }
virtual PSZ GetText(PGLOBAL g, PSTRG text);
virtual bool Merge(PGLOBAL g, PJSON jsp);
virtual bool IsNull(void);
// Specific
PJPR AddPair(PGLOBAL g, PCSZ key);
PJVAL GetKeyValue(const char* key);
PJAR GetKeyList(PGLOBAL g);
PJAR GetValList(PGLOBAL g);
void SetKeyValue(PGLOBAL g, PJVAL jvp, PCSZ key);
void DeleteKey(PCSZ k);
protected:
PJPR First;
PJPR Last;
}; // end of class JOBJECT
/***********************************************************************/
/* Class JARRAY. */
/***********************************************************************/
class JARRAY : public JSON {
friend class SWAP;
public:
JARRAY(void);
JARRAY(int i) : JSON(i) {}
// Methods
virtual void Clear(void) { First = Last = NULL; Size = 0; }
virtual int size(void) { return Size; }
virtual PJAR GetArray(void) { return this; }
virtual int GetSize(bool b);
virtual PJVAL GetArrayValue(int i);
virtual PSZ GetText(PGLOBAL g, PSTRG text);
virtual bool Merge(PGLOBAL g, PJSON jsp);
virtual bool DeleteValue(int n);
virtual bool IsNull(void);
// Specific
PJVAL AddArrayValue(PGLOBAL g, PJVAL jvp = NULL, int* x = NULL);
bool SetArrayValue(PGLOBAL g, PJVAL jvp, int i);
void InitArray(PGLOBAL g);
protected:
// Members
int Size; // The number of items in the array
int Alloc; // The Mvals allocated size
PJVAL First; // Used when constructing
PJVAL Last; // Last constructed value
PJVAL* Mvals; // Allocated when finished
}; // end of class JARRAY
/***********************************************************************/
/* Class JVALUE. */
/***********************************************************************/
class JVALUE : public JSON {
friend class JARRAY;
friend class JSNX;
friend class JSONDISC;
friend class JSONCOL;
friend class JSON;
friend class JDOC;
friend class SWAP;
public:
JVALUE(void) : JSON() { Type = TYPE_JVAL; Clear(); }
JVALUE(PJSON jsp);
JVALUE(PGLOBAL g, PVAL valp);
JVALUE(PGLOBAL g, PCSZ strp);
JVALUE(int i) : JSON(i) {}
// Methods
virtual void Clear(void);
//virtual JTYP GetType(void) {return TYPE_JVAL;}
virtual JTYP GetValType(void);
virtual PJOB GetObject(void);
virtual PJAR GetArray(void);
virtual PJSON GetJsp(void) { return (DataType == TYPE_JSON ? Jsp : NULL); }
virtual PSZ GetText(PGLOBAL g, PSTRG text);
virtual bool IsNull(void);
// Specific
inline PJSON GetJson(void) { return (DataType == TYPE_JSON ? Jsp : this); }
PSZ GetString(PGLOBAL g, char* buff = NULL);
int GetInteger(void);
long long GetBigint(void);
double GetFloat(void);
PVAL GetValue(PGLOBAL g);
void SetValue(PJSON jsp);
void SetValue(PGLOBAL g, PVAL valp);
void SetString(PGLOBAL g, PSZ s, int ci = 0);
void SetInteger(PGLOBAL g, int n);
void SetBigint(PGLOBAL g, longlong ll);
void SetFloat(PGLOBAL g, double f);
void SetBool(PGLOBAL g, bool b);
protected:
union {
PJSON Jsp; // To the json value
char* Strp; // Ptr to a string
int N; // An integer value
long long LLn; // A big integer value
double F; // A (double) float value
bool B; // True or false
};
PJVAL Next; // Next value in array
JTYP DataType; // The data value type
int Nd; // Decimal number
bool Del; // True when deleted
}; // end of class JVALUE
#endif // 0
storage/connect/json.h
View file @
477b5256
...
...
@@ -15,18 +15,22 @@
#define X
#endif
enum
JTYP
{
TYPE_NULL
=
TYPE_VOID
,
enum
JTYP
:
short
{
TYPE_NULL
=
TYPE_VOID
,
TYPE_STRG
=
TYPE_STRING
,
TYPE_DBL
=
TYPE_DOUBLE
,
TYPE_BOOL
=
TYPE_TINY
,
TYPE_BINT
=
TYPE_BIGINT
,
TYPE_DTM
=
TYPE_DATE
,
TYPE_INTG
=
TYPE_INT
,
TYPE_VAL
=
12
,
TYPE_JSON
,
TYPE_DTM
=
TYPE_DATE
,
TYPE_FLOAT
,
TYPE_JAR
,
TYPE_JOB
,
TYPE_JVAL
};
TYPE_JVAL
,
TYPE_JSON
,
TYPE_DEL
,
TYPE_UNKNOWN
};
class
JDOC
;
class
JOUT
;
...
...
storage/connect/jsonudf.cpp
View file @
477b5256
...
...
@@ -1252,9 +1252,9 @@ static PJVAL JvalNew(PGLOBAL g, JTYP type, void *vp)
case
TYPE_JOB
:
jvp
=
new
(
g
)
JVALUE
((
PJSON
)
vp
);
break
;
case
TYPE_VAL
:
jvp
=
new
(
g
)
JVALUE
(
g
,
(
PVAL
)
vp
);
break
;
//
case TYPE_VAL:
//
jvp = new(g) JVALUE(g, (PVAL)vp);
//
break;
case
TYPE_DTM
:
case
TYPE_STRG
:
jvp
=
new
(
g
)
JVALUE
(
g
,
(
PCSZ
)
vp
);
...
...
@@ -5376,7 +5376,7 @@ char *jbin_get_item(UDF_INIT *initid, UDF_ARGS *args, char *result,
// Get the json tree
if
((
jvp
=
jsx
->
GetRowValue
(
g
,
jsp
,
0
,
false
)))
{
jsp
=
(
jvp
->
GetJsp
())
?
jvp
->
GetJsp
()
:
JvalNew
(
g
,
TYPE_VAL
,
jvp
->
GetValue
(
g
));
jsp
=
(
jvp
->
GetJsp
())
?
jvp
->
GetJsp
()
:
JvalNew
(
g
,
TYPE_
J
VAL
,
jvp
->
GetValue
(
g
));
if
((
bsp
=
JbinAlloc
(
g
,
args
,
initid
->
max_length
,
jsp
)))
strcat
(
bsp
->
Msg
,
" item"
);
...
...
storage/connect/jsonudf.h
View file @
477b5256
...
...
@@ -10,7 +10,7 @@
#include "block.h"
#include "osutil.h"
#include "maputil.h"
#include "
j
son.h"
#include "
b
son.h"
#define UDF_EXEC_ARGS \
UDF_INIT*, UDF_ARGS*, char*, unsigned long*, char*, char*
...
...
storage/connect/myutil.cpp
View file @
477b5256
...
...
@@ -168,10 +168,9 @@ const char *PLGtoMYSQLtype(int type, bool dbf, char v)
case
TYPE_BIGINT
:
return
"BIGINT"
;
case
TYPE_TINY
:
return
"TINYINT"
;
case
TYPE_DECIM
:
return
"DECIMAL"
;
default:
return
"CHAR(0)
"
;
default:
return
(
v
)
?
"VARCHAR"
:
"CHAR
"
;
}
// endswitch mytype
return
"CHAR(0)"
;
}
// end of PLGtoMYSQLtype
/************************************************************************/
...
...
storage/connect/tabfmt.cpp
View file @
477b5256
...
...
@@ -67,7 +67,7 @@
/* This should be an option. */
/***********************************************************************/
#define MAXCOL 200
/* Default max column nb in result */
#define TYPE_UNKNOWN 1
0
/* Must be greater than other types */
#define TYPE_UNKNOWN 1
2
/* Must be greater than other types */
/***********************************************************************/
/* External function. */
...
...
storage/connect/tabjson.cpp
View file @
477b5256
...
...
@@ -46,7 +46,7 @@
/* This should be an option. */
/***********************************************************************/
#define MAXCOL 200
/* Default max column nb in result */
#define TYPE_UNKNOWN 12
/* Must be greater than other types */
//
#define TYPE_UNKNOWN 12 /* Must be greater than other types */
/***********************************************************************/
/* External functions. */
...
...
@@ -114,7 +114,7 @@ PQRYRES JSONColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt, bool info)
/*********************************************************************/
for
(
i
=
0
,
jcp
=
pjdc
->
fjcp
;
jcp
;
i
++
,
jcp
=
jcp
->
Next
)
{
if
(
jcp
->
Type
==
TYPE_UNKNOWN
)
jcp
->
Type
=
TYPE_STR
ING
;
// Void column
jcp
->
Type
=
TYPE_STR
G
;
// Void column
crp
=
qrp
->
Colresp
;
// Column Name
crp
->
Kdata
->
SetValue
(
jcp
->
Name
,
i
);
...
...
@@ -506,7 +506,7 @@ bool JSONDISC::Find(PGLOBAL g, PJVAL jvp, PCSZ key, int j)
}
else
if
(
JsonAllPath
()
&&
!
fmt
[
bf
])
strcat
(
fmt
,
colname
);
jcol
.
Type
=
TYPE_STR
IN
G
;
jcol
.
Type
=
TYPE_STRG
;
jcol
.
Len
=
sz
;
jcol
.
Scale
=
0
;
jcol
.
Cbn
=
true
;
...
...
@@ -528,23 +528,23 @@ void JSONDISC::AddColumn(PGLOBAL g)
if
(
jcp
)
{
if
(
jcp
->
Type
!=
jcol
.
Type
)
{
if
(
jcp
->
Type
==
TYPE_UNKNOWN
||
jc
ol
.
Type
==
TYPE_VOID
)
if
(
jcp
->
Type
==
TYPE_UNKNOWN
||
jc
p
->
Type
==
TYPE_NULL
)
jcp
->
Type
=
jcol
.
Type
;
// else if (jcol.Type != TYPE_UNKNOWN && jcol.Type != TYPE_VOID)
// jcp->Type = TYPE_STRING;
else
if
(
jcp
->
Type
!=
TYPE_STR
IN
G
)
else
if
(
jcp
->
Type
!=
TYPE_STRG
)
switch
(
jcol
.
Type
)
{
case
TYPE_STR
IN
G
:
case
TYPE_D
OUBLE
:
case
TYPE_STRG
:
case
TYPE_D
BL
:
jcp
->
Type
=
jcol
.
Type
;
break
;
case
TYPE_BI
GI
NT
:
if
(
jcp
->
Type
==
TYPE_INT
||
jcp
->
Type
==
TYPE_TINY
)
case
TYPE_BINT
:
if
(
jcp
->
Type
==
TYPE_INT
G
||
jcp
->
Type
==
TYPE_BOOL
)
jcp
->
Type
=
jcol
.
Type
;
break
;
case
TYPE_INT
:
if
(
jcp
->
Type
==
TYPE_
TINY
)
case
TYPE_INT
G
:
if
(
jcp
->
Type
==
TYPE_
BOOL
)
jcp
->
Type
=
jcol
.
Type
;
break
;
...
...
storage/connect/tabjson.h
View file @
477b5256
...
...
@@ -35,7 +35,7 @@ typedef struct _jncol {
struct
_jncol
*
Next
;
char
*
Name
;
char
*
Fmt
;
int
Type
;
JTYP
Type
;
int
Len
;
int
Scale
;
bool
Cbn
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment