Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vg ip 2: Use C++20, build shared library, improve performance and usability. #1

Merged
merged 23 commits into from
Jul 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
673a76f
.gitignore: Add `.cache`.
sreiter Apr 25, 2024
761268a
Add function to request optional type.
sreiter Apr 25, 2024
1cee5b3
Convert `Types` from collection of static methods to regular class.
sreiter Apr 25, 2024
cdd6d9b
CMake: Export symbols and build shared dll.
sreiter Apr 25, 2024
b136c79
Export methods of Reader and Writer.
sreiter Apr 25, 2024
c5cedb6
Type: Use `type_index` instead of hash. No longer rely on names.
sreiter Apr 25, 2024
d3b5b56
JSON: Write more precise numbers.
sreiter Jun 28, 2024
74f0713
JSON: Rename .cpp files.
sreiter Jul 1, 2024
7c06690
Read/Write: Add binary writer and reader.
sreiter Jul 1, 2024
de724ee
Remove unnecessary `static` specifier.
sreiter Jul 3, 2024
3976fba
BINARY: Allow creation of reader/writer on stream reference.
sreiter Jul 4, 2024
d0fc4fb
C++20. Also, add binary serialization to stl tests.
sreiter Jul 4, 2024
cc72799
enum to string conversion: Use `magic_enum` library.
sreiter Jul 4, 2024
eb83ce5
json/stl test for nested arrays.
sreiter Jul 5, 2024
e7292cf
Unpacking of ranges is now supported from inside vectors.
sreiter Jul 5, 2024
152bac1
Merge branch 'master' into vg_ip_2
sreiter Jul 21, 2024
e439393
Fix compilation after merge.
sreiter Jul 21, 2024
66abe3f
Rename moosesample to moose_sample.
sreiter Jul 21, 2024
8245af3
Merge branch 'master' into vg_ip_2
sreiter Jul 21, 2024
37b1eaa
Only export/import classes and functions on windows systems.
sreiter Jul 21, 2024
e49c365
Use std::setprecision instead of std::format for better compiler support
sreiter Jul 21, 2024
e01c0c8
Use nested name specifier in type traits declaration.
sreiter Jul 21, 2024
758416e
Remove travis build status. GitHub Actions are used now...
sreiter Jul 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 21 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,19 @@ option (MOOSE_BUILD_TESTS "Build the moose tests")

project (libmoose)

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)

set (mooseSrc src/moose/archive.cpp
src/moose/binary_reader.cpp
src/moose/input_archive.cpp
src/moose/json_archive_in.cpp
src/moose/json_archive_out.cpp
src/moose/json_reader.cpp
src/moose/json_writer.cpp
src/moose/output_archive.cpp
src/moose/type.cpp
src/moose/types.cpp
src/moose/version.cpp)

add_library(moose STATIC ${mooseSrc})
add_library(moose SHARED ${mooseSrc})

target_include_directories(moose
PUBLIC
Expand All @@ -50,14 +53,27 @@ target_include_directories(moose
${CMAKE_CURRENT_SOURCE_DIR}/deps/rapidjson-v1.1.0.s1/include
)

target_compile_features(moose PUBLIC cxx_std_17)
target_compile_features(moose PUBLIC cxx_std_20)

if(MSVC)
target_compile_options(moose PRIVATE /W4 /WX)
#/wd5054 is a warning from rapidjson.
target_compile_options(moose PRIVATE /W4 /WX /wd5054)
else()
target_compile_options(moose PRIVATE -Wall -Wextra -Wpedantic -Werror)
endif()

target_compile_definitions (moose PRIVATE MOOSE_COMPILING_LIBRARY)

include (FetchContent)
FetchContent_Declare (
magic_enum
GIT_REPOSITORY https://github.com/Neargye/magic_enum
GIT_TAG v0.9.6
GIT_SHALLOW ON)
FetchContent_MakeAvailable (magic_enum)

target_link_libraries (moose PUBLIC magic_enum)

if (MOOSE_BUILD_SAMPLE)
add_subdirectory (sample)
endif ()
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# moose      [![Build Status](https://travis-ci.com/sreiter/moose.svg?branch=master)](https://travis-ci.com/sreiter/moose)
# moose
## Introduction
**Moose** (**MO**ose **O**bject **SE**rialization) is a *BSD* licensed *C++* library for the serialization of complex data structures.

Expand All @@ -18,7 +18,7 @@ function for a given ```Object``` type, or by providing a method

one can add serialization support for custom types.

The implementation of **moose** is kept simple on purpose to allow users of the library to easily create **custom archives**, which may be used to support more file formats.
The implementation of **moose** is kept simple on purpose to allow users of the library to easily create **custom readers/writers**, which may be used to support more file formats.

Another interesting application for **archives** is the generation and synchronization of **GUI** elements given a serializable object.

Expand Down Expand Up @@ -52,7 +52,7 @@ Please note that ```ClassA``` and ```ClassB``` derive from a common base class `

In addition to the **moose** library, the following executable will be build:

sample/moosesample
sample/moose_sample

## Building moose as a part of your project
To build **moose** as part of your project, simply add the line
Expand Down
15 changes: 8 additions & 7 deletions include/moose/archive.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

#include <memory>
#include <string>
#include <moose/export.h>
#include <moose/range.h>
#include <moose/type_traits.h>
#include <moose/version.h>
Expand All @@ -42,16 +43,16 @@ namespace moose
class Archive
{
public:
Archive (std::shared_ptr<Reader> archive);
Archive (std::shared_ptr<Writer> archive);
MOOSE_EXPORT Archive (std::shared_ptr<Reader> archive);
MOOSE_EXPORT Archive (std::shared_ptr<Writer> archive);

/** For output archives, latestVersion is stored as version of the currently processed type
and is also returned.

For input archives, the type version stored in the underlying archive is returned.
If no version was stored, {0,0,0} is returned.
*/
auto type_version (Version const& latestVersion) -> Version;
MOOSE_EXPORT auto type_version (Version const& latestVersion) -> Version;

/** \brief Read/write without default value.
If the archive is reading and the given name can not be found, an exception is thrown.
Expand All @@ -74,12 +75,12 @@ namespace moose
template <class T>
void operator () (const char* name, T const& value, const T& defVal, Hint hint = Hint::None);

bool is_reading () const;
bool is_writing () const;
MOOSE_EXPORT bool is_reading () const;
MOOSE_EXPORT bool is_writing () const;

private:
bool begin_entry (const char* name, ContentType contentType, Hint hint);
void end_entry (const char* name, ContentType contentType);
MOOSE_EXPORT bool begin_entry (const char* name, ContentType contentType, Hint hint);
MOOSE_EXPORT void end_entry (const char* name, ContentType contentType);

/// Used to allow for different overloads based on the entryType.
template <EntryType entryType>
Expand Down
58 changes: 47 additions & 11 deletions include/moose/archive.i
Original file line number Diff line number Diff line change
Expand Up @@ -132,16 +132,16 @@ namespace moose
{
if (is_writing ())
{
auto const& type = Types::get_polymorphic (instance);
auto const& type = types ().get_polymorphic (instance);
mOutput->write_type_name (type.name ());
return type;
}
else
{
auto const& typeName = mInput->type_name ();
if (typeName.empty ())
return Types::get <T> ();
return Types::get (typeName);
return types ().get <T> ();
return types ().get (typeName);
}
}

Expand Down Expand Up @@ -205,21 +205,57 @@ namespace moose
template <class T>
void Archive::archive (const char* name, T& value, EntryTypeDummy <EntryType::Vector>)
{
using Traits = TypeTraits<T>;
using ValueType = typename Traits::ValueType;

constexpr bool unpack = wantsToUnpack<T> () && canBeUnpacked<ValueType> ();

if (is_reading ())
{
TypeTraits<T>::clear (value);
while(mInput->array_has_next (name))
Traits::clear (value);
if constexpr (unpack)
{
while(mInput->array_has_next (name))
{
ValueType childValue;
auto childRange = TypeTraits<ValueType>::toRange (childValue);
for (auto i = childRange.begin; i != childRange.end; ++i)
{
if (!mInput->array_has_next (name))
throw ArchiveError () << "Too few entries while reading range '" << name << "'";

(*this) ("", *i);
}
Traits::pushBack (value, childValue);
}
}
else
{
using ValueType = typename TypeTraits<T>::ValueType;
ValueType tmpVal = detail::GetInitialValue <ValueType> ();
(*this) ("", tmpVal);
TypeTraits<T>::pushBack (value, tmpVal);
while(mInput->array_has_next (name))
{
ValueType tmpVal = detail::GetInitialValue <ValueType> ();
(*this) ("", tmpVal);
Traits::pushBack (value, tmpVal);
}
}
}
else
{
// Writing a vector type is the same as writing a range
archive (name, value, EntryTypeDummy <EntryType::Range> ());
if constexpr (unpack)
{
auto range = Traits::toRange (value);
for (auto i = range.begin; i != range.end; ++i)
{
auto childRange = TypeTraits<ValueType>::toRange (*i);
for (auto j = childRange.begin; j != childRange.end; ++j)
(*this) ("", *j);
}
}
else
{
// Writing a vector type is the same as writing a range
archive (name, value, EntryTypeDummy <EntryType::Range> ());
}
}
}

Expand Down
81 changes: 81 additions & 0 deletions include/moose/binary_reader.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// This file is part of moose, a C++ serialization library
//
// Copyright (C) 2024 Volume Graphics
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#pragma once

#include <moose/export.h>
#include <moose/reader.h>

#include <memory>
#include <stack>

namespace moose
{
class BinaryReader : public Reader {
public:
MOOSE_EXPORT static auto fromFile (const char* filename) -> std::shared_ptr<BinaryReader>;

public:
BinaryReader () = delete;
MOOSE_EXPORT BinaryReader (BinaryReader&& other) = default;
MOOSE_EXPORT BinaryReader (std::istream& in);
MOOSE_EXPORT BinaryReader (std::shared_ptr<std::istream> in);

BinaryReader (BinaryReader const&) = delete;

MOOSE_EXPORT ~BinaryReader () override = default;

BinaryReader& operator = (BinaryReader const&) = delete;
MOOSE_EXPORT BinaryReader& operator = (BinaryReader&& other) = default;

bool begin_entry (const char* name, ContentType type) override;
void end_entry (const char* name, ContentType type) override;

bool array_has_next (const char* name) const override;

auto type_name () const -> std::string override;
auto type_version () const -> Version override;

void read (const char* name, bool& value) const override;
void read (const char* name, double& value) const override;
void read (const char* name, std::string& value) const override;

private:
struct Entry
{
ContentType mType;
bool mArrayHasNext {false};
};

private:
auto current () -> Entry&;
auto current () const -> Entry const&;
bool readArrayHasNext ();
auto in () const -> std::istream&;

private:
std::shared_ptr<std::istream> mStreamStorage;
std::istream* mIn;
std::stack<Entry> mEntries;
};
}// end of namespace moose
78 changes: 78 additions & 0 deletions include/moose/binary_writer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// This file is part of moose, a C++ serialization library
//
// Copyright (C) 2024 Volume Graphics
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#pragma once

#include <fstream>
#include <stack>
#include <memory>
#include <moose/writer.h>

namespace moose
{

/** Writes binary data to a given stream, using its
`write (const char_type* s, std::streamsize count)` method.
*/
template <class STREAM = std::ofstream>
class BinaryWriter : public Writer
{
public:
static auto toFile (const char* filename) -> std::shared_ptr<BinaryWriter>;

BinaryWriter (STREAM& out);
BinaryWriter (std::shared_ptr<STREAM> out);

BinaryWriter (BinaryWriter const&) = delete;
BinaryWriter (BinaryWriter&& other) = default;


~BinaryWriter () override = default;

BinaryWriter& operator = (BinaryWriter const&) = delete;
BinaryWriter& operator = (BinaryWriter&& other) = default;

bool begin_entry (const char* name, ContentType type, Hint hint) override;
void end_entry (const char* name, ContentType type) override;

void write_type_name (std::string const& typeName) override;
void write_type_version (Version const& version) override;

void write (const char* name, bool value) override;
void write (const char* name, double value) override;
void write (const char* name, std::string const& value) override;

private:
auto out () -> STREAM&;

private:
std::shared_ptr<STREAM> mStreamStorage;
STREAM* mOut;
std::stack<ContentType> mContentStack;
std::stack<std::string> mNameStack;
};

}// end of namespace moose

#include <moose/binary_writer.i>
Loading