.
This commit is contained in:
@@ -95,6 +95,7 @@ ExternalProject_Add( celix_project
|
||||
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
CONFIGURE_COMMAND cmake ${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
-DCMAKE_INSTALL_PREFIX=${CATKIN_DEVEL_PREFIX}
|
||||
-DBUILD_SHARED_LIBS=TRUE
|
||||
-DBUILD_FRAMEWORK=TRUE
|
||||
-DBUILD_LAUNCHER=TRUE
|
||||
-DBUILD_UTILS=TRUE
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
cmake_minimum_required(VERSION 2.8.3)
|
||||
project(hos_cosgi_core)
|
||||
|
||||
## Find catkin macros and libraries
|
||||
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
|
||||
## is used, also find other catkin packages
|
||||
find_package(catkin REQUIRED COMPONENTS
|
||||
hos_celix
|
||||
)
|
||||
|
||||
## System dependencies are found with CMake's conventions
|
||||
# find_package(Boost REQUIRED COMPONENTS system)
|
||||
|
||||
|
||||
## Uncomment this if the package has a setup.py. This macro ensures
|
||||
## modules and global scripts declared therein get installed
|
||||
## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html
|
||||
# catkin_python_setup()
|
||||
|
||||
################################################
|
||||
## Declare ROS messages, services and actions ##
|
||||
################################################
|
||||
|
||||
## To declare and build messages, services or actions from within this
|
||||
## package, follow these steps:
|
||||
## * Let MSG_DEP_SET be the set of packages whose message types you use in
|
||||
## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
|
||||
## * In the file package.xml:
|
||||
## * add a build_depend and a run_depend tag for each package in MSG_DEP_SET
|
||||
## * If MSG_DEP_SET isn't empty the following dependencies might have been
|
||||
## pulled in transitively but can be declared for certainty nonetheless:
|
||||
## * add a build_depend tag for "message_generation"
|
||||
## * add a run_depend tag for "message_runtime"
|
||||
## * In this file (CMakeLists.txt):
|
||||
## * add "message_generation" and every package in MSG_DEP_SET to
|
||||
## find_package(catkin REQUIRED COMPONENTS ...)
|
||||
## * add "message_runtime" and every package in MSG_DEP_SET to
|
||||
## catkin_package(CATKIN_DEPENDS ...)
|
||||
## * uncomment the add_*_files sections below as needed
|
||||
## and list every .msg/.srv/.action file to be processed
|
||||
## * uncomment the generate_messages entry below
|
||||
## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)
|
||||
|
||||
## Generate messages in the 'msg' folder
|
||||
# add_message_files(
|
||||
# FILES
|
||||
# Message1.msg
|
||||
# Message2.msg
|
||||
# )
|
||||
|
||||
## Generate services in the 'srv' folder
|
||||
# add_service_files(
|
||||
# FILES
|
||||
# Service1.srv
|
||||
# Service2.srv
|
||||
# )
|
||||
|
||||
## Generate actions in the 'action' folder
|
||||
# add_action_files(
|
||||
# FILES
|
||||
# Action1.action
|
||||
# Action2.action
|
||||
# )
|
||||
|
||||
## Generate added messages and services with any dependencies listed here
|
||||
# generate_messages(
|
||||
# DEPENDENCIES
|
||||
# std_msgs # Or other packages containing msgs
|
||||
# )
|
||||
|
||||
###################################
|
||||
## catkin specific configuration ##
|
||||
###################################
|
||||
## The catkin_package macro generates cmake config files for your package
|
||||
## Declare things to be passed to dependent projects
|
||||
## INCLUDE_DIRS: uncomment this if you package contains header files
|
||||
## LIBRARIES: libraries you create in this project that dependent projects also need
|
||||
## CATKIN_DEPENDS: catkin_packages dependent projects also need
|
||||
## DEPENDS: system dependencies of this project that dependent projects also need
|
||||
catkin_package(
|
||||
INCLUDE_DIRS include
|
||||
# LIBRARIES hos_cosgi_core
|
||||
CATKIN_DEPENDS hos_celix
|
||||
# DEPENDS system_lib
|
||||
)
|
||||
|
||||
###########
|
||||
## Build ##
|
||||
###########
|
||||
|
||||
## Specify additional locations of header files
|
||||
## Your package locations should be listed before other locations
|
||||
# include_directories(include)
|
||||
include_directories(
|
||||
${catkin_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
## Declare a cpp library
|
||||
# add_library(hos_cosgi_core
|
||||
# src/${PROJECT_NAME}/hos_cosgi_core.cpp
|
||||
# )
|
||||
|
||||
## Declare a cpp executable
|
||||
# add_executable(hos_cosgi_core_node src/hos_cosgi_core_node.cpp)
|
||||
|
||||
## Add cmake target dependencies of the executable/library
|
||||
## as an example, message headers may need to be generated before nodes
|
||||
# add_dependencies(hos_cosgi_core_node hos_cosgi_core_generate_messages_cpp)
|
||||
|
||||
## Specify libraries to link a library or executable target against
|
||||
# target_link_libraries(hos_cosgi_core_node
|
||||
# ${catkin_LIBRARIES}
|
||||
# )
|
||||
|
||||
#############
|
||||
## Install ##
|
||||
#############
|
||||
|
||||
# all install targets should use catkin DESTINATION variables
|
||||
# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html
|
||||
|
||||
## Mark executable scripts (Python etc.) for installation
|
||||
## in contrast to setup.py, you can choose the destination
|
||||
# install(PROGRAMS
|
||||
# scripts/my_python_script
|
||||
# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
|
||||
# )
|
||||
|
||||
## Mark executables and/or libraries for installation
|
||||
# install(TARGETS hos_cosgi_core hos_cosgi_core_node
|
||||
# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
|
||||
# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
|
||||
# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
|
||||
# )
|
||||
|
||||
## Mark cpp header files for installation
|
||||
install(DIRECTORY include/${PROJECT_NAME}/
|
||||
DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
|
||||
FILES_MATCHING PATTERN "*.h"
|
||||
PATTERN ".svn" EXCLUDE
|
||||
)
|
||||
|
||||
## Mark other files for installation (e.g. launch and bag files, etc.)
|
||||
# install(FILES
|
||||
# # myfile1
|
||||
# # myfile2
|
||||
# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
|
||||
# )
|
||||
|
||||
#############
|
||||
## Testing ##
|
||||
#############
|
||||
|
||||
## Add gtest based cpp test target and link libraries
|
||||
# catkin_add_gtest(${PROJECT_NAME}-test test/test_hos_cosgi_core.cpp)
|
||||
# if(TARGET ${PROJECT_NAME}-test)
|
||||
# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
|
||||
# endif()
|
||||
|
||||
## Add folders to be run by python nosetests
|
||||
# catkin_add_nosetests(test)
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* cosgi_core.h
|
||||
*
|
||||
* Created on: 19.04.2015
|
||||
* Author: matzman
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_HOS_COSGI_CORE_COSGI_CORE_H_
|
||||
#define INCLUDE_HOS_COSGI_CORE_COSGI_CORE_H_
|
||||
|
||||
|
||||
class COSGI_Object_Interface {
|
||||
public:
|
||||
virtual ~COSGI_Object_Interface() {}
|
||||
};
|
||||
|
||||
|
||||
class COSGI_Service_Interface : public COSGI_Object_Interface {
|
||||
public:
|
||||
virtual const char* getServiceName() = 0;
|
||||
virtual void getServiceVersion(int& major, int& minor) = 0;
|
||||
};
|
||||
|
||||
|
||||
#endif /* INCLUDE_HOS_COSGI_CORE_COSGI_CORE_H_ */
|
||||
@@ -0,0 +1,52 @@
|
||||
<?xml version="1.0"?>
|
||||
<package>
|
||||
<name>hos_cosgi_core</name>
|
||||
<version>0.0.0</version>
|
||||
<description>The hos_cosgi_core package</description>
|
||||
|
||||
<!-- One maintainer tag required, multiple allowed, one person per tag -->
|
||||
<!-- Example: -->
|
||||
<!-- <maintainer email="jane.doe@example.com">Jane Doe</maintainer> -->
|
||||
<maintainer email="matzman@todo.todo">matzman</maintainer>
|
||||
|
||||
|
||||
<!-- One license tag required, multiple allowed, one license per tag -->
|
||||
<!-- Commonly used license strings: -->
|
||||
<!-- BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 -->
|
||||
<license>TODO</license>
|
||||
|
||||
|
||||
<!-- Url tags are optional, but mutiple are allowed, one per tag -->
|
||||
<!-- Optional attribute type can be: website, bugtracker, or repository -->
|
||||
<!-- Example: -->
|
||||
<!-- <url type="website">http://wiki.ros.org/hos_cosgi_core</url> -->
|
||||
|
||||
|
||||
<!-- Author tags are optional, mutiple are allowed, one per tag -->
|
||||
<!-- Authors do not have to be maintianers, but could be -->
|
||||
<!-- Example: -->
|
||||
<!-- <author email="jane.doe@example.com">Jane Doe</author> -->
|
||||
|
||||
|
||||
<!-- The *_depend tags are used to specify dependencies -->
|
||||
<!-- Dependencies can be catkin packages or system dependencies -->
|
||||
<!-- Examples: -->
|
||||
<!-- Use build_depend for packages you need at compile time: -->
|
||||
<!-- <build_depend>message_generation</build_depend> -->
|
||||
<!-- Use buildtool_depend for build tool packages: -->
|
||||
<!-- <buildtool_depend>catkin</buildtool_depend> -->
|
||||
<!-- Use run_depend for packages you need at runtime: -->
|
||||
<!-- <run_depend>message_runtime</run_depend> -->
|
||||
<!-- Use test_depend for packages you need only for testing: -->
|
||||
<!-- <test_depend>gtest</test_depend> -->
|
||||
<buildtool_depend>catkin</buildtool_depend>
|
||||
<build_depend>hos_celix</build_depend>
|
||||
<run_depend>hos_celix</run_depend>
|
||||
|
||||
|
||||
<!-- The export tag contains other, unspecified, tags -->
|
||||
<export>
|
||||
<!-- Other tools can request additional information be placed here -->
|
||||
|
||||
</export>
|
||||
</package>
|
||||
@@ -8,6 +8,9 @@ find_package(catkin REQUIRED COMPONENTS
|
||||
hos_celix
|
||||
hos_core_msgs
|
||||
hos_cosgi_launcher
|
||||
hos_cosgi_core
|
||||
hos_libvariant
|
||||
roscpp
|
||||
)
|
||||
|
||||
## System dependencies are found with CMake's conventions
|
||||
@@ -87,7 +90,7 @@ find_package(Boost REQUIRED)
|
||||
catkin_package(
|
||||
INCLUDE_DIRS include
|
||||
# LIBRARIES hos_cosgi_devicerepository
|
||||
CATKIN_DEPENDS hos_celix hos_core_msgs hos_cosgi_launcher
|
||||
CATKIN_DEPENDS hos_celix hos_core_msgs hos_cosgi_launcher roscpp hos_cosgi_core hos_libvariant
|
||||
# DEPENDS system_lib
|
||||
)
|
||||
|
||||
|
||||
+6
-10
@@ -2,6 +2,7 @@
|
||||
#define _HOS_DEVICEREPOSITORY_SERVICE_H_
|
||||
|
||||
|
||||
#include <hos_cosgi_core/cosgi_core.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -11,10 +12,8 @@ namespace hos {
|
||||
class DeviceEvent;
|
||||
class DeviceEventListener;
|
||||
|
||||
class GenericDevice {
|
||||
class GenericDevice : public COSGI_Object_Interface {
|
||||
public:
|
||||
virtual ~GenericDevice() {}
|
||||
|
||||
virtual std::string getDeviceID() = 0;
|
||||
|
||||
virtual bool registerDeviceStatusListener(DeviceEventListener& listener) = 0;
|
||||
@@ -30,26 +29,23 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class DeviceEventListener {
|
||||
class DeviceEventListener : public COSGI_Object_Interface {
|
||||
public:
|
||||
virtual ~DeviceEventListener() {}
|
||||
virtual void deviceEventReceived(const DeviceEvent& event) = 0;
|
||||
};
|
||||
|
||||
|
||||
class HOSDeviceRepositoryService {
|
||||
class HOSDeviceRepositoryService : public COSGI_Service_Interface {
|
||||
public:
|
||||
static constexpr const char* SERVICE_NAME = "hos_devicerepository_service";
|
||||
|
||||
virtual ~HOSDeviceRepositoryService() {}
|
||||
static constexpr int SERVICE_VERSION_MAJOR = 1;
|
||||
static constexpr int SERVICE_VERSION_MINOR = 0;
|
||||
|
||||
virtual GenericDevice* getDevice(std::string device_id) = 0;
|
||||
virtual std::vector<GenericDevice*>& getDevices(std::vector<GenericDevice*>& devices) = 0;
|
||||
|
||||
virtual bool registerDeviceStatusListener(DeviceEventListener& listener) = 0;
|
||||
virtual bool unregisterDeviceStatusListener(DeviceEventListener& listener) = 0;
|
||||
|
||||
virtual void getVersion(int& major, int& minor) = 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -43,9 +43,15 @@
|
||||
<build_depend>hos_celix</build_depend>
|
||||
<build_depend>hos_core_msgs</build_depend>
|
||||
<build_depend>hos_cosgi_launcher</build_depend>
|
||||
<build_depend>roscpp</build_depend>
|
||||
<build_depend>hos_cosgi_core</build_depend>
|
||||
<build_depend>hos_libvariant</build_depend>
|
||||
<run_depend>hos_celix</run_depend>
|
||||
<run_depend>hos_core_msgs</run_depend>
|
||||
<run_depend>hos_cosgi_launcher</run_depend>
|
||||
<run_depend>roscpp</run_depend>
|
||||
<run_depend>hos_cosgi_core</run_depend>
|
||||
<run_depend>hos_libvariant</run_depend>
|
||||
|
||||
|
||||
<!-- The export tag contains other, unspecified, tags -->
|
||||
@@ -56,4 +62,4 @@
|
||||
<!-- Other tools can request additional information be placed here -->
|
||||
|
||||
</export>
|
||||
</package>
|
||||
</package>
|
||||
|
||||
@@ -56,7 +56,7 @@ celix_status_t bundleActivator_start(void * userData, bundle_context_pt context)
|
||||
ROS_ERROR("DeviceRepositoryService: Could not retrieve HOSCoreService.");
|
||||
} else {
|
||||
int major = 0, minor = 0;
|
||||
coreService->getVersion(major, minor);
|
||||
coreService->getServiceVersion(major, minor);
|
||||
ROS_INFO_STREAM("DeviceRepositoryService: Found HOSCoreService Version " << major << "." << minor);
|
||||
// Create and register hos-devicerepository-service
|
||||
if (myUserData->serviceReg != nullptr) {
|
||||
|
||||
@@ -41,8 +41,6 @@ HOSDeviceRepositoryServiceImpl::HOSDeviceRepositoryServiceImpl(HOSCoreService& c
|
||||
privateNodeHandle.getParam("~device_repository_prefix", deviceRepositoryPrefix);
|
||||
}
|
||||
|
||||
HOSDeviceRepositoryServiceImpl::~HOSDeviceRepositoryServiceImpl() {}
|
||||
|
||||
GenericDevice* HOSDeviceRepositoryServiceImpl::getDevice(std::string device_id) {
|
||||
return this->devices[device_id];
|
||||
}
|
||||
@@ -75,9 +73,9 @@ bool HOSDeviceRepositoryServiceImpl::unregisterDeviceStatusListener(DeviceEventL
|
||||
}
|
||||
|
||||
|
||||
void HOSDeviceRepositoryServiceImpl::getVersion(int& major, int& minor) {
|
||||
major = 1;
|
||||
minor = 0;
|
||||
void HOSDeviceRepositoryServiceImpl::getServiceVersion(int& major, int& minor) {
|
||||
major = SERVICE_VERSION_MAJOR;
|
||||
minor = SERVICE_VERSION_MINOR;
|
||||
}
|
||||
|
||||
int HOSDeviceRepositoryServiceImpl::getRefCount() {
|
||||
|
||||
@@ -45,7 +45,6 @@ private:
|
||||
|
||||
public:
|
||||
HOSDeviceRepositoryServiceImpl(HOSCoreService& coreService);
|
||||
virtual ~HOSDeviceRepositoryServiceImpl();
|
||||
|
||||
virtual GenericDevice* getDevice(std::string device_id);
|
||||
virtual std::vector<GenericDevice*>& getDevices(std::vector<GenericDevice*>& devices);
|
||||
@@ -53,7 +52,9 @@ public:
|
||||
virtual bool registerDeviceStatusListener(DeviceEventListener& listener);
|
||||
virtual bool unregisterDeviceStatusListener(DeviceEventListener& listener);
|
||||
|
||||
virtual void getVersion(int& major, int& minor);
|
||||
virtual const char* getServiceName() { return SERVICE_NAME; }
|
||||
virtual void getServiceVersion(int& major, int& minor);
|
||||
|
||||
virtual int getRefCount();
|
||||
};
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ project(hos_cosgi_launcher)
|
||||
find_package(catkin REQUIRED COMPONENTS
|
||||
hos_celix
|
||||
roscpp
|
||||
hos_cosgi_core
|
||||
)
|
||||
|
||||
## System dependencies are found with CMake's conventions
|
||||
@@ -82,7 +83,7 @@ find_package(APR REQUIRED)
|
||||
catkin_package(
|
||||
INCLUDE_DIRS include
|
||||
# LIBRARIES hos_cosgi_launcher
|
||||
CATKIN_DEPENDS hos_celix
|
||||
CATKIN_DEPENDS hos_celix hos_cosgi_core
|
||||
# DEPENDS system_lib
|
||||
)
|
||||
|
||||
|
||||
@@ -2,22 +2,24 @@
|
||||
#define SRC_HOS_CORE_SERVICE_H_
|
||||
|
||||
|
||||
#include <hos_cosgi_core/cosgi_core.h>
|
||||
|
||||
|
||||
namespace ros {
|
||||
class NodeHandle;
|
||||
}
|
||||
|
||||
namespace hos {
|
||||
|
||||
class HOSCoreService {
|
||||
class HOSCoreService : public COSGI_Service_Interface {
|
||||
public:
|
||||
static constexpr const char* SERVICE_NAME = "hos_core_service";
|
||||
|
||||
virtual ~HOSCoreService() {}
|
||||
static constexpr int SERVICE_VERSION_MAJOR = 1;
|
||||
static constexpr int SERVICE_VERSION_MINOR = 0;
|
||||
|
||||
virtual ros::NodeHandle& getPublicNodeHandle() = 0;
|
||||
virtual ros::NodeHandle& getPrivateNodeHandle() = 0;
|
||||
virtual void requestShutdown() = 0;
|
||||
virtual void getVersion(int& major, int& minor) = 0;
|
||||
};
|
||||
|
||||
} // namespace hos
|
||||
|
||||
@@ -42,8 +42,10 @@
|
||||
<buildtool_depend>catkin</buildtool_depend>
|
||||
<build_depend>hos_celix</build_depend>
|
||||
<build_depend>roscpp</build_depend>
|
||||
<build_depend>hos_cosgi_core</build_depend>
|
||||
<run_depend>hos_celix</run_depend>
|
||||
<run_depend>roscpp</run_depend>
|
||||
<run_depend>hos_cosgi_core</run_depend>
|
||||
|
||||
|
||||
<!-- The export tag contains other, unspecified, tags -->
|
||||
|
||||
@@ -14,8 +14,6 @@ namespace hos {
|
||||
HOSCoreServiceImpl::HOSCoreServiceImpl(ros::NodeHandle& publicNodeHandle, ros::NodeHandle& privateNodeHandle)
|
||||
: publicNodeHandle(publicNodeHandle), privateNodeHandle(privateNodeHandle) {}
|
||||
|
||||
HOSCoreServiceImpl::~HOSCoreServiceImpl() {}
|
||||
|
||||
|
||||
ros::NodeHandle& HOSCoreServiceImpl::getPublicNodeHandle() {
|
||||
return publicNodeHandle;
|
||||
@@ -31,9 +29,9 @@ void HOSCoreServiceImpl::requestShutdown() {
|
||||
ros::shutdown();
|
||||
}
|
||||
|
||||
void HOSCoreServiceImpl::getVersion(int& major, int& minor) {
|
||||
major = 1;
|
||||
minor = 0;
|
||||
void HOSCoreServiceImpl::getServiceVersion(int& major, int& minor) {
|
||||
major = SERVICE_VERSION_MAJOR;
|
||||
minor = SERVICE_VERSION_MINOR;
|
||||
}
|
||||
|
||||
} // namespace hos
|
||||
|
||||
@@ -20,12 +20,12 @@ private:
|
||||
|
||||
public:
|
||||
HOSCoreServiceImpl(ros::NodeHandle& publicNodeHandle, ros::NodeHandle& privateNodeHandle);
|
||||
virtual ~HOSCoreServiceImpl();
|
||||
|
||||
virtual ros::NodeHandle& getPublicNodeHandle();
|
||||
virtual ros::NodeHandle& getPrivateNodeHandle();
|
||||
virtual void requestShutdown();
|
||||
virtual void getVersion(int& major, int& minor);
|
||||
virtual const char* getServiceName() { return SERVICE_NAME; }
|
||||
virtual void getServiceVersion(int& major, int& minor);
|
||||
};
|
||||
|
||||
} // namespace hos
|
||||
|
||||
@@ -0,0 +1,193 @@
|
||||
cmake_minimum_required(VERSION 2.8.3)
|
||||
project(hos_libvariant)
|
||||
|
||||
## Find catkin macros and libraries
|
||||
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
|
||||
## is used, also find other catkin packages
|
||||
find_package(catkin REQUIRED)
|
||||
|
||||
## System dependencies are found with CMake's conventions
|
||||
# find_package(Boost REQUIRED COMPONENTS system)
|
||||
|
||||
|
||||
## Uncomment this if the package has a setup.py. This macro ensures
|
||||
## modules and global scripts declared therein get installed
|
||||
## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html
|
||||
# catkin_python_setup()
|
||||
|
||||
################################################
|
||||
## Declare ROS messages, services and actions ##
|
||||
################################################
|
||||
|
||||
## To declare and build messages, services or actions from within this
|
||||
## package, follow these steps:
|
||||
## * Let MSG_DEP_SET be the set of packages whose message types you use in
|
||||
## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
|
||||
## * In the file package.xml:
|
||||
## * add a build_depend and a run_depend tag for each package in MSG_DEP_SET
|
||||
## * If MSG_DEP_SET isn't empty the following dependencies might have been
|
||||
## pulled in transitively but can be declared for certainty nonetheless:
|
||||
## * add a build_depend tag for "message_generation"
|
||||
## * add a run_depend tag for "message_runtime"
|
||||
## * In this file (CMakeLists.txt):
|
||||
## * add "message_generation" and every package in MSG_DEP_SET to
|
||||
## find_package(catkin REQUIRED COMPONENTS ...)
|
||||
## * add "message_runtime" and every package in MSG_DEP_SET to
|
||||
## catkin_package(CATKIN_DEPENDS ...)
|
||||
## * uncomment the add_*_files sections below as needed
|
||||
## and list every .msg/.srv/.action file to be processed
|
||||
## * uncomment the generate_messages entry below
|
||||
## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)
|
||||
|
||||
## Generate messages in the 'msg' folder
|
||||
# add_message_files(
|
||||
# FILES
|
||||
# Message1.msg
|
||||
# Message2.msg
|
||||
# )
|
||||
|
||||
## Generate services in the 'srv' folder
|
||||
# add_service_files(
|
||||
# FILES
|
||||
# Service1.srv
|
||||
# Service2.srv
|
||||
# )
|
||||
|
||||
## Generate actions in the 'action' folder
|
||||
# add_action_files(
|
||||
# FILES
|
||||
# Action1.action
|
||||
# Action2.action
|
||||
# )
|
||||
|
||||
## Generate added messages and services with any dependencies listed here
|
||||
# generate_messages(
|
||||
# DEPENDENCIES
|
||||
# std_msgs # Or other packages containing msgs
|
||||
# )
|
||||
|
||||
###################################
|
||||
## catkin specific configuration ##
|
||||
###################################
|
||||
## The catkin_package macro generates cmake config files for your package
|
||||
## Declare things to be passed to dependent projects
|
||||
## INCLUDE_DIRS: uncomment this if you package contains header files
|
||||
## LIBRARIES: libraries you create in this project that dependent projects also need
|
||||
## CATKIN_DEPENDS: catkin_packages dependent projects also need
|
||||
## DEPENDS: system dependencies of this project that dependent projects also need
|
||||
catkin_package(
|
||||
INCLUDE_DIRS include
|
||||
LIBRARIES Variant
|
||||
# CATKIN_DEPENDS other_catkin_pkg
|
||||
# DEPENDS system_lib
|
||||
)
|
||||
|
||||
###########
|
||||
## Build ##
|
||||
###########
|
||||
|
||||
include(ExternalProject)
|
||||
|
||||
ExternalProject_Add( libvariant_project
|
||||
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
CONFIGURE_COMMAND cmake ${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
-DCMAKE_INSTALL_PREFIX=${CATKIN_DEVEL_PREFIX}
|
||||
-DBUILD_SHARED_LIBS=FALSE
|
||||
-DLIBVARIANT_BUILD_EXAMPLES=FALSE
|
||||
-DLIBVARIANT_BUILD_TESTS=FALSE
|
||||
-DLIBVARIANT_BUILD_WALL=TRUE
|
||||
-DLIBVARIANT_ENABLE_CURL=TRUE
|
||||
-DLIBVARIANT_ENABLE_MSGPACK=FALSE
|
||||
-DLIBVARIANT_ENABLE_XML=TRUE
|
||||
-DLIBVARIANT_ENABLE_YAML=TRUE
|
||||
BUILD_COMMAND make all
|
||||
INSTALL_COMMAND make install
|
||||
)
|
||||
|
||||
add_library( Variant STATIC IMPORTED )
|
||||
set_property( TARGET Variant PROPERTY IMPORTED_LOCATION "${CATKIN_DEVEL_PREFIX}/lib/libVariant.a")
|
||||
add_dependencies( Variant libvariant_project )
|
||||
|
||||
## Specify additional locations of header files
|
||||
## Your package locations should be listed before other locations
|
||||
# include_directories(include)
|
||||
|
||||
## Declare a cpp library
|
||||
# add_library(hos_libvariant
|
||||
# src/${PROJECT_NAME}/hos_libvariant.cpp
|
||||
# )
|
||||
|
||||
## Declare a cpp executable
|
||||
# add_executable(hos_libvariant_node src/hos_libvariant_node.cpp)
|
||||
|
||||
## Add cmake target dependencies of the executable/library
|
||||
## as an example, message headers may need to be generated before nodes
|
||||
# add_dependencies(hos_libvariant_node hos_libvariant_generate_messages_cpp)
|
||||
|
||||
## Specify libraries to link a library or executable target against
|
||||
# target_link_libraries(hos_libvariant_node
|
||||
# ${catkin_LIBRARIES}
|
||||
# )
|
||||
|
||||
#############
|
||||
## Install ##
|
||||
#############
|
||||
|
||||
install(DIRECTORY include/${PROJECT_NAME}/
|
||||
DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
|
||||
)
|
||||
install(DIRECTORY ${CATKIN_DEVEL_PREFIX}/lib/
|
||||
DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
|
||||
)
|
||||
install(DIRECTORY ${CATKIN_DEVEL_PREFIX}/bin/
|
||||
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
|
||||
USE_SOURCE_PERMISSIONS
|
||||
)
|
||||
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/cmake/
|
||||
DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/cmake
|
||||
FILES_MATCHING PATTERN "*.cmake"
|
||||
)
|
||||
|
||||
# all install targets should use catkin DESTINATION variables
|
||||
# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html
|
||||
|
||||
## Mark executable scripts (Python etc.) for installation
|
||||
## in contrast to setup.py, you can choose the destination
|
||||
# install(PROGRAMS
|
||||
# scripts/my_python_script
|
||||
# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
|
||||
# )
|
||||
|
||||
## Mark executables and/or libraries for installation
|
||||
# install(TARGETS hos_libvariant hos_libvariant_node
|
||||
# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
|
||||
# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
|
||||
# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
|
||||
# )
|
||||
|
||||
## Mark cpp header files for installation
|
||||
# install(DIRECTORY include/${PROJECT_NAME}/
|
||||
# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
|
||||
# FILES_MATCHING PATTERN "*.h"
|
||||
# PATTERN ".svn" EXCLUDE
|
||||
# )
|
||||
|
||||
## Mark other files for installation (e.g. launch and bag files, etc.)
|
||||
# install(FILES
|
||||
# # myfile1
|
||||
# # myfile2
|
||||
# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
|
||||
# )
|
||||
|
||||
#############
|
||||
## Testing ##
|
||||
#############
|
||||
|
||||
## Add gtest based cpp test target and link libraries
|
||||
# catkin_add_gtest(${PROJECT_NAME}-test test/test_hos_libvariant.cpp)
|
||||
# if(TARGET ${PROJECT_NAME}-test)
|
||||
# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
|
||||
# endif()
|
||||
|
||||
## Add folders to be run by python nosetests
|
||||
# catkin_add_nosetests(test)
|
||||
@@ -0,0 +1,302 @@
|
||||
/** \file
|
||||
* \author John Bridgman
|
||||
* \brief
|
||||
*/
|
||||
#ifndef VARIANT_ARGPARSER_H
|
||||
#define VARIANT_ARGPARSER_H
|
||||
|
||||
#pragma once
|
||||
#include "../hos_libvariant/Variant.h"
|
||||
#include <algorithm>
|
||||
#include <iosfwd>
|
||||
namespace libvariant {
|
||||
|
||||
|
||||
enum ArgParseAction {
|
||||
ARGACTION_UNKNOWN, // Unknown action (invalid)
|
||||
ARGACTION_STORE, // Interpret the option argument and store it at the path
|
||||
ARGACTION_STORE_CONST, // Store const into the path
|
||||
ARGACTION_STORE_TRUE, // Store true into the path
|
||||
ARGACTION_STORE_FALSE, // Store false into the path
|
||||
ARGACTION_APPEND, // Append the option argument to the list at path
|
||||
ARGACTION_COUNT, // Make the value at path be the count of this options occurrences
|
||||
ARGACTION_HELP, // Print out the help text and exit
|
||||
ARGACTION_ADVHELP, // Print the advanced help and exit
|
||||
ARGACTION_CONFIG, // Consider the option argument a filename to be loaded and parsed as a config
|
||||
ARGACTION_CONFIG_JSON, // force parser to use jscn
|
||||
ARGACTION_CONFIG_YAML, // force parser to use yaml
|
||||
ARGACTION_CONFIG_PLIST, // force parser to use xmlplist
|
||||
ARGACTION_PRINT_CONFIG // At the end of parsing print out the resulting config and exit.
|
||||
};
|
||||
|
||||
// A constrained list of only the valid types for ArgParse
|
||||
enum ArgParseType {
|
||||
ARGTYPE_GUESS = Variant::NullType, // No type specification, guess, uses deserialize machinery
|
||||
ARGTYPE_INT = Variant::IntegerType, // Error if it cannot be turned into an integer
|
||||
ARGTYPE_UINT = Variant::UnsignedType, // Error if it cannot be turned into a unsigned
|
||||
ARGTYPE_FLOAT = Variant::FloatType, // Error if it cannot be turned into a float
|
||||
ARGTYPE_STRING = Variant::StringType, // store as string
|
||||
ARGTYPE_BOOL = Variant::BoolType // Error if it cannot be turned into a boolean type
|
||||
// it treats 0 or the strings 'false' and 'no' or any substring ignoring case as false
|
||||
// and everything else as true
|
||||
};
|
||||
|
||||
//! Valid values are:
|
||||
// This is used for converting the enum to a Variant and back for
|
||||
// ArgParse::GetDescription and ArgParse::Merge
|
||||
// store -- store the value into the key (default)
|
||||
// store_const -- store const (see Const) into the key
|
||||
// store_true -- store true into the key (i.e. no option argument)
|
||||
// store_false -- store false into the key
|
||||
// append -- make the value a list of instances of the option
|
||||
// count -- count the number of instances of this argument
|
||||
// help -- display the help text and exit
|
||||
// config -- load a file and merge it into the result (uses GuessFormat)
|
||||
// config_json -- same as config, force to use json parser
|
||||
// config_yaml -- same as config, force to use yaml parser
|
||||
// config_plist -- same as config, force to use xml-plist parser
|
||||
// config_print -- when finished parsing, print out the config and exit
|
||||
ArgParseAction ArgParseActionFromStr(const std::string &action);
|
||||
std::string ArgParseActionToStr(ArgParseAction action);
|
||||
|
||||
class ArgParse;
|
||||
struct ArgParseImpl;
|
||||
struct ArgParseOptImpl;
|
||||
struct ArgParseGroupImpl;
|
||||
|
||||
//! ArgParseOption is a part of class ArgParse.
|
||||
// ArgParseOption is the interface that ArgParse provides to the user to be able
|
||||
// to conveniently set the options for an option.
|
||||
class ArgParseOption {
|
||||
public:
|
||||
|
||||
//! Set the title of this option. The title is used
|
||||
// as an argument placeholder string.
|
||||
ArgParseOption &Title(const std::string &title);
|
||||
|
||||
//! What action to perform when this option is encountered.
|
||||
// See ArgParseAction above for a list of actions.
|
||||
ArgParseOption &Action(ArgParseAction action);
|
||||
DEPRECATED ArgParseOption &Action(const std::string &action);
|
||||
|
||||
//! Set the type parsing and validation.
|
||||
// If set and the argument is not of this type, then it is invalid.
|
||||
// Default: ARGTYPE_GUESS
|
||||
// If type is ARGTYPE_GUESS then ArgParse attempts to parse the
|
||||
// argument with the same machinery that is used by the deserializers
|
||||
// to figure out the type of a scalar.
|
||||
// ARGTYPE_UINT is the same as ARGTYPE_INT but with
|
||||
// Minimum set to 0.
|
||||
// See ArgParseType for the list of valid types.
|
||||
ArgParseOption &Type(ArgParseType type);
|
||||
// Same as above but throws on invalid type
|
||||
DEPRECATED ArgParseOption &Type(Variant::Type_t type);
|
||||
// String version of the above
|
||||
// Valid types are "string", "number", "integer", "boolean", or "null".
|
||||
// Default type is "null".
|
||||
DEPRECATED ArgParseOption &Type(const std::string &type);
|
||||
|
||||
//! Set the const value for "store_const"
|
||||
ArgParseOption &Const(Variant val);
|
||||
|
||||
//! Set the default value used when the option is not set.
|
||||
ArgParseOption &Default(Variant val);
|
||||
|
||||
//! Set the environment variable name to check for a value for this option.
|
||||
// When the environment variable is present this acts like Default was set
|
||||
// to the environment variable's value. I.e., this overrides default,
|
||||
// command line arguments override this.
|
||||
ArgParseOption &Env(const char *env);
|
||||
|
||||
//! If the resulting value is a number, require to be at least this minimum.
|
||||
ArgParseOption &Minimum(Variant val);
|
||||
|
||||
//! If the resulting value is a number, require to be at most this maximum.
|
||||
ArgParseOption &Maximum(Variant val);
|
||||
|
||||
//! Add choices.
|
||||
// If a choice is added, the value of the option must be one of the choices.
|
||||
ArgParseOption &AddChoice(Variant val);
|
||||
|
||||
//! Set choices (old ones forgotten) from a vector.
|
||||
ArgParseOption &SetChoices(const std::vector<Variant> &val);
|
||||
|
||||
//! Return the vector of choices set.
|
||||
const std::vector<Variant> &GetChoices();
|
||||
|
||||
//! Is this option required?
|
||||
ArgParseOption &Required(bool req=true);
|
||||
|
||||
//! Set the help text for this option.
|
||||
ArgParseOption &Help(const std::string &helptxt);
|
||||
|
||||
//! If this option is a string, it must match the regex in pattern.
|
||||
ArgParseOption &Pattern(const std::string &pattern);
|
||||
|
||||
//! If this option is a string, it must be no longer than maxLength.
|
||||
ArgParseOption &MaxLength(unsigned l);
|
||||
|
||||
//! If this option is a string, it must be no shorter than minLength.
|
||||
ArgParseOption &MinLength(unsigned l);
|
||||
|
||||
//! If this option can be specified multiple times, it must be
|
||||
// specified minArgs times at least.
|
||||
// A value of 0 means zero arguments is valid.
|
||||
ArgParseOption &MinArgs(unsigned l);
|
||||
|
||||
//! If this option can be specified multiple times, it cannot be
|
||||
// specified more than maxArgs.
|
||||
// A value of 0 means any number
|
||||
ArgParseOption &MaxArgs(unsigned l);
|
||||
|
||||
//! Specify that this argument must be present l times.
|
||||
// Sets both minArgs and maxArgs to l
|
||||
ArgParseOption &NumArgs(unsigned l);
|
||||
|
||||
//! Adds this option to group gname. If gname does not exist,
|
||||
//it will be created with an empty title and description.
|
||||
ArgParseOption &Group(const std::string &gname);
|
||||
|
||||
//! Sets this argument to be an advanced option
|
||||
// This hides the option when not printing advanced options
|
||||
ArgParseOption &Advanced(bool adv = true);
|
||||
|
||||
private:
|
||||
ArgParseOption(ArgParseOptImpl *i) : impl(i) {}
|
||||
ArgParseOptImpl *impl;
|
||||
friend class ArgParse;
|
||||
};
|
||||
|
||||
//! Groups are a way to organize the option and to provide mutual exclusion
|
||||
//of option. An argument may be part of more than one group, but may only
|
||||
//be part of one group that has a non-empty title and description. An
|
||||
//attempt is made to order the help text so that options within the same
|
||||
//group appear together and if a group has a title and/or description the
|
||||
//options are placed within a subsection headed with the title and
|
||||
//description.
|
||||
class OptionGroup {
|
||||
public:
|
||||
//! Set the title for this group
|
||||
OptionGroup &Title(const std::string &t);
|
||||
//! Set the description for this group
|
||||
OptionGroup &Description(const std::string &d);
|
||||
//! Set that the options in this group are mutually exclusive
|
||||
OptionGroup &MutuallyExclusive(bool exclusive=true);
|
||||
//! Set that at least one option in this group is required.
|
||||
//Has no meaning when the group is not mutually exclusive.
|
||||
OptionGroup &Required(bool req=true);
|
||||
|
||||
OptionGroup &Add(const std::string &keypath);
|
||||
OptionGroup &Add(const Path &keypath);
|
||||
|
||||
//! Sets this option group to be advanced
|
||||
// Hide the group when not printing advanced options.
|
||||
// This only hides the group when it has a title or description
|
||||
OptionGroup &Advanced(bool adv=true);
|
||||
private:
|
||||
OptionGroup(ArgParseGroupImpl *i) : impl(i) {}
|
||||
ArgParseGroupImpl *impl;
|
||||
friend class ArgParse;
|
||||
};
|
||||
|
||||
class ArgParse {
|
||||
public:
|
||||
//! addhelp true causes AddHelp to be called.
|
||||
ArgParse(bool addhelp=true);
|
||||
ArgParse(const std::string &pname, bool addhelp=true);
|
||||
|
||||
//! Add the option and configure it as an option that takes an argument.
|
||||
//The default action will be "store" and type will be unspecified
|
||||
//
|
||||
// keypath must be a valid path as defined in Path.h
|
||||
//
|
||||
// For no short option, shortOpt may be 0, and for no long option, longOpt may be
|
||||
// the empty string. If both shortOpt is 0 and longOpt is empty then this option
|
||||
// is hidden unless Env is also set for the option.
|
||||
ArgParseOption AddOption(const std::string &keypath, int shortOpt, const std::string &longOpt="",
|
||||
const std::string &helptxt="");
|
||||
|
||||
//! Convenience methods for getting an existing option.
|
||||
// ArgParse args(argv[0]);
|
||||
// args.AddOption("key1", 'k', "key1", "how many things").Type("integer");
|
||||
// args.AddOption("key2", 'K', "key2", "what to name it").Type("string");
|
||||
// (... some intermediate code ...)
|
||||
// args.At("key1").Default(42);
|
||||
// args["key2"].Default("foo");
|
||||
ArgParseOption At(const std::string &keypath);
|
||||
ArgParseOption operator[](const std::string &keypath) { return At(keypath); }
|
||||
|
||||
//! Add the option and configure it as an option that is default false and
|
||||
//if present sets to true
|
||||
//i.e., same as:
|
||||
// AddOption(keypath, shortOpt, longOpt, helptxt).Type("boolean")
|
||||
// .Action("store_true").Default(false);
|
||||
ArgParseOption AddFlag(const std::string &keypath, int shortOpt, const std::string &longOpt="",
|
||||
const std::string &helptxt="");
|
||||
|
||||
//! Adds the group name.
|
||||
OptionGroup AddGroup(const std::string &name, const std::string &title="", const std::string &description="");
|
||||
//! Returns the group name.
|
||||
OptionGroup GetGroup(const std::string &name);
|
||||
|
||||
//! Add a positional argument.
|
||||
// By default the new positional argument will have NumArgs as 1.
|
||||
// Arguments are processed in the order they are added.
|
||||
// If maxArgs is 0, then no positional arguments after this one will
|
||||
// be processed.
|
||||
// Default action is store.
|
||||
ArgParseOption AddArgument(const std::string &keypath, const std::string &helptxt="");
|
||||
|
||||
//! Convenience methods for getting an existing argument.
|
||||
// ArgParse args(argv[0]);
|
||||
// args.AddArgument("arg0", "pick one").AddChoice("AAA").AddChoice("BBB");
|
||||
// args.AddArgument("arg1", "scale factor").Type("float");
|
||||
// (... some intermediate code ...)
|
||||
// args.At(0).AddChoice("CCC");
|
||||
// args[1].Default(0.456);
|
||||
ArgParseOption At(size_t argumentIndex);
|
||||
ArgParseOption operator[](size_t argumentIndex) { return At(argumentIndex); }
|
||||
|
||||
//! When this is on, trying to add a second option with the same short option
|
||||
//will cause the second option to act as though it had no short option specified.
|
||||
void ConflictResolution(bool resolve=true);
|
||||
|
||||
//! Add a --config and --print-config option
|
||||
// --config is set with action ARGACTION_CONFIG and
|
||||
// --print-config is set with action ARGACTION_PRINT_CONFIG
|
||||
void AddConfigDefaults();
|
||||
|
||||
//! Add -h,--help option with action ARGACTION_HELP
|
||||
void AddHelp();
|
||||
|
||||
//! Set the description text that follows the usage message.
|
||||
void SetDescription(const std::string &txt);
|
||||
//! Set the epilog text at the end of help.
|
||||
void SetEpilog(const std::string &txt);
|
||||
//! Override the default program name.
|
||||
void SetProgramName(const std::string &pname, bool do_basename=true);
|
||||
std::string GetProgramName() const;
|
||||
|
||||
void Merge(Variant newopts);
|
||||
void Merge(const ArgParse &other);
|
||||
|
||||
//! Validate the argparse description against the internal schema
|
||||
void Validate() const;
|
||||
|
||||
//! Parse the arguments with the internal description
|
||||
Variant Parse(int argc, char *const *argv);
|
||||
|
||||
//! Print the help message and exit.
|
||||
void PrintHelp(bool advanced=false) const;
|
||||
|
||||
//! Return the Variant that describes the arguments
|
||||
Variant GetDescription() const;
|
||||
|
||||
//! Generate a schema for the Variant returned by Parse from the argument description
|
||||
Variant GenerateSchema() const;
|
||||
|
||||
private:
|
||||
shared_ptr<ArgParseImpl> impl;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,63 @@
|
||||
/** \file
|
||||
* \author John Bridgman
|
||||
* \brief
|
||||
*/
|
||||
#ifndef VARIANT_BLOB_H
|
||||
#define VARIANT_BLOB_H
|
||||
|
||||
#pragma once
|
||||
#include "../../../src/include/Variant/SharedPtr.h"
|
||||
#include <vector>
|
||||
#include <sys/uio.h>
|
||||
|
||||
namespace libvariant {
|
||||
class Blob;
|
||||
typedef shared_ptr<Blob> BlobPtr;
|
||||
typedef shared_ptr<const Blob> ConstBlobPtr;
|
||||
|
||||
typedef void (*BlobFreeFunc)(void *ptr, void *ctx);
|
||||
|
||||
class Blob {
|
||||
public:
|
||||
|
||||
/// Reference the buffer and call ffunc when Blob no longer references it
|
||||
static BlobPtr Create(void *ptr, unsigned len, BlobFreeFunc ffunc, void *context);
|
||||
/// Will call ffunc on each buffer in iov
|
||||
static BlobPtr Create(struct iovec *iov, unsigned iov_len, BlobFreeFunc ffunc, void *context);
|
||||
/// Copy the data into a newly allocatd buffer
|
||||
static BlobPtr CreateCopy(const void *ptr, unsigned len);
|
||||
static BlobPtr CreateCopy(const struct iovec *iov, unsigned iov_len);
|
||||
/// Reference the buffer and when done call free to free the buffer
|
||||
static BlobPtr CreateFree(void *ptr, unsigned len);
|
||||
static BlobPtr CreateFree(struct iovec *iov, unsigned iov_len);
|
||||
/// Reference the buffer, assume static or other allocation lifetime where
|
||||
// calling a free function is not required
|
||||
static BlobPtr CreateReferenced(void *ptr, unsigned len);
|
||||
static BlobPtr CreateReferenced(struct iovec *iov, unsigned iov_len);
|
||||
~Blob();
|
||||
|
||||
BlobPtr Copy() const;
|
||||
|
||||
void *GetPtr(unsigned i) { return iov[i].iov_base; }
|
||||
const void *GetPtr(unsigned i) const { return iov[i].iov_base; }
|
||||
unsigned GetLength(unsigned i) const { return iov[i].iov_len; }
|
||||
struct iovec *GetIOVec() { return &iov[0]; }
|
||||
const struct iovec *GetIOVec() const { return &iov[0]; }
|
||||
unsigned GetNumBuffers() const { return iov.size(); }
|
||||
unsigned GetTotalLength() const;
|
||||
|
||||
int Compare(ConstBlobPtr other) const;
|
||||
|
||||
private:
|
||||
Blob();
|
||||
Blob(const Blob&);
|
||||
Blob(struct iovec *v, unsigned l, BlobFreeFunc f, void *c);
|
||||
Blob operator=(const Blob&);
|
||||
|
||||
std::vector<struct iovec> iov;
|
||||
BlobFreeFunc free_func;
|
||||
void *ctx;
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,13 @@
|
||||
/** \file
|
||||
* \author John Bridgman
|
||||
* \brief
|
||||
*/
|
||||
#ifndef VARIANT_CONFIG_H
|
||||
#define VARIANT_CONFIG_H
|
||||
#pragma once
|
||||
|
||||
/* #undef HAVE_CXX11_SHAREDPTR */
|
||||
#define HAVE_TR1_SHAREDPTR 1
|
||||
/* #undef USE_BOOST_SHAREDPTR */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,226 @@
|
||||
//=============================================================================
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Library General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// The GNU Public License is available in the file LICENSE, or you
|
||||
// can write to the Free Software Foundation, Inc., 59 Temple Place -
|
||||
// Suite 330, Boston, MA 02111-1307, USA, or you can find it on the
|
||||
// World Wide Web at http://www.fsf.org.
|
||||
//=============================================================================
|
||||
/** \file
|
||||
* \author John Bridgman
|
||||
* \brief
|
||||
*/
|
||||
#ifndef VARIANT_EMITTER_H
|
||||
#define VARIANT_EMITTER_H
|
||||
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include "../../../src/include/Variant/Variant.h"
|
||||
#include "../../../src/include/Variant/Blob.h"
|
||||
#include "../../../src/include/Variant/EmitterOutput.h"
|
||||
#include <iosfwd>
|
||||
#include <stdio.h>
|
||||
|
||||
namespace libvariant {
|
||||
|
||||
/**
|
||||
* Class to override to implement an Emitter
|
||||
*/
|
||||
class EmitterImpl {
|
||||
public:
|
||||
virtual ~EmitterImpl();
|
||||
|
||||
virtual void BeginDocument() = 0;
|
||||
virtual void EndDocument() = 0;
|
||||
virtual void BeginMap(int length) = 0;
|
||||
virtual void EndMap() = 0;
|
||||
virtual void BeginList(int length) = 0;
|
||||
virtual void EndList() = 0;
|
||||
|
||||
virtual void EmitNull() = 0;
|
||||
virtual void EmitTrue() = 0;
|
||||
virtual void EmitFalse() = 0;
|
||||
virtual void Emit(const char *v) = 0;
|
||||
virtual void Emit(intmax_t v) = 0;
|
||||
virtual void Emit(uintmax_t v) = 0;
|
||||
virtual void Emit(double v) = 0;
|
||||
virtual void Emit(ConstBlobPtr b) = 0;
|
||||
|
||||
virtual void Flush() = 0;
|
||||
virtual void Close() = 0;
|
||||
|
||||
virtual Variant GetParam(const std::string &key) = 0;
|
||||
virtual Variant GetParams() = 0;
|
||||
virtual void SetParam(const std::string &key, Variant value) = 0;
|
||||
virtual void SetParams(Variant params);
|
||||
};
|
||||
|
||||
/**
|
||||
* Actual emitter class.
|
||||
*/
|
||||
class Emitter {
|
||||
public:
|
||||
Emitter();
|
||||
Emitter(shared_ptr<EmitterImpl> i);
|
||||
~Emitter();
|
||||
|
||||
Emitter &BeginDocument();
|
||||
Emitter &EndDocument();
|
||||
|
||||
//Some emitter implementations require the length of the map at the
|
||||
//beginning. Such implementations should buffer events if length == -1
|
||||
//Implementations are free to ignore the length.
|
||||
Emitter &BeginMap() { return BeginMap(-1); }
|
||||
Emitter &BeginMap(int length);
|
||||
Emitter &EndMap();
|
||||
//Some emitter implementations require the length of the list at the
|
||||
//beginning. Such implementations should buffer events if length == -1
|
||||
Emitter &BeginList() { return BeginList(-1); }
|
||||
Emitter &BeginList(int length);
|
||||
Emitter &EndList();
|
||||
|
||||
Emitter &EmitNull();
|
||||
Emitter &EmitTrue();
|
||||
Emitter &EmitFalse();
|
||||
Emitter &Emit(bool v) { return (v ? EmitTrue() : EmitFalse()); }
|
||||
Emitter &Emit(const std::string &v);
|
||||
Emitter &Emit(const char *v);
|
||||
Emitter &Emit(intmax_t v);
|
||||
Emitter &Emit(uintmax_t v);
|
||||
Emitter &Emit(double v);
|
||||
Emitter &Emit(ConstBlobPtr b);
|
||||
|
||||
void Flush();
|
||||
void Close();
|
||||
|
||||
/// Get the value of parameters of the parser (e.g. pretty printing,
|
||||
// styles, etc.)
|
||||
// See individual emitter below for supported values.
|
||||
Variant GetParam(const std::string &key);
|
||||
/// Get a dict of all parameters
|
||||
Variant GetParams();
|
||||
/// Set the value of parameters.
|
||||
// See individual emitter below for supported values.
|
||||
void SetParam(const std::string &key, Variant value);
|
||||
/// Set all parameters from a dict
|
||||
void SetParams(Variant params);
|
||||
/// Internal/advanced function to get the underlying implementation
|
||||
shared_ptr<EmitterImpl> GetImpl() { return impl; }
|
||||
private:
|
||||
shared_ptr<EmitterImpl> impl;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline Emitter &operator<<(Emitter &e, const std::vector<T> &v) {
|
||||
e.BeginList(v.size());
|
||||
for (typename std::vector<T>::const_iterator i(v.begin()), end(v.end()); i!=end; i++) {
|
||||
e << *i;
|
||||
}
|
||||
e.EndList();
|
||||
return e;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline Emitter &operator<<(Emitter &e, const std::map<std::string, T> &v) {
|
||||
e.BeginMap(v.size());
|
||||
for (typename std::map<std::string, T>::const_iterator i(v.begin()), end(v.end()); i!=end; ++i) {
|
||||
e.Emit(i->first);
|
||||
e << i->second;
|
||||
}
|
||||
e.EndMap();
|
||||
return e;
|
||||
}
|
||||
inline Emitter &operator<<(Emitter &e, bool v) { e.Emit(v); return e; }
|
||||
inline Emitter &operator<<(Emitter &e, char v) { e.Emit(intmax_t(v)); return e; }
|
||||
inline Emitter &operator<<(Emitter &e, short v) { e.Emit(intmax_t(v)); return e; }
|
||||
inline Emitter &operator<<(Emitter &e, int v) { e.Emit(intmax_t(v)); return e; }
|
||||
inline Emitter &operator<<(Emitter &e, long v) { e.Emit(intmax_t(v)); return e; }
|
||||
inline Emitter &operator<<(Emitter &e, long long v) { e.Emit(intmax_t(v)); return e; }
|
||||
inline Emitter &operator<<(Emitter &e, unsigned char v) { e.Emit(uintmax_t(v)); return e; }
|
||||
inline Emitter &operator<<(Emitter &e, unsigned short v) { e.Emit(uintmax_t(v)); return e; }
|
||||
inline Emitter &operator<<(Emitter &e, unsigned int v) { e.Emit(uintmax_t(v)); return e; }
|
||||
inline Emitter &operator<<(Emitter &e, unsigned long v) { e.Emit(uintmax_t(v)); return e; }
|
||||
inline Emitter &operator<<(Emitter &e, unsigned long long v) { e.Emit(uintmax_t(v)); return e; }
|
||||
inline Emitter &operator<<(Emitter &e, const char *v) { e.Emit(v); return e; }
|
||||
inline Emitter &operator<<(Emitter &e, const std::string &v) { e.Emit(v); return e; }
|
||||
inline Emitter &operator<<(Emitter &e, float v) { e.Emit(double(v)); return e; }
|
||||
inline Emitter &operator<<(Emitter &e, double v) { e.Emit(v); return e; }
|
||||
inline Emitter &operator<<(Emitter &e, ConstBlobPtr v) { e.Emit(v); return e; }
|
||||
|
||||
shared_ptr<EmitterOutput> CreateEmitterOutput(void *ptr, unsigned len, unsigned *out_len=0);
|
||||
shared_ptr<EmitterOutput> CreateEmitterOutput(const char *filename);
|
||||
shared_ptr<EmitterOutput> CreateEmitterOutput(FILE *f);
|
||||
shared_ptr<EmitterOutput> CreateEmitterOutput(std::streambuf *sb);
|
||||
|
||||
/**
|
||||
* Create an Emiter that Emits the format specified by type.
|
||||
* Supported parameters are dependent on type (see below).
|
||||
*/
|
||||
Emitter CreateEmitter(shared_ptr<EmitterOutput> o, SerializeType type, Variant params = Variant::NullType);
|
||||
|
||||
/**
|
||||
* Create an Emitter that Emits the JSON format.
|
||||
*
|
||||
* Supported parameters are:
|
||||
* "pretty": boolean
|
||||
* "indent": integer (number of spaces to indent when pretty is on,
|
||||
* default 4)
|
||||
* "precision": integer (number of digits for floats)
|
||||
* "strict": be more strict about emitting correct json
|
||||
*/
|
||||
Emitter JSONEmitter(shared_ptr<EmitterOutput> o, Variant params = Variant::NullType);
|
||||
|
||||
/**
|
||||
* Supported parameters are (first is default):
|
||||
*
|
||||
* "scalar_style": "any"|"plain"|"single quoted"|"double
|
||||
* quoted"|"literal"|"folded"
|
||||
*
|
||||
* "map_style": "any"|"block"|"flow"
|
||||
*
|
||||
* "list_style": "any"|"block"|"flow"
|
||||
*
|
||||
* "implicit_document_begin": false|true
|
||||
*
|
||||
* "implicit_document_end": false|true
|
||||
*
|
||||
* "indent": integer (number of spaces to indent)
|
||||
*
|
||||
* "width": integer (set prefered line width)
|
||||
*
|
||||
* "precision": integer (number of digits for floats)
|
||||
*/
|
||||
Emitter YAMLEmitter(shared_ptr<EmitterOutput> o, Variant params = Variant::NullType);
|
||||
|
||||
/**
|
||||
* Supported params are:
|
||||
*
|
||||
* "pretty": true|false
|
||||
* "indent": integer (amount to indent for pretty)
|
||||
* "precision": integer (number of digits for floats)
|
||||
*/
|
||||
Emitter XMLPLISTEmitter(shared_ptr<EmitterOutput> o, Variant params = Variant::NullType);
|
||||
/**
|
||||
* Supported params are:
|
||||
*
|
||||
* "precision": integer (number of digits for floats)
|
||||
*/
|
||||
Emitter BundleHdrEmitter(shared_ptr<EmitterOutput> o, Variant params = Variant::NullType);
|
||||
|
||||
/**
|
||||
* No parameters supported.
|
||||
*/
|
||||
Emitter MsgPackEmitter(shared_ptr<EmitterOutput> o, Variant params = Variant::NullType);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,87 @@
|
||||
//=============================================================================
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Library General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// The GNU Public License is available in the file LICENSE, or you
|
||||
// can write to the Free Software Foundation, Inc., 59 Temple Place -
|
||||
// Suite 330, Boston, MA 02111-1307, USA, or you can find it on the
|
||||
// World Wide Web at http://www.fsf.org.
|
||||
//=============================================================================
|
||||
/** \file
|
||||
* \author John Bridgman
|
||||
* \brief
|
||||
*
|
||||
* The end user should not need to look at this file unless they are
|
||||
* creating custom outputs for the emitters.
|
||||
*/
|
||||
#ifndef VARIANT_EMITTEROUTPUT_H
|
||||
#define VARIANT_EMITTEROUTPUT_H
|
||||
#pragma once
|
||||
#include <stdio.h>
|
||||
#include <iosfwd>
|
||||
|
||||
namespace libvariant {
|
||||
|
||||
class EmitterOutput {
|
||||
public:
|
||||
virtual ~EmitterOutput();
|
||||
/// Return the number of bytes written, or throw an exception
|
||||
virtual unsigned Write(const void *ptr, unsigned len) = 0;
|
||||
virtual void Flush() {}
|
||||
virtual unsigned NumBytesWritten() const = 0;
|
||||
};
|
||||
|
||||
class EmitterFileOutput : public EmitterOutput {
|
||||
public:
|
||||
EmitterFileOutput(FILE *f, bool c);
|
||||
~EmitterFileOutput();
|
||||
virtual unsigned Write(const void *ptr, unsigned len);
|
||||
virtual void Flush();
|
||||
virtual unsigned NumBytesWritten() const { return num_bytes; }
|
||||
protected:
|
||||
FILE *file;
|
||||
unsigned num_bytes;
|
||||
bool cls;
|
||||
};
|
||||
|
||||
class EmitterFilenameOutput : public EmitterFileOutput {
|
||||
public:
|
||||
EmitterFilenameOutput(const char *filename, const char *mode="w");
|
||||
};
|
||||
|
||||
class EmitterStreambufOutput : public EmitterOutput {
|
||||
public:
|
||||
EmitterStreambufOutput(std::streambuf *sb, bool d);
|
||||
~EmitterStreambufOutput();
|
||||
virtual unsigned Write(const void *ptr, unsigned len);
|
||||
virtual void Flush();
|
||||
virtual unsigned NumBytesWritten() const { return num_bytes; }
|
||||
protected:
|
||||
std::streambuf *streambuf;
|
||||
unsigned num_bytes;
|
||||
bool del;
|
||||
};
|
||||
|
||||
class EmitterMemoryOutput : public EmitterOutput {
|
||||
public:
|
||||
EmitterMemoryOutput(void *ptr, unsigned len, unsigned *out_len = 0);
|
||||
|
||||
virtual unsigned Write(const void *ptr, unsigned len);
|
||||
|
||||
virtual unsigned NumBytesWritten() const { return *out_length; }
|
||||
protected:
|
||||
void *data_ptr;
|
||||
unsigned length;
|
||||
unsigned out_length_dummy;
|
||||
unsigned *out_length;
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,88 @@
|
||||
//=============================================================================
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Library General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// The GNU Public License is available in the file LICENSE, or you
|
||||
// can write to the Free Software Foundation, Inc., 59 Temple Place -
|
||||
// Suite 330, Boston, MA 02111-1307, USA, or you can find it on the
|
||||
// World Wide Web at http://www.fsf.org.
|
||||
//=============================================================================
|
||||
/** \file
|
||||
* \author John Bridgman
|
||||
* \brief
|
||||
*/
|
||||
#ifndef VARIANT_EXCEPTIONS_H
|
||||
#define VARIANT_EXCEPTIONS_H
|
||||
#include <stdexcept>
|
||||
#include <iosfwd>
|
||||
#include <vector>
|
||||
|
||||
#include "../../../src/include/Variant/VariantDefines.h"
|
||||
namespace libvariant {
|
||||
|
||||
/// \brief Exception thrown when a key does not exist.
|
||||
class KeyError : public std::runtime_error {
|
||||
public:
|
||||
KeyError(const std::string &key) throw();
|
||||
};
|
||||
|
||||
/// \brief Exception thrown when internal state is corrupt.
|
||||
class UnknownTypeError : public std::runtime_error {
|
||||
public:
|
||||
UnknownTypeError(VariantDefines::Type_t type) throw();
|
||||
};
|
||||
|
||||
/// \brief Exception thrown when a function expects a specific type but the action type conflicts.
|
||||
class UnexpectedTypeError : public std::runtime_error {
|
||||
public:
|
||||
UnexpectedTypeError(VariantDefines::Type_t expected, VariantDefines::Type_t value) throw();
|
||||
UnexpectedTypeError(const std::vector<VariantDefines::Type_t> &expected, VariantDefines::Type_t value) throw();
|
||||
};
|
||||
|
||||
/// \brief Exception thrown when a function cannot convert the Variant to an acceptable type for the routine.
|
||||
class UnableToConvertError : public std::runtime_error {
|
||||
public:
|
||||
UnableToConvertError(VariantDefines::Type_t sourcetype, const std::string &targettype) throw();
|
||||
};
|
||||
|
||||
/// \brief Exception thrown when trying to index a type other than map or list.
|
||||
class TypeNotIndexableError : public std::runtime_error {
|
||||
public:
|
||||
TypeNotIndexableError(VariantDefines::Type_t type) throw();
|
||||
};
|
||||
|
||||
/// \brief Exception thrown when attempting a numeric operation on a non numeric type.
|
||||
class NotNumericTypeError : public std::runtime_error {
|
||||
public:
|
||||
NotNumericTypeError(VariantDefines::Type_t type) throw();
|
||||
};
|
||||
|
||||
/// \brief Exception thrown from path functions
|
||||
class BadPathError : public std::runtime_error {
|
||||
public:
|
||||
BadPathError(VariantDefines::Type_t type) throw();
|
||||
BadPathError(const std::string &msg) throw();
|
||||
};
|
||||
|
||||
class InvalidReferenceError : public std::runtime_error {
|
||||
public:
|
||||
InvalidReferenceError(const std::string &msg) throw();
|
||||
};
|
||||
|
||||
class InvalidOperationError : public std::runtime_error {
|
||||
public:
|
||||
InvalidOperationError(VariantDefines::Type_t type, const std::string &opname) throw();
|
||||
};
|
||||
|
||||
std::ostream &operator <<(std::ostream &os, VariantDefines::Type_t type);
|
||||
|
||||
void AddStackTrace(std::ostream &os, int level);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,92 @@
|
||||
//=============================================================================
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Library General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// The GNU Public License is available in the file LICENSE, or you
|
||||
// can write to the Free Software Foundation, Inc., 59 Temple Place -
|
||||
// Suite 330, Boston, MA 02111-1307, USA, or you can find it on the
|
||||
// World Wide Web at http://www.fsf.org.
|
||||
//=============================================================================
|
||||
/** \file
|
||||
* \author Josh Staley
|
||||
* \brief Useful extension functions for Variant
|
||||
*/
|
||||
|
||||
#ifndef VARIANT_EXTENSIONS_H
|
||||
#define VARIANT_EXTENSIONS_H
|
||||
|
||||
#include "../../../src/include/Variant/Variant.h"
|
||||
|
||||
namespace libvariant {
|
||||
|
||||
/// \brief Returns a default parameters for use with FlattenPath and ExpandPath functions.
|
||||
Variant ExtensionParams();
|
||||
|
||||
/// \brief Sets any missing Extension parameters to 'params' for use with FlattenPath and ExpandPath functions.
|
||||
void ExtensionParams( VariantRef params );
|
||||
|
||||
/// \brief Returns a version of 'var' with flat paths based on 'params'
|
||||
Variant FlattenPath( const Variant &var, Variant params = ExtensionParams() );
|
||||
|
||||
/// \brief Returns a version of 'var' with expanded paths based on 'params'
|
||||
Variant ExpandPath( const Variant &var, Variant params = ExtensionParams() );
|
||||
|
||||
/// \brief Flattens 'var' paths to 'flat' based on 'params'
|
||||
void FlattenPathTo( VariantRef flat, const Variant &var, Variant params = ExtensionParams(), std::string prefix = "" );
|
||||
|
||||
/// \brief Expands 'var' paths to 'expand' based on 'params'
|
||||
void ExpandPathTo( VariantRef expand, const Variant &var, Variant params = ExtensionParams() );
|
||||
|
||||
/// \brief Returns a string string map representation of 'var' based on 'params'
|
||||
std::map<std::string,std::string>
|
||||
FlattenPathToStrStrMap( const Variant &var, Variant params = ExtensionParams() );
|
||||
|
||||
/// \brief Returns a variant representing elements in 'compare' that differ from 'base' recursively
|
||||
Variant RDiff( const Variant &base, const Variant &compare );
|
||||
|
||||
/// \brief Sets elements into 'diff' from 'compare' that differ from 'base' recursively
|
||||
void RDiff( VariantRef diff, const Variant &base, const Variant &compare );
|
||||
|
||||
/// \brief Updates 'base' with entries in 'update' recursively
|
||||
void RUpdate( VariantRef base, const Variant &update );
|
||||
|
||||
/// Perform an operations on v according to RFC6901 and RFC6902.
|
||||
// Note that JSON Pointer is ambiguous without the presence of a document.
|
||||
// These function throw if the lookup fails because of incorrect types or
|
||||
// on ambiguity.
|
||||
// On return (or throw) the operation will have either succedded or no
|
||||
// change will have been made.
|
||||
|
||||
/// Add data to v at the spot specified by pointer
|
||||
void JSONPointerAdd(const std::string &pointer, VariantRef v, Variant data);
|
||||
/// Remove the element in v at the spot specified by pointer
|
||||
void JSONPointerRemove(const std::string &pointer, VariantRef v);
|
||||
/// Replace the value at pointer with data, error if the location does not already exist
|
||||
void JSONPointerReplace(const std::string &pointer, VariantRef v, Variant data);
|
||||
/// Move the value from src to dst (equivalent to get(src), remove(src), add(dst)
|
||||
void JSONPointerMove(const std::string &src, const std::string &dst, VariantRef v);
|
||||
/// Copy the value from src to dst (equivalent to add(dst, get(src).Copy()))
|
||||
void JSONPointerCopy(const std::string &src, const std::string &dst, VariantRef v);
|
||||
/// Perform a lookup into v according to RFC6901, return a reference to the value at the location
|
||||
VariantRef JSONPointerLookup(const std::string &pointer, VariantRef v);
|
||||
|
||||
std::string FormJSONPointer(const Path &path);
|
||||
|
||||
/// Perform a patch operation on v with the patch as described by diff according to RFC6902
|
||||
// Returns true if the patch is applied and all tests pass,
|
||||
// false if any tests failed and no patch is applied
|
||||
std::pair<bool, std::string> JSONPatch(VariantRef v, const Variant &diff);
|
||||
|
||||
/// Create a diff suitable to give to JSONPatch to transform src into dst.
|
||||
Variant JSONDiff(const Variant &src, const Variant &dst);
|
||||
|
||||
} // namespace libvariant
|
||||
|
||||
#endif /*#ifndef VARIANT_EXTENSIONS_H*/
|
||||
@@ -0,0 +1,23 @@
|
||||
/** \file
|
||||
* \author John Bridgman
|
||||
* \brief
|
||||
*/
|
||||
#ifndef VARIANT_GUESSFORMAT_H
|
||||
#define VARIANT_GUESSFORMAT_H
|
||||
|
||||
#pragma once
|
||||
#include "../../../src/include/Variant/Variant.h"
|
||||
#include "../../../src/include/Variant/Parser.h"
|
||||
namespace libvariant {
|
||||
|
||||
///
|
||||
// Try to guess the format of the input without removing any
|
||||
// input from the input object.
|
||||
//
|
||||
// Currently only looks at the first non-whitespace character
|
||||
// and if it is '<' then says XMLPLIST, otherwise says YAML
|
||||
// if enabled otherwise JSON.
|
||||
//
|
||||
SerializeType GuessFormat(ParserInput* in);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,158 @@
|
||||
/** \file
|
||||
* \author John Bridgman
|
||||
* \brief
|
||||
*/
|
||||
#ifndef VARIANT_PARSER_H
|
||||
#define VARIANT_PARSER_H
|
||||
|
||||
#pragma once
|
||||
#include <stdexcept>
|
||||
#include <stdint.h>
|
||||
#include "../../../src/include/Variant/Blob.h"
|
||||
#include "../../../src/include/Variant/ParserInput.h"
|
||||
#include "../../../src/include/Variant/Variant.h"
|
||||
#include <deque>
|
||||
|
||||
namespace libvariant {
|
||||
|
||||
class ParserImpl;
|
||||
|
||||
class ParserActions {
|
||||
public:
|
||||
virtual ~ParserActions();
|
||||
virtual void BeginDocument(ParserImpl *p)
|
||||
{ throw std::runtime_error("Parser: Unexpected event"); }
|
||||
virtual void EndDocument(ParserImpl *p)
|
||||
{ throw std::runtime_error("Parser: Unexpected event"); }
|
||||
// If length < 0, unknown length
|
||||
virtual void BeginMap(ParserImpl *p, int length, const char *anchor, const char *tag)
|
||||
{ throw std::runtime_error("Parser: Unexpected event"); }
|
||||
virtual void EndMap(ParserImpl *p)
|
||||
{ throw std::runtime_error("Parser: Unexpected event"); }
|
||||
// If length < 0, unknown length
|
||||
virtual void BeginList(ParserImpl *p, int length, const char *anchor, const char *tag)
|
||||
{ throw std::runtime_error("Parser: Unexpected event"); }
|
||||
virtual void EndList(ParserImpl *p)
|
||||
{ throw std::runtime_error("Parser: Unexpected event"); }
|
||||
virtual void Alias(ParserImpl *p, const char *anchor)
|
||||
{ throw std::runtime_error("Parser: Unexpected event"); }
|
||||
virtual void Scalar(ParserImpl *p, double v, const char *anchor, const char *tag)
|
||||
{ throw std::runtime_error("Parser: Unexpected event"); }
|
||||
virtual void Scalar(ParserImpl *p, const char *str, unsigned length, const char *anchor, const char *tag)
|
||||
{ throw std::runtime_error("Parser: Unexpected event"); }
|
||||
virtual void Scalar(ParserImpl *p, bool v, const char *anchor, const char *tag)
|
||||
{ throw std::runtime_error("Parser: Unexpected event"); }
|
||||
virtual void Null(ParserImpl *p, const char *anchor, const char *tag)
|
||||
{ throw std::runtime_error("Parser: Unexpected event"); }
|
||||
virtual void Scalar(ParserImpl *p, intmax_t v, const char *anchor, const char *tag)
|
||||
{ throw std::runtime_error("Parser: Unexpected event"); }
|
||||
virtual void Scalar(ParserImpl *p, uintmax_t v, const char *anchor, const char *tag)
|
||||
{ throw std::runtime_error("Parser: Unexpected event"); }
|
||||
virtual void Scalar(ParserImpl *p, BlobPtr b, const char *anchor, const char *tag)
|
||||
{ throw std::runtime_error("Parser: Unexpected event"); }
|
||||
};
|
||||
|
||||
/// The class that parser implementations override
|
||||
class ParserImpl {
|
||||
public:
|
||||
virtual ~ParserImpl();
|
||||
/**
|
||||
* Attempt to parse some actions.
|
||||
* At least one ParserActions should be on the action stack.
|
||||
*
|
||||
* Run is not guaranteed to be recursively callable from inside a
|
||||
* ParserActions callback. Do not do that.
|
||||
*
|
||||
* return 0 on success
|
||||
* return 1 when done
|
||||
* return -1 if needing more data is detected (not all parsers support this; can be treated as an error)
|
||||
* throw on error
|
||||
*/
|
||||
virtual int Run() = 0;
|
||||
|
||||
/**
|
||||
* Push a new ParserActions handler onto the action handler stack.
|
||||
*/
|
||||
virtual void PushAction(shared_ptr<ParserActions> action) { action_stack.push_back(action); }
|
||||
|
||||
/**
|
||||
* Pop the top ParserActions handler off the action handler stack and
|
||||
* return it.
|
||||
*/
|
||||
virtual shared_ptr<ParserActions> PopAction() {
|
||||
if (action_stack.empty())
|
||||
{ throw std::runtime_error("Parser: Attempting to parse an actions without any action handlers"); }
|
||||
shared_ptr<ParserActions> ret = action_stack.back();
|
||||
action_stack.pop_back();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access the top ParserActions
|
||||
*/
|
||||
ParserActions *TopAction() {
|
||||
if (action_stack.empty())
|
||||
{ throw std::runtime_error("Parser: Attempting to parse an actions without any action handlers"); }
|
||||
return action_stack.back().get();
|
||||
}
|
||||
|
||||
/** These three functiosn can be used to query the state
|
||||
* later.
|
||||
* Done means that a call to Process will immediately return 1
|
||||
* Error if Process threw an exception last
|
||||
* Ok if everything looks good (Process never been called, or last return 0 or possibly -1)
|
||||
*/
|
||||
virtual bool Done() const = 0;
|
||||
virtual bool Error() const = 0;
|
||||
virtual bool Ok() const = 0;
|
||||
/// Return a string describing the last error suitable for presentation to a user
|
||||
virtual std::string ErrorStr() const = 0;
|
||||
/// Reset the parser
|
||||
virtual void Reset() = 0;
|
||||
protected:
|
||||
std::deque< shared_ptr< ParserActions > > action_stack;
|
||||
};
|
||||
|
||||
class Parser {
|
||||
public:
|
||||
Parser();
|
||||
Parser(shared_ptr<ParserImpl> pi);
|
||||
~Parser();
|
||||
/// 0 on success, 1 when done, -1 other problem, throw on error
|
||||
int Run() { return impl->Run(); }
|
||||
/// Push an action handler onto the action stack.
|
||||
void PushAction(shared_ptr<ParserActions> action) { impl->PushAction(action); }
|
||||
/// Pop the top action handler off the stack.
|
||||
shared_ptr<ParserActions> PopAction() { return impl->PopAction(); }
|
||||
|
||||
/// Query state
|
||||
bool Done() const { return impl->Done(); }
|
||||
bool Error() const { return impl->Error(); }
|
||||
bool Ok() const { return impl->Ok(); }
|
||||
/// Return a string describing the last error suitable for presentation to a user
|
||||
std::string ErrorStr() const { return impl->ErrorStr(); }
|
||||
/// Reset the parser if applicable (some types will throw)
|
||||
void Reset() { impl->Reset(); }
|
||||
|
||||
/// Internal/advanced function to get the underlying implementation
|
||||
shared_ptr<ParserImpl> GetImpl() { return impl; }
|
||||
private:
|
||||
shared_ptr<ParserImpl> impl;
|
||||
};
|
||||
|
||||
shared_ptr<ParserInput> CreateParserInput(const std::string &str);
|
||||
shared_ptr<ParserInput> CreateParserInput(const char *str);
|
||||
shared_ptr<ParserInput> CreateParserInput(const void *ptr, unsigned len);
|
||||
shared_ptr<ParserInput> CreateParserInputFile(const char *filename);
|
||||
shared_ptr<ParserInput> CreateParserInputFile(FILE *f);
|
||||
shared_ptr<ParserInput> CreateParserInputFile(std::streambuf *sb);
|
||||
|
||||
Parser CreateParser(shared_ptr<ParserInput> i, SerializeType type);
|
||||
Parser CreateParserGuess(shared_ptr<ParserInput> i);
|
||||
Parser JSONParser(shared_ptr<ParserInput> i);
|
||||
Parser YAMLParser(shared_ptr<ParserInput> i);
|
||||
Parser XMLPLISTParser(shared_ptr<ParserInput> i);
|
||||
Parser BundleHdrParser(shared_ptr<ParserInput> i);
|
||||
Parser MsgPackParser(shared_ptr<ParserInput> i);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,104 @@
|
||||
//=============================================================================
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Library General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// The GNU Public License is available in the file LICENSE, or you
|
||||
// can write to the Free Software Foundation, Inc., 59 Temple Place -
|
||||
// Suite 330, Boston, MA 02111-1307, USA, or you can find it on the
|
||||
// World Wide Web at http://www.fsf.org.
|
||||
//=============================================================================
|
||||
/** \file
|
||||
* \author John Bridgman
|
||||
* \brief
|
||||
*/
|
||||
#ifndef VARIANT_PARSERINPUT_H
|
||||
#define VARIANT_PARSERINPUT_H
|
||||
#pragma once
|
||||
#include <stdio.h>
|
||||
#include <iosfwd>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace libvariant {
|
||||
|
||||
class ParserInput {
|
||||
public:
|
||||
virtual ~ParserInput();
|
||||
// Get a pointer and length to the unprocessed data that is available
|
||||
// (return null on end of data) len being an in/out parameter,
|
||||
// the initial value of len is how much the parser wants. An input value of zero
|
||||
// in means give whatever is currently available.
|
||||
virtual const void *GetPtr(unsigned &len) = 0;
|
||||
|
||||
// Tell the input that the parser is done with len bytes from the last
|
||||
// GetPtr
|
||||
virtual void Release(unsigned len) = 0;
|
||||
};
|
||||
|
||||
class ParserStreamInput : public ParserInput {
|
||||
public:
|
||||
ParserStreamInput(unsigned buffer_len);
|
||||
virtual const void *GetPtr(unsigned &len);
|
||||
virtual void Release(unsigned len);
|
||||
/// return number of bytes read into ptr, 0 on EOF
|
||||
// and throw on error
|
||||
virtual unsigned Read(void *ptr, unsigned len) = 0;
|
||||
protected:
|
||||
std::vector<char> buffer;
|
||||
unsigned num;
|
||||
unsigned offset;
|
||||
bool eof;
|
||||
};
|
||||
|
||||
class ParserMemoryInput : public ParserInput {
|
||||
public:
|
||||
ParserMemoryInput(const void *ptr, unsigned len);
|
||||
virtual const void *GetPtr(unsigned &len);
|
||||
virtual void Release(unsigned len);
|
||||
protected:
|
||||
const void *data_ptr;
|
||||
unsigned data_len;
|
||||
unsigned offset;
|
||||
};
|
||||
|
||||
class ParserStringInput : public ParserInput {
|
||||
public:
|
||||
ParserStringInput(const std::string &str);
|
||||
virtual const void *GetPtr(unsigned &len);
|
||||
virtual void Release(unsigned len);
|
||||
protected:
|
||||
const std::string val;
|
||||
unsigned offset;
|
||||
};
|
||||
|
||||
class ParserFileInput : public ParserStreamInput {
|
||||
public:
|
||||
ParserFileInput(FILE *f);
|
||||
virtual unsigned Read(void *ptr, unsigned len);
|
||||
protected:
|
||||
FILE *file;
|
||||
};
|
||||
|
||||
class ParserFilenameInput : public ParserFileInput {
|
||||
public:
|
||||
ParserFilenameInput(const char *filename, const char *mode = "r");
|
||||
~ParserFilenameInput();
|
||||
};
|
||||
|
||||
class ParserStreambufInput : public ParserStreamInput {
|
||||
public:
|
||||
ParserStreambufInput(std::streambuf *sb);
|
||||
unsigned Read(void *ptr, unsigned len);
|
||||
protected:
|
||||
std::streambuf *streambuf;
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,100 @@
|
||||
//=============================================================================
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Library General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// The GNU Public License is available in the file LICENSE, or you
|
||||
// can write to the Free Software Foundation, Inc., 59 Temple Place -
|
||||
// Suite 330, Boston, MA 02111-1307, USA, or you can find it on the
|
||||
// World Wide Web at http://www.fsf.org.
|
||||
//=============================================================================
|
||||
/** \file
|
||||
* \author John Bridgman
|
||||
* \brief
|
||||
*/
|
||||
#ifndef VARIANT_PATH_H
|
||||
#define VARIANT_PATH_H
|
||||
|
||||
#pragma once
|
||||
#include <deque>
|
||||
#include <string>
|
||||
#include "../../../src/include/Variant/Exceptions.h"
|
||||
namespace libvariant {
|
||||
|
||||
// A simple xpath like path functionality for Variant
|
||||
//
|
||||
// Map keys are specified using a "/" then the key.
|
||||
// List indeces are specified using [index]
|
||||
// A "/" at the end of the path is ignored.
|
||||
// Characters "\/[]" must all be escaped with "\"
|
||||
//
|
||||
// For example:
|
||||
// {
|
||||
// "key1": [ 1, 2, 3, { "blork": true } ],
|
||||
// "key2": {
|
||||
// "subkey": [ "a", { "furple": 1 }, 2 ],
|
||||
// "sub/key2": true
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Then all paths enumerated are:
|
||||
// Path Value
|
||||
// "/" Identity
|
||||
// "/key1" [ 1, 2, 3, { "blork": true } ],
|
||||
// "/key1[0]" 1
|
||||
// "/key1[1]" 2
|
||||
// "/key1[2]" 3
|
||||
// "/key1[3]" { "blork": true }
|
||||
// "/key1[3]/blork" true
|
||||
// "/key2" { "subkey": [ "a", { "furple": 1 }, 2 ], "sub/key2": true }
|
||||
// "/key2/subkey" [ "a", { "furple": 1 }, 2 ]
|
||||
// "/key2/subkey[0]" "a"
|
||||
// "/key2/subkey[1]" { "furple": 1 }
|
||||
// "/key2/subkey[1]/furple" 1
|
||||
// "/key2/subkey[2]" 2
|
||||
// "/key2/sub\/key2" true
|
||||
//
|
||||
// For all these functions PathList must act like a vector<Variant>
|
||||
// It may be of some other type (like deque<Variant>)
|
||||
|
||||
class PathElement {
|
||||
public:
|
||||
enum Type_t { INDEX, KEY };
|
||||
PathElement(const std::string &k) : type(KEY), key(k) {}
|
||||
PathElement(const char *k) : type(KEY), key(k) {}
|
||||
PathElement(unsigned i) : type(INDEX), index(i) {}
|
||||
|
||||
bool IsNumber() const { return type == INDEX; }
|
||||
unsigned AsUnsigned() const {
|
||||
if (type != INDEX) throw BadPathError("Variant path element is not a number");
|
||||
return index;
|
||||
}
|
||||
bool IsString() const { return type == KEY; }
|
||||
const std::string &AsString() const {
|
||||
if (type != KEY) throw BadPathError("Variant path element is not a key");
|
||||
return key;
|
||||
}
|
||||
private:
|
||||
Type_t type;
|
||||
unsigned index;
|
||||
std::string key;
|
||||
};
|
||||
|
||||
typedef std::deque<PathElement> Path;
|
||||
|
||||
//!
|
||||
// Parse the path string into path tokens.
|
||||
void ParsePath(Path &parsed_path, const std::string &path);
|
||||
Path ParsePath(const std::string &path);
|
||||
|
||||
//! Take the set of path tokens and turn it into a path string
|
||||
std::string PathString(const Path &path);
|
||||
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,130 @@
|
||||
//=============================================================================
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Library General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// The GNU Public License is available in the file LICENSE, or you
|
||||
// can write to the Free Software Foundation, Inc., 59 Temple Place -
|
||||
// Suite 330, Boston, MA 02111-1307, USA, or you can find it on the
|
||||
// World Wide Web at http://www.fsf.org.
|
||||
//=============================================================================
|
||||
/** \file
|
||||
* \author John Bridgman
|
||||
* \brief
|
||||
*/
|
||||
#ifndef VARIANT_PAYLOAD_H
|
||||
#define VARIANT_PAYLOAD_H
|
||||
|
||||
#pragma once
|
||||
#include "../hos_libvariant/Variant.h"
|
||||
#include "../hos_libvariant/Emitter.h"
|
||||
#include "../hos_libvariant/Parser.h"
|
||||
namespace libvariant {
|
||||
|
||||
// Serialize and Deserialize a header, null byte, and a binary payload
|
||||
//
|
||||
// All restrictions of the given serialization format are required.
|
||||
//
|
||||
// Parameters for payload data location:
|
||||
// "length_path": path to where the payload length should be
|
||||
// placed for serialization and where the payload length should be read
|
||||
// from for deserialization
|
||||
// Defaults to:
|
||||
#define VARIANT_PAYLOAD_LENGTH_PATH "payload/length"
|
||||
#define VARIANT_BUNDLE_PAYLOAD_LENGTH_PATH "payload.length"
|
||||
// "data_path": path to where the payload is located for
|
||||
// serialization and path to store payload for deserialization
|
||||
// Defaults to:
|
||||
#define VARIANT_PAYLOAD_DATA_PATH "payload/data"
|
||||
#define VARIANT_BUNDLE_PAYLOAD_DATA_PATH "payload.data"
|
||||
// The defaults are the values for compatibility with the bundle format.
|
||||
//
|
||||
// Serialize only parameters:
|
||||
// "ignore_payload": true|false (default false)
|
||||
// Don't output the payload, only the header, alignment and null byte.
|
||||
// If the payload exists in the Variant, use the length for the payload length
|
||||
// value, if not look in parameters for the payload length value, if not there
|
||||
// look in the Variant for the payload length.
|
||||
// "payload_length": num
|
||||
// Payload length override, put this number in as the payload length
|
||||
// regardless of what size the blob is.
|
||||
// Note that unless ingnore_payload is true, the emitter will try to output the whole
|
||||
// payload (and no more) regardless of what this number is.
|
||||
|
||||
void SerializeWithPayload(shared_ptr<EmitterOutput> out, Variant v, SerializeType type,
|
||||
Variant params = Variant::NullType);
|
||||
Variant DeserializeWithPayload(shared_ptr<ParserInput> in, SerializeType type,
|
||||
Variant params = Variant::NullType, bool be_safe=true);
|
||||
|
||||
std::string SerializeWithPayload(Variant v, SerializeType type, Variant params = Variant::NullType);
|
||||
void SerializeWithPayload(const std::string &filename, Variant v, SerializeType type,
|
||||
Variant params = Variant::NullType);
|
||||
void SerializeWithPayload(FILE *f, Variant v, SerializeType type,
|
||||
Variant params = Variant::NullType);
|
||||
void SerializeWithPayload(std::streambuf *sb, Variant v, SerializeType type,
|
||||
Variant params = Variant::NullType);
|
||||
unsigned SerializeWithPayload(void *ptr, unsigned len, Variant v, SerializeType type,
|
||||
Variant params = Variant::NullType);
|
||||
|
||||
Variant DeserializeWithPayload(const std::string &str, SerializeType type,
|
||||
Variant params = Variant::NullType);
|
||||
/// If the be_safe parameter is false, then it is considered OK
|
||||
// to __/NOT/__ copy the payload and just reference it in the BlobPtr.
|
||||
// This is only safe when you know your buffer is going to stick around
|
||||
// until after your done with the resulting Variant.
|
||||
// (This is to support zero copy)
|
||||
// No null terminated string version provided as these formats contain nulls.
|
||||
Variant DeserializeWithPayload(const void *ptr, unsigned len, SerializeType type,
|
||||
Variant params = Variant::NullType, bool be_safe=true);
|
||||
Variant DeserializeWithPayloadFile(const char *filename, SerializeType type,
|
||||
Variant params = Variant::NullType);
|
||||
Variant DeserializeWithPayloadFile(FILE *f, SerializeType type,
|
||||
Variant params = Variant::NullType);
|
||||
Variant DeserializeWithPayloadFile(std::streambuf *sb, SerializeType type,
|
||||
Variant params = Variant::NullType);
|
||||
|
||||
|
||||
/// Bundle is a simple format used internally at ARL for passing around
|
||||
// a textual key value map plus a binary payload. The payload is often a very large
|
||||
// array of numbers that would produce unacceptable overhead to serialize into text.
|
||||
// These serialize routines assume that the passed in Variant is of MapType
|
||||
// and if a key named "payload.data" exists it is to be written as the payload
|
||||
// of the Bundle.
|
||||
//
|
||||
// If a key "payload.data" does not exist, these are almost the same as using the BundleHdrEmitter
|
||||
// except it adds a null byte at the end.
|
||||
inline std::string SerializeBundle(Variant v)
|
||||
{ return SerializeWithPayload(v, SERIALIZE_BUNDLEHDR); }
|
||||
inline void SerializeBundle(const std::string &filename, Variant v)
|
||||
{ SerializeWithPayload(filename, v, SERIALIZE_BUNDLEHDR); }
|
||||
inline void SerializeBundle(FILE *f, Variant v)
|
||||
{ SerializeWithPayload(f, v, SERIALIZE_BUNDLEHDR); }
|
||||
inline void SerializeBundle(std::streambuf *sb, Variant v)
|
||||
{ SerializeWithPayload(sb, v, SERIALIZE_BUNDLEHDR); }
|
||||
inline unsigned SerializeBundle(void *ptr, unsigned len, Variant v)
|
||||
{ return SerializeWithPayload(ptr, len, v, SERIALIZE_BUNDLEHDR); }
|
||||
|
||||
inline Variant DeserializeBundle(const std::string &str)
|
||||
{ return DeserializeWithPayload(str, SERIALIZE_BUNDLEHDR); }
|
||||
/// If the be_safe parameter is false, then it is considered OK
|
||||
// to __/NOT/__ copy the payload and just reference it in the BlobPtr.
|
||||
// This is only safe when you know your buffer is going to stick around
|
||||
// until after your done with the resulting Variant.
|
||||
// (This is to support zero copy)
|
||||
// No null terminated string version provided as bundles contain nulls.
|
||||
inline Variant DeserializeBundle(const void *ptr, unsigned len, bool be_safe=true)
|
||||
{ return DeserializeWithPayload(ptr, len, SERIALIZE_BUNDLEHDR, Variant::NullType, be_safe); }
|
||||
inline Variant DeserializeBundleFile(const char *filename)
|
||||
{ return DeserializeWithPayloadFile(filename, SERIALIZE_BUNDLEHDR); }
|
||||
inline Variant DeserializeBundleFile(FILE *f) { return DeserializeWithPayloadFile(f, SERIALIZE_BUNDLEHDR); }
|
||||
inline Variant DeserializeBundleFile(std::streambuf *sb)
|
||||
{ return DeserializeWithPayloadFile(sb, SERIALIZE_BUNDLEHDR); }
|
||||
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,175 @@
|
||||
//=============================================================================
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Library General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// The GNU Public License is available in the file LICENSE, or you
|
||||
// can write to the Free Software Foundation, Inc., 59 Temple Place -
|
||||
// Suite 330, Boston, MA 02111-1307, USA, or you can find it on the
|
||||
// World Wide Web at http://www.fsf.org.
|
||||
//=============================================================================
|
||||
/** \file
|
||||
* \author John Bridgman
|
||||
* \brief A schema validator.
|
||||
*
|
||||
* This code is based on the public domain JSONv4 validator tv4.
|
||||
* tv4 is available at http://geraintluff.github.com/tv4/
|
||||
*/
|
||||
#ifndef VARIANT_SCHEMA_H
|
||||
#define VARIANT_SCHEMA_H
|
||||
|
||||
#pragma once
|
||||
#include "../../../src/include/Variant/Variant.h"
|
||||
#include <map>
|
||||
#include <iosfwd>
|
||||
#include <deque>
|
||||
#include <sstream>
|
||||
namespace libvariant {
|
||||
|
||||
class SchemaResult;
|
||||
|
||||
class ValidationError {
|
||||
public:
|
||||
ValidationError(const std::string &m, const Path &dpath,
|
||||
const Path &spath);
|
||||
|
||||
void AddSubError(const SchemaResult &err);
|
||||
|
||||
const std::string &GetMessage() const { return message; }
|
||||
const Path &GetDataPath() const { return data_path; }
|
||||
std::string GetDataPathStr() const;
|
||||
const Path &GetSchemaPath() const { return schema_path; }
|
||||
std::string GetSchemaPathStr() const;
|
||||
const std::vector<SchemaResult> &GetSubErrors() const { return sub_errors; }
|
||||
|
||||
std::string PrettyPrintMessage() const;
|
||||
void PrettyPrintMessage(std::ostream &os, unsigned indent=0) const;
|
||||
private:
|
||||
std::string message;
|
||||
Path data_path;
|
||||
Path schema_path;
|
||||
std::vector<SchemaResult> sub_errors;
|
||||
};
|
||||
|
||||
class SchemaError {
|
||||
public:
|
||||
SchemaError(const std::string &m, const Path &spath);
|
||||
|
||||
const std::string &GetMessage() const { return message; }
|
||||
const Path &GetSchemaPath() const { return schema_path; }
|
||||
std::string GetSchemaPathStr() const;
|
||||
|
||||
std::string PrettyPrintMessage() const;
|
||||
void PrettyPrintMessage(std::ostream &os, unsigned indent=0) const;
|
||||
private:
|
||||
std::string message;
|
||||
Path schema_path;
|
||||
};
|
||||
|
||||
class SchemaResult {
|
||||
public:
|
||||
SchemaResult();
|
||||
|
||||
void AddError(const ValidationError &err);
|
||||
void AddSchemaError(const SchemaError &err);
|
||||
|
||||
bool Error() const { return !errors.empty() || !schema_errors.empty(); }
|
||||
bool ValidationErrors() const { return !errors.empty(); }
|
||||
bool SchemaErrors() const { return !schema_errors.empty(); }
|
||||
|
||||
const std::vector<ValidationError> &GetErrors() const { return errors; }
|
||||
const std::vector<SchemaError> &GetSchemaErrors() const { return schema_errors; }
|
||||
|
||||
std::string PrettyPrintMessage() const;
|
||||
void PrettyPrintMessage(std::ostream &os, unsigned indent=0) const;
|
||||
private:
|
||||
std::vector<ValidationError> errors;
|
||||
std::vector<SchemaError> schema_errors;
|
||||
};
|
||||
|
||||
inline std::ostream &operator<<(std::ostream &os, const SchemaResult &sr) {
|
||||
sr.PrettyPrintMessage(os);
|
||||
return os;
|
||||
}
|
||||
|
||||
class SchemaLoader {
|
||||
public:
|
||||
class LoaderError {
|
||||
public:
|
||||
LoaderError();
|
||||
~LoaderError();
|
||||
void AddError(const std::string &uri, const std::string &msg);
|
||||
std::string GetErrorMessage() const { return erross.str(); }
|
||||
private:
|
||||
std::ostringstream erross;
|
||||
};
|
||||
|
||||
typedef bool (*MissingHandlerType)(SchemaLoader*,const std::string&,LoaderError &,void*);
|
||||
SchemaLoader();
|
||||
SchemaLoader(SchemaLoader *b);
|
||||
virtual ~SchemaLoader();
|
||||
// Get the schema at the uri specified.
|
||||
// Internal lookup first, then call HandleMissing if the uri is not internally available.
|
||||
// If the schema then is still not available return Variant::NullType.
|
||||
virtual Variant GetSchema(const std::string &uri);
|
||||
// Add a schema to the loader at the uri specified.
|
||||
// returns the schema(s) added with the corresponding uri(s)
|
||||
virtual std::map<std::string, Variant> AddSchema(const std::string &uri, Variant schema);
|
||||
// Forget a schema with the specified uri.
|
||||
virtual void ForgetSchema(const std::string &uri);
|
||||
// Called when a schema is not in the loader.
|
||||
// Default implementation is to call the missing handler
|
||||
// or add a not found error to the LoaderError and return false
|
||||
// Return true on success, otherwise false, any errors are filled into the LoaderError
|
||||
virtual bool HandleMissing(const std::string &uri, LoaderError &error);
|
||||
void SetMissingHandler(MissingHandlerType, void *ctx);
|
||||
|
||||
static void NormSchema(Variant &schema, const std::string &uri);
|
||||
//!
|
||||
// A realpath function for schema URIs.
|
||||
// href is the "current working directory" and base is
|
||||
// possibly a relative path.
|
||||
static std::string ResolveURI(const std::string &base, const std::string &href);
|
||||
|
||||
struct URIInfo {
|
||||
std::string href; // EX: the whole uri if matched
|
||||
std::string protocol; // EX: http://
|
||||
std::string authority; // user:host@hostname:port
|
||||
std::string pathname; // The path segment
|
||||
std::string search; // ?q=234
|
||||
std::string hash; // #tag
|
||||
};
|
||||
|
||||
//! Break a uri into its components and store them into the URIInfo struct
|
||||
//! returns true if the parsing was successful
|
||||
static bool ParseURI(URIInfo &info, const std::string &uri);
|
||||
protected:
|
||||
|
||||
static void SearchForTrustedSchemas(std::map<std::string, Variant> &m, Variant schema, const std::string &uri);
|
||||
MissingHandlerType missingHandler;
|
||||
void *missingctx;
|
||||
std::map<std::string, Variant> schemas;
|
||||
SchemaLoader *base;
|
||||
};
|
||||
|
||||
//! Validate data against a schema.
|
||||
//!
|
||||
//! The schema parameter is either a schema, a string uri to a schema, or null.
|
||||
//! If it is a schema then data is validated against it.
|
||||
//! If it is a string then it calls loader->GetSchema() and validates data against the result.
|
||||
//! If schema is null, then look for a key "$schema" in data, set schema to it and proceed as above.
|
||||
SchemaResult SchemaValidate(Variant schema, Variant data, SchemaLoader *loader=0);
|
||||
|
||||
//! Add the defaults specified in schema to data if they do not exist.
|
||||
//! Ignores default in some combinations and types that could match multiple entries (not,
|
||||
//! additionalProperties, patternProperties, etc.)
|
||||
//! schema is processed the same as for SchemaValidate
|
||||
void AddSchemaDefaults(Variant schema, VariantRef data, SchemaLoader *loader=0);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,54 @@
|
||||
//=============================================================================
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Library General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// The GNU Public License is available in the file LICENSE, or you
|
||||
// can write to the Free Software Foundation, Inc., 59 Temple Place -
|
||||
// Suite 330, Boston, MA 02111-1307, USA, or you can find it on the
|
||||
// World Wide Web at http://www.fsf.org.
|
||||
//=============================================================================
|
||||
/** \file
|
||||
* \author John Bridgman
|
||||
* \brief An advanced schema loader.
|
||||
*/
|
||||
#ifndef VARIANT_SCHEMALOADER_H
|
||||
#define VARIANT_SCHEMALOADER_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../../../src/include/Variant/Schema.h"
|
||||
|
||||
namespace libvariant {
|
||||
|
||||
//! The advanced schema loader will try to load missing schemas from
|
||||
//! the file system and optionally curl if built.
|
||||
//! If the url begins with file:// it will always use LoadFromFile
|
||||
//! otherwise if the protocol is empty it will try loading from a file
|
||||
//! then try loading from curl. Otherwise if the protocol is not file://
|
||||
//! it will try to load from curl.
|
||||
class AdvSchemaLoader : public SchemaLoader {
|
||||
public:
|
||||
|
||||
//! The advanced schema loader will search for a schema in the paths
|
||||
//! added to it on the file system. If the schema uri looks like a
|
||||
//! relative path, then it will be searched for in the paths set with
|
||||
//! this function. If no paths are added, then only absolute paths will
|
||||
//! be looked up in the file system.
|
||||
//
|
||||
void AddPath(const std::string &path);
|
||||
|
||||
virtual bool HandleMissing(const std::string &uri, LoaderError &error);
|
||||
protected:
|
||||
bool LoadFromFile(URIInfo &info, LoaderError &error);
|
||||
bool LoadFromCurl(URIInfo &info, LoaderError &error);
|
||||
std::vector< std::string > paths;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,41 @@
|
||||
/** \file
|
||||
* \author John Bridgman
|
||||
* \brief
|
||||
*/
|
||||
#ifndef VARIANT_SHAREDPTR_H
|
||||
#define VARIANT_SHAREDPTR_H
|
||||
|
||||
#pragma once
|
||||
#include "../hos_libvariant/Config.h"
|
||||
|
||||
#if defined(__GXX_EXPERIMENTAL_CXX0X) || __cplusplus >= 201103L || defined(HAVE_CXX11_SHAREDPTR)
|
||||
// The C++11 implementation is available
|
||||
#include <memory>
|
||||
namespace libvariant {
|
||||
using std::shared_ptr;
|
||||
using std::dynamic_pointer_cast;
|
||||
}
|
||||
|
||||
#elif defined(HAVE_TR1_SHAREDPTR)
|
||||
// Use the tr1 implementation
|
||||
#include <tr1/memory>
|
||||
namespace libvariant {
|
||||
using std::tr1::shared_ptr;
|
||||
using std::tr1::dynamic_pointer_cast;
|
||||
}
|
||||
|
||||
#elif defined(USE_BOOST_SHAREDPTR)
|
||||
// Use the boost implementation
|
||||
#include <boost/shared_ptr.hpp>
|
||||
namespace libvariant {
|
||||
using boost::shared_ptr;
|
||||
using boost::dynamic_pointer_cast;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#error libvariant requires a shared_ptr implementation
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,816 @@
|
||||
// vim: foldmethod=marker
|
||||
//=============================================================================
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Library General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// The GNU Public License is available in the file LICENSE, or you
|
||||
// can write to the Free Software Foundation, Inc., 59 Temple Place -
|
||||
// Suite 330, Boston, MA 02111-1307, USA, or you can find it on the
|
||||
// World Wide Web at http://www.fsf.org.
|
||||
//=============================================================================
|
||||
|
||||
/** \file
|
||||
*
|
||||
* \brief Main implementation file for Variant and related functions
|
||||
*/
|
||||
|
||||
|
||||
#ifndef VARIANT_VARIANT_H
|
||||
#define VARIANT_VARIANT_H
|
||||
|
||||
#pragma once
|
||||
#include "../../../src/include/Variant/Blob.h"
|
||||
#include "../../../src/include/Variant/SharedPtr.h"
|
||||
#include "../../../src/include/Variant/Exceptions.h"
|
||||
#include "../../../src/include/Variant/VariantInternal.h"
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stddef.h>
|
||||
#include <map>
|
||||
#include <iterator>
|
||||
#include <complex>
|
||||
|
||||
namespace libvariant {
|
||||
|
||||
/** \brief The Variant class.
|
||||
* This is a variant type inspired by types from several different
|
||||
* scripting languages.
|
||||
*
|
||||
* \author John Bridgman
|
||||
*
|
||||
* This class gives the power and convenience of a scripting language variable
|
||||
* to C++ with all the same /downsides/ that such a variable has as well. The
|
||||
* main idea is that things should be simple, lists are behind the scenes an
|
||||
* std::vector and maps are an std::map.
|
||||
*
|
||||
* A Variant may be null, a number, a string, a boolean, a reference to a list,
|
||||
* or a reference to a map. This means that const Variant of a map is not a
|
||||
* const map but a const reference. Lists and maps are reference counted. If
|
||||
* one wants to copy use the Copy member function.
|
||||
*
|
||||
* If you need a reference to a Variant to assign to it or change its type,
|
||||
* use VariantRef.
|
||||
* A const Variant & should be used for an immutable reference.
|
||||
* E.g., void foo(VariantRef inout_param, const Variant &in_param);
|
||||
* That is to say, if you think you want Variant &, you don't, you want
|
||||
* VariantRef.
|
||||
* The library is written so that:
|
||||
* Variant v;
|
||||
* void bar(Variant &);
|
||||
* bar(v["foo"]);
|
||||
* is a compile error.
|
||||
* But
|
||||
* Variant v;
|
||||
* void moo(const Variant &);
|
||||
* moo(v["moo"]);
|
||||
* is correct.
|
||||
*
|
||||
*
|
||||
* Note that this implementation will let you create a back reference (i.e., a
|
||||
* map with itself as a member) but unless the user explicitly breaks it, it
|
||||
* will result in a memory leak. Checking for this case was deemed too
|
||||
* expensive.
|
||||
*
|
||||
* A Variant will only change its own type if the type is null. That is to say
|
||||
* that a null Variant that gets treated as a map will become a map. But, a
|
||||
* Variant of any other type will never automatically convert.
|
||||
*
|
||||
*/
|
||||
class Variant : protected Internal::Data, public VariantDefines {
|
||||
public:
|
||||
|
||||
typedef VariantRefImpl<Variant> VariantRef;
|
||||
|
||||
typedef std::vector<Variant> List;
|
||||
typedef std::map<std::string, Variant> Map;
|
||||
|
||||
typedef Map::iterator MapIterator;
|
||||
typedef Map::const_iterator ConstMapIterator;
|
||||
typedef List::iterator ListIterator;
|
||||
typedef List::const_iterator ConstListIterator;
|
||||
|
||||
Variant() {}
|
||||
Variant(VariantDefines::Type_t type) { Assign(type); }
|
||||
Variant(bool v) { Assign(v); }
|
||||
|
||||
Variant(int v) { Assign(v); }
|
||||
Variant(unsigned v) { Assign(v); }
|
||||
Variant(long v) { Assign(v); }
|
||||
Variant(unsigned long v) { Assign(v); }
|
||||
Variant(long long v) { Assign(v); }
|
||||
Variant(unsigned long long v) { Assign(v); }
|
||||
Variant(double v) { Assign(v); }
|
||||
Variant(long double v) { Assign(v); }
|
||||
|
||||
Variant(BlobPtr b) { Assign(b); }
|
||||
|
||||
Variant(const std::string &v) { Assign(v); }
|
||||
Variant(const char *v) { Assign(v); }
|
||||
Variant(const Variant &v) { Assign(v); }
|
||||
Variant(const VariantRefImpl<Variant> &v) { Assign(v); }
|
||||
|
||||
/// Construct a list from a std::vector.
|
||||
template<typename T>
|
||||
Variant(const std::vector<T> &v) { Assign(v); }
|
||||
|
||||
/// Construct a map from a std::map.
|
||||
template<typename T>
|
||||
Variant(const std::map<std::string, T> &v) { Assign(v); }
|
||||
|
||||
~Variant();
|
||||
|
||||
Variant &operator=(const Variant &o) { Assign(o); return *this; }
|
||||
|
||||
Variant &operator=(VariantDefines::Type_t v) { Assign(v); return *this; }
|
||||
Variant &operator=(bool v) { Assign(v); return *this; }
|
||||
Variant &operator=(int v) { Assign(v); return *this; }
|
||||
Variant &operator=(unsigned v) { Assign(v); return *this; }
|
||||
Variant &operator=(long v) { Assign(v); return *this; }
|
||||
Variant &operator=(unsigned long v) { Assign(v); return *this; }
|
||||
Variant &operator=(long long v) { Assign(v); return *this; }
|
||||
Variant &operator=(unsigned long long v) { Assign(v); return *this; }
|
||||
Variant &operator=(double v) { Assign(v); return *this; }
|
||||
Variant &operator=(long double v) { Assign(v); return *this; }
|
||||
Variant &operator=(BlobPtr v) { Assign(v); return *this; }
|
||||
Variant &operator=(const std::string & v) { Assign(v); return *this; }
|
||||
Variant &operator=(const char * v) { Assign(v); return *this; }
|
||||
|
||||
template<typename T>
|
||||
Variant &operator=(const std::vector<T> &v) { Assign(v); return *this; }
|
||||
template<typename T>
|
||||
Variant &operator=(const std::map<std::string, T> &v) { Assign(v); return *this; }
|
||||
|
||||
// Type query functions
|
||||
|
||||
Type_t GetType() const; ///< Return the type of this Variant
|
||||
|
||||
bool IsNull() const { return NullType == GetType(); }
|
||||
bool IsBool() const { return BoolType == GetType(); }
|
||||
bool IsTrue() const { return (BoolType == GetType()) && AsBool(); }
|
||||
bool IsFalse() const { return (BoolType == GetType()) && !AsBool(); }
|
||||
bool IsNumber() const
|
||||
{ return IntegerType == GetType() || UnsignedType == GetType() || FloatType == GetType(); }
|
||||
bool IsInt() const { return IntegerType == GetType(); }
|
||||
bool IsUnsigned() const { return UnsignedType == GetType(); }
|
||||
bool IsFloat() const { return FloatType == GetType(); }
|
||||
bool IsString() const { return StringType == GetType(); }
|
||||
bool IsList() const { return ListType == GetType(); }
|
||||
bool IsMap() const { return MapType == GetType(); }
|
||||
bool IsBlob() const { return BlobType == GetType(); }
|
||||
|
||||
|
||||
// Accessor functions
|
||||
|
||||
bool AsBool() const; ///< Return the value as a bool
|
||||
long double AsLongDouble() const; ///< Return the value as a long double
|
||||
double AsDouble() const { return (double)AsLongDouble(); }
|
||||
uintmax_t AsUnsigned() const; ///< Return the value as an unsigned
|
||||
intmax_t AsInt() const; ///< Return the value as an integer
|
||||
template<typename T>
|
||||
T AsNumber() const { return static_cast<T>(AsLongDouble()); }
|
||||
std::string AsString() const; ///< Return the value as a string
|
||||
BlobPtr AsBlob();
|
||||
ConstBlobPtr AsBlob() const;
|
||||
|
||||
template<typename T>
|
||||
T As() const;
|
||||
|
||||
/// \brief If the type is string, list, map or blob returns its size,
|
||||
/// otherwise throws an exception
|
||||
unsigned Size() const;
|
||||
|
||||
/// \brief If the type is string, list or map return if size == 0 otherwise
|
||||
/// throw an exception
|
||||
bool Empty() const;
|
||||
|
||||
/// \brief If the type is string, list or map, empty the container otherwise
|
||||
/// set type to NullType
|
||||
void Clear();
|
||||
|
||||
// List specific accessors
|
||||
List &AsList();
|
||||
const List &AsList() const;
|
||||
ListIterator ListBegin() ///< Equivalent to AsList().begin()
|
||||
{ return AsList().begin(); }
|
||||
ConstListIterator ListBegin() const ///< Equivalent to AsList().begin()
|
||||
{ return AsList().begin(); }
|
||||
ListIterator ListEnd() ///< Equivalent to AsList().end()
|
||||
{ return AsList().end(); }
|
||||
ConstListIterator ListEnd() const ///< Equivalent to AsList().end()
|
||||
{ return AsList().end(); }
|
||||
VariantRef At(unsigned i); //< Return a proxy/reference to the element at index i
|
||||
VariantRef At(unsigned i, Variant def); //< sets to def if doesn't exist
|
||||
const Variant &At(unsigned i) const;
|
||||
Variant Get(unsigned i) const; //< Return the element at index i or throw
|
||||
Variant Get(unsigned i, Variant def) const; //< Return the element at index i or return def
|
||||
Variant &Set(unsigned i, Variant v); //< Set the element at index i to v
|
||||
/// \brief Only valid when of type ListType Returns *this, so you can
|
||||
/// do Variant().Append(v1).Append(v2)...
|
||||
Variant &Append(Variant value);
|
||||
|
||||
/// \brief If list return true if list is at least i in size, if map then convert i
|
||||
/// to a string, otherwise throw
|
||||
bool Contains(unsigned i) const;
|
||||
/// \brief Return the index hat v is at.
|
||||
/// If v is not contained in the list it return this->Size()
|
||||
unsigned Index(Variant v) const;
|
||||
|
||||
/// \brief If list set index i to null, if index at end, reduce size by 1
|
||||
/// throw if not a list
|
||||
void Erase(unsigned i);
|
||||
|
||||
// Map specific accessors
|
||||
Map &AsMap();
|
||||
const Map &AsMap() const;
|
||||
MapIterator MapBegin() ///< Equivalent to AsMap().begin()
|
||||
{ return AsMap().begin(); }
|
||||
ConstMapIterator MapBegin() const ///< Equivalent to AsMap().begin()
|
||||
{ return AsMap().begin(); }
|
||||
MapIterator MapEnd() ///< Equivalent to AsMap().end()
|
||||
{ return AsMap().end(); }
|
||||
ConstMapIterator MapEnd() const ///< Equivalent to AsMap().end()
|
||||
{ return AsMap().end(); }
|
||||
VariantRef At(const std::string &s); // Return a proxy/reference to the element at key s
|
||||
VariantRef At(const std::string &s, Variant def); //< Sets to def if doesn't exist and return a reference to it
|
||||
const Variant &At(const std::string &s) const;
|
||||
|
||||
/// \brief If s in *this: return this->At(s); else throw;
|
||||
Variant Get(const std::string &s) const;
|
||||
/// \brief If s in *this: return this->At(s); else return def
|
||||
/// Only works if type is map
|
||||
Variant Get(const std::string &s, Variant def) const;
|
||||
|
||||
/// \brief Set the key s to v
|
||||
// returns *this
|
||||
Variant &Set(const std::string &s, Variant v);
|
||||
|
||||
/// \brief If map return true if s is a key in the map, if list then convert
|
||||
/// s to an unsigned and the above Contains, otherwise throw
|
||||
bool Contains(const std::string &s) const;
|
||||
/// \brief Erase a key in a map, throws if type is not MapType
|
||||
void Erase(const std::string &key);
|
||||
|
||||
VariantRef operator[](int i) { return At(i); }
|
||||
const Variant &operator[](int i) const { return At(i); }
|
||||
|
||||
VariantRef operator[](unsigned i) { return At(i); }
|
||||
const Variant &operator[](unsigned i) const { return At(i); }
|
||||
|
||||
VariantRef operator[](const std::string &s) { return At(s); }
|
||||
const Variant &operator[](const std::string &s) const { return At(s); }
|
||||
|
||||
// Path related accessors
|
||||
// These are the same as the non-path functions but take a path instead.
|
||||
VariantRef AtPath(const Path &path);
|
||||
VariantRef AtPath(const std::string &path) { return AtPath(ParsePath(path)); }
|
||||
VariantRef AtPath(const Path &path, Variant def);
|
||||
VariantRef AtPath(const std::string &path, Variant def) { return AtPath(ParsePath(path), def); }
|
||||
const Variant &AtPath(const Path &path) const;
|
||||
const Variant &AtPath(const std::string &path) const { return AtPath(ParsePath(path)); }
|
||||
|
||||
/// \brief Like Variant::Get but it takes a path instead.
|
||||
Variant GetPath(const Path &path) const;
|
||||
Variant GetPath(const std::string &path) const { return GetPath(ParsePath(path)); }
|
||||
/// \brief Like Variant::Get but it takes a path instead. The path is
|
||||
/// very like xpath, /key[index]/key/key. See Variant/Path.h
|
||||
Variant GetPath(const Path &path, Variant def) const;
|
||||
Variant GetPath(const std::string &path, Variant def) const { return GetPath(ParsePath(path), def); }
|
||||
|
||||
/// \brief Set the value at the path, creating elements if they do not
|
||||
/// exist. throws if an intermediate path element exists but is not a
|
||||
/// map or list. returns *this
|
||||
Variant &SetPath(const Path &path, Variant val);
|
||||
Variant &SetPath(const std::string &path, Variant val) { return SetPath(ParsePath(path), val); }
|
||||
|
||||
/// \brief Erase a value at a path, if remove_empty is false only erase the very end
|
||||
/// otherwise erase empty lists and maps in the path. returns *this
|
||||
Variant &ErasePath(const Path &path, bool remove_empty=false);
|
||||
Variant &ErasePath(const std::string &path, bool remove_empty=false)
|
||||
{ return ErasePath(ParsePath(path), remove_empty); }
|
||||
|
||||
/// \brief Tester functions for paths, returns true if path is valid and exists.
|
||||
bool HasPath(const Path &path) const;
|
||||
bool HasPath(const std::string &path) const { return HasPath(ParsePath(path)); }
|
||||
|
||||
/// \brief Just like Variant::Get except a reference to the value to
|
||||
/// set is passed in and Variant does the casting.
|
||||
template<typename T>
|
||||
void GetInto(T &lvalue, const std::string &s) const;
|
||||
|
||||
/// \brief An into version of GetPath
|
||||
template<typename T>
|
||||
void GetPathInto(T &lvalue, const Path &path) const;
|
||||
template<typename T>
|
||||
void GetPathInto(T &lvalue, const std::string &path) const
|
||||
{ GetPathInto(lvalue, ParsePath(path)); }
|
||||
|
||||
/// \brief Just like Variant::Get except a reference to the value to
|
||||
/// set is passed in and Variant does the casting.
|
||||
template<typename T>
|
||||
void GetInto(T &lvalue, const std::string &s, const T &def) const;
|
||||
|
||||
/// \brief An into version of GetPath
|
||||
template<typename T>
|
||||
void GetPathInto(T &lvalue, const Path &path, const T &def) const;
|
||||
template<typename T>
|
||||
void GetPathInto(T &lvalue, const std::string &path, const T &def) const
|
||||
{ GetPathInto(lvalue, ParsePath(path), def); }
|
||||
|
||||
/// \brief This type and other type must be MapType.
|
||||
/// for (k, v) in other: this[k] = v
|
||||
void Merge(Variant other);
|
||||
|
||||
/// \brief Comparison operator
|
||||
/// Returns -1 if we are less than other
|
||||
/// 0 if we are equal
|
||||
/// 1 if we are greater than
|
||||
/// This function always returns 1 if Comparable returns false
|
||||
/// This compare is not completely consistent
|
||||
/// i.e. it can be such that two Variants are
|
||||
/// both < and > (ex map and list types)
|
||||
int Compare(const Variant &other) const;
|
||||
|
||||
/// \brief Return true if this and other are comparable. Two types are
|
||||
/// considered comparable if they have the same type or if they are both
|
||||
/// number types.
|
||||
bool Comparable(const Variant &other) const;
|
||||
|
||||
void Incr();
|
||||
void Decr();
|
||||
void Add(const Variant &o);
|
||||
void Sub(const Variant &o);
|
||||
void Mul(const Variant &o);
|
||||
void Div(const Variant &o);
|
||||
void Rem(const Variant &o);
|
||||
|
||||
Variant Neg() const;
|
||||
|
||||
Variant &operator++() { Incr(); return *this; }
|
||||
Variant &operator--() { Decr(); return *this; }
|
||||
Variant operator++(int) { Variant tmp = *this; ++(*this); return tmp; }
|
||||
Variant operator--(int) { Variant tmp = *this; --(*this); return tmp; }
|
||||
Variant operator-() const { return Neg(); }
|
||||
Variant operator+() const { return *this; }
|
||||
|
||||
Variant &operator+=(const Variant &o) { Add(o); return *this; }
|
||||
Variant &operator-=(const Variant &o) { Sub(o); return *this; }
|
||||
Variant &operator*=(const Variant &o) { Mul(o); return *this; }
|
||||
Variant &operator/=(const Variant &o) { Div(o); return *this; }
|
||||
Variant &operator%=(const Variant &o) { Rem(o); return *this; }
|
||||
|
||||
VariantRef Ref(); //< Return a new VariantRef to this Variant
|
||||
Variant Copy() const; //< Return a copy of this Variant
|
||||
Variant &Resolve(); //< Return *this or return the Variant this is a reference to
|
||||
const Variant &Resolve() const;
|
||||
/// Return *this or Variant referenced to if exists, otherwise create it with def.
|
||||
Variant &Resolve(const Variant &def);
|
||||
/// Return weather or not Resolve() const would throw.
|
||||
bool Exists() const;
|
||||
|
||||
/// Make this equal other.
|
||||
void Assign(const Variant &other);
|
||||
|
||||
void Assign(VariantDefines::Type_t type);
|
||||
void Assign(bool v);
|
||||
void Assign(int v);
|
||||
void Assign(unsigned v);
|
||||
void Assign(long v);
|
||||
void Assign(unsigned long v);
|
||||
void Assign(long long v);
|
||||
void Assign(unsigned long long v);
|
||||
void Assign(double v);
|
||||
void Assign(long double v);
|
||||
void Assign(BlobPtr b);
|
||||
void Assign(const std::string &v);
|
||||
void Assign(const char *v);
|
||||
|
||||
template<typename T>
|
||||
void Assign(const std::vector<T> &v) {
|
||||
Assign(VariantDefines::ListType);
|
||||
AsList().assign(v.begin(), v.end());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void Assign(const std::map<std::string, T> &v) {
|
||||
Assign(VariantDefines::MapType);
|
||||
AsMap().insert(v.begin(), v.end());
|
||||
}
|
||||
|
||||
protected:
|
||||
Variant(const RefTag &, const Variant &o);
|
||||
Variant(const RefTag &, Variant &o, Path::const_iterator b, Path::const_iterator e);
|
||||
/// Reassing this reference, only available through the VariantRef interface.
|
||||
/// The regular Assign makes what this is refering to equal the new value, this
|
||||
/// function makes this reference refer to the new value.
|
||||
void ReassignRef(const Variant &o);
|
||||
friend class Internal::VTable;
|
||||
};
|
||||
|
||||
typedef VariantRefImpl<Variant> VariantRef;
|
||||
|
||||
inline bool operator==(const Variant &lhs, const Variant &rhs) { return lhs.Compare(rhs) == 0; }
|
||||
inline bool operator!=(const Variant &lhs, const Variant &rhs) { return lhs.Compare(rhs) != 0; }
|
||||
inline bool operator<(const Variant &lhs, const Variant &rhs) { return lhs.Compare(rhs) < 0; }
|
||||
inline bool operator>(const Variant &lhs, const Variant &rhs) { return lhs.Compare(rhs) > 0; }
|
||||
inline bool operator<=(const Variant &lhs, const Variant &rhs) { return lhs.Compare(rhs) <= 0; }
|
||||
inline bool operator>=(const Variant &lhs, const Variant &rhs) { return lhs.Compare(rhs) >= 0; }
|
||||
|
||||
inline Variant operator+(const Variant &lhs, const Variant &rhs) {
|
||||
Variant ret = lhs;
|
||||
return ret += rhs;
|
||||
}
|
||||
inline Variant operator-(const Variant &lhs, const Variant &rhs) {
|
||||
Variant ret = lhs;
|
||||
return ret -= rhs;
|
||||
}
|
||||
inline Variant operator*(const Variant &lhs, const Variant &rhs) {
|
||||
Variant ret = lhs;
|
||||
return ret *= rhs;
|
||||
}
|
||||
inline Variant operator/(const Variant &lhs, const Variant &rhs) {
|
||||
Variant ret = lhs;
|
||||
return ret /= rhs;
|
||||
}
|
||||
inline Variant operator%(const Variant &lhs, const Variant &rhs) {
|
||||
Variant ret = lhs;
|
||||
return ret %= rhs;
|
||||
}
|
||||
|
||||
/// \defgroup variant_cast Template casting operators.
|
||||
/// These are for use inside templates to extract the value of a Variant into
|
||||
/// a templated type.
|
||||
/// @{
|
||||
|
||||
template<typename T>
|
||||
struct VariantCaster {
|
||||
static T Cast(const Variant &v);
|
||||
};
|
||||
|
||||
// Default
|
||||
template<typename T> inline T VariantCaster<T>::Cast(const Variant &v) { return T(v); }
|
||||
|
||||
template<typename T>
|
||||
inline T variant_cast(const Variant &v) { return VariantCaster<T>::Cast(v); }
|
||||
|
||||
// Provide specializations for all the basic types
|
||||
template<> inline bool VariantCaster<bool>::Cast(const Variant &v) { return v.AsBool(); }
|
||||
template<> inline char VariantCaster<char>::Cast(const Variant &v) { return (char)v.AsInt(); }
|
||||
template<> inline unsigned char VariantCaster<unsigned char>::Cast(const Variant &v) { return (unsigned char)v.AsUnsigned(); }
|
||||
template<> inline signed char VariantCaster<signed char>::Cast(const Variant &v) { return (signed char)v.AsUnsigned(); }
|
||||
template<> inline short VariantCaster<short>::Cast(const Variant &v) { return (short)v.AsInt(); }
|
||||
template<> inline unsigned short VariantCaster<unsigned short>::Cast(const Variant &v) { return (unsigned short)v.AsUnsigned(); }
|
||||
template<> inline int VariantCaster<int>::Cast(const Variant &v) { return (int)v.AsInt(); }
|
||||
template<> inline unsigned VariantCaster<unsigned>::Cast(const Variant &v) { return (unsigned)v.AsUnsigned(); }
|
||||
template<> inline long VariantCaster<long>::Cast(const Variant &v) { return (long)v.AsInt(); }
|
||||
template<> inline unsigned long VariantCaster<unsigned long>::Cast(const Variant &v) { return (unsigned long)v.AsUnsigned(); }
|
||||
template<> inline long long VariantCaster<long long>::Cast(const Variant &v) { return (long long)v.AsInt(); }
|
||||
template<> inline unsigned long long VariantCaster<unsigned long long>::Cast(const Variant &v) { return (unsigned long long)v.AsUnsigned(); }
|
||||
template<> inline float VariantCaster<float>::Cast(const Variant &v) { return (float)v.AsDouble(); }
|
||||
template<> inline double VariantCaster<double>::Cast(const Variant &v) { return v.AsDouble(); }
|
||||
template<> inline long double VariantCaster<long double>::Cast(const Variant &v) { return v.AsLongDouble(); }
|
||||
template<> inline std::string VariantCaster<std::string>::Cast(const Variant &v) { return v.AsString(); }
|
||||
|
||||
// Allow things like variant_cast< std::vector<int> >(v) to work
|
||||
template<typename T>
|
||||
struct VariantCaster< std::vector<T> > {
|
||||
static std::vector<T> Cast(const Variant &v);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline std::vector<T> VariantCaster< std::vector<T> >::Cast(const Variant &v) {
|
||||
std::vector<T> ret;
|
||||
for (Variant::ConstListIterator i(v.ListBegin()), e(v.ListEnd()); i != e; ++i) {
|
||||
ret.push_back( variant_cast<T>( *i ) );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<> inline Variant::List VariantCaster<Variant::List>::Cast(const Variant &v) { return v.AsList(); }
|
||||
|
||||
// allow things like variant_cast< std::map<std::string, std::string> >(v)
|
||||
// to work
|
||||
template<typename T>
|
||||
struct VariantCaster< std::map<std::string, T> > {
|
||||
static std::map<std::string, T> Cast(const Variant &v);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline std::map<std::string, T> VariantCaster< std::map<std::string, T> >::Cast(const Variant &v) {
|
||||
std::map<std::string, T> ret;
|
||||
for (Variant::ConstMapIterator i(v.MapBegin()), e(v.MapEnd()); i != e; ++i) {
|
||||
ret.insert( std::make_pair( i->first, variant_cast<T>( i->second ) ) );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<> inline Variant::Map VariantCaster<Variant::Map>::Cast(const Variant &v) { return v.AsMap(); }
|
||||
|
||||
template<typename T>
|
||||
struct VariantCaster< std::complex<T> > {
|
||||
static std::complex<T> Cast(const Variant &v);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
std::complex<T> VariantCaster< std::complex<T> >::Cast(const Variant &v) {
|
||||
if (v.IsNull()) {
|
||||
return std::complex<T>();
|
||||
} else if (v.IsNumber()) {
|
||||
return std::complex<T>(v.As<T>(), T());
|
||||
} else if (v.IsMap()) {
|
||||
T r = variant_cast<T>(v.Get("real", T()));
|
||||
T c = variant_cast<T>(v.Get("imag", T()));
|
||||
return std::complex<T>(r, c);
|
||||
} else if (v.IsList()) {
|
||||
if (v.Size() > 1) {
|
||||
return std::complex<T>(v[0].As<T>(), v[1].As<T>());
|
||||
} else if (v.Size() > 0) {
|
||||
return std::complex<T>(v[0].As<T>(), T());
|
||||
} else {
|
||||
return std::complex<T>();
|
||||
}
|
||||
}
|
||||
throw UnableToConvertError(v.GetType(), "std::complex<T>");
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
template<typename T>
|
||||
T Variant::As() const { return variant_cast<T>(*this); }
|
||||
|
||||
template<typename T>
|
||||
void Variant::GetInto(T &lvalue, const std::string &s) const {
|
||||
lvalue = variant_cast<T>(Get(s));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void Variant::GetPathInto(T &lvalue, const Path &p) const {
|
||||
lvalue = variant_cast<T>(GetPath(p));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void Variant::GetInto(T &lvalue, const std::string &s, const T &def) const {
|
||||
if (Contains(s)) { lvalue = variant_cast<T>(Get(s)); }
|
||||
else { lvalue = def; }
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void Variant::GetPathInto(T &lvalue, const Path &p, const T &def) const {
|
||||
lvalue = variant_cast<T>(GetPath(p, def));
|
||||
}
|
||||
|
||||
class Parser;
|
||||
/// \brief Takes a parser and produces a Variant from it.
|
||||
Variant ParseVariant(Parser &p);
|
||||
|
||||
class Emitter;
|
||||
/// Takes a Variant and Emitter and emits the Variant.
|
||||
Emitter &operator<<(Emitter &e, const Variant &v);
|
||||
|
||||
/// \brief The different types of serialization supported.
|
||||
enum SerializeType {
|
||||
// Attempt to guess the format
|
||||
// Cannot be specified as an output format.
|
||||
SERIALIZE_GUESS = 0x0,
|
||||
|
||||
// Built in text formats
|
||||
SERIALIZE_JSON = 0x00000001,
|
||||
SERIALIZE_YAML,
|
||||
SERIALIZE_XMLPLIST,
|
||||
SERIALIZE_BUNDLEHDR,
|
||||
|
||||
// Built in binary formats
|
||||
SERIALIZE_MSGPACK = 0x000000FF,
|
||||
|
||||
};
|
||||
|
||||
|
||||
/// \brief An iterator that iterates over all documents that the parser will generate
|
||||
class LoadAllIterator {
|
||||
public:
|
||||
typedef Variant value_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef Variant* pointer;
|
||||
typedef Variant& reference;
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
|
||||
LoadAllIterator();
|
||||
explicit LoadAllIterator(Parser &parser);
|
||||
Variant &operator*() { return Get(); }
|
||||
Variant *operator->() { return &Get(); }
|
||||
Variant &Get();
|
||||
void Next();
|
||||
LoadAllIterator &operator++() {
|
||||
Next();
|
||||
return *this;
|
||||
}
|
||||
LoadAllIterator operator++(int) {
|
||||
LoadAllIterator copy = *this;
|
||||
Next();
|
||||
return copy;
|
||||
}
|
||||
bool operator==(const LoadAllIterator &that) const;
|
||||
bool operator!=(const LoadAllIterator &that) const { return !(*this == that); }
|
||||
private:
|
||||
class Impl;
|
||||
shared_ptr<Impl> impl;
|
||||
struct Value;
|
||||
shared_ptr<Value> value;
|
||||
};
|
||||
|
||||
// Some convenience functions
|
||||
// A version is provided that will go to/from a string,
|
||||
// a memory buffer, a file name, an open FILE*, and
|
||||
// a streambuf* (usually acquired through iostream.rdbuf()).
|
||||
|
||||
/// \brief Serialize a Variant to a string using format type.
|
||||
std::string Serialize(Variant v, SerializeType type, Variant params = Variant::NullType);
|
||||
/// \brief Serialize a Variant to a file using format type.
|
||||
void Serialize(const std::string &filename, Variant v, SerializeType type,
|
||||
Variant params = Variant::NullType);
|
||||
/// \brief Serialize a Variant to a FILE pointer using format type.
|
||||
void Serialize(FILE *f, Variant v, SerializeType type,
|
||||
Variant params = Variant::NullType);
|
||||
/// \brief Serialize a Variant to a streambuf* (iostrem.rdbuf()) using format type.
|
||||
void Serialize(std::streambuf *sb, Variant v, SerializeType type,
|
||||
Variant params = Variant::NullType);
|
||||
/// \brief Serialize a Variant to a memory buffer of length len, using format type
|
||||
//and return how many bytes produced.
|
||||
unsigned Serialize(void *ptr, unsigned len, Variant v, SerializeType type,
|
||||
Variant params = Variant::NullType);
|
||||
|
||||
// The basic deserializing functions
|
||||
|
||||
/// \brief Attempt to deserialize a string in format type to a Variant
|
||||
Variant Deserialize(const std::string &str, SerializeType type);
|
||||
/// \brief Attempt to deserialize a null terminated string in format type to a Variant
|
||||
Variant Deserialize(const char *str, SerializeType type);
|
||||
/// \brief Attempt to deserialize a pointer and length in format type to a Variant
|
||||
Variant Deserialize(const void *ptr, unsigned len, SerializeType type);
|
||||
/// \brief Attempt to deserialize the file to a Variant in format type
|
||||
Variant DeserializeFile(const char *filename, SerializeType type);
|
||||
/// \brief Deserialize from a FILE pointer to a Variant in format type
|
||||
Variant DeserializeFile(FILE *f, SerializeType type);
|
||||
/// \brief Deserialize from a streambuf to a Variant in format type
|
||||
Variant DeserializeFile(std::streambuf *sb, SerializeType type);
|
||||
|
||||
/// \defgroup deserialize_guess Guess format
|
||||
/// These functions attempt to guess the type of the input. The guessing
|
||||
/// function only looks at the first non-whitespace character to make the
|
||||
/// decision. As such on sufficiently badly behaved input can select the
|
||||
/// wrong format.
|
||||
/// @{
|
||||
Variant DeserializeGuess(const std::string &str);
|
||||
Variant DeserializeGuess(const char *str);
|
||||
Variant DeserializeGuess(const void *ptr, unsigned len);
|
||||
Variant DeserializeGuessFile(const char *filename);
|
||||
Variant DeserializeGuessFile(FILE *f);
|
||||
Variant DeserializeGuessFile(std::streambuf *sb);
|
||||
/// @}
|
||||
|
||||
/// \defgroup deserialize_all Deserialize all elements
|
||||
/// These functions return an iterator. These are for format types that
|
||||
/// support multiple documents in one stream. Otherwise same as Deserialize
|
||||
/// functions above.
|
||||
/// @{
|
||||
LoadAllIterator DeserializeAll(const std::string &str, SerializeType type);
|
||||
LoadAllIterator DeserializeAll(const char *str, SerializeType type);
|
||||
LoadAllIterator DeserializeAll(const void *ptr, unsigned len, SerializeType type);
|
||||
LoadAllIterator DeserializeAllFile(const char *filename, SerializeType type);
|
||||
/// File must remain open for as long as the iterator is referenced
|
||||
LoadAllIterator DeserializeAllFile(FILE *f, SerializeType type);
|
||||
/// Streambuf must exist for as long as the iterator is referenced
|
||||
LoadAllIterator DeserializeAllFile(std::streambuf *sb, SerializeType type);
|
||||
/// @}
|
||||
|
||||
|
||||
// Serialize and Deserializing JSON
|
||||
//
|
||||
inline std::string SerializeJSON(Variant v, bool pretty=false) {
|
||||
Variant param = Variant::MapType; param["pretty"] = pretty;
|
||||
return Serialize(v, SERIALIZE_JSON, param);
|
||||
}
|
||||
inline void SerializeJSON(const std::string &filename, Variant v, bool pretty=false) {
|
||||
Variant param = Variant::MapType; param["pretty"] = pretty;
|
||||
Serialize(filename, v, SERIALIZE_JSON, param);
|
||||
}
|
||||
inline void SerializeJSON(FILE *f, Variant v, bool pretty=false) {
|
||||
Variant param = Variant::MapType; param["pretty"] = pretty;
|
||||
Serialize(f, v, SERIALIZE_JSON, param);
|
||||
}
|
||||
inline void SerializeJSON(std::streambuf *sb, Variant v, bool pretty=false) {
|
||||
Variant param = Variant::MapType; param["pretty"] = pretty;
|
||||
Serialize(sb, v, SERIALIZE_JSON, param);
|
||||
}
|
||||
inline unsigned SerializeJSON(void *ptr, unsigned len, Variant v, bool pretty=false) {
|
||||
Variant param = Variant::MapType; param["pretty"] = pretty;
|
||||
return Serialize(ptr, len, v, SERIALIZE_JSON, param);
|
||||
}
|
||||
inline Variant DeserializeJSON(const std::string &str) { return Deserialize(str, SERIALIZE_JSON); }
|
||||
inline Variant DeserializeJSON(const char *str) { return Deserialize(str, SERIALIZE_JSON); }
|
||||
inline Variant DeserializeJSON(const void *ptr, unsigned len) { return Deserialize(ptr, len, SERIALIZE_JSON); }
|
||||
inline Variant DeserializeJSONFile(const char *filename) { return DeserializeFile(filename, SERIALIZE_JSON); }
|
||||
inline Variant DeserializeJSONFile(FILE *f) { return DeserializeFile(f, SERIALIZE_JSON); }
|
||||
inline Variant DeserializeJSONFile(std::streambuf *sb) { return DeserializeFile(sb, SERIALIZE_JSON); }
|
||||
|
||||
//Serialize and Deserialize YAML
|
||||
//
|
||||
inline std::string SerializeYAML(Variant v) { return Serialize(v, SERIALIZE_YAML); }
|
||||
inline void SerializeYAML(const std::string &filename, Variant v) { Serialize(filename, v, SERIALIZE_YAML); }
|
||||
inline void SerializeYAML(FILE *f, Variant v) { Serialize(f, v, SERIALIZE_YAML); }
|
||||
inline void SerializeYAML(std::streambuf *sb, Variant v) { Serialize(sb, v, SERIALIZE_YAML); }
|
||||
inline unsigned SerializeYAML(void *ptr, unsigned len, Variant v) { return Serialize(ptr, len, v, SERIALIZE_YAML); }
|
||||
|
||||
inline Variant DeserializeYAML(const std::string &str) { return Deserialize(str, SERIALIZE_YAML); }
|
||||
inline Variant DeserializeYAML(const char *str) { return Deserialize(str, SERIALIZE_YAML); }
|
||||
inline Variant DeserializeYAML(const void *ptr, unsigned len) { return Deserialize(ptr, len, SERIALIZE_YAML); }
|
||||
inline Variant DeserializeYAMLFile(const char *filename) { return DeserializeFile(filename, SERIALIZE_YAML); }
|
||||
inline Variant DeserializeYAMLFile(FILE *f) { return DeserializeFile(f, SERIALIZE_YAML); }
|
||||
inline Variant DeserializeYAMLFile(std::streambuf *sb) { return DeserializeFile(sb, SERIALIZE_YAML); }
|
||||
|
||||
inline LoadAllIterator DeserializeYAMLAll(const std::string &str) { return DeserializeAll(str, SERIALIZE_YAML); }
|
||||
inline LoadAllIterator DeserializeYAMLAll(const char *str) { return DeserializeAll(str, SERIALIZE_YAML); }
|
||||
inline LoadAllIterator DeserializeYAMLAll(const void *ptr, unsigned len) { return DeserializeAll(ptr, len, SERIALIZE_YAML); }
|
||||
inline LoadAllIterator DeserializeYAMLAllFile(const char *filename) { return DeserializeAllFile(filename, SERIALIZE_YAML); }
|
||||
inline LoadAllIterator DeserializeYAMLAllFile(FILE *f) { return DeserializeAllFile(f, SERIALIZE_YAML); }
|
||||
inline LoadAllIterator DeserializeYAMLAllFile(std::streambuf *sb) { return DeserializeAllFile(sb, SERIALIZE_YAML); }
|
||||
|
||||
//Serialize and Deserialize XML plist
|
||||
//
|
||||
inline std::string SerializeXMLPLIST(Variant v, bool pretty=false) {
|
||||
Variant param = Variant::MapType; param["pretty"] = pretty;
|
||||
return Serialize(v, SERIALIZE_XMLPLIST, param);
|
||||
}
|
||||
inline void SerializeXMLPLIST(const std::string &filename, Variant v, bool pretty=false) {
|
||||
Variant param = Variant::MapType; param["pretty"] = pretty;
|
||||
Serialize(filename, v, SERIALIZE_XMLPLIST, param);
|
||||
}
|
||||
inline void SerializeXMLPLIST(FILE *f, Variant v, bool pretty=false) {
|
||||
Variant param = Variant::MapType; param["pretty"] = pretty;
|
||||
Serialize(f, v, SERIALIZE_XMLPLIST, param);
|
||||
}
|
||||
inline void SerializeXMLPLIST(std::streambuf *sb, Variant v, bool pretty=false) {
|
||||
Variant param = Variant::MapType; param["pretty"] = pretty;
|
||||
Serialize(sb, v, SERIALIZE_XMLPLIST, param);
|
||||
}
|
||||
inline unsigned SerializeXMLPLIST(void *ptr, unsigned len, Variant v, bool pretty=false) {
|
||||
Variant param = Variant::MapType; param["pretty"] = pretty;
|
||||
return Serialize(ptr, len, v, SERIALIZE_XMLPLIST, param);
|
||||
}
|
||||
|
||||
inline Variant DeserializeXMLPLIST(const std::string &str) { return Deserialize(str, SERIALIZE_XMLPLIST); }
|
||||
inline Variant DeserializeXMLPLIST(const char *str) { return Deserialize(str, SERIALIZE_XMLPLIST); }
|
||||
inline Variant DeserializeXMLPLIST(const void *ptr, unsigned len) { return Deserialize(ptr, len, SERIALIZE_XMLPLIST); }
|
||||
inline Variant DeserializeXMLPLISTFile(const char *filename) { return DeserializeFile(filename, SERIALIZE_XMLPLIST); }
|
||||
inline Variant DeserializeXMLPLISTFile(FILE *f) { return DeserializeFile(f, SERIALIZE_XMLPLIST); }
|
||||
inline Variant DeserializeXMLPLISTFile(std::streambuf *sb) { return DeserializeFile(sb, SERIALIZE_XMLPLIST); }
|
||||
|
||||
//Serialize and Deserialize BundleHdr
|
||||
//
|
||||
// BundleHdr requires the root element to be of MapType and
|
||||
// no submaps exist.
|
||||
//
|
||||
// Note that these do not add a null byte to the end.
|
||||
// Use SerializeBundle for that.
|
||||
|
||||
inline std::string SerializeBundleHdr(Variant v) {
|
||||
Variant param = Variant::MapType;
|
||||
return Serialize(v, SERIALIZE_BUNDLEHDR, param);
|
||||
}
|
||||
inline void SerializeBundleHdr(const std::string &filename, Variant v) {
|
||||
Variant param = Variant::MapType;
|
||||
Serialize(filename, v, SERIALIZE_BUNDLEHDR, param);
|
||||
}
|
||||
inline void SerializeBundleHdr(FILE *f, Variant v) {
|
||||
Variant param = Variant::MapType;
|
||||
Serialize(f, v, SERIALIZE_BUNDLEHDR, param);
|
||||
}
|
||||
inline void SerializeBundleHdr(std::streambuf *sb, Variant v) {
|
||||
Variant param = Variant::MapType;
|
||||
Serialize(sb, v, SERIALIZE_BUNDLEHDR, param);
|
||||
}
|
||||
inline unsigned SerializeBundleHdr(void *ptr, unsigned len, Variant v) {
|
||||
Variant param = Variant::MapType;
|
||||
return Serialize(ptr, len, v, SERIALIZE_BUNDLEHDR, param);
|
||||
}
|
||||
|
||||
inline Variant DeserializeBundleHdr(const std::string &str) { return Deserialize(str, SERIALIZE_BUNDLEHDR); }
|
||||
inline Variant DeserializeBundleHdr(const char *str) { return Deserialize(str, SERIALIZE_BUNDLEHDR); }
|
||||
inline Variant DeserializeBundleHdr(const void *ptr, unsigned len) { return Deserialize(ptr, len, SERIALIZE_BUNDLEHDR); }
|
||||
inline Variant DeserializeBundleHdrFile(const char *filename) { return DeserializeFile(filename, SERIALIZE_BUNDLEHDR); }
|
||||
inline Variant DeserializeBundleHdrFile(FILE *f) { return DeserializeFile(f, SERIALIZE_BUNDLEHDR); }
|
||||
inline Variant DeserializeBundleHdrFile(std::streambuf *sb) { return DeserializeFile(sb, SERIALIZE_BUNDLEHDR); }
|
||||
|
||||
}
|
||||
|
||||
/// Debug function not inside the namespace to print out a variant (calls SerializeJSON)
|
||||
void VariantPrint(const libvariant::Variant v);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,50 @@
|
||||
//=============================================================================
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Library General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// The GNU Public License is available in the file LICENSE, or you
|
||||
// can write to the Free Software Foundation, Inc., 59 Temple Place -
|
||||
// Suite 330, Boston, MA 02111-1307, USA, or you can find it on the
|
||||
// World Wide Web at http://www.fsf.org.
|
||||
//=============================================================================
|
||||
/** \file
|
||||
* \author John Bridgman
|
||||
* \brief
|
||||
*/
|
||||
#ifndef VARIANT_DEFINES_H
|
||||
#define VARIANT_DEFINES_H
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define DEPRECATED __attribute__((deprecated))
|
||||
#elif defined(_MSC_VER)
|
||||
#define DEPRECATED __declspec(deprecated)
|
||||
#else
|
||||
#pragma message("WARNING: You need to implement DEPRECATED for this compiler")
|
||||
#define DEPRECATED
|
||||
#endif
|
||||
|
||||
namespace libvariant {
|
||||
class VariantDefines {
|
||||
public:
|
||||
enum Type_t {
|
||||
NullType = 0, // Explicitly defined as 0
|
||||
BoolType,
|
||||
IntegerType,
|
||||
UnsignedType,
|
||||
FloatType,
|
||||
StringType,
|
||||
ListType,
|
||||
MapType,
|
||||
BlobType
|
||||
};
|
||||
|
||||
};
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,96 @@
|
||||
//=============================================================================
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Library General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// The GNU Public License is available in the file LICENSE, or you
|
||||
// can write to the Free Software Foundation, Inc., 59 Temple Place -
|
||||
// Suite 330, Boston, MA 02111-1307, USA, or you can find it on the
|
||||
// World Wide Web at http://www.fsf.org.
|
||||
//=============================================================================
|
||||
/** \file
|
||||
* \author John Bridgman
|
||||
* \brief
|
||||
*/
|
||||
#ifndef VARIANT_BASE_H
|
||||
#define VARIANT_BASE_H
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "../hos_libvariant/Blob.h"
|
||||
#include "../hos_libvariant/Path.h"
|
||||
#include "../hos_libvariant/SharedPtr.h"
|
||||
#include "../hos_libvariant/VariantDefines.h"
|
||||
namespace libvariant {
|
||||
|
||||
struct RefTag {};
|
||||
|
||||
class Variant;
|
||||
template<typename Base> class VariantRefImpl;
|
||||
|
||||
|
||||
/**
|
||||
* Action implementation for the VariantRef class.
|
||||
*/
|
||||
template<typename Base>
|
||||
class VariantRefImpl : public Base {
|
||||
public:
|
||||
VariantRefImpl(const Variant &o) : Base(RefTag(), o) {}
|
||||
VariantRefImpl(Variant &o, const Path &path)
|
||||
: Base(RefTag(), o, path.begin(), path.end()) {}
|
||||
VariantRefImpl(Variant &o, Path::const_iterator b, Path::const_iterator e)
|
||||
: Base(RefTag(), o, b, e) {}
|
||||
VariantRefImpl(const VariantRefImpl<Base> &o)
|
||||
: Base(RefTag(), o) {}
|
||||
|
||||
using Base::operator=;
|
||||
using Base::As;
|
||||
using Base::AsNumber;
|
||||
using Base::GetInto;
|
||||
using Base::GetPathInto;
|
||||
using Base::Assign;
|
||||
|
||||
using Base::ReassignRef;
|
||||
};
|
||||
|
||||
namespace Internal {
|
||||
|
||||
class VTable;
|
||||
struct Storage;
|
||||
struct MapStorage;
|
||||
struct ListStorage;
|
||||
struct ProxyStorage;
|
||||
struct RefData;
|
||||
|
||||
struct Data {
|
||||
Data();
|
||||
const VTable *vtable;
|
||||
union {
|
||||
bool b;
|
||||
long double f;
|
||||
intmax_t i;
|
||||
uintmax_t u;
|
||||
std::string *s;
|
||||
MapStorage *m;
|
||||
ListStorage *l;
|
||||
BlobPtr *blob;
|
||||
Data *ref;
|
||||
ProxyStorage *proxy;
|
||||
};
|
||||
shared_ptr<RefData> ref_data;
|
||||
shared_ptr<Storage> storage;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,50 @@
|
||||
<?xml version="1.0"?>
|
||||
<package>
|
||||
<name>hos_libvariant</name>
|
||||
<version>0.0.0</version>
|
||||
<description>The hos_libvariant package</description>
|
||||
|
||||
<!-- One maintainer tag required, multiple allowed, one person per tag -->
|
||||
<!-- Example: -->
|
||||
<!-- <maintainer email="jane.doe@example.com">Jane Doe</maintainer> -->
|
||||
<maintainer email="matzman@todo.todo">matzman</maintainer>
|
||||
|
||||
|
||||
<!-- One license tag required, multiple allowed, one license per tag -->
|
||||
<!-- Commonly used license strings: -->
|
||||
<!-- BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 -->
|
||||
<license>TODO</license>
|
||||
|
||||
|
||||
<!-- Url tags are optional, but mutiple are allowed, one per tag -->
|
||||
<!-- Optional attribute type can be: website, bugtracker, or repository -->
|
||||
<!-- Example: -->
|
||||
<!-- <url type="website">http://wiki.ros.org/hos_libvariant</url> -->
|
||||
|
||||
|
||||
<!-- Author tags are optional, mutiple are allowed, one per tag -->
|
||||
<!-- Authors do not have to be maintianers, but could be -->
|
||||
<!-- Example: -->
|
||||
<!-- <author email="jane.doe@example.com">Jane Doe</author> -->
|
||||
|
||||
|
||||
<!-- The *_depend tags are used to specify dependencies -->
|
||||
<!-- Dependencies can be catkin packages or system dependencies -->
|
||||
<!-- Examples: -->
|
||||
<!-- Use build_depend for packages you need at compile time: -->
|
||||
<!-- <build_depend>message_generation</build_depend> -->
|
||||
<!-- Use buildtool_depend for build tool packages: -->
|
||||
<!-- <buildtool_depend>catkin</buildtool_depend> -->
|
||||
<!-- Use run_depend for packages you need at runtime: -->
|
||||
<!-- <run_depend>message_runtime</run_depend> -->
|
||||
<!-- Use test_depend for packages you need only for testing: -->
|
||||
<!-- <test_depend>gtest</test_depend> -->
|
||||
<buildtool_depend>catkin</buildtool_depend>
|
||||
|
||||
|
||||
<!-- The export tag contains other, unspecified, tags -->
|
||||
<export>
|
||||
<!-- Other tools can request additional information be placed here -->
|
||||
|
||||
</export>
|
||||
</package>
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
default
|
||||
@@ -0,0 +1,2 @@
|
||||
055488b93468e27c2893da3834e86506b1cd4b10 4
|
||||
055488b93468e27c2893da3834e86506b1cd4b10 o default
|
||||
Binary file not shown.
@@ -0,0 +1,2 @@
|
||||
[paths]
|
||||
default = https://bitbucket.org/gallen/libvariant
|
||||
@@ -0,0 +1,4 @@
|
||||
dotencode
|
||||
fncache
|
||||
revlogv1
|
||||
store
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user