Page Menu
Home
Phabricator (Chris)
Search
Configure Global Search
Log In
Files
F618260
bind_json.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Authored By
Unknown
Size
14 KB
Referenced Files
None
Subscribers
None
bind_json.cpp
View Options
#include
"rapidjson/document.h"
#include
"rapidjson/writer.h"
#include
"rapidjson/prettywriter.h"
#include
"util/refcount.h"
#include
<stdint.h>
#include
<string>
#include
<fstream>
#include
"main/initialization.h"
#include
"scripts/binds.h"
#include
"files.h"
#include
"threads.h"
#include
"manager.h"
namespace
scripts
{
class
StrOutputStream
{
public
:
std
::
string
value
;
StrOutputStream
()
{}
void
Put
(
char
c
)
{
value
+=
c
;
}
void
Flush
()
{}
};
static
Threaded
(
rapidjson
::
MemoryPoolAllocator
<>*
)
allocator
=
0
;
rapidjson
::
MemoryPoolAllocator
<>&
getAllocator
()
{
if
(
!
allocator
)
{
allocator
=
new
rapidjson
::
MemoryPoolAllocator
<>
();
addThreadCleanup
([]()
{
delete
allocator
;
allocator
=
0
;
});
}
return
*
allocator
;
}
class
JSONTree
:
public
AtomicRefCounted
{
public
:
rapidjson
::
Document
doc
;
void
parse
(
const
std
::
string
&
str
)
{
doc
.
Parse
<
0
>
(
str
.
c_str
());
}
void
readFile
(
const
std
::
string
&
fname
)
{
if
(
!
isAccessible
(
fname
))
{
scripts
::
throwException
(
"Cannot access file outside game or profile directories."
);
return
;
}
doc
.
Parse
<
0
>
(
getFileContents
(
fname
).
c_str
());
}
void
writeFile
(
const
std
::
string
&
fname
,
bool
pretty
)
{
if
(
!
isAccessible
(
fname
))
{
scripts
::
throwException
(
"Cannot access file outside game or profile directories."
);
return
;
}
std
::
fstream
file
(
fname
,
std
::
ios_base
::
out
);
file
<<
toString
(
pretty
);
}
std
::
string
toString
(
bool
pretty
)
{
StrOutputStream
stream
;
if
(
pretty
)
{
rapidjson
::
PrettyWriter
<
StrOutputStream
>
writer
(
stream
);
writer
.
SetIndent
(
'\t'
,
1
);
doc
.
Accept
(
writer
);
}
else
{
rapidjson
::
Writer
<
StrOutputStream
>
writer
(
stream
);
doc
.
Accept
(
writer
);
}
return
stream
.
value
;
}
rapidjson
::
Value
*
root
()
{
return
&
doc
;
}
};
static
JSONTree
*
makeJSONTree
()
{
return
new
JSONTree
();
}
static
std
::
string
nodeString
(
rapidjson
::
Value
*
node
)
{
if
(
!
node
->
IsString
())
{
scripts
::
throwException
(
"Node is not a string value."
);
return
""
;
}
return
std
::
string
(
node
->
GetString
());
}
static
int
nodeBool
(
rapidjson
::
Value
*
node
)
{
if
(
!
node
->
IsBool
())
{
scripts
::
throwException
(
"Node is not a boolean value."
);
return
0
;
}
return
node
->
GetBool
();
}
static
int
nodeInt
(
rapidjson
::
Value
*
node
)
{
if
(
!
node
->
IsInt
())
{
scripts
::
throwException
(
"Node is not an int value."
);
return
0
;
}
return
node
->
GetInt
();
}
static
unsigned
nodeUint
(
rapidjson
::
Value
*
node
)
{
if
(
!
node
->
IsUint
())
{
scripts
::
throwException
(
"Node is not a uint value."
);
return
0
;
}
return
node
->
GetUint
();
}
static
int64_t
nodeInt64
(
rapidjson
::
Value
*
node
)
{
if
(
!
node
->
IsInt64
())
{
scripts
::
throwException
(
"Node is not an int64 value."
);
return
0
;
}
return
node
->
GetInt64
();
}
static
uint64_t
nodeUint64
(
rapidjson
::
Value
*
node
)
{
if
(
!
node
->
IsUint64
())
{
scripts
::
throwException
(
"Node is not a uint64 value."
);
return
0
;
}
return
node
->
GetUint64
();
}
static
double
nodeDouble
(
rapidjson
::
Value
*
node
)
{
if
(
!
node
->
IsDouble
())
{
scripts
::
throwException
(
"Node is not a double value."
);
return
0
;
}
return
node
->
GetDouble
();
}
static
double
nodeNumber
(
rapidjson
::
Value
*
node
)
{
if
(
node
->
IsDouble
())
return
node
->
GetDouble
();
if
(
node
->
IsInt
())
return
(
double
)
node
->
GetInt
();
if
(
node
->
IsUint
())
return
(
double
)
node
->
GetUint
();
if
(
node
->
IsInt64
())
return
(
double
)
node
->
GetInt64
();
if
(
node
->
IsUint64
())
return
(
double
)
node
->
GetUint64
();
scripts
::
throwException
(
"Node is not a numeric value."
);
return
0
;
}
static
rapidjson
::
Value
*
findMember
(
rapidjson
::
Value
*
node
,
const
std
::
string
&
name
)
{
if
(
!
node
->
IsObject
())
{
scripts
::
throwException
(
"Node is not an object."
);
return
0
;
}
rapidjson
::
Value
::
Member
*
mem
=
node
->
FindMember
(
name
.
c_str
());
if
(
!
mem
)
return
0
;
return
&
mem
->
value
;
}
static
void
removeMember
(
rapidjson
::
Value
*
node
,
const
std
::
string
&
name
)
{
if
(
!
node
->
IsObject
())
{
scripts
::
throwException
(
"Node is not an object."
);
return
;
}
node
->
RemoveMember
(
name
.
c_str
());
}
static
rapidjson
::
Value
*
getMember
(
rapidjson
::
Value
*
node
,
const
std
::
string
&
name
)
{
if
(
!
node
->
IsObject
())
{
scripts
::
throwException
(
"Node is not an object."
);
return
0
;
}
rapidjson
::
Value
::
Member
*
mem
=
node
->
FindMember
(
name
.
c_str
());
if
(
mem
)
return
&
mem
->
value
;
rapidjson
::
Value
nullValue
;
node
->
AddMember
(
name
.
c_str
(),
getAllocator
(),
nullValue
,
getAllocator
());
return
findMember
(
node
,
name
);
}
static
void
clearItems
(
rapidjson
::
Value
*
node
)
{
if
(
!
node
->
IsArray
())
{
scripts
::
throwException
(
"Node is not an array."
);
return
;
}
node
->
Clear
();
}
static
rapidjson
::
Value
*
getItem
(
rapidjson
::
Value
*
node
,
unsigned
index
)
{
if
(
!
node
->
IsArray
())
{
scripts
::
throwException
(
"Node is not an array."
);
return
0
;
}
if
(
index
>=
node
->
Size
())
{
scripts
::
throwException
(
"Index out of bounds."
);
return
0
;
}
return
&
(
*
node
)[
index
];
}
static
unsigned
arrSize
(
rapidjson
::
Value
*
node
)
{
if
(
!
node
->
IsArray
())
{
scripts
::
throwException
(
"Node is not an array."
);
return
0
;
}
return
node
->
Size
();
}
static
void
arrReserve
(
rapidjson
::
Value
*
node
,
unsigned
amount
)
{
if
(
!
node
->
IsArray
())
{
scripts
::
throwException
(
"Node is not an array."
);
return
;
}
node
->
Reserve
(
amount
,
getAllocator
());
}
static
rapidjson
::
Value
*
arrPush
(
rapidjson
::
Value
*
node
)
{
if
(
!
node
->
IsArray
())
{
scripts
::
throwException
(
"Node is not an array."
);
return
0
;
}
rapidjson
::
Value
nullValue
;
node
->
PushBack
(
nullValue
,
getAllocator
());
return
&
(
*
node
)[
node
->
Size
()
-
1
];
}
static
void
arrPop
(
rapidjson
::
Value
*
node
)
{
if
(
!
node
->
IsArray
())
{
scripts
::
throwException
(
"Node is not an array."
);
return
;
}
node
->
PopBack
();
}
static
rapidjson
::
Value
*
setString
(
rapidjson
::
Value
*
node
,
const
std
::
string
&
value
)
{
node
->
SetString
(
value
.
c_str
(),
value
.
size
(),
getAllocator
());
return
node
;
}
void
RegisterJSONBinds
()
{
ClassBind
node
(
"JSONNode"
,
asOBJ_REF
|
asOBJ_NOCOUNT
);
classdoc
(
node
,
"A node within a json tree. Careful when holding references, as"
" changes to the tree can invalidate them."
);
//* Tree methods *//
ClassBind
tree
(
"JSONTree"
,
asOBJ_REF
);
classdoc
(
tree
,
"Represents a tree of json nodes that can be altered."
" Please make note that JSONNode@ references are not reference counted,"
" and can be invalidated by changes to the tree. Do not hold references"
" unless you know what you're doing."
);
tree
.
addFactory
(
"JSONTree@ f()"
,
asFUNCTION
(
makeJSONTree
));
tree
.
setReferenceFuncs
(
asMETHOD
(
JSONTree
,
grab
),
asMETHOD
(
JSONTree
,
drop
));
tree
.
addMethod
(
"void parse(const string& data)"
,
asMETHOD
(
JSONTree
,
parse
))
doc
(
"Parse a json tree from string data."
,
"Data string to parse."
);
tree
.
addMethod
(
"void readFile(const string& filename)"
,
asMETHOD
(
JSONTree
,
readFile
))
doc
(
"Read a json tree from a file."
,
"Filename of the file to read from."
);
tree
.
addMethod
(
"string toString(bool pretty = false)"
,
asMETHOD
(
JSONTree
,
toString
))
doc
(
"Dump the json tree to a string."
,
"Whether to pretty-print with newlines and indentation."
,
"Output data string."
);
tree
.
addMethod
(
"void writeFile(const string& filename, bool pretty = false)"
,
asMETHOD
(
JSONTree
,
writeFile
))
doc
(
"Write a json tree to a file."
,
"Filename of the file to write to."
,
"Whether to pretty-print with newlines and indentation."
);
tree
.
addMethod
(
"JSONNode@ get_root()"
,
asMETHOD
(
JSONTree
,
root
))
doc
(
""
,
"The root json node in this tree."
);
//* Node methods *//
node
.
addMethod
(
"bool isNull()"
,
asMETHOD
(
rapidjson
::
Value
,
IsNull
))
doc
(
""
,
"Whether the node is a null."
);
node
.
addMethod
(
"bool isFalse()"
,
asMETHOD
(
rapidjson
::
Value
,
IsFalse
))
doc
(
""
,
"Whether the node is a false."
);
node
.
addMethod
(
"bool isTrue()"
,
asMETHOD
(
rapidjson
::
Value
,
IsTrue
))
doc
(
""
,
"Whether the node is a true."
);
node
.
addMethod
(
"bool isBool()"
,
asMETHOD
(
rapidjson
::
Value
,
IsBool
))
doc
(
""
,
"Whether the node is a boolean value (true or false)."
);
node
.
addMethod
(
"bool isObject()"
,
asMETHOD
(
rapidjson
::
Value
,
IsObject
))
doc
(
""
,
"Whether the node is an object / mapping."
);
node
.
addMethod
(
"bool isArray()"
,
asMETHOD
(
rapidjson
::
Value
,
IsArray
))
doc
(
""
,
"Whether the node is an array."
);
node
.
addMethod
(
"bool isNumber()"
,
asMETHOD
(
rapidjson
::
Value
,
IsNumber
))
doc
(
""
,
"Whether the node is a numerical type."
);
node
.
addMethod
(
"bool isInt()"
,
asMETHOD
(
rapidjson
::
Value
,
IsInt
))
doc
(
""
,
"Whether the node is an integer."
);
node
.
addMethod
(
"bool isUint()"
,
asMETHOD
(
rapidjson
::
Value
,
IsUint
))
doc
(
""
,
"Whether the node is an unsigned integer."
);
node
.
addMethod
(
"bool isInt64()"
,
asMETHOD
(
rapidjson
::
Value
,
IsInt64
))
doc
(
""
,
"Whether the node is an long integer."
);
node
.
addMethod
(
"bool isUint64()"
,
asMETHOD
(
rapidjson
::
Value
,
IsUint64
))
doc
(
""
,
"Whether the node is an long unsigned integer."
);
node
.
addMethod
(
"bool isDouble()"
,
asMETHOD
(
rapidjson
::
Value
,
IsDouble
))
doc
(
""
,
"Whether the node is a double."
);
node
.
addMethod
(
"bool isString()"
,
asMETHOD
(
rapidjson
::
Value
,
IsString
))
doc
(
""
,
"Whether the node is a string."
);
node
.
addMethod
(
"JSONNode& setNull()"
,
asMETHOD
(
rapidjson
::
Value
,
SetNull
))
doc
(
"Set this node to a null value."
,
"This node."
);
node
.
addMethod
(
"JSONNode& setBool(bool value)"
,
asMETHOD
(
rapidjson
::
Value
,
SetBool
))
doc
(
"Set this node to a boolean value."
,
"Boolean value to set to."
,
"This node."
);
node
.
addMethod
(
"JSONNode& makeArray()"
,
asMETHOD
(
rapidjson
::
Value
,
SetArray
))
doc
(
"Set this node to be an array."
,
"This node."
);
node
.
addMethod
(
"JSONNode& makeObject()"
,
asMETHOD
(
rapidjson
::
Value
,
SetObject
))
doc
(
"Set this node to be an object."
,
"This node."
);
node
.
addMethod
(
"JSONNode& setInt(int value)"
,
asMETHOD
(
rapidjson
::
Value
,
SetInt
))
doc
(
"Set this node to an int value."
,
"Integer value to set to."
,
"This node."
);
node
.
addMethod
(
"JSONNode& setUint(uint value)"
,
asMETHOD
(
rapidjson
::
Value
,
SetUint
))
doc
(
"Set this node to an unsigned int value."
,
"Unsigned integer value to set to."
,
"This node."
);
node
.
addMethod
(
"JSONNode& setInt64(int64 value)"
,
asMETHOD
(
rapidjson
::
Value
,
SetInt64
))
doc
(
"Set this node to a long int value."
,
"Long integer value to set to."
,
"This node."
);
node
.
addMethod
(
"JSONNode& setUint64(uint64 value)"
,
asMETHOD
(
rapidjson
::
Value
,
SetUint64
))
doc
(
"Set this node to a long unsigned int value."
,
"Long unsigned integer value to set to."
,
"This node."
);
node
.
addMethod
(
"JSONNode& setDouble(double value)"
,
asMETHOD
(
rapidjson
::
Value
,
SetDouble
))
doc
(
"Set this node to a double value."
,
"Double value to set to."
,
"This node."
);
node
.
addExternMethod
(
"JSONNode& setString(const string&in value)"
,
asFUNCTION
(
setString
))
doc
(
"Set this node to a string value."
,
"String value to set to."
,
"This node."
);
node
.
addMethod
(
"JSONNode& opAssign(int value)"
,
asMETHOD
(
rapidjson
::
Value
,
SetInt
))
doc
(
"Set this node to an int value."
,
"Integer value to set to."
,
"This node."
);
node
.
addMethod
(
"JSONNode& opAssign(uint value)"
,
asMETHOD
(
rapidjson
::
Value
,
SetUint
))
doc
(
"Set this node to an unsigned int value."
,
"Unsigned integer value to set to."
,
"This node."
);
node
.
addMethod
(
"JSONNode& opAssign(int64 value)"
,
asMETHOD
(
rapidjson
::
Value
,
SetInt64
))
doc
(
"Set this node to a long int value."
,
"Long integer value to set to."
,
"This node."
);
node
.
addMethod
(
"JSONNode& opAssign(uint64 value)"
,
asMETHOD
(
rapidjson
::
Value
,
SetUint64
))
doc
(
"Set this node to a long unsigned int value."
,
"Long unsigned integer value to set to."
,
"This node."
);
node
.
addMethod
(
"JSONNode& opAssign(double value)"
,
asMETHOD
(
rapidjson
::
Value
,
SetDouble
))
doc
(
"Set this node to a double value."
,
"Double value to set to."
,
"This node."
);
node
.
addExternMethod
(
"JSONNode& opAssign(const string&in value)"
,
asFUNCTION
(
setString
))
doc
(
"Set this node to a string value."
,
"String value to set to."
,
"This node."
);
node
.
addExternMethod
(
"string getString()"
,
asFUNCTION
(
nodeString
))
doc
(
""
,
"The string value of the node."
);
node
.
addExternMethod
(
"bool getBool()"
,
asFUNCTION
(
nodeBool
))
doc
(
""
,
"The boolean value of the node."
);
node
.
addExternMethod
(
"int getInt()"
,
asFUNCTION
(
nodeInt
))
doc
(
""
,
"The integer value of the node."
);
node
.
addExternMethod
(
"uint getUint()"
,
asFUNCTION
(
nodeUint
))
doc
(
""
,
"The unsigned integer value of the node."
);
node
.
addExternMethod
(
"int64 getInt64()"
,
asFUNCTION
(
nodeInt64
))
doc
(
""
,
"The long integer value of the node."
);
node
.
addExternMethod
(
"uint64 getUint64()"
,
asFUNCTION
(
nodeUint64
))
doc
(
""
,
"The long unsigned integer value of the node."
);
node
.
addExternMethod
(
"double getDouble()"
,
asFUNCTION
(
nodeDouble
))
doc
(
""
,
"The double value of the node."
);
node
.
addExternMethod
(
"double getNumber()"
,
asFUNCTION
(
nodeNumber
))
doc
(
""
,
"The numeric value of the node."
);
node
.
addExternMethod
(
"JSONNode@ findMember(const string& name)"
,
asFUNCTION
(
findMember
))
doc
(
"Retrieve a member node from an object."
,
"The name of the member."
,
"Reference to the member node. Null if it does not exist."
);
node
.
addExternMethod
(
"JSONNode@ getMember(const string& name)"
,
asFUNCTION
(
getMember
))
doc
(
"Retrieve a member node from an object, creating it if it does not exist."
,
"The name of the member."
,
"Reference to the member node, can be a newly created null node."
);
node
.
addExternMethod
(
"JSONNode@ opIndex(const string& name)"
,
asFUNCTION
(
getMember
))
doc
(
"Retrieve a member node from an object, creating it if it does not exist."
,
"The name of the member."
,
"Reference to the member node, can be a newly created null node."
);
node
.
addExternMethod
(
"void removeMember(const string& name)"
,
asFUNCTION
(
removeMember
))
doc
(
"Remove a member from an object."
,
"Name of the member to remove."
);
node
.
addExternMethod
(
"void clearItems()"
,
asFUNCTION
(
clearItems
))
doc
(
"Clear all items from an array node."
);
node
.
addExternMethod
(
"JSONNode@ getItem(uint index)"
,
asFUNCTION
(
getItem
))
doc
(
"Get an item from an array node."
,
"Index of the item."
,
"Node at the specified index in the array."
);
node
.
addExternMethod
(
"JSONNode@ opIndex(uint index)"
,
asFUNCTION
(
getItem
))
doc
(
"Get an item from an array node."
,
"Index of the item."
,
"Node at the specified index in the array."
);
node
.
addExternMethod
(
"uint size()"
,
asFUNCTION
(
arrSize
))
doc
(
""
,
"The size of the array node."
);
node
.
addExternMethod
(
"void reserve(uint amount)"
,
asFUNCTION
(
arrReserve
))
doc
(
"Reserve an array node to hold an amount of items."
,
"Amount of items to reserve for."
);
node
.
addExternMethod
(
"JSONNode@ pushBack()"
,
asFUNCTION
(
arrPush
))
doc
(
"Add a new node to the end of an array node."
,
"Newly created null node."
);
node
.
addExternMethod
(
"void popBack()"
,
asFUNCTION
(
arrPop
))
doc
(
"Remove a node from the end of an array node."
);
}
};
File Metadata
Details
Attached
Mime Type
text/x-c++
Expires
Sat, Nov 14, 2:53 PM (14 m, 52 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
128603
Default Alt Text
bind_json.cpp (14 KB)
Attached To
Mode
R80 StarRuler2-Source
Attached
Detach File
Event Timeline