Improve README and make it work with md2pdf
This commit is contained in:
parent
9e11d805c1
commit
e6c54a37e4
91
README.md
91
README.md
|
@ -18,27 +18,28 @@ The reflection implementation used behind the scenes of this library is exchange
|
|||
## Current state
|
||||
The basic functionality is implemented, tested and documented:
|
||||
|
||||
* serialization and deserialization of datatypes listed under "Supported datatypes"
|
||||
* nesting and inheritance is possible
|
||||
* adapting 3rdparty structs/classes is supported
|
||||
* basic error handling when deserializing
|
||||
* Serialization and deserialization of datatypes listed under "Supported datatypes"
|
||||
* Nesting and inheritance is possible
|
||||
* Adapting 3rdparty structs/classes is supported
|
||||
* Basic error handling when deserializing
|
||||
* CMake macro to conveniently include the code generator into the build process
|
||||
* allow to use Boost.Hana
|
||||
* Allow to use Boost.Hana
|
||||
|
||||
### TODOs
|
||||
There are still things missing which would likely be very useful in practise. The following list contains the open TODOs which are supposed to be most relevant in practise:
|
||||
### Planned features and TODOs
|
||||
There are still things missing which would likely be very useful in practise. The following list contains the
|
||||
open TODOs which are supposed to be most relevant in practise:
|
||||
|
||||
* [ ] Allow to specify which member variables should be considered
|
||||
* This could work similar to Qt's Signals & Slots macros.
|
||||
* but there should also be a way to do this for 3rdparty types.
|
||||
* Note that currently, *all* public member variables are (de)serialized.
|
||||
* But there should also be a way to do this for 3rdparty types.
|
||||
* Note that currently all public, non-static member variables are (de)serialized.
|
||||
* [ ] Support getter/setter methods
|
||||
* [ ] Allow to serialize the result of methods
|
||||
* [ ] Allow to pass a deserialized value to a method
|
||||
* [ ] Validate enum values when deserializing
|
||||
* [ ] Untie serialization and deserialization
|
||||
|
||||
For a full list of TODOs, see [TODOs.md](./TODOs.md).
|
||||
For a full list of further ideas, see [TODOs.md](./TODOs.md).
|
||||
|
||||
## Supported datatypes
|
||||
The following table shows the mapping of supported C++ types to supported JSON types:
|
||||
|
@ -74,7 +75,7 @@ The following table shows the mapping of supported C++ types to supported JSON t
|
|||
|
||||
## Usage
|
||||
This example shows how the library can be used to make a `struct` serializable:
|
||||
```
|
||||
<pre>
|
||||
#include <reflective_rapidjson/json/serializable.h>
|
||||
|
||||
// define structures, eg.
|
||||
|
@ -103,22 +104,26 @@ const auto obj = NestingArray::fromJson(...);
|
|||
|
||||
// in exactly one of the project's translation units
|
||||
#include "reflection/code-defining-structs.h"
|
||||
```
|
||||
</pre>
|
||||
|
||||
Note that the header included at the bottom must be generated by invoking the code generator appropriately, eg.:
|
||||
```
|
||||
reflective_rapidjson_generator --input-file "$srcdir/code-defining-structs.cpp" --output-file "$builddir/reflection/code-defining-structs.h"
|
||||
```
|
||||
<pre>
|
||||
reflective_rapidjson_generator \
|
||||
--input-file "$srcdir/code-defining-structs.cpp" \
|
||||
--output-file "$builddir/reflection/code-defining-structs.h"
|
||||
</pre>
|
||||
|
||||
#### Invoking code generator with CMake macro
|
||||
It is possible to use the provided CMake macro to automate the code generator invocation:
|
||||
```
|
||||
<pre>
|
||||
# find the package and make macro available
|
||||
find_package(reflective-rapidjson REQUIRED)
|
||||
list(APPEND CMAKE_MODULE_PATH ${REFLECTIVE_RAPIDJSON_MODULE_DIRS})
|
||||
include(ReflectionGenerator)
|
||||
|
||||
# "link" against reflective_rapidjson (it is a header-only lib so this will only add the required include paths to your target)
|
||||
# "link" against reflective_rapidjson
|
||||
# it is a header-only lib so this will only add the required include paths
|
||||
# to your target
|
||||
target_link_libraries(mytarget PRIVATE reflective_rapidjson)
|
||||
|
||||
# invoke macro
|
||||
|
@ -128,14 +133,14 @@ add_reflection_generator_invocation(
|
|||
OUTPUT_LISTS LIST_OF_GENERATED_HEADERS
|
||||
CLANG_OPTIONS_FROM_TARGETS mytarget
|
||||
)
|
||||
```
|
||||
</pre>
|
||||
|
||||
This will produce the file `code-defining-structs.h` in the directory `reflection` in the current build directory. So
|
||||
make sure the current build directory is added to the include directories of your target. The default output directory can
|
||||
also be overridden by passing `OUTPUT_DIRECTORY custom/directory` to the arguments.
|
||||
|
||||
It is possible to specify multiple input files at once. A separate output file is generated for each input. The output files
|
||||
will always have the extension "`.h`", independently of the extension of the input file.
|
||||
will always have the extension `.h`, independently of the extension of the input file.
|
||||
|
||||
The full paths of the generated files are also appended to the variable `LIST_OF_GENERATED_HEADERS` which then can be added
|
||||
to the sources of your target. Of course this can be skipped if not required/wanted.
|
||||
|
@ -164,23 +169,24 @@ To adjust the default location, just add eg. `--clang-opt -resource-dir /usr/lib
|
|||
It makes most sense to specify the same options for the code generator as during the actual compilation. This way the code
|
||||
generator uses the same flags, defines and include directories as the compiler and hence behaves like the compiler.
|
||||
When using the CMake macro, it is possible to automatically pass all compile flags, compile definitions and include directories
|
||||
from certain targets to the code generator. The targets can be specified using the `CLANG_OPTIONS_FROM_TARGETS` argument.
|
||||
from certain targets to the code generator. Those targets can be specified using the
|
||||
Macro's `CLANG_OPTIONS_FROM_TARGETS` argument.
|
||||
|
||||
#### Notes regarding cross-compilation
|
||||
* For cross compilation, it is required to build the code generator for the platform you're building on.
|
||||
* Since the code generator is likely not required under the target platform, you should add `-DNO_GENERATOR:BOOL=ON` to the CMake
|
||||
arguments when building Reflective RapidJSON for the target platform.
|
||||
* When using the `add_reflection_generator_invocation` macro, you need to set the following CMake cache variables:
|
||||
* `REFLECTION_GENERATOR_EXECUTABLE:FILEPATH=/path/to/executable`
|
||||
* `REFLECTION_GENERATOR_EXECUTABLE:FILEPATH=/path/to/reflective_rapidjson_generator`
|
||||
* specifies the path of the code generator executable built for the platform you're building on
|
||||
* only required if executable not in path anyways
|
||||
* only required if the executable is not in the path anyways
|
||||
* `REFLECTION_GENERATOR_TRIPLE:STRING=machine-vendor-operatingsystem`
|
||||
* specifies the GNU platform triple for the target platform
|
||||
* examples for cross compiling with mingw-w64 under GNU/Linux:
|
||||
* examples for cross compiling with mingw-w64 under GNU/Linux:
|
||||
`x86_64-w64-mingw32`, `i686-w64-mingw32`
|
||||
* `REFLECTION_GENERATOR_INCLUDE_DIRECTORIES:STRING=/custom/prefix/include`
|
||||
* directories containing header files for target platform
|
||||
* example for cross compiling with mingw-w64 under GNU/Linux:
|
||||
* implicit include directories for target platform
|
||||
* example for cross compiling with mingw-w64 under GNU/Linux:
|
||||
`/usr/lib/gcc/x86_64-w64-mingw32/7.2.1/include;/usr/x86_64-w64-mingw32/include/c++/7.2.1/x86_64-w64-mingw32;/usr/x86_64-w64-mingw32/include`
|
||||
* The Arch Linux packages mentioned at the end of the README file also include `mingw-w64` variants which give a concrete example how
|
||||
cross-compilation can be done.
|
||||
|
@ -188,7 +194,7 @@ from certain targets to the code generator. The targets can be specified using t
|
|||
### Using Boost.Hana instead of the code generator
|
||||
The same example as above. However, this time Boost.Hana is used - so it doesn't require invoking the generator.
|
||||
|
||||
```
|
||||
<pre>
|
||||
#include "<reflective_rapidjson/json/serializable-boosthana.h>
|
||||
|
||||
// define structures using BOOST_HANA_DEFINE_STRUCT, eg.
|
||||
|
@ -220,7 +226,7 @@ cout << "JSON: " << obj.toJson().GetString();
|
|||
|
||||
// deserialize from JSON
|
||||
const auto obj = NestingArray::fromJson(...);
|
||||
```
|
||||
</pre>
|
||||
|
||||
So beside the `BOOST_HANA_DEFINE_STRUCT` macro, the usage remains the same.
|
||||
|
||||
|
@ -229,7 +235,6 @@ So beside the `BOOST_HANA_DEFINE_STRUCT` macro, the usage remains the same.
|
|||
* No context information for errors like type-mismatch available
|
||||
* Inherited members not considered
|
||||
* Proper support for enums is unlikely
|
||||
* Attempt to access private members can not be prevented
|
||||
|
||||
### Enable reflection for 3rd party classes/structs
|
||||
It is obvious that the previously shown examples do not work for classes
|
||||
|
@ -240,7 +245,7 @@ To work around this issue, one can use the `REFLECTIVE_RAPIDJSON_MAKE_JSON_SERIA
|
|||
macro. It will enable the `toJson` and `fromJson` methods for the specified class
|
||||
in the `ReflectiveRapidJSON::JsonReflector` namespace:
|
||||
|
||||
```
|
||||
<pre>
|
||||
// somewhere in included header
|
||||
struct ThridPartyStruct
|
||||
{ ... };
|
||||
|
@ -251,7 +256,7 @@ REFLECTIVE_RAPIDJSON_MAKE_JSON_SERIALIZABLE(ThridPartyStruct)
|
|||
// (de)serialization
|
||||
ReflectiveRapidJSON::JsonReflector::toJson(...).GetString();
|
||||
ReflectiveRapidJSON::JsonReflector::fromJson<ThridPartyStruct>("...");
|
||||
```
|
||||
</pre>
|
||||
|
||||
The code generator will emit the code in the same way as if `JsonSerializable` was
|
||||
used.
|
||||
|
@ -264,7 +269,7 @@ By default, private members are not considered for (de)serialization. However, i
|
|||
to enable this by adding `friend` methods for the helper functions of Reflective RapidJSON.
|
||||
|
||||
To make things easier, there's a macro provided:
|
||||
```
|
||||
<pre>
|
||||
struct SomeStruct : public JsonSerializable<SomeStruct> {
|
||||
REFLECTIVE_RAPIDJSON_ENABLE_PRIVATE_MEMBERS(SomeStruct);
|
||||
|
||||
|
@ -274,7 +279,7 @@ public:
|
|||
private:
|
||||
std::string privateMember = "will be (de)serialized with the help of REFLECTIVE_RAPIDJSON_ENABLE_PRIVATE_MEMBERS macro";
|
||||
};
|
||||
```
|
||||
</pre>
|
||||
|
||||
#### Caveats
|
||||
* It will obviously not work for 3rd party structs.
|
||||
|
@ -285,15 +290,15 @@ private:
|
|||
### Custom (de)serialization
|
||||
Sometimes it is appropriate to implement custom (de)serialization. For instance, a
|
||||
custom object representing a time value should likey be serialized as a string rather
|
||||
than an object with the internal data members.
|
||||
than an object containing the internal structure.
|
||||
|
||||
An example for such custom (de)serialization can be found in the file
|
||||
`json/reflector-chronoutilities.h`. It provides (de)serialization of `DateTime` and
|
||||
`TimeSpan` objects from the C++ utilities library.
|
||||
`TimeSpan` objects from the C++ utilities library mentioned under dependencies.
|
||||
|
||||
### Remarks
|
||||
* Static member variables are currently ignored by the generator.
|
||||
* It is currently not possible to ignore a specific member.
|
||||
* Static member variables and member functions are currently ignored by the generator.
|
||||
* It is currently not possible to ignore a specific member variable.
|
||||
|
||||
### Further examples
|
||||
* Checkout the test cases for further examples. Relevant files are in
|
||||
|
@ -340,7 +345,7 @@ Reflective RapidJSON.
|
|||
provided (so far).
|
||||
* I usually develop using the latest version of those dependencies. So it is recommend to get the
|
||||
the latest versions as well. I tested the following versions so far:
|
||||
* GCC 7.2.1 or Clang 5.0 as compiler
|
||||
* GCC 7.2.1/7.3.0 or Clang 5.0 as compiler
|
||||
* libstdc++ from GCC 7.2.1
|
||||
* CMake 3.10.1
|
||||
* Clang 5.0.0/5.0.1 for LibTooling
|
||||
|
@ -370,12 +375,12 @@ you can skip this step of course.
|
|||
|
||||
To specify custom locations, just set some environment variables before invoking CMake. This
|
||||
can likely be done in your IDE settings and of course at command line. Here is a Bash example:
|
||||
```
|
||||
<pre>
|
||||
export PATH=$CUSTOM_INSTALL_PREFIX/bin:$PATH
|
||||
export CMAKE_PREFIX_PATH=$CUSTOM_INSTALL_PREFIX:$CMAKE_PREFIX_PATH
|
||||
export CMAKE_LIBRARY_PATH=$CUSTOM_INSTALL_PREFIX/lib:$CMAKE_LIBRARY_PATH
|
||||
export CMAKE_INCLUDE_PATH=$CUSTOM_INSTALL_PREFIX/include:$CMAKE_INCLUDE_PATH
|
||||
```
|
||||
</pre>
|
||||
|
||||
There are also a lot of [useful variables](https://cmake.org/Wiki/CMake_Useful_Variables)
|
||||
that can be specified as CMake arguments. It is also possible to create a
|
||||
|
@ -383,17 +388,17 @@ that can be specified as CMake arguments. It is also possible to create a
|
|||
|
||||
|
||||
#### 3. Get sources, eg. using Git:
|
||||
```
|
||||
<pre>
|
||||
cd $SOURCES
|
||||
git clone https://github.com/Martchus/cpp-utilities.git c++utilities
|
||||
git clone https://github.com/Martchus/reflective-rapidjson.git
|
||||
```
|
||||
</pre>
|
||||
|
||||
If you don't want to build the development version, just checkout the desired version tag.
|
||||
|
||||
#### 4. Run the build script
|
||||
Here is an example for building with GNU Make:
|
||||
```
|
||||
<pre>
|
||||
cd $BUILD_DIR
|
||||
# generate Makefile
|
||||
cmake \
|
||||
|
@ -411,7 +416,7 @@ make tests
|
|||
make apidoc
|
||||
# install header files, libraries and generator
|
||||
make install DESTDIR="/temporary/install/location"
|
||||
```
|
||||
</pre>
|
||||
Add eg. `-j$(nproc)` to `make` arguments for using all cores.
|
||||
|
||||
### Packages
|
||||
|
|
Loading…
Reference in New Issue