{
# specify rate in requests/second (because comments are helpful!)
rate: 1000
// prefer c-style comments?
/* feeling old fashioned? */
# did you notice that rate doesn't need quotes?
hey: look ma, no quotes for strings either!
# best of all
notice: []
anything: ?
# yes, commas are optional!
}
The C++ implementation of Hjson is based on hjson-go. For other platforms see hjson.org.
The easiest way to use hjson-cpp is to simply include all of the files from the folders src
and include
into you own project. The only requirement is that your compiler fully supports C++11.
GCC 4.8 has the C++11 headers for regex, but unfortunately not a working implementation, so for GCC at least version 4.9 is required.
The second easiest way to use hjson-cpp is to either add it as a subfolder to your own Cmake project, or to install the hjson lib on your system by using Cmake. Works on Linux and Windows. Your mileage may vary on other platforms.
Instead of building a lib, you can choose to include hjson as a subfolder in your own Cmake project. That way, hjson will be built together with your own project, with the same settings. In Visual Studio that also means the hjson source code will be visible in a project in your own solution. Example CMakeLists.txt
for your own project, if your executable is called myapp
:
add_executable(myapp main.cpp)
add_subdirectory(../hjson-cpp ${CMAKE_BINARY_DIR}/hjson)
target_link_libraries(myapp hjson)
- First create a Makefile using Cmake.
$ cd hjson-cpp
$ mkdir build
$ cd build
$ cmake .. -DHJSON_ENABLE_TEST=ON -DHJSON_ENABLE_INSTALL=ON
- Then you can optionally run the tests.
$ make runtest
- Install the include files and static lib to make them accessible system wide (optional).
$ sudo make install
- If you haven't done either step 2 or step 3, you must at least compile the code into a library by calling make.
$ make
The Cmake GUI is the most convenient way to generate a Visual Studio solution. Make sure that you tick the boxes for HJSON_ENABLE_TEST
and HJSON_ENABLE_INSTALL
if you want to run tests or make the hjson lib accessible system wide.
After generating the solution and opening it in Visual Studio you can run the tests by right-clicking the project runtest
and selecting Build
. Make sure to have selected a Debug target, otherwise the assertions will have been optimized away.
In order to make the hjson lib accessible system wide you must run Visual Studio as an administrator. In Windows 7 you can do that by right-clicking on the Visual Studio icon in the start menu and selecting Run as an administrator
. Then open the hjson solution, right-click the INSTALL
project and select Build
. Make sure to do that for both the Debug
and Release
targets.
The hjson lib can now be used in your own Cmake projects, for example like this if your application is called myapp
:
add_executable(myapp main.cpp)
find_package(hjson REQUIRED)
target_link_libraries(myapp hjson)
On Windows it's important that you compiled or installed both Debug
and Release
hjson libraries before Cmake-generating your own project. Otherwise the target type you didn't compile/install will not be available in your own project.
If you did not install hjson system wide, you can still use it like in the example above if you specify the location of the hjson build when running Cmake for your own project. Example:
$ cmake .. -Dhjson_DIR=../hjson-cpp/build
The most important functions in the Hjson namespace are:
std::string Marshal(Value v);
Value Unmarshal(const char *data, size_t dataSize);
Value Unmarshal(const char *data);
Value Merge(const Value base, const Value ext);
Marshal is the output-function, transforming an Hjson::Value tree (represented by its root node) to a string that can be written to a file.
Unmarshal is the input-function, transforming a string to a Hjson::Value tree. The string is expected to be UTF8 encoded. Other encodings might work too, but have not been tested. The function comes in two flavors: with or without the dataSize
parameter. Without it, the data
parameter must be null-terminated (like all normal strings).
Merge returns an Hjson::Value tree that is a cloned combination of the input Hjson::Value trees base
and ext
, with values from ext
used whenever both base
and ext
has a value for some specific position in the tree. The function is convenient when implementing an application with a default configuration (base
) that can be overridden by input parameters (ext
).
Two more functions exist, allowing adjustments to the output formatting when creating an Hjson string:
EncoderOptions DefaultOptions();
std::string MarshalWithOptions(Value v, EncoderOptions options);
Input strings are unmarshalled into a tree representation where each node in the tree is an object of the type Hjson::Value. The class Hjson::Value mimics the behavior of Javascript in that you can assign any type of primitive value to it without casting. Examples:
Hjson::Value myValue(true);
Hjson::Value myValue2 = 3.0;
myValue2 = "A text.";
An Hjson::Value can behave both like a vector (array) and like a map (Object in Javascript):
Hjson::Value map;
map["down1"]["down2"]["down3"] = "three levels deep!";
map["down1"]["number"] = 7;
Hjson::Value arr;
arr.push_back("first");
std::string myString = arr[0];
If you try to access a map element that doesn't exist, an Hjson::Value of type Hjson::Value::UNDEFINED is returned. But if you try to access a vector element that doesn't exist, an Hjson::index_out_of_bounds exception is thrown.
These are the possible types for an Hjson::Value:
UNDEFINED
HJSON_NULL
BOOL
DOUBLE
STRING
VECTOR
MAP
The default constructor creates an Hjson::Value of the type Hjson::Value::UNDEFINED.
#include <hjson.h>
int main() {
// Now let's look at decoding Hjson data into Hjson::Value.
std::string sampleText = R"(
{
# specify rate in requests/second
rate: 1000
array:
[
foo
bar
]
}
)";
// Decode. Throws Hjson::syntax_error on failure.
Hjson::Value dat = Hjson::Unmarshal(sampleText.c_str(), sampleText.size());
// Values can be assigned directly without casting.
int rate = dat["rate"];
printf("%d\n", rate);
// Sometimes it's difficult for the compiler to know
// what primitive type to convert the Hjson::Value to.
// Then an explicit cast can be used.
printf("%s\n", static_cast<const char*>(dat["array"][0]));
// To encode to Hjson with default options:
Hjson::Value sampleMap;
sampleMap["apple"] = 5;
sampleMap["lettuce"] = 7;
std::string hjson = Hjson::Marshal(sampleMap);
// this is short for:
// auto options = Hjson::DefaultOptions();
// std::string hjson = Hjson::MarshalWithOptions(sampleMap, options);
printf("%s\n", hjson.c_str());
}
Iterating through the elements of an Hjson::Value of type Hjson::Value::VECTOR:
for (int index = 0; index < int(arr.size()); ++index) {
std::cout << arr[index].to_string() << std::endl;
}
Iterating through the elements of an Hjson::Value of type Hjson::Value::MAP:
for (auto it = map.begin(); it != map.end(); ++it) {
std::cout << "key: " << it->first << " value: " << it->second.to_string() << std::endl;
}
Having a default configuration:
#include <hjson.h>
#include <cstdio>
static const char *_szDefaultConfig = R"(
{
imageSource: NO DEFAULT
showImages: true
writeImages: true
printFrameIndex: false
printFrameRate: true
}
)";
Hjson::Value GetConfig(const char *szInputConfig) {
Hjson::Value defaultConfig = Hjson::Unmarshal(_szDefaultConfig);
Hjson::Value inputConfig
try {
inputConfig = Hjson::Unmarshal(szInputConfig);
} catch(std::exception e) {
std::fprintf(stderr, "Error: Failed to unmarshal input config\n");
std::fprintf(stdout, "Default config:\n");
std::fprintf(stdout, _szDefaultConfig);
return Hjson::Value();
}
return Hjson::Merge(defaultConfig, inputConfig);
}