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

Taojson #66

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
bench
vpack-to-json
json-to-vpack
taocpp-json
core
AsmTest
*.o
Expand Down
6 changes: 6 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ matrix:
- build_type=Release
- SANITIZER=false
- CXX_STANDARD=17
- TAO=ON
addons:
apt:
packages: ['gcc-8', 'g++-8', 'cmake']
Expand Down Expand Up @@ -92,6 +93,7 @@ matrix:
#build settings
- build_type=Release
- CXX_STANDARD=17
- TAO=ON
addons:
apt:
sources:
Expand All @@ -105,12 +107,16 @@ matrix:
compiler: clang
env:
- build_type=Release
- TAO=ON

install:
- git clone https://github.com/taocpp/json.git taocpp-json
- ( cd taocpp-json; git checkout 631095f4bfa45c63af5ccc1cb35ea16eb9ead450; )
- export CXX=$CXX
- export CC=$CC
- export CXX_STANDARD=${CXX_STANDARD:-17}
- export BUILD_TYPE=${build_type}
- export TAO=${TAO:-OFF}
- cmake --version
- $CXX --version

Expand Down
11 changes: 11 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,15 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Mo

option(BuildVelocyPackExamples "Build examples" ON)
option(Maintainer "Build maintainer tools" OFF)
option(TaoJson "Add support for taocpp::json" OFF)

if(TaoJson)
if(NOT TARGET taocpp::json)
set(TAOCPP_JSON_BUILD_TESTS OFF CACHE BOOL "Build test programs" FORCE)
set(TAOCPP_JSON_BUILD_EXAMPLES OFF CACHE BOOL "Build example programs" FORCE)
add_subdirectory(taocpp-json EXCLUDE_FROM_ALL)
endif()
endif()

set(HashType "xxhash" CACHE STRING "Hash type (fasthash, xxhash)" )

Expand Down Expand Up @@ -44,6 +53,7 @@ set(VELOCY_SOURCE
src/Iterator.cpp
src/Options.cpp
src/Parser.cpp
$<$<BOOL:${TaoJson}>:src/TaoParser.cpp>
src/Serializable.cpp
src/Slice.cpp
src/SliceStaticData.cpp
Expand Down Expand Up @@ -79,6 +89,7 @@ message(STATUS "Building with hash type: ${HashType}")
add_library(velocypack STATIC ${VELOCY_SOURCE})
target_include_directories(velocypack PRIVATE src)
target_include_directories(velocypack PUBLIC include)
target_link_libraries(velocypack PUBLIC $<$<BOOL:${TaoJson}>:taocpp::json>)

if(Maintainer)
add_executable(buildVersion scripts/build-version.cpp)
Expand Down
21 changes: 21 additions & 0 deletions LICENSE.taocpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
The MIT License (MIT)

Copyright (c) 2007-2017 Dr. Colin Hirsch and Daniel Frey

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
265 changes: 265 additions & 0 deletions include/velocypack/Json.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,265 @@
// Author: Dr. Colin Hirsch

#ifndef ARANGODB_VELOCYPACK_JSON_H
#define ARANGODB_VELOCYPACK_JSON_H

#include <string>
#include <vector>

#include "tao/json.hpp"

#include "velocypack/Builder.h"
#include "velocypack/Iterator.h"
#include "velocypack/Options.h"
#include "velocypack/Slice.h"
#include "velocypack/Value.h"
#include "velocypack/ValueType.h"

namespace arangodb
{
namespace velocypack
{
// Class that consumes taocpp/json Events, i.e.
// implements the standard taocpp/json Events
// API, and feeds them into a Builder.

class EventsToBuilder
{
private:
std::string m_key;
bool m_member = false;

void add( const Value& v )
{
if ( m_member ) {
builder->add( m_key, v );
m_member = false;
}
else {
builder->add( v );
}
}

void add( const ValuePair& v )
{
if ( m_member ) {
builder->add( m_key, v );
m_member = false;
}
else {
builder->add( v );
}
}

public:
std::shared_ptr< Builder > builder;

EventsToBuilder()
: builder( std::make_shared< Builder >() )
{
}

EventsToBuilder( std::shared_ptr< Builder > && builder )
: builder( std::move( builder ) )
{
}

EventsToBuilder( const std::shared_ptr< Builder > & builder )
: builder( builder )
{
}

void null()
{
add( Value( ValueType::Null ) );
}

void boolean( const bool v )
{
add( Value( v ) );
}

void number( const std::int64_t v )
{
add( Value( v ) );
}

void number( const std::uint64_t v )
{
add( Value( v ) );
}

void number( const double v )
{
add( Value( v ) );
}

void string( const std::string_view v )
{
add( ValuePair( reinterpret_cast< const uint8_t* >( v.data() ), v.size(), ValueType::String ) );
}

void binary( const tao::binary_view v )
{
add( ValuePair( reinterpret_cast< const uint8_t* >( v.data() ), v.size(), ValueType::Binary ) );
}

void begin_array( const std::size_t = 0 )
{
add( Value( ValueType::Array ) );
}

void element()
{
}

void end_array( const std::size_t = 0 )
{
builder->close();
}

void begin_object( const std::size_t = 0 )
{
add( Value( ValueType::Object ) );
}

void key( const std::string& v )
{
m_key = v;
m_member = true;
}

void key( std::string&& v )
{
m_key = std::move( v );
m_member = true;
}

void member()
{
}

void end_object( const std::size_t = 0 )
{
builder->close();
}
};

// Function that produces taocpp/json Events from
// a given Slice (or Builder); the consumer must
// implement the taocpp/json Events API methods.

template< typename Consumer >
void sliceToEvents( Consumer& consumer, const Slice& slice )
{
switch( slice.type() ) {
case ValueType::None:
case ValueType::Illegal:
// TOOD: Decide what to do; for now fall through.
case ValueType::Null:
consumer.null();
break;
case ValueType::Bool:
consumer.boolean( slice.getBool() );
break;
case ValueType::Array: {
const auto size = slice.length();
consumer.begin_array( size );
for ( const auto& s : ArrayIterator( slice ) ) {
sliceToEvents( consumer, s );
consumer.element();
}
consumer.end_array( size );
} break;
case ValueType::Object: {
const auto size = slice.length();
consumer.begin_object( size );
for ( const auto& s : ObjectIterator( slice ) ) {
ValueLength size;
const char * data = s.key.getString( size );
consumer.key( std::string_view( data, size ) );
sliceToEvents( consumer, s.value );
consumer.member();
}
consumer.end_object( size );
} break;
case ValueType::Double:
consumer.number( slice.getDouble() );
break;
case ValueType::UTCDate:
// TODO: Implement when taocpp/json datetime support is finished.
break;
case ValueType::External:
// TODO: What?
break;
case ValueType::MinKey:
case ValueType::MaxKey:
// TODO: What?
break;
case ValueType::Int:
consumer.number( slice.getInt() );
break;
case ValueType::UInt:
consumer.number( slice.getUInt() );
break;
case ValueType::SmallInt:
consumer.number( slice.getSmallInt() );
break;
case ValueType::String: {
ValueLength size;
const char * data = slice.getString( size );
consumer.string( std::string_view( data, size ) );
} break;
case ValueType::Binary: {
ValueLength size;
const auto * data = slice.getBinary( size );
consumer.binary( tao::binary_view( reinterpret_cast< const std::byte* >( data ), size ) );
} break;
case ValueType::BCD:
// TODO: Convert to other number format or string?
break;
case ValueType::Custom:
// TODO: What?
case ValueType::Tagged:
// TODO: What?
break;
}
}

template< typename Consumer >
void builderToEvents( Consumer& consumer, const Builder& builder )
{
sliceToEvents( consumer, Slice( builder.start() ) );
}

inline void builderToJsonStream( std::ostream& stream, const Builder& builder )
{
tao::json::events::to_stream events( stream );
builderToEvents( events, builder );
}

inline void builderToPrettyJsonStream( std::ostream& stream, const Builder& builder, const std::size_t indent = 3 )
{
tao::json::events::to_pretty_stream events( stream, indent );
builderToEvents( events, builder );
}

inline std::string builderToJsonString( const Builder& builder )
{
std::ostringstream stream;
builderToJsonStream( stream, builder );
return stream.str();
}

inline std::string builderToPrettyJsonString( const Builder& builder, const std::size_t indent = 3 )
{
std::ostringstream stream;
builderToPrettyJsonStream( stream, builder, indent );
return stream.str();
}

} // velocypack

} // namespace arangodb

#endif
Loading