Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • android_compatible_0.14
  • ipaaca-json
  • ipaaca-rsb
  • ipaaca3-dev
  • ipaaca4
  • ipaaca4py3
  • kompass
  • legacy-str
  • master
  • mqtt_port
  • rsb0.11
  • rsb0.14
  • ryt-fullport
  • softwareweek2019
  • windows-compatibility
15 results

Target

Select target project
  • scs/ipaaca
  • ramin.yaghoubzadeh/ipaaca
2 results
Select Git revision
  • ipaaca-rsb
  • ipaaca3-dev
  • ipaaca4
  • kompass
  • master
  • rsb0.14
6 results
Show changes
Showing
with 5964 additions and 3577 deletions
/*
* This file is part of IPAACA, the
* "Incremental Processing Architecture
* for Artificial Conversational Agents".
*
* Copyright (c) 2009-2022 Social Cognitive Systems Group
* (formerly the Sociable Agents Group)
* CITEC, Bielefeld University
*
* http://opensource.cit-ec.de/projects/ipaaca/
* http://purl.org/net/ipaaca
*
* This file may be licensed under the terms of of the
* GNU Lesser General Public License Version 3 (the ``LGPL''),
* or (at your option) any later version.
*
* Software distributed under the License is distributed
* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
* express or implied. See the LGPL for the specific language
* governing rights and limitations.
*
* You should have received a copy of the LGPL along with this
* program. If not, go to http://www.gnu.org/licenses/lgpl.html
* or write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The development of this software was supported by the
* Excellence Cluster EXC 277 Cognitive Interaction Technology.
* The Excellence Cluster EXC 277 is a grant of the Deutsche
* Forschungsgemeinschaft (DFG) in the context of the German
* Excellence Initiative.
*/
/**
* \file ipaaca-cmdline_parser.h
*
* \brief Header file for basic command line parser
*
* Users should not include this file directly, but use ipaaca.h
*
* \author Ramin Yaghoubzadeh (ryaghoubzadeh@uni-bielefeld.de)
* \date February, 2019
*/
#ifndef __ipaaca_cmdline_parser_h_INCLUDED__
#define __ipaaca_cmdline_parser_h_INCLUDED__
#ifndef __ipaaca_h_INCLUDED__
#error "Please do not include this file directly, use ipaaca.h instead"
#endif
// in ipaaca-cmdline-parser.cc
// additional misc classes ( Command line options )//{{{
/** \brief Command line argument container for CommandLineParser
*
* Contains the results of argument parsing from CommandLineParser::parse()
*
* The parser is preconfigured to handle some standard options:
*
* Option | Function
* --------------------------------|------------------------------------------------------------------------------
* --help | Print list of available options
* --verbose | Set verbose flag
* --character-name <name> | Set character name (legacy)
* --component-name <name> | Set component name (legacy)
* --ipaaca-payload-type <type> | Set default ipaaca payload type (default JSON, set STR for legacy protocol)
* --ipaaca-default-channel <name> | Set default channel name (default 'default')
* --ipaaca-enable-logging <level> | Set console log level, one of NONE, DEBUG, INFO, WARNING, ERROR, CRITICAL
* --rsb-enable-logging <level> | Set rsb (transport) log level
*
*/
class CommandLineOptions {
public:
IPAACA_HEADER_EXPORT inline CommandLineOptions()
{ }
IPAACA_HEADER_EXPORT inline ~CommandLineOptions() {
}
IPAACA_MEMBER_VAR_EXPORT std::map<std::string, std::string> param_opts;
IPAACA_MEMBER_VAR_EXPORT std::map<std::string, bool> param_set;
public:
IPAACA_HEADER_EXPORT void set_option(const std::string& name, bool expect, const char* optarg);
/// Get the option argument or default value (if the option expected an argument)
IPAACA_HEADER_EXPORT std::string get_param(const std::string& o);
/// Check whether option has been set
IPAACA_HEADER_EXPORT bool is_set(const std::string& o);
IPAACA_HEADER_EXPORT void dump();
public:
typedef std::shared_ptr<CommandLineOptions> ptr;
};
/**
* \brief Command line parser for ipaaca programs.
*
* The parser is preconfigured to handle some standard options:
*
* Option | Function
* --------------------------------|------------------------------------------------------------------------------
* --help | Print list of available options
* --verbose | Set verbose flag
* --character-name <name> | Set character name (legacy)
* --component-name <name> | Set component name (legacy)
* --ipaaca-payload-type <type> | Set default ipaaca payload type (default JSON, set STR for legacy protocol)
* --ipaaca-default-channel <name> | Set default channel name (default 'default')
* --ipaaca-enable-logging <level> | Set console log level, one of NONE, DEBUG, INFO, WARNING, ERROR, CRITICAL
* --rsb-enable-logging <level> | Set rsb (transport) log level
*
*/
class CommandLineParser {
protected:
IPAACA_MEMBER_VAR_EXPORT std::map<char, std::string> longopt; // letter->name
IPAACA_MEMBER_VAR_EXPORT std::map<std::string, char> shortopt; // letter->name
IPAACA_MEMBER_VAR_EXPORT std::map<std::string, bool> options; // name / expect_param
IPAACA_MEMBER_VAR_EXPORT std::map<std::string, std::string> defaults; // for opt params
IPAACA_MEMBER_VAR_EXPORT std::map<std::string, int> set_flag; // for paramless opts
protected:
IPAACA_HEADER_EXPORT CommandLineParser();
IPAACA_MEMBER_VAR_EXPORT bool library_options_handled;
IPAACA_HEADER_EXPORT bool consume_library_option(const std::string& name, bool expect, const char* optarg);
IPAACA_HEADER_EXPORT void ensure_defaults_in( CommandLineOptions::ptr clo );
public:
IPAACA_HEADER_EXPORT inline ~CommandLineParser() { }
/// Create a new parser object reference.
IPAACA_HEADER_EXPORT static inline std::shared_ptr<CommandLineParser> create() {
return std::shared_ptr<CommandLineParser>(new CommandLineParser());
}
IPAACA_HEADER_EXPORT void initialize_parser_defaults();
IPAACA_HEADER_EXPORT void dump_options();
/** \brief Add a user-defined option
*
* \param optname The long option name, e.g. verbose for --verbose
* \param shortn The short option (or \0 for none)
* \param expect_param Whether an argument is expected for the option
* \param defaultv The default string value (unused if expect_param is false)
*/
IPAACA_HEADER_EXPORT void add_option(const std::string& optname, char shortn, bool expect_param, const std::string& defaultv);
/** \brief Parse argument list and return result.
*
* Parse argument list (e.g. from main()) with the parser, consuming the internal options.
* The remaining options are packaged into a CommandLineOptions object.
*/
IPAACA_HEADER_EXPORT CommandLineOptions::ptr parse(int argc, char* const* argv);
public:
typedef std::shared_ptr<CommandLineParser> ptr;
};
//}}}
#endif
/*
* This file is part of IPAACA, the
* "Incremental Processing Architecture
* for Artificial Conversational Agents".
*
* Copyright (c) 2009-2022 Social Cognitive Systems Group
* (formerly the Sociable Agents Group)
* CITEC, Bielefeld University
*
* http://opensource.cit-ec.de/projects/ipaaca/
* http://purl.org/net/ipaaca
*
* This file may be licensed under the terms of of the
* GNU Lesser General Public License Version 3 (the ``LGPL''),
* or (at your option) any later version.
*
* Software distributed under the License is distributed
* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
* express or implied. See the LGPL for the specific language
* governing rights and limitations.
*
* You should have received a copy of the LGPL along with this
* program. If not, go to http://www.gnu.org/licenses/lgpl.html
* or write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The development of this software was supported by the
* Excellence Cluster EXC 277 Cognitive Interaction Technology.
* The Excellence Cluster EXC 277 is a grant of the Deutsche
* Forschungsgemeinschaft (DFG) in the context of the German
* Excellence Initiative.
*/
/**
* \file ipaaca-backend.h
*
* \brief Header file for abstract backend participant implementation
* (used in the core library and as a base to derive specific backends).
*
* Users should not include this file directly, but use ipaaca.h
*
* \b Note: This file is only included during compilation of ipaaca,
* for regular use, the full internal API is not exposed.
* Users generally need never touch the internal transport layer.
*
* \author Ramin Yaghoubzadeh Torky (ryaghoubzadeh@uni-bielefeld.de)
* \date December, 2018
*/
#ifndef __ipaaca_config_h_INCLUDED__
#define __ipaaca_config_h_INCLUDED__
#ifndef __ipaaca_h_INCLUDED__
#error "Please do not include this file directly, use ipaaca.h instead"
#endif
class Config {
public:
typedef std::shared_ptr<Config> ptr;
protected:
std::map<std::string, std::string> _data;
std::set<std::string> _messages_delivered;
template<typename T> T get_with_default_internal(const std::string& key, T const& default_value, bool warn);
template<typename T> void config_key_not_found(const std::string& key, T const& default_value, bool warn)
{
if (!_messages_delivered.count(key)) {
if (warn) { IPAACA_WARNING("Config: no key '" << key << "', using default value " << default_value) }
else { IPAACA_DEBUG("Config: no key '" << key << "', using default value " << default_value) }
_messages_delivered.insert(key);
}
}
template<typename T> void config_conversion_failed(const std::string& key, T const& default_value)
{
if (!_messages_delivered.count(key)) {
IPAACA_WARNING("Config: failed conversion for key '" << key << "', using default value " << default_value)
_messages_delivered.insert(key);
}
}
bool get_key_and_value(const std::string& line, std::string& key, std::string& value);
public:
inline std::map<std::string, std::string>::const_iterator data_cbegin() const { return _data.begin(); }
inline std::map<std::string, std::string>::const_iterator data_cend() const { return _data.end(); }
void populate_from_global_sources();
void populate_from_environment();
void populate_from_any_conf_files();
void populate_from_conf_file(std::fstream& fs);
template<typename T> T get_with_default(const std::string& key, T const& default_value) {
return get_with_default_internal(key, default_value, false);
}
template<typename T> T get_with_default_and_warning(const std::string& key, T const& default_value) {
return get_with_default_internal(key, default_value, true);
}
//inline std::map<std::string, std::string>::iterator begin() { return std::map<std::string, std::string>::begin(); }
//inline std::map<std::string, std::string>::iterator end() { return std::map<std::string, std::string>::end(); }
};
Config::ptr get_global_config(bool auto_parse_on_demand=true);
#endif
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* "Incremental Processing Architecture * "Incremental Processing Architecture
* for Artificial Conversational Agents". * for Artificial Conversational Agents".
* *
* Copyright (c) 2009-2015 Social Cognitive Systems Group * Copyright (c) 2009-2022 Social Cognitive Systems Group
* (formerly the Sociable Agents Group) * (formerly the Sociable Agents Group)
* CITEC, Bielefeld University * CITEC, Bielefeld University
* *
...@@ -49,86 +49,58 @@ ...@@ -49,86 +49,58 @@
* \date March, 2015 * \date March, 2015
*/ */
#ifndef __ipaaca_internal_h_INCLUDED__ #ifndef __ipaaca_converters_h_INCLUDED__
#define __ipaaca_internal_h_INCLUDED__ #define __ipaaca_converters_h_INCLUDED__
#ifndef __ipaaca_h_INCLUDED__ #ifndef __ipaaca_h_INCLUDED__
#error "Please do not include this file directly, use ipaaca.h instead" #error "Please do not include this file directly, use ipaaca.h instead"
#endif #endif
namespace converters {
#ifdef IPAACA_EXPOSE_FULL_RSB_API // Wrap a serialized inner object and a wire type in a protobuf::TransportLevelWrapper
std::string cooked_message(const std::string& raw_message, ipaaca::protobuf::TransportMessageType msg_type);
IPAACA_HEADER_EXPORT class CallbackIUPayloadUpdate: public rsb::patterns::LocalServer::Callback<IUPayloadUpdate, int> {//{{{ // protobuf serialization for all supported types (replaces converter repository)
protected: std::string internal_serialize(std::shared_ptr<ipaaca::IU> iu);
IPAACA_MEMBER_VAR_EXPORT Buffer* _buffer; //std::string internal_serialize(std::shared_ptr<ipaaca::Message> msg);
public: std::string internal_serialize(std::shared_ptr<ipaaca::IUPayloadUpdate> pup);
IPAACA_HEADER_EXPORT CallbackIUPayloadUpdate(Buffer* buffer); std::string internal_serialize(std::shared_ptr<ipaaca::IULinkUpdate> lup);
IPAACA_HEADER_EXPORT boost::shared_ptr<int> call(const std::string& methodName, boost::shared_ptr<IUPayloadUpdate> update); std::string internal_serialize(std::shared_ptr<protobuf::RemoteRequestResult> pb);
};//}}} std::string internal_serialize(std::shared_ptr<protobuf::IURetraction> pb);
IPAACA_HEADER_EXPORT class CallbackIULinkUpdate: public rsb::patterns::LocalServer::Callback<IULinkUpdate, int> {//{{{ std::string internal_serialize(std::shared_ptr<protobuf::IUCommission> pb);
protected: std::string internal_serialize(std::shared_ptr<protobuf::IUResendRequest> pb);
IPAACA_MEMBER_VAR_EXPORT Buffer* _buffer; std::string internal_serialize(std::shared_ptr<protobuf::IUPayloadUpdateRequest> pb);
public: std::string internal_serialize(std::shared_ptr<protobuf::IULinkUpdateRequest> pb);
IPAACA_HEADER_EXPORT CallbackIULinkUpdate(Buffer* buffer); std::string internal_serialize(std::shared_ptr<protobuf::IUCommissionRequest> pb);
public:
IPAACA_HEADER_EXPORT boost::shared_ptr<int> call(const std::string& methodName, boost::shared_ptr<IULinkUpdate> update);
};//}}}
IPAACA_HEADER_EXPORT class CallbackIUCommission: public rsb::patterns::LocalServer::Callback<protobuf::IUCommission, int> {//{{{
protected:
IPAACA_MEMBER_VAR_EXPORT Buffer* _buffer;
public:
IPAACA_HEADER_EXPORT CallbackIUCommission(Buffer* buffer);
public:
IPAACA_HEADER_EXPORT boost::shared_ptr<int> call(const std::string& methodName, boost::shared_ptr<protobuf::IUCommission> update);
};//}}}
IPAACA_HEADER_EXPORT class CallbackIUResendRequest: public rsb::patterns::LocalServer::Callback<protobuf::IUResendRequest, int> {//{{{
protected:
IPAACA_MEMBER_VAR_EXPORT Buffer* _buffer;
public:
IPAACA_HEADER_EXPORT CallbackIUResendRequest(Buffer* buffer);
public:
IPAACA_HEADER_EXPORT boost::shared_ptr<int> call(const std::string& methodName, boost::shared_ptr<protobuf::IUResendRequest> update);
};//}}}
IPAACA_HEADER_EXPORT class CallbackIURetraction: public rsb::patterns::LocalServer::Callback<protobuf::IURetraction, int> {//{{{
protected:
IPAACA_MEMBER_VAR_EXPORT Buffer* _buffer;
public:
IPAACA_HEADER_EXPORT CallbackIURetraction(Buffer* buffer);
public:
IPAACA_HEADER_EXPORT boost::shared_ptr<int> call(const std::string& methodName, boost::shared_ptr<protobuf::IURetraction> update);
};//}}}
IPAACA_HEADER_EXPORT class IUConverter: public rsb::converter::Converter<std::string> {//{{{ // deserialization (just switching here instead of the converter registry business)
public: std::shared_ptr<ipaaca::backend::Event> internal_deserialize(const std::string& wire);
IPAACA_HEADER_EXPORT IUConverter();
IPAACA_HEADER_EXPORT std::string serialize(const rsb::AnnotatedData& data, std::string& wire); class IUConverter {//{{{
IPAACA_HEADER_EXPORT rsb::AnnotatedData deserialize(const std::string& wireSchema, const std::string& wire);
};//}}}
IPAACA_HEADER_EXPORT class MessageConverter: public rsb::converter::Converter<std::string> {//{{{
public: public:
IPAACA_HEADER_EXPORT MessageConverter(); IPAACA_HEADER_EXPORT static std::string serialize(std::shared_ptr<ipaaca::IU> iu); // const rsb::AnnotatedData& data, std::string& wire);
IPAACA_HEADER_EXPORT std::string serialize(const rsb::AnnotatedData& data, std::string& wire); IPAACA_HEADER_EXPORT static std::shared_ptr<ipaaca::IUInterface> deserialize(const std::string& wire);
IPAACA_HEADER_EXPORT rsb::AnnotatedData deserialize(const std::string& wireSchema, const std::string& wire);
};//}}} };//}}}
IPAACA_HEADER_EXPORT class IUPayloadUpdateConverter: public rsb::converter::Converter<std::string> {//{{{ /*
IPAACA_HEADER_EXPORT class MessageConverter {//{{{
public: public:
IPAACA_HEADER_EXPORT IUPayloadUpdateConverter(); IPAACA_HEADER_EXPORT static std::string serialize(std::shared_ptr<ipaaca::Message> msg); // const rsb::AnnotatedData& data, std::string& wire);
IPAACA_HEADER_EXPORT std::string serialize(const rsb::AnnotatedData& data, std::string& wire); IPAACA_HEADER_EXPORT static std::shared_ptr<ipaaca::RemoteMessage> deserialize(const std::string& wire);
IPAACA_HEADER_EXPORT rsb::AnnotatedData deserialize(const std::string& wireSchema, const std::string& wire);
};//}}} };//}}}
IPAACA_HEADER_EXPORT class IULinkUpdateConverter: public rsb::converter::Converter<std::string> {//{{{ */
class IUPayloadUpdateConverter {//{{{
public: public:
IPAACA_HEADER_EXPORT IULinkUpdateConverter(); IPAACA_HEADER_EXPORT static std::string serialize(std::shared_ptr<ipaaca::IUPayloadUpdate> pup); // const rsb::AnnotatedData& data, std::string& wire);
IPAACA_HEADER_EXPORT std::string serialize(const rsb::AnnotatedData& data, std::string& wire); IPAACA_HEADER_EXPORT static std::shared_ptr<ipaaca::IUPayloadUpdate> deserialize(const std::string& wire);
IPAACA_HEADER_EXPORT rsb::AnnotatedData deserialize(const std::string& wireSchema, const std::string& wire);
};//}}} };//}}}
IPAACA_HEADER_EXPORT class IntConverter: public rsb::converter::Converter<std::string> {//{{{ class IULinkUpdateConverter {//{{{
public: public:
IPAACA_HEADER_EXPORT IntConverter(); IPAACA_HEADER_EXPORT static std::string serialize(std::shared_ptr<ipaaca::IULinkUpdate> lup); // const rsb::AnnotatedData& data, std::string& wire);
IPAACA_HEADER_EXPORT std::string serialize(const rsb::AnnotatedData& data, std::string& wire); IPAACA_HEADER_EXPORT static std::shared_ptr<ipaaca::IULinkUpdate> deserialize(const std::string& wire);
IPAACA_HEADER_EXPORT rsb::AnnotatedData deserialize(const std::string& wireSchema, const std::string& wire);
};//}}} };//}}}
#endif
#endif } // of namespace converters
#endif // __ipaaca_converters_h_INCLUDED__
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* "Incremental Processing Architecture * "Incremental Processing Architecture
* for Artificial Conversational Agents". * for Artificial Conversational Agents".
* *
* Copyright (c) 2009-2015 Social Cognitive Systems Group * Copyright (c) 2009-2022 Social Cognitive Systems Group
* (formerly the Sociable Agents Group) * (formerly the Sociable Agents Group)
* CITEC, Bielefeld University * CITEC, Bielefeld University
* *
...@@ -96,324 +96,4 @@ enum IUAccessMode { ...@@ -96,324 +96,4 @@ enum IUAccessMode {
/// generate a UUID as an ASCII string /// generate a UUID as an ASCII string
IPAACA_HEADER_EXPORT std::string generate_uuid_string(); IPAACA_HEADER_EXPORT std::string generate_uuid_string();
/**
* Exception with string description
*/
class Exception: public std::exception//{{{
{
protected:
IPAACA_MEMBER_VAR_EXPORT std::string _description;
public:
IPAACA_HEADER_EXPORT inline Exception(const std::string& description=""): _description(description) { }
IPAACA_HEADER_EXPORT inline ~Exception() throw() { }
IPAACA_HEADER_EXPORT const char* what() const throw() {
return _description.c_str();
}
};//}}}
class Abort: public std::exception//{{{
{
protected:
IPAACA_MEMBER_VAR_EXPORT std::string _description;
public:
IPAACA_HEADER_EXPORT inline Abort(const std::string& description=""): _description(description) { }
IPAACA_HEADER_EXPORT inline ~Abort() throw() { }
IPAACA_HEADER_EXPORT const char* what() const throw() {
return _description.c_str();
}
};//}}}
/// IU was not found in a buffer
class IUNotFoundError: public Exception//{{{
{
public:
IPAACA_HEADER_EXPORT inline ~IUNotFoundError() throw() { }
IPAACA_HEADER_EXPORT inline IUNotFoundError() { //boost::shared_ptr<IU> iu) {
_description = "IUNotFoundError";
}
};//}}}
/// IU was already published
class IUPublishedError: public Exception//{{{
{
public:
IPAACA_HEADER_EXPORT inline ~IUPublishedError() throw() { }
IPAACA_HEADER_EXPORT inline IUPublishedError() {
_description = "IUPublishedError";
}
};//}}}
/// IU had already been committed to
class IUCommittedError: public Exception//{{{
{
public:
IPAACA_HEADER_EXPORT inline ~IUCommittedError() throw() { }
IPAACA_HEADER_EXPORT inline IUCommittedError() {
_description = "IUCommittedError";
}
};//}}}
/// IU had already been retracted
class IURetractedError: public Exception//{{{
{
public:
IPAACA_HEADER_EXPORT inline ~IURetractedError() throw() { }
IPAACA_HEADER_EXPORT inline IURetractedError() {
_description = "IURetractedError";
}
};//}}}
/// Remote IU update failed because it had been modified in the mean time
class IUUpdateFailedError: public Exception//{{{
{
public:
IPAACA_HEADER_EXPORT inline ~IUUpdateFailedError() throw() { }
IPAACA_HEADER_EXPORT inline IUUpdateFailedError() {
_description = "IUUpdateFailedError";
}
};//}}}
/// Requested resend of old IU due to malformed channel specification
class IUResendRequestFailedError: public Exception//{{{
{
public:
IPAACA_HEADER_EXPORT inline ~IUResendRequestFailedError() throw() { }
IPAACA_HEADER_EXPORT inline IUResendRequestFailedError() {
_description = "IUResendRequestFailedError";
}
};//}}}
/// Write operation failed because IU had been set read-only
class IUReadOnlyError: public Exception//{{{
{
public:
IPAACA_HEADER_EXPORT inline ~IUReadOnlyError() throw() { }
IPAACA_HEADER_EXPORT inline IUReadOnlyError() {
_description = "IUReadOnlyError";
}
};//}}}
/// Buffer::add() failed because the IU had been previously placed in another buffer
class IUAlreadyInABufferError: public Exception//{{{
{
public:
IPAACA_HEADER_EXPORT inline ~IUAlreadyInABufferError() throw() { }
IPAACA_HEADER_EXPORT inline IUAlreadyInABufferError() {
_description = "IUAlreadyInABufferError";
}
};//}}}
/// A request was made that is only valid for an already published IU
class IUUnpublishedError: public Exception//{{{
{
public:
IPAACA_HEADER_EXPORT inline ~IUUnpublishedError() throw() { }
IPAACA_HEADER_EXPORT inline IUUnpublishedError() {
_description = "IUUnpublishedError";
}
};//}}}
/// IU had already been allocated a UID
class IUAlreadyHasAnUIDError: public Exception//{{{
{
public:
IPAACA_HEADER_EXPORT inline ~IUAlreadyHasAnUIDError() throw() { }
IPAACA_HEADER_EXPORT inline IUAlreadyHasAnUIDError() {
_description = "IUAlreadyHasAnUIDError";
}
};//}}}
/// IU had already been allocated an owner name
class IUAlreadyHasAnOwnerNameError: public Exception//{{{
{
public:
IPAACA_HEADER_EXPORT inline ~IUAlreadyHasAnOwnerNameError() throw() { }
IPAACA_HEADER_EXPORT inline IUAlreadyHasAnOwnerNameError() {
_description = "IUAlreadyHasAnOwnerNameError";
}
};//}}}
/// UID generation failed (Windows only)
class UUIDGenerationError: public Exception//{{{
{
public:
IPAACA_HEADER_EXPORT inline ~UUIDGenerationError() throw() { }
IPAACA_HEADER_EXPORT inline UUIDGenerationError() {
_description = "UUIDGenerationError";
}
};//}}}
/// Not implemented (e.g. invalid request parameters via backend)
class NotImplementedError: public Exception//{{{
{
public:
IPAACA_HEADER_EXPORT inline ~NotImplementedError() throw() { }
IPAACA_HEADER_EXPORT inline NotImplementedError() {
_description = "NotImplementedError";
}
};//}}}
/// PayloadEntryProxy requested type conversion failed (including lenient interpretation)
class PayloadTypeConversionError: public Exception//{{{
{
public:
IPAACA_HEADER_EXPORT inline ~PayloadTypeConversionError() throw() { }
IPAACA_HEADER_EXPORT inline PayloadTypeConversionError() {
_description = "PayloadTypeConversionError";
}
};//}}}
/// PayloadEntryProxy was addressed as list when not a list or as map when not a map
class PayloadAddressingError: public Exception//{{{
{
public:
IPAACA_HEADER_EXPORT inline ~PayloadAddressingError() throw() { }
IPAACA_HEADER_EXPORT inline PayloadAddressingError() {
_description = "PayloadAddressingError";
}
};//}}}
/// Malformed json was received for a Payload
class JsonParsingError: public Exception//{{{
{
public:
IPAACA_HEADER_EXPORT inline ~JsonParsingError() throw() { }
IPAACA_HEADER_EXPORT inline JsonParsingError() {
_description = "JsonParsingError";
}
};//}}}
/// PayloadEntryProxy invalidated (unused)
class PayloadEntryProxyInvalidatedError: public Exception//{{{
{
public:
IPAACA_HEADER_EXPORT inline ~PayloadEntryProxyInvalidatedError() throw() { }
IPAACA_HEADER_EXPORT inline PayloadEntryProxyInvalidatedError() {
_description = "PayloadEntryProxyInvalidatedError";
}
};//}}}
/// Iterator over Payload entries was invalidated by an intermediate IU update operation
class PayloadIteratorInvalidError: public Exception//{{{
{
public:
IPAACA_HEADER_EXPORT inline ~PayloadIteratorInvalidError() throw() { }
IPAACA_HEADER_EXPORT inline PayloadIteratorInvalidError() {
_description = "PayloadIteratorInvalidError";
}
};//}}}
/** \brief Static library initialization for backend
*
* This static class (singleton) is called once (explicitly or on-demand).
* Unless called manually, it is initialized when ipaaca is first used
* (i.e. the first Buffer is created).
*/
class Initializer
{
public:
/// Initialize the backend [DEPRECATED] (old name, use initialize_backend() instead)
[[deprecated("Use initialize_backend() instead")]]
IPAACA_HEADER_EXPORT static void initialize_ipaaca_rsb_if_needed();
/// Explicitly initialize the backend (usually not required). No effect if already initialized. Automatically called during first Buffer construction.
IPAACA_HEADER_EXPORT static void initialize_backend();
IPAACA_HEADER_EXPORT static bool initialized();
IPAACA_HEADER_EXPORT static void dump_current_default_config();
protected:
/** Perform rsb pre-setup before the implicit initialization
* (when first instantiating something). Pre-setup includes
* finding the RSB plugin dir, looking through several parent
* directories for a path "deps/lib/rsb*"/plugins. The path
* can also be set directly (env var RSB_PLUGINS_CPP_PATH),
* which disables the automatic search.
*/
IPAACA_HEADER_EXPORT static void auto_configure_rsb();
IPAACA_MEMBER_VAR_EXPORT static bool _initialized;
};
// in ipaaca-cmdline-parser.cc
// additional misc classes ( Command line options )//{{{
/** \brief Command line argument container for CommandLineParser
*
* Contains the results of argument parsing from CommandLineParser::parse()
*
* The parser is preconfigured to handle some standard options:
*
* Option | Function
* --------------------------------|------------------------------------------------------------------------------
* --help | Print list of available options
* --verbose | Set verbose flag
* --character-name <name> | Set character name (legacy)
* --component-name <name> | Set component name (legacy)
* --ipaaca-payload-type <type> | Set default ipaaca payload type (default JSON, set STR for legacy protocol)
* --ipaaca-default-channel <name> | Set default channel name (default 'default')
* --ipaaca-enable-logging <level> | Set console log level, one of NONE, DEBUG, INFO, WARNING, ERROR, CRITICAL
* --rsb-enable-logging <level> | Set rsb (transport) log level
*
*/
class CommandLineOptions {
public:
IPAACA_HEADER_EXPORT inline CommandLineOptions()
{ }
IPAACA_HEADER_EXPORT inline ~CommandLineOptions() {
}
IPAACA_MEMBER_VAR_EXPORT std::map<std::string, std::string> param_opts;
IPAACA_MEMBER_VAR_EXPORT std::map<std::string, bool> param_set;
public:
IPAACA_HEADER_EXPORT void set_option(const std::string& name, bool expect, const char* optarg);
/// Get the option argument or default value (if the option expected an argument)
IPAACA_HEADER_EXPORT std::string get_param(const std::string& o);
/// Check whether option has been set
IPAACA_HEADER_EXPORT bool is_set(const std::string& o);
IPAACA_HEADER_EXPORT void dump();
public:
typedef boost::shared_ptr<CommandLineOptions> ptr;
};
/**
* \brief Command line parser for ipaaca programs.
*
* The parser is preconfigured to handle some standard options:
*
* Option | Function
* --------------------------------|------------------------------------------------------------------------------
* --help | Print list of available options
* --verbose | Set verbose flag
* --character-name <name> | Set character name (legacy)
* --component-name <name> | Set component name (legacy)
* --ipaaca-payload-type <type> | Set default ipaaca payload type (default JSON, set STR for legacy protocol)
* --ipaaca-default-channel <name> | Set default channel name (default 'default')
* --ipaaca-enable-logging <level> | Set console log level, one of NONE, DEBUG, INFO, WARNING, ERROR, CRITICAL
* --rsb-enable-logging <level> | Set rsb (transport) log level
*
*/
class CommandLineParser {
protected:
IPAACA_MEMBER_VAR_EXPORT std::map<char, std::string> longopt; // letter->name
IPAACA_MEMBER_VAR_EXPORT std::map<std::string, char> shortopt; // letter->name
IPAACA_MEMBER_VAR_EXPORT std::map<std::string, bool> options; // name / expect_param
IPAACA_MEMBER_VAR_EXPORT std::map<std::string, std::string> defaults; // for opt params
IPAACA_MEMBER_VAR_EXPORT std::map<std::string, int> set_flag; // for paramless opts
protected:
IPAACA_HEADER_EXPORT CommandLineParser();
IPAACA_MEMBER_VAR_EXPORT bool library_options_handled;
IPAACA_HEADER_EXPORT bool consume_library_option(const std::string& name, bool expect, const char* optarg);
IPAACA_HEADER_EXPORT void ensure_defaults_in( CommandLineOptions::ptr clo );
public:
IPAACA_HEADER_EXPORT inline ~CommandLineParser() { }
/// Create a new parser object reference.
IPAACA_HEADER_EXPORT static inline boost::shared_ptr<CommandLineParser> create() {
return boost::shared_ptr<CommandLineParser>(new CommandLineParser());
}
IPAACA_HEADER_EXPORT void initialize_parser_defaults();
IPAACA_HEADER_EXPORT void dump_options();
/** \brief Add a user-defined option
*
* \param optname The long option name, e.g. verbose for --verbose
* \param shortn The short option (or \0 for none)
* \param expect_param Whether an argument is expected for the option
* \param defaultv The default string value (unused if expect_param is false)
*/
IPAACA_HEADER_EXPORT void add_option(const std::string& optname, char shortn, bool expect_param, const std::string& defaultv);
/** \brief Parse argument list and return result.
*
* Parse argument list (e.g. from main()) with the parser, consuming the internal options.
* The remaining options are packaged into a CommandLineOptions object.
*/
IPAACA_HEADER_EXPORT CommandLineOptions::ptr parse(int argc, char* const* argv);
public:
typedef boost::shared_ptr<CommandLineParser> ptr;
};
//}}}
// in ipaaca-string-utils.cc
// additional misc functions ( String splitting / joining )//{{{
IPAACA_HEADER_EXPORT std::string str_trim(const std::string &s);
IPAACA_HEADER_EXPORT std::string str_join(const std::set<std::string>& set,const std::string& sep);
IPAACA_HEADER_EXPORT std::string str_join(const std::vector<std::string>& vec,const std::string& sep);
IPAACA_HEADER_EXPORT void str_split_wipe(const std::string& str, std::vector<std::string>& tokens, const std::string& delimiters );
IPAACA_HEADER_EXPORT void str_split_append(const std::string& str, std::vector<std::string>& tokens, const std::string& delimiters );
//}}}
#endif #endif
/*
* This file is part of IPAACA, the
* "Incremental Processing Architecture
* for Artificial Conversational Agents".
*
* Copyright (c) 2009-2022 Social Cognitive Systems Group
* (formerly the Sociable Agents Group)
* CITEC, Bielefeld University
*
* http://opensource.cit-ec.de/projects/ipaaca/
* http://purl.org/net/ipaaca
*
* This file may be licensed under the terms of of the
* GNU Lesser General Public License Version 3 (the ``LGPL''),
* or (at your option) any later version.
*
* Software distributed under the License is distributed
* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
* express or implied. See the LGPL for the specific language
* governing rights and limitations.
*
* You should have received a copy of the LGPL along with this
* program. If not, go to http://www.gnu.org/licenses/lgpl.html
* or write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The development of this software was supported by the
* Excellence Cluster EXC 277 Cognitive Interaction Technology.
* The Excellence Cluster EXC 277 is a grant of the Deutsche
* Forschungsgemeinschaft (DFG) in the context of the German
* Excellence Initiative.
*/
/**
* \file ipaaca-errors.h
*
* \brief Header file for all errors and exceptions
*
* Users should not include this file directly, but use ipaaca.h
*
* \author Ramin Yaghoubzadeh (ryaghoubzadeh@uni-bielefeld.de)
* \date February, 2019
*/
#ifndef __ipaaca_errors_h_INCLUDED__
#define __ipaaca_errors_h_INCLUDED__
#ifndef __ipaaca_h_INCLUDED__
#error "Please do not include this file directly, use ipaaca.h instead"
#endif
/**
* Exception with string description
*/
class Exception: public std::exception//{{{
{
protected:
IPAACA_MEMBER_VAR_EXPORT std::string _description;
public:
IPAACA_HEADER_EXPORT inline Exception(const std::string& description=""): _description(description) { }
IPAACA_HEADER_EXPORT inline ~Exception() throw() { }
IPAACA_HEADER_EXPORT const char* what() const throw() {
return _description.c_str();
}
};//}}}
class Abort: public std::exception//{{{
{
protected:
IPAACA_MEMBER_VAR_EXPORT std::string _description;
public:
IPAACA_HEADER_EXPORT inline Abort(const std::string& description=""): _description(description) { }
IPAACA_HEADER_EXPORT inline ~Abort() throw() { }
IPAACA_HEADER_EXPORT const char* what() const throw() {
return _description.c_str();
}
};//}}}
/// BackEnd failed conditions, e.g. limits
class BackEndBadConditionError: public Exception//{{{
{
public:
IPAACA_HEADER_EXPORT inline ~BackEndBadConditionError() throw() { }
IPAACA_HEADER_EXPORT inline BackEndBadConditionError() { //std::shared_ptr<BackEnd> iu) {
_description = "BackEndBadConditionError";
}
};//}}}
/// BackEnd [hard-]failed to connect a participant
class BackEndConnectionFailedError: public Exception//{{{
{
public:
IPAACA_HEADER_EXPORT inline ~BackEndConnectionFailedError() throw() { }
IPAACA_HEADER_EXPORT inline BackEndConnectionFailedError() { //std::shared_ptr<BackEnd> iu) {
_description = "BackEndConnectionFailedError";
}
};//}}}
/// BackEnd not found
class BackEndNotFoundError: public Exception//{{{
{
public:
IPAACA_HEADER_EXPORT inline ~BackEndNotFoundError() throw() { }
IPAACA_HEADER_EXPORT inline BackEndNotFoundError() { //std::shared_ptr<BackEnd> iu) {
_description = "BackEndNotFoundError";
}
};//}}}
/// Unknown wire type encountered
class UnhandledWireTypeError: public Exception//{{{
{
public:
IPAACA_HEADER_EXPORT inline ~UnhandledWireTypeError() throw() { }
IPAACA_HEADER_EXPORT inline UnhandledWireTypeError(int wire_type=-1) {
if (wire_type>0) {
_description = "UnhandledWireTypeError (wire type encountered: " + std::to_string(wire_type) + ")";
} else {
_description = "UnhandledWireTypeError (value not provided)";
}
}
};//}}}
/// IU was not found in a buffer
class IUNotFoundError: public Exception//{{{
{
public:
IPAACA_HEADER_EXPORT inline ~IUNotFoundError() throw() { }
IPAACA_HEADER_EXPORT inline IUNotFoundError() { //std::shared_ptr<IU> iu) {
_description = "IUNotFoundError";
}
};//}}}
/// IU was already published
class IUPublishedError: public Exception//{{{
{
public:
IPAACA_HEADER_EXPORT inline ~IUPublishedError() throw() { }
IPAACA_HEADER_EXPORT inline IUPublishedError() {
_description = "IUPublishedError";
}
};//}}}
/// IU had already been committed to
class IUCommittedError: public Exception//{{{
{
public:
IPAACA_HEADER_EXPORT inline ~IUCommittedError() throw() { }
IPAACA_HEADER_EXPORT inline IUCommittedError() {
_description = "IUCommittedError";
}
};//}}}
/// IU had already been retracted
class IURetractedError: public Exception//{{{
{
public:
IPAACA_HEADER_EXPORT inline ~IURetractedError() throw() { }
IPAACA_HEADER_EXPORT inline IURetractedError() {
_description = "IURetractedError";
}
};//}}}
/// Remote IU update failed because it had been modified in the mean time
class IUUpdateFailedError: public Exception//{{{
{
public:
IPAACA_HEADER_EXPORT inline ~IUUpdateFailedError() throw() { }
IPAACA_HEADER_EXPORT inline IUUpdateFailedError() {
_description = "IUUpdateFailedError";
}
};//}}}
/// Requested resend of old IU due to malformed channel specification
class IUResendRequestFailedError: public Exception//{{{
{
public:
IPAACA_HEADER_EXPORT inline ~IUResendRequestFailedError() throw() { }
IPAACA_HEADER_EXPORT inline IUResendRequestFailedError() {
_description = "IUResendRequestFailedError";
}
};//}}}
/// Write operation failed because IU had been set read-only
class IUReadOnlyError: public Exception//{{{
{
public:
IPAACA_HEADER_EXPORT inline ~IUReadOnlyError() throw() { }
IPAACA_HEADER_EXPORT inline IUReadOnlyError() {
_description = "IUReadOnlyError";
}
};//}}}
/// Buffer::add() failed because the IU had been previously placed in another buffer
class IUAlreadyInABufferError: public Exception//{{{
{
public:
IPAACA_HEADER_EXPORT inline ~IUAlreadyInABufferError() throw() { }
IPAACA_HEADER_EXPORT inline IUAlreadyInABufferError() {
_description = "IUAlreadyInABufferError";
}
};//}}}
/// A request was made that is only valid for an already published IU
class IUUnpublishedError: public Exception//{{{
{
public:
IPAACA_HEADER_EXPORT inline ~IUUnpublishedError() throw() { }
IPAACA_HEADER_EXPORT inline IUUnpublishedError() {
_description = "IUUnpublishedError";
}
};//}}}
/// IU had already been allocated a UID
class IUAlreadyHasAnUIDError: public Exception//{{{
{
public:
IPAACA_HEADER_EXPORT inline ~IUAlreadyHasAnUIDError() throw() { }
IPAACA_HEADER_EXPORT inline IUAlreadyHasAnUIDError() {
_description = "IUAlreadyHasAnUIDError";
}
};//}}}
/// IU had already been allocated an owner name
class IUAlreadyHasAnOwnerNameError: public Exception//{{{
{
public:
IPAACA_HEADER_EXPORT inline ~IUAlreadyHasAnOwnerNameError() throw() { }
IPAACA_HEADER_EXPORT inline IUAlreadyHasAnOwnerNameError() {
_description = "IUAlreadyHasAnOwnerNameError";
}
};//}}}
/// UID generation failed (Windows only)
class UUIDGenerationError: public Exception//{{{
{
public:
IPAACA_HEADER_EXPORT inline ~UUIDGenerationError() throw() { }
IPAACA_HEADER_EXPORT inline UUIDGenerationError() {
_description = "UUIDGenerationError";
}
};//}}}
/// Not implemented (e.g. invalid request parameters via backend)
class NotImplementedError: public Exception//{{{
{
public:
IPAACA_HEADER_EXPORT inline ~NotImplementedError() throw() { }
IPAACA_HEADER_EXPORT inline NotImplementedError() {
_description = "NotImplementedError";
}
};//}}}
/// PayloadEntryProxy requested type conversion failed (including lenient interpretation)
class PayloadTypeConversionError: public Exception//{{{
{
public:
IPAACA_HEADER_EXPORT inline ~PayloadTypeConversionError() throw() { }
IPAACA_HEADER_EXPORT inline PayloadTypeConversionError() {
_description = "PayloadTypeConversionError";
}
};//}}}
/// PayloadEntryProxy was addressed as list when not a list or as map when not a map
class PayloadAddressingError: public Exception//{{{
{
public:
IPAACA_HEADER_EXPORT inline ~PayloadAddressingError() throw() { }
IPAACA_HEADER_EXPORT inline PayloadAddressingError() {
_description = "PayloadAddressingError";
}
};//}}}
/// Malformed json was received for a Payload
class JsonParsingError: public Exception//{{{
{
public:
IPAACA_HEADER_EXPORT inline ~JsonParsingError() throw() { }
IPAACA_HEADER_EXPORT inline JsonParsingError() {
_description = "JsonParsingError";
}
};//}}}
/// PayloadEntryProxy invalidated (unused)
class PayloadEntryProxyInvalidatedError: public Exception//{{{
{
public:
IPAACA_HEADER_EXPORT inline ~PayloadEntryProxyInvalidatedError() throw() { }
IPAACA_HEADER_EXPORT inline PayloadEntryProxyInvalidatedError() {
_description = "PayloadEntryProxyInvalidatedError";
}
};//}}}
/// Iterator over Payload entries was invalidated by an intermediate IU update operation
class PayloadIteratorInvalidError: public Exception//{{{
{
public:
IPAACA_HEADER_EXPORT inline ~PayloadIteratorInvalidError() throw() { }
IPAACA_HEADER_EXPORT inline PayloadIteratorInvalidError() {
_description = "PayloadIteratorInvalidError";
}
};//}}}
#endif
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* "Incremental Processing Architecture * "Incremental Processing Architecture
* for Artificial Conversational Agents". * for Artificial Conversational Agents".
* *
* Copyright (c) 2009-2015 Social Cognitive Systems Group * Copyright (c) 2009-2022 Social Cognitive Systems Group
* (formerly the Sociable Agents Group) * (formerly the Sociable Agents Group)
* CITEC, Bielefeld University * CITEC, Bielefeld University
* *
...@@ -52,6 +52,15 @@ ...@@ -52,6 +52,15 @@
/* /*
* forward declarations * forward declarations
*/ */
namespace backend {
//class Scope;
class Event;
class Informer;
class Listener;
class LocalServer;
class RemoteServer;
} // of namespace backend
class PayloadDocumentEntry; class PayloadDocumentEntry;
class PayloadBatchUpdateLock; class PayloadBatchUpdateLock;
...@@ -62,6 +71,7 @@ class IUInterface; ...@@ -62,6 +71,7 @@ class IUInterface;
class IU; class IU;
class Message; class Message;
class RemotePushIU; class RemotePushIU;
class RemoteMessage;
class IULinkUpdate; class IULinkUpdate;
class IUPayloadUpdate; class IUPayloadUpdate;
class IUStore; class IUStore;
...@@ -80,7 +90,7 @@ class IUConverter; ...@@ -80,7 +90,7 @@ class IUConverter;
class MessageConverter; class MessageConverter;
class IUPayloadUpdateConverter; class IUPayloadUpdateConverter;
class IULinkUpdateConverter; class IULinkUpdateConverter;
class IntConverter; //class IntConverter;
class BufferConfiguration; class BufferConfiguration;
class BufferConfigurationBuilder; class BufferConfigurationBuilder;
......
/*
* This file is part of IPAACA, the
* "Incremental Processing Architecture
* for Artificial Conversational Agents".
*
* Copyright (c) 2009-2022 Social Cognitive Systems Group
* (formerly the Sociable Agents Group)
* CITEC, Bielefeld University
*
* http://opensource.cit-ec.de/projects/ipaaca/
* http://purl.org/net/ipaaca
*
* This file may be licensed under the terms of of the
* GNU Lesser General Public License Version 3 (the ``LGPL''),
* or (at your option) any later version.
*
* Software distributed under the License is distributed
* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
* express or implied. See the LGPL for the specific language
* governing rights and limitations.
*
* You should have received a copy of the LGPL along with this
* program. If not, go to http://www.gnu.org/licenses/lgpl.html
* or write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The development of this software was supported by the
* Excellence Cluster EXC 277 Cognitive Interaction Technology.
* The Excellence Cluster EXC 277 is a grant of the Deutsche
* Forschungsgemeinschaft (DFG) in the context of the German
* Excellence Initiative.
*/
/**
* \file ipaaca-initializer.h
*
* \brief Header file for the global initializer unit
*
* Users should not include this file directly, but use ipaaca.h
*
* \author Ramin Yaghoubzadeh (ryaghoubzadeh@uni-bielefeld.de)
* \date February, 2019
*/
#ifndef __ipaaca_initializer_h_INCLUDED__
#define __ipaaca_initializer_h_INCLUDED__
#ifndef __ipaaca_h_INCLUDED__
#error "Please do not include this file directly, use ipaaca.h instead"
#endif
/** \brief Static library initialization for backend
*
* This static class (singleton) is called once (explicitly or on-demand).
* Unless called manually, it is initialized when ipaaca is first used
* (i.e. the first Buffer is created).
*/
class Initializer
{
public:
/// Initialize the backend [DEPRECATED] (old name, use initialize_backend() instead)
[[deprecated("Use initialize_backend() instead")]]
IPAACA_HEADER_EXPORT static void initialize_ipaaca_rsb_if_needed();
/// Explicitly initialize the backend (usually not required). No effect if already initialized. Automatically called during first Buffer construction.
IPAACA_HEADER_EXPORT static void initialize_backend();
IPAACA_HEADER_EXPORT static bool initialized();
IPAACA_HEADER_EXPORT static void dump_current_default_config();
protected:
/** Perform rsb pre-setup before the implicit initialization
* (when first instantiating something). Pre-setup includes
* finding the RSB plugin dir, looking through several parent
* directories for a path "deps/lib/rsb*"/plugins. The path
* can also be set directly (env var RSB_PLUGINS_CPP_PATH),
* which disables the automatic search.
*/
IPAACA_HEADER_EXPORT static void override_env_with_cmdline_set_variables();
IPAACA_MEMBER_VAR_EXPORT static bool _initialized;
};
#endif
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* "Incremental Processing Architecture * "Incremental Processing Architecture
* for Artificial Conversational Agents". * for Artificial Conversational Agents".
* *
* Copyright (c) 2009-2015 Social Cognitive Systems Group * Copyright (c) 2009-2022 Social Cognitive Systems Group
* (formerly the Sociable Agents Group) * (formerly the Sociable Agents Group)
* CITEC, Bielefeld University * CITEC, Bielefeld University
* *
...@@ -59,8 +59,8 @@ ...@@ -59,8 +59,8 @@
* *
*/ */
class IUInterface {//{{{ class IUInterface {//{{{
friend class IUConverter; friend class ipaaca::converters::IUConverter;
friend class MessageConverter; //friend class ipaaca::converters::MessageConverter;
friend std::ostream& operator<<(std::ostream& os, const IUInterface& obj); friend std::ostream& operator<<(std::ostream& os, const IUInterface& obj);
protected: protected:
IPAACA_HEADER_EXPORT IUInterface(); IPAACA_HEADER_EXPORT IUInterface();
...@@ -76,7 +76,7 @@ class IUInterface {//{{{ ...@@ -76,7 +76,7 @@ class IUInterface {//{{{
IPAACA_MEMBER_VAR_EXPORT bool _retracted; IPAACA_MEMBER_VAR_EXPORT bool _retracted;
IPAACA_MEMBER_VAR_EXPORT IUAccessMode _access_mode; IPAACA_MEMBER_VAR_EXPORT IUAccessMode _access_mode;
IPAACA_MEMBER_VAR_EXPORT bool _read_only; IPAACA_MEMBER_VAR_EXPORT bool _read_only;
//boost::shared_ptr<Buffer> _buffer; //std::shared_ptr<Buffer> _buffer;
IPAACA_MEMBER_VAR_EXPORT Buffer* _buffer; IPAACA_MEMBER_VAR_EXPORT Buffer* _buffer;
IPAACA_MEMBER_VAR_EXPORT SmartLinkMap _links; IPAACA_MEMBER_VAR_EXPORT SmartLinkMap _links;
protected: protected:
...@@ -85,7 +85,7 @@ class IUInterface {//{{{ ...@@ -85,7 +85,7 @@ class IUInterface {//{{{
// e.g. sending a notification across the network // e.g. sending a notification across the network
IPAACA_HEADER_EXPORT _IPAACA_ABSTRACT_ virtual void _modify_links(bool is_delta, const LinkMap& new_links, const LinkMap& links_to_remove, const std::string& writer_name) = 0; IPAACA_HEADER_EXPORT _IPAACA_ABSTRACT_ virtual void _modify_links(bool is_delta, const LinkMap& new_links, const LinkMap& links_to_remove, const std::string& writer_name) = 0;
IPAACA_HEADER_EXPORT _IPAACA_ABSTRACT_ virtual void _modify_payload(bool is_delta, const std::map<std::string, PayloadDocumentEntry::ptr>& new_items, const std::vector<std::string>& keys_to_remove, const std::string& writer_name) = 0; IPAACA_HEADER_EXPORT _IPAACA_ABSTRACT_ virtual void _modify_payload(bool is_delta, const std::map<std::string, PayloadDocumentEntry::ptr>& new_items, const std::vector<std::string>& keys_to_remove, const std::string& writer_name) = 0;
//void _set_buffer(boost::shared_ptr<Buffer> buffer); //void _set_buffer(std::shared_ptr<Buffer> buffer);
IPAACA_HEADER_EXPORT void _associate_with_buffer(Buffer* buffer); IPAACA_HEADER_EXPORT void _associate_with_buffer(Buffer* buffer);
IPAACA_HEADER_EXPORT void _set_buffer(Buffer* buffer); IPAACA_HEADER_EXPORT void _set_buffer(Buffer* buffer);
IPAACA_HEADER_EXPORT void _set_uid(const std::string& uid); IPAACA_HEADER_EXPORT void _set_uid(const std::string& uid);
...@@ -117,7 +117,7 @@ class IUInterface {//{{{ ...@@ -117,7 +117,7 @@ class IUInterface {//{{{
IPAACA_HEADER_EXPORT inline IUAccessMode access_mode() const { return _access_mode; } IPAACA_HEADER_EXPORT inline IUAccessMode access_mode() const { return _access_mode; }
/// Return whether IU is read only (committed, a Message, or explicitly set read-only by owner) /// Return whether IU is read only (committed, a Message, or explicitly set read-only by owner)
IPAACA_HEADER_EXPORT inline bool read_only() const { return _read_only; } IPAACA_HEADER_EXPORT inline bool read_only() const { return _read_only; }
//inline boost::shared_ptr<Buffer> buffer() { return _buffer; } //inline std::shared_ptr<Buffer> buffer() { return _buffer; }
/// Return owning buffer [CAVEAT: do not rely on this function for future code] /// Return owning buffer [CAVEAT: do not rely on this function for future code]
IPAACA_HEADER_EXPORT inline Buffer* buffer() const { return _buffer; } IPAACA_HEADER_EXPORT inline Buffer* buffer() const { return _buffer; }
/// Return the link set for an arbitrary link type (e.g. "grounded_in"), or EMPTY_LINK_SET /// Return the link set for an arbitrary link type (e.g. "grounded_in"), or EMPTY_LINK_SET
...@@ -133,7 +133,7 @@ class IUInterface {//{{{ ...@@ -133,7 +133,7 @@ class IUInterface {//{{{
/// Commit to an IU (only possible for the IU owner) /// Commit to an IU (only possible for the IU owner)
IPAACA_HEADER_EXPORT _IPAACA_ABSTRACT_ virtual void commit() = 0; IPAACA_HEADER_EXPORT _IPAACA_ABSTRACT_ virtual void commit() = 0;
// functions to modify and update links: // functions to modify and update links:
//IPAACA_HEADER_EXPORT void _publish_resend(boost::shared_ptr<IU> iu, const std::string& hidden_scope_name); //IPAACA_HEADER_EXPORT void _publish_resend(std::shared_ptr<IU> iu, const std::string& hidden_scope_name);
/// Add a set of new UIDs for a specific link type /// Add a set of new UIDs for a specific link type
IPAACA_HEADER_EXPORT void add_links(const std::string& type, const LinkSet& targets, const std::string& writer_name = ""); IPAACA_HEADER_EXPORT void add_links(const std::string& type, const LinkSet& targets, const std::string& writer_name = "");
...@@ -148,7 +148,7 @@ class IUInterface {//{{{ ...@@ -148,7 +148,7 @@ class IUInterface {//{{{
IPAACA_HEADER_EXPORT void add_link(const std::string& type, const std::string& target, const std::string& writer_name = ""); IPAACA_HEADER_EXPORT void add_link(const std::string& type, const std::string& target, const std::string& writer_name = "");
/// Convenience function (C++): remove a single UID string from an arbitrary link set (if contained) /// Convenience function (C++): remove a single UID string from an arbitrary link set (if contained)
IPAACA_HEADER_EXPORT void remove_link(const std::string& type, const std::string& target, const std::string& writer_name = ""); IPAACA_HEADER_EXPORT void remove_link(const std::string& type, const std::string& target, const std::string& writer_name = "");
typedef boost::shared_ptr<IUInterface> ptr; typedef std::shared_ptr<IUInterface> ptr;
};//}}} };//}}}
/** \brief Class of locally-owned IU objects. /** \brief Class of locally-owned IU objects.
...@@ -163,10 +163,7 @@ class IU: public IUInterface {//{{{ ...@@ -163,10 +163,7 @@ class IU: public IUInterface {//{{{
friend class Buffer; friend class Buffer;
friend class InputBuffer; friend class InputBuffer;
friend class OutputBuffer; friend class OutputBuffer;
friend class CallbackIUPayloadUpdate; friend class ipaaca::backend::LocalServer;
friend class CallbackIULinkUpdate;
friend class CallbackIUCommission;
friend class CallbackIUResendRequest;
public: public:
IPAACA_MEMBER_VAR_EXPORT Payload _payload; IPAACA_MEMBER_VAR_EXPORT Payload _payload;
protected: protected:
...@@ -178,8 +175,8 @@ class IU: public IUInterface {//{{{ ...@@ -178,8 +175,8 @@ class IU: public IUInterface {//{{{
IPAACA_HEADER_EXPORT inline ~IU() { IPAACA_HEADER_EXPORT inline ~IU() {
} }
[[deprecated("Please use the new argument order: category, payload_type, read_only")]] [[deprecated("Please use the new argument order: category, payload_type, read_only")]]
IPAACA_HEADER_EXPORT static boost::shared_ptr<IU> create(const std::string& category, IUAccessMode access_mode, bool read_only=false, const std::string& payload_type="" ); IPAACA_HEADER_EXPORT static std::shared_ptr<IU> create(const std::string& category, IUAccessMode access_mode, bool read_only=false, const std::string& payload_type="" );
IPAACA_HEADER_EXPORT static boost::shared_ptr<IU> create(const std::string& category, const std::string& payload_type="", bool read_only=false); IPAACA_HEADER_EXPORT static std::shared_ptr<IU> create(const std::string& category, const std::string& payload_type="", bool read_only=false);
IPAACA_HEADER_EXPORT inline Payload& payload() _IPAACA_OVERRIDE_ { return _payload; } IPAACA_HEADER_EXPORT inline Payload& payload() _IPAACA_OVERRIDE_ { return _payload; }
IPAACA_HEADER_EXPORT inline const Payload& const_payload() const _IPAACA_OVERRIDE_ { return _payload; } IPAACA_HEADER_EXPORT inline const Payload& const_payload() const _IPAACA_OVERRIDE_ { return _payload; }
IPAACA_HEADER_EXPORT void commit() _IPAACA_OVERRIDE_; IPAACA_HEADER_EXPORT void commit() _IPAACA_OVERRIDE_;
...@@ -189,7 +186,7 @@ class IU: public IUInterface {//{{{ ...@@ -189,7 +186,7 @@ class IU: public IUInterface {//{{{
protected: protected:
IPAACA_HEADER_EXPORT virtual void _internal_commit(const std::string& writer_name = ""); IPAACA_HEADER_EXPORT virtual void _internal_commit(const std::string& writer_name = "");
public: public:
typedef boost::shared_ptr<IU> ptr; typedef std::shared_ptr<IU> ptr;
};//}}} };//}}}
/** \brief Class of locally-owned message objects ('one-shot' IUs). /** \brief Class of locally-owned message objects ('one-shot' IUs).
* *
...@@ -207,25 +204,22 @@ class Message: public IU {//{{{ ...@@ -207,25 +204,22 @@ class Message: public IU {//{{{
friend class Buffer; friend class Buffer;
friend class InputBuffer; friend class InputBuffer;
friend class OutputBuffer; friend class OutputBuffer;
friend class CallbackIUPayloadUpdate; friend class ipaaca::backend::LocalServer;
friend class CallbackIULinkUpdate;
friend class CallbackIUCommission;
friend class CallbackIUResendRequest;
protected: protected:
IPAACA_HEADER_EXPORT Message(const std::string& category, IUAccessMode access_mode=IU_ACCESS_MESSAGE, bool read_only=true, const std::string& payload_type="" ); IPAACA_HEADER_EXPORT Message(const std::string& category, IUAccessMode access_mode=IU_ACCESS_MESSAGE, bool read_only=true, const std::string& payload_type="" );
public: public:
IPAACA_HEADER_EXPORT inline ~Message() { IPAACA_HEADER_EXPORT inline ~Message() {
} }
[[deprecated("Please use the new argument order: category, payload_type")]] [[deprecated("Please use the new argument order: category, payload_type")]]
IPAACA_HEADER_EXPORT static boost::shared_ptr<Message> create(const std::string& category, IUAccessMode access_mode, bool read_only=true, const std::string& payload_type="" ); IPAACA_HEADER_EXPORT static std::shared_ptr<Message> create(const std::string& category, IUAccessMode access_mode, bool read_only=true, const std::string& payload_type="" );
IPAACA_HEADER_EXPORT static boost::shared_ptr<Message> create(const std::string& category, const std::string& payload_type=""); IPAACA_HEADER_EXPORT static std::shared_ptr<Message> create(const std::string& category, const std::string& payload_type="");
protected: protected:
IPAACA_HEADER_EXPORT void _modify_links(bool is_delta, const LinkMap& new_links, const LinkMap& links_to_remove, const std::string& writer_name = "") _IPAACA_OVERRIDE_; IPAACA_HEADER_EXPORT void _modify_links(bool is_delta, const LinkMap& new_links, const LinkMap& links_to_remove, const std::string& writer_name = "") _IPAACA_OVERRIDE_;
IPAACA_HEADER_EXPORT void _modify_payload(bool is_delta, const std::map<std::string, PayloadDocumentEntry::ptr>& new_items, const std::vector<std::string>& keys_to_remove, const std::string& writer_name = "") _IPAACA_OVERRIDE_; IPAACA_HEADER_EXPORT void _modify_payload(bool is_delta, const std::map<std::string, PayloadDocumentEntry::ptr>& new_items, const std::vector<std::string>& keys_to_remove, const std::string& writer_name = "") _IPAACA_OVERRIDE_;
protected: protected:
IPAACA_HEADER_EXPORT void _internal_commit(const std::string& writer_name = ""); IPAACA_HEADER_EXPORT void _internal_commit(const std::string& writer_name = "");
public: public:
typedef boost::shared_ptr<Message> ptr; typedef std::shared_ptr<Message> ptr;
};//}}} };//}}}
/// Copy of a remote IU, received in an InputBuffer. Setter functions call RPC over the backend (RSB). \b Note: Typically handled only as reference in a handler in user space. /// Copy of a remote IU, received in an InputBuffer. Setter functions call RPC over the backend (RSB). \b Note: Typically handled only as reference in a handler in user space.
...@@ -233,13 +227,13 @@ class RemotePushIU: public IUInterface {//{{{ ...@@ -233,13 +227,13 @@ class RemotePushIU: public IUInterface {//{{{
friend class Buffer; friend class Buffer;
friend class InputBuffer; friend class InputBuffer;
friend class OutputBuffer; friend class OutputBuffer;
friend class IUConverter; friend class ipaaca::converters::IUConverter;
friend class MessageConverter; //friend class ipaaca::converters::MessageConverter;
public: public:
IPAACA_MEMBER_VAR_EXPORT Payload _payload; IPAACA_MEMBER_VAR_EXPORT Payload _payload;
protected: protected:
IPAACA_HEADER_EXPORT RemotePushIU(); IPAACA_HEADER_EXPORT RemotePushIU();
IPAACA_HEADER_EXPORT static boost::shared_ptr<RemotePushIU> create(); IPAACA_HEADER_EXPORT static std::shared_ptr<RemotePushIU> create();
public: public:
IPAACA_HEADER_EXPORT inline ~RemotePushIU() { IPAACA_HEADER_EXPORT inline ~RemotePushIU() {
} }
...@@ -254,20 +248,20 @@ class RemotePushIU: public IUInterface {//{{{ ...@@ -254,20 +248,20 @@ class RemotePushIU: public IUInterface {//{{{
IPAACA_HEADER_EXPORT void _apply_link_update(IULinkUpdate::ptr update); IPAACA_HEADER_EXPORT void _apply_link_update(IULinkUpdate::ptr update);
IPAACA_HEADER_EXPORT void _apply_commission(); IPAACA_HEADER_EXPORT void _apply_commission();
IPAACA_HEADER_EXPORT void _apply_retraction(); IPAACA_HEADER_EXPORT void _apply_retraction();
typedef boost::shared_ptr<RemotePushIU> ptr; typedef std::shared_ptr<RemotePushIU> ptr;
};//}}} };//}}}
/// Copy of a remote Message, received in an InputBuffer. Setter functions all fail.\b Note: Typically handled only as reference in a handler in user space. /// Copy of a remote Message, received in an InputBuffer. Setter functions all fail.\b Note: Typically handled only as reference in a handler in user space.
class RemoteMessage: public IUInterface {//{{{ class RemoteMessage: public IUInterface {//{{{
friend class Buffer; friend class Buffer;
friend class InputBuffer; friend class InputBuffer;
friend class OutputBuffer; friend class OutputBuffer;
friend class IUConverter; friend class ipaaca::converters::IUConverter;
friend class MessageConverter; //friend class ipaaca::converters::MessageConverter;
public: public:
IPAACA_MEMBER_VAR_EXPORT Payload _payload; IPAACA_MEMBER_VAR_EXPORT Payload _payload;
protected: protected:
IPAACA_HEADER_EXPORT RemoteMessage(); IPAACA_HEADER_EXPORT RemoteMessage();
IPAACA_HEADER_EXPORT static boost::shared_ptr<RemoteMessage> create(); IPAACA_HEADER_EXPORT static std::shared_ptr<RemoteMessage> create();
public: public:
IPAACA_HEADER_EXPORT inline ~RemoteMessage() { IPAACA_HEADER_EXPORT inline ~RemoteMessage() {
} }
...@@ -282,7 +276,7 @@ class RemoteMessage: public IUInterface {//{{{ ...@@ -282,7 +276,7 @@ class RemoteMessage: public IUInterface {//{{{
IPAACA_HEADER_EXPORT void _apply_link_update(IULinkUpdate::ptr update); IPAACA_HEADER_EXPORT void _apply_link_update(IULinkUpdate::ptr update);
IPAACA_HEADER_EXPORT void _apply_commission(); IPAACA_HEADER_EXPORT void _apply_commission();
IPAACA_HEADER_EXPORT void _apply_retraction(); IPAACA_HEADER_EXPORT void _apply_retraction();
typedef boost::shared_ptr<RemoteMessage> ptr; typedef std::shared_ptr<RemoteMessage> ptr;
};//}}} };//}}}
#ifdef IPAACA_BUILD_MOCK_OBJECTS #ifdef IPAACA_BUILD_MOCK_OBJECTS
...@@ -291,13 +285,13 @@ class FakeIU: public IUInterface {//{{{ ...@@ -291,13 +285,13 @@ class FakeIU: public IUInterface {//{{{
friend class Buffer; friend class Buffer;
friend class InputBuffer; friend class InputBuffer;
friend class OutputBuffer; friend class OutputBuffer;
friend class IUConverter; friend class ipaaca::converters::IUConverter;
friend class MessageConverter; //friend class ipaaca::converters::MessageConverter;
protected: protected:
IPAACA_MEMBER_VAR_EXPORT Payload _payload; IPAACA_MEMBER_VAR_EXPORT Payload _payload;
IPAACA_HEADER_EXPORT FakeIU(); IPAACA_HEADER_EXPORT FakeIU();
public: public:
IPAACA_HEADER_EXPORT static boost::shared_ptr<FakeIU> create(); IPAACA_HEADER_EXPORT static std::shared_ptr<FakeIU> create();
IPAACA_HEADER_EXPORT ~FakeIU(); IPAACA_HEADER_EXPORT ~FakeIU();
IPAACA_HEADER_EXPORT Payload& payload() _IPAACA_OVERRIDE_; IPAACA_HEADER_EXPORT Payload& payload() _IPAACA_OVERRIDE_;
IPAACA_HEADER_EXPORT const Payload& const_payload() const _IPAACA_OVERRIDE_; IPAACA_HEADER_EXPORT const Payload& const_payload() const _IPAACA_OVERRIDE_;
...@@ -312,7 +306,7 @@ class FakeIU: public IUInterface {//{{{ ...@@ -312,7 +306,7 @@ class FakeIU: public IUInterface {//{{{
IPAACA_HEADER_EXPORT void _apply_commission(); IPAACA_HEADER_EXPORT void _apply_commission();
IPAACA_HEADER_EXPORT void _apply_retraction(); IPAACA_HEADER_EXPORT void _apply_retraction();
public: public:
typedef boost::shared_ptr<FakeIU> ptr; typedef std::shared_ptr<FakeIU> ptr;
};//}}} };//}}}
#endif #endif
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* "Incremental Processing Architecture * "Incremental Processing Architecture
* for Artificial Conversational Agents". * for Artificial Conversational Agents".
* *
* Copyright (c) 2009-2015 Social Cognitive Systems Group * Copyright (c) 2009-2022 Social Cognitive Systems Group
* (formerly the Sociable Agents Group) * (formerly the Sociable Agents Group)
* CITEC, Bielefeld University * CITEC, Bielefeld University
* *
...@@ -54,7 +54,7 @@ ...@@ -54,7 +54,7 @@
class Lock class Lock
{ {
protected: protected:
boost::recursive_mutex _mutex; std::recursive_mutex _mutex;
public: public:
IPAACA_HEADER_EXPORT inline Lock() { IPAACA_HEADER_EXPORT inline Lock() {
} }
...@@ -101,7 +101,9 @@ class Locker ...@@ -101,7 +101,9 @@ class Locker
* *
* \see Locker * \see Locker
*/ */
#ifndef WIN32 #if _WIN32 || _WIN64
// nothing for Windows
#else
#include <pthread.h> #include <pthread.h>
class PthreadMutexLocker class PthreadMutexLocker
{ {
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* "Incremental Processing Architecture * "Incremental Processing Architecture
* for Artificial Conversational Agents". * for Artificial Conversational Agents".
* *
* Copyright (c) 2009-2015 Social Cognitive Systems Group * Copyright (c) 2009-2022 Social Cognitive Systems Group
* (formerly the Sociable Agents Group) * (formerly the Sociable Agents Group)
* CITEC, Bielefeld University * CITEC, Bielefeld University
* *
...@@ -147,16 +147,16 @@ class Payload: public Lock //{{{ ...@@ -147,16 +147,16 @@ class Payload: public Lock //{{{
friend class Message; friend class Message;
friend class RemotePushIU; friend class RemotePushIU;
friend class RemoteMessage; friend class RemoteMessage;
friend class IUConverter; friend class ipaaca::converters::IUConverter;
friend class MessageConverter; //friend class ipaaca::converters::MessageConverter;
friend class CallbackIUPayloadUpdate; friend class ipaaca::backend::LocalServer;
friend class PayloadEntryProxy; friend class PayloadEntryProxy;
friend class PayloadIterator; friend class PayloadIterator;
friend class FakeIU; friend class FakeIU;
protected: protected:
IPAACA_MEMBER_VAR_EXPORT std::string _owner_name; IPAACA_MEMBER_VAR_EXPORT std::string _owner_name;
IPAACA_MEMBER_VAR_EXPORT PayloadDocumentStore _document_store; IPAACA_MEMBER_VAR_EXPORT PayloadDocumentStore _document_store;
IPAACA_MEMBER_VAR_EXPORT boost::weak_ptr<IUInterface> _iu; IPAACA_MEMBER_VAR_EXPORT std::weak_ptr<IUInterface> _iu;
IPAACA_MEMBER_VAR_EXPORT Lock _payload_operation_mode_lock; //< enforcing atomicity wrt the bool flag below IPAACA_MEMBER_VAR_EXPORT Lock _payload_operation_mode_lock; //< enforcing atomicity wrt the bool flag below
IPAACA_MEMBER_VAR_EXPORT bool _update_on_every_change; //< true: batch update not active; false: collecting updates (payload locked) IPAACA_MEMBER_VAR_EXPORT bool _update_on_every_change; //< true: batch update not active; false: collecting updates (payload locked)
IPAACA_MEMBER_VAR_EXPORT std::map<std::string, PayloadDocumentEntry::ptr> _collected_modifications; IPAACA_MEMBER_VAR_EXPORT std::map<std::string, PayloadDocumentEntry::ptr> _collected_modifications;
...@@ -170,7 +170,7 @@ class Payload: public Lock //{{{ ...@@ -170,7 +170,7 @@ class Payload: public Lock //{{{
/// thread ID for current write access (to let that thread read from cache and others from old payload) /// thread ID for current write access (to let that thread read from cache and others from old payload)
IPAACA_MEMBER_VAR_EXPORT std::string _writing_thread_id; IPAACA_MEMBER_VAR_EXPORT std::string _writing_thread_id;
protected: protected:
IPAACA_HEADER_EXPORT void initialize(boost::shared_ptr<IUInterface> iu); IPAACA_HEADER_EXPORT void initialize(std::shared_ptr<IUInterface> iu);
IPAACA_HEADER_EXPORT inline void _set_owner_name(const std::string& name) { _owner_name = name; } IPAACA_HEADER_EXPORT inline void _set_owner_name(const std::string& name) { _owner_name = name; }
IPAACA_HEADER_EXPORT void _remotely_enforced_wipe(); IPAACA_HEADER_EXPORT void _remotely_enforced_wipe();
IPAACA_HEADER_EXPORT void _remotely_enforced_delitem(const std::string& k); IPAACA_HEADER_EXPORT void _remotely_enforced_delitem(const std::string& k);
...@@ -209,7 +209,7 @@ class Payload: public Lock //{{{ ...@@ -209,7 +209,7 @@ class Payload: public Lock //{{{
IPAACA_HEADER_EXPORT PayloadIterator begin(); IPAACA_HEADER_EXPORT PayloadIterator begin();
/// obtain a standard iterator past the last entry in the payload /// obtain a standard iterator past the last entry in the payload
IPAACA_HEADER_EXPORT PayloadIterator end(); IPAACA_HEADER_EXPORT PayloadIterator end();
typedef boost::shared_ptr<Payload> ptr; typedef std::shared_ptr<Payload> ptr;
};//}}} };//}}}
/** \brief Standard iterator for Payload (example below) /** \brief Standard iterator for Payload (example below)
...@@ -247,7 +247,7 @@ class PayloadIterator//{{{ ...@@ -247,7 +247,7 @@ class PayloadIterator//{{{
class PayloadEntryProxyMapIterator//{{{ class PayloadEntryProxyMapIterator//{{{
{ {
public: public:
typedef rapidjson::GenericDocument<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>, rapidjson::CrtAllocator>::MemberIterator RawIterator; typedef rapidjson::GenericDocument<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>, rapidjson::CrtAllocator>::ConstMemberIterator RawIterator;
protected: protected:
IPAACA_MEMBER_VAR_EXPORT PayloadEntryProxy* proxy; IPAACA_MEMBER_VAR_EXPORT PayloadEntryProxy* proxy;
IPAACA_MEMBER_VAR_EXPORT RawIterator raw_iterator; IPAACA_MEMBER_VAR_EXPORT RawIterator raw_iterator;
...@@ -299,7 +299,7 @@ class PayloadEntryProxyListDecorator//{{{ ...@@ -299,7 +299,7 @@ class PayloadEntryProxyListDecorator//{{{
}; };
//}}} //}}}
/** \brief Reference to an existent or nonexistent payload entry (or a value deeper in the json tree) /** \brief Reference to an existent or nonexistent payload entry (or a value deeper in the json tree) - examples below:
* *
* This class is returned by IUInterface::operator[]. * This class is returned by IUInterface::operator[].
* The proxy handles automatic type conversions, requests remote changes of payloads, and enables navigation into and iteration over structured json objects. * The proxy handles automatic type conversions, requests remote changes of payloads, and enables navigation into and iteration over structured json objects.
...@@ -356,6 +356,11 @@ class PayloadEntryProxy//{{{ ...@@ -356,6 +356,11 @@ class PayloadEntryProxy//{{{
/// currently navigated value in json tree (or a new Null value) /// currently navigated value in json tree (or a new Null value)
IPAACA_MEMBER_VAR_EXPORT rapidjson::Value* json_value; ///< json value that corresponds to the current navigation (or nullptr) IPAACA_MEMBER_VAR_EXPORT rapidjson::Value* json_value; ///< json value that corresponds to the current navigation (or nullptr)
protected: protected:
// set internal json value object
void set_json_value(rapidjson::Value* json_value, const std::string& diag) {
IPAACA_DEBUG("Set json_value of " << _key << " to ptr " << (off_t) json_value << " - reason: " << diag)
this->json_value = json_value;
}
// constructor to create a new top-most parent proxy (from a payload key) // constructor to create a new top-most parent proxy (from a payload key)
IPAACA_HEADER_EXPORT PayloadEntryProxy(Payload* payload, const std::string& key); IPAACA_HEADER_EXPORT PayloadEntryProxy(Payload* payload, const std::string& key);
// constructors for navigation through objects // constructors for navigation through objects
...@@ -429,6 +434,8 @@ class PayloadEntryProxy//{{{ ...@@ -429,6 +434,8 @@ class PayloadEntryProxy//{{{
/// Conversion to std::string (explicit or implicit) /// Conversion to std::string (explicit or implicit)
IPAACA_HEADER_EXPORT operator std::string(); IPAACA_HEADER_EXPORT operator std::string();
/// Conversion to int (explicit or implicit)
IPAACA_HEADER_EXPORT operator int();
/// Conversion to long (explicit or implicit) /// Conversion to long (explicit or implicit)
IPAACA_HEADER_EXPORT operator long(); IPAACA_HEADER_EXPORT operator long();
/// Conversion to double (explicit or implicit) /// Conversion to double (explicit or implicit)
...@@ -468,12 +475,18 @@ class PayloadEntryProxy//{{{ ...@@ -468,12 +475,18 @@ class PayloadEntryProxy//{{{
IPAACA_HEADER_EXPORT std::string to_str(); IPAACA_HEADER_EXPORT std::string to_str();
//long to_int() { return operator long(); ; //long to_int() { return operator long(); ;
/// [DECPRECATED] use normal type conversion syntax instead /// [DECPRECATED] use normal type conversion syntax instead
[[deprecated("Use operator int() instead (i.e. explicit or implicit cast)")]]
IPAACA_HEADER_EXPORT int to_int();
/// [DECPRECATED] use normal type conversion syntax instead
[[deprecated("Use operator long() instead (i.e. explicit or implicit cast)")]] [[deprecated("Use operator long() instead (i.e. explicit or implicit cast)")]]
IPAACA_HEADER_EXPORT long to_long(); IPAACA_HEADER_EXPORT long to_long();
/// [DECPRECATED] use normal type conversion syntax instead /// [DECPRECATED] use normal type conversion syntax instead
[[deprecated("Use operator double() instead (i.e. explicit or implicit cast)")]] [[deprecated("Use operator double() instead (i.e. explicit or implicit cast)")]]
IPAACA_HEADER_EXPORT double to_float(); IPAACA_HEADER_EXPORT double to_float();
/// [DECPRECATED] use normal type conversion syntax instead /// [DECPRECATED] use normal type conversion syntax instead
[[deprecated("Use operator double() instead (i.e. explicit or implicit cast)")]]
IPAACA_HEADER_EXPORT double to_double();
/// [DECPRECATED] use normal type conversion syntax instead
[[deprecated("Use operator bool() instead (i.e. explicit or implicit cast)")]] [[deprecated("Use operator bool() instead (i.e. explicit or implicit cast)")]]
IPAACA_HEADER_EXPORT bool to_bool(); IPAACA_HEADER_EXPORT bool to_bool();
/// Append a supported type to a list-type payload value /// Append a supported type to a list-type payload value
......
/*
* This file is part of IPAACA, the
* "Incremental Processing Architecture
* for Artificial Conversational Agents".
*
* Copyright (c) 2009-2022 Social Cognitive Systems Group
* (formerly the Sociable Agents Group)
* CITEC, Bielefeld University
*
* http://opensource.cit-ec.de/projects/ipaaca/
* http://purl.org/net/ipaaca
*
* This file may be licensed under the terms of of the
* GNU Lesser General Public License Version 3 (the ``LGPL''),
* or (at your option) any later version.
*
* Software distributed under the License is distributed
* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
* express or implied. See the LGPL for the specific language
* governing rights and limitations.
*
* You should have received a copy of the LGPL along with this
* program. If not, go to http://www.gnu.org/licenses/lgpl.html
* or write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The development of this software was supported by the
* Excellence Cluster EXC 277 Cognitive Interaction Technology.
* The Excellence Cluster EXC 277 is a grant of the Deutsche
* Forschungsgemeinschaft (DFG) in the context of the German
* Excellence Initiative.
*/
/**
* \file ipaaca-string_utils.h
*
* \brief Header file for data and exception types and helper functions.
*
* Users should not include this file directly, but use ipaaca.h
*
* \author Ramin Yaghoubzadeh (ryaghoubzadeh@uni-bielefeld.de)
* \date March, 2015
*/
#ifndef __ipaaca_string_utils_h_INCLUDED__
#define __ipaaca_string_utils_h_INCLUDED__
#ifndef __ipaaca_h_INCLUDED__
#error "Please do not include this file directly, use ipaaca.h instead"
#endif
// in ipaaca-string-utils.cc
// additional misc functions ( String splitting / joining )//{{{
IPAACA_HEADER_EXPORT std::string str_trim(const std::string &s);
IPAACA_HEADER_EXPORT std::string str_join(const std::set<std::string>& set,const std::string& sep);
IPAACA_HEADER_EXPORT std::string str_join(const std::vector<std::string>& vec,const std::string& sep);
IPAACA_HEADER_EXPORT int str_split_wipe(const std::string& str, std::vector<std::string>& tokens, const std::string& delimiters );
IPAACA_HEADER_EXPORT int str_split_append(const std::string& str, std::vector<std::string>& tokens, const std::string& delimiters );
//}}}
#endif
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* "Incremental Processing Architecture * "Incremental Processing Architecture
* for Artificial Conversational Agents". * for Artificial Conversational Agents".
* *
* Copyright (c) 2009-2015 Social Cognitive Systems Group * Copyright (c) 2009-2022 Social Cognitive Systems Group
* (formerly the Sociable Agents Group) * (formerly the Sociable Agents Group)
* CITEC, Bielefeld University * CITEC, Bielefeld University
* *
...@@ -44,10 +44,19 @@ ...@@ -44,10 +44,19 @@
/** /**
\mainpage Documentation for IPAACA-C++ \mainpage Documentation for IPAACA-C++
This is the automatically generated documentation for the C++ implementation of IPAACA. This is the automatically generated documentation for the C++ implementation of IPAACA.
List of most relevant entry points: Protocol version: $(IPAACA_PROTOCOL_VERSION_MAJOR).$(IPAACA_PROTOCOL_VERSION_MINOR) \n
Release number: $(IPAACA_CPP_RELEASE_NUMBER) \n
Release date: $(IPAACA_CPP_RELEASE_DATE)
<b>IPAACA, the Incremental Processing Architecture for Artificial Conversational Agents, is available via <a href="https://opensource.cit-ec.de/projects/ipaaca/wiki"><b>its project page on CITEC Open Source</b></a>.</b>
IPAACA is (c) 2009-2022 Social Cognitive Systems Group, CITEC, Bielefeld University, Germany
The corresponding maintainer of this C++ version is Ramin Yaghoubzadeh Torky, ryaghoubzadeh@uni-bielefeld.de
<h3>List of most relevant entry points for application developers:</h3>
Buffers: InputBuffer, OutputBuffer Buffers: InputBuffer, OutputBuffer
...@@ -56,44 +65,113 @@ IUs: IUInterface, IU, Message ...@@ -56,44 +65,113 @@ IUs: IUInterface, IU, Message
IU handling (user-set): #IUEventHandlerFunction IU handling (user-set): #IUEventHandlerFunction
IU payload contents: Payload, PayloadEntryProxy IU payload contents: Payload, PayloadEntryProxy
<h3>Short examples:</h3>
<h4>Encapsulated listener</h4>
<pre>
#include <ipaaca/ipaaca.h>
class ReceiverCpp {
public:
void handle_iu_inbuf(ipaaca::IUInterface::ptr iu, ipaaca::IUEventType etype, bool local)
{
// Inspect category and IUEventType (ADDED, UPDATED...)
std::cout << ipaaca::iu_event_type_to_str(etype) << " category=" << iu->category() << " uid=" << iu->uid() << std::endl;
// Access payload
for (auto kv : iu->payload()) {
std::cout << "Payload entry '" << kv.first << "': " << ((std::string) kv.second) << std::endl;
}
// Access any links
auto links = iu->get_all_links();
for (auto kv : iu->get_all_links()) {
std::cout << "'" << kv.first << "' links to these IUs: ";
for (const auto& lnk : kv.second) {
std::cout << lnk << " ";
}
std::cout << std::endl;
}
}
int run()
{
auto ib = ipaaca::InputBuffer::create("myRecvProgName", std::set<std::string>{"myCategory"});
ib->register_handler(IPAACA_BIND_CLASS_HANDLER(&ReceiverCpp::handle_iu_inbuf, this)) // bind to member
std::cout << "Listening for all IU events (until Ctrl-C) ..." << std::endl;
while (true) {
sleep(5);
}
return 0;
}
};
int main(int argc, char** argv)
{
ipaaca::__ipaaca_static_option_log_level = IPAACA_LOG_LEVEL_DEBUG; // if you want this
ReceiverCpp rcpp;
rcpp.run();
}
</pre>
<h4>Minimal sender</h4>
<pre>
#include <ipaaca/ipaaca.h>
int main(int argc, char** argv)
{
auto out_buf = ipaaca::OutputBuffer::create("myProgramName");
auto iu = ipaaca::Message::create("myCategory");
iu->payload()["test"] = 123; // NOTE: see also #PayloadEntryProxy
out_buf->add(iu); // will be broadcast now
return 0;
}
</pre>
*/ */
#ifndef __ipaaca_h_INCLUDED__ #ifndef __ipaaca_h_INCLUDED__
#define __ipaaca_h_INCLUDED__ #define __ipaaca_h_INCLUDED__
/// ipaaca/IU/RSB protocol major version number /// ipaaca/IU/RSB protocol major version number
#define IPAACA_PROTOCOL_VERSION_MAJOR 2 #define IPAACA_PROTOCOL_VERSION_MAJOR 4
/// ipaaca/IU/RSB protocol minor version number /// ipaaca/IU/RSB protocol minor version number
#define IPAACA_PROTOCOL_VERSION_MINOR 0 #define IPAACA_PROTOCOL_VERSION_MINOR 1
/// running release number of ipaaca-c++ /// running release number of ipaaca-c++
#define IPAACA_CPP_RELEASE_NUMBER 13 #define IPAACA_CPP_RELEASE_NUMBER 17
/// date of last release number increment /// date of last release number increment
#define IPAACA_CPP_RELEASE_DATE "2015-12-04" #define IPAACA_CPP_RELEASE_DATE "2019-02-14"
#ifndef __FUNCTION_NAME__ #ifndef __FUNCTION_NAME__
#ifdef WIN32 // Windows #if _WIN32 || _WIN64 // Windows
#define __FUNCTION_NAME__ __FUNCTION__ #define __FUNCTION_NAME__ __FUNCTION__
#else // POSIX #else // POSIX
#define __FUNCTION_NAME__ __func__ #define __FUNCTION_NAME__ __func__
#endif #endif
#endif #endif
#ifdef WIN32 #if _WIN32 || _WIN64
#define IPAACA_SYSTEM_DEPENDENT_CLASS_NAME(c) "class "##c #define IPAACA_SYSTEM_DEPENDENT_CLASS_NAME(c) "class "##c
#else #else
#define IPAACA_SYSTEM_DEPENDENT_CLASS_NAME(c) c #define IPAACA_SYSTEM_DEPENDENT_CLASS_NAME(c) c
#endif #endif
#ifdef WIN32 #if _WIN32 || _WIN64
#if defined(ipaaca_EXPORTS) #if defined(IPAACA_STATIC_BINARY)
#define IPAACA_EXPORT #define IPAACA_EXPORT
#define IPAACA_HEADER_EXPORT __declspec(dllexport) #define IPAACA_HEADER_EXPORT
#define IPAACA_MEMBER_VAR_EXPORT #define IPAACA_MEMBER_VAR_EXPORT
#else #else
#define IPAACA_EXPORT #if defined(ipaaca_EXPORTS)
#define IPAACA_HEADER_EXPORT __declspec(dllimport) #define IPAACA_EXPORT
#define IPAACA_MEMBER_VAR_EXPORT #define IPAACA_HEADER_EXPORT __declspec(dllexport)
#define IPAACA_MEMBER_VAR_EXPORT
#else
#define IPAACA_EXPORT
#define IPAACA_HEADER_EXPORT __declspec(dllimport)
#define IPAACA_MEMBER_VAR_EXPORT
#endif
#endif #endif
#else #else
#define IPAACA_EXPORT #define IPAACA_EXPORT
...@@ -101,41 +179,42 @@ IU payload contents: Payload, PayloadEntryProxy ...@@ -101,41 +179,42 @@ IU payload contents: Payload, PayloadEntryProxy
#define IPAACA_MEMBER_VAR_EXPORT #define IPAACA_MEMBER_VAR_EXPORT
#endif #endif
// retrieve basename of source files for more readable logging
#define __FILE_BASENAME__ (strrchr(__FILE__,'/') ? strrchr(__FILE__,'/')+1 : __FILE__)
#if _WIN32 || _WIN64
#define _IPAACA_LOG_COLOR_NORMAL ""
#define _IPAACA_LOG_COLOR_DEBUG ""
#define _IPAACA_LOG_COLOR_WARN ""
#define _IPAACA_LOG_COLOR_ERROR ""
#else
#define _IPAACA_LOG_COLOR_NORMAL "\033[m"
#define _IPAACA_LOG_COLOR_DEBUG "\033[37m"
#define _IPAACA_LOG_COLOR_WARN "\033[38;5;208m"
#define _IPAACA_LOG_COLOR_ERROR "\033[38;5;196m"
#endif
#ifdef IPAACA_DEBUG_MESSAGES #ifdef IPAACA_DEBUG_MESSAGES
#define IPAACA_DEBUG(i) if (__ipaaca_static_option_log_level>=IPAACA_LOG_LEVEL_DEBUG) { std::cout << __FILE__ << ":" << __LINE__ << ": " << __FUNCTION_NAME__ << "() -- Debug: " << i << std::endl; } // Full debug messages mode
#define IPAACA_INFO(i) if (__ipaaca_static_option_log_level>=IPAACA_LOG_LEVEL_INFO) { std::cout << __FILE__ << ":" << __LINE__ << ": " << __FUNCTION_NAME__ << "() -- Info: " << i << std::endl; } #define IPAACA_DEBUG(i) if (__ipaaca_static_option_log_level>=IPAACA_LOG_LEVEL_DEBUG) { std::cout << _IPAACA_LOG_COLOR_DEBUG << "[Debug] " << __FILE_BASENAME__ << ":" << __LINE__ << ": " << __FUNCTION_NAME__ << "() -- " << i << _IPAACA_LOG_COLOR_NORMAL << std::endl; }
#define IPAACA_WARNING(i) if (__ipaaca_static_option_log_level>=IPAACA_LOG_LEVEL_WARNING) { std::cout << __FILE__ << ":" << __LINE__ << ": " << __FUNCTION_NAME__ << "() -- WARNING: " << i << std::endl; } #define IPAACA_IMPLEMENT_ME if (__ipaaca_static_option_log_level>=IPAACA_LOG_LEVEL_INFO) { std::cout << "[Info] " << __FILE_BASENAME__ << ":" << __LINE__ << ": " << __FUNCTION_NAME__ << "() -- IMPLEMENT ME" << std::endl; }
#define IPAACA_ERROR(i) if (__ipaaca_static_option_log_level>=IPAACA_LOG_LEVEL_ERROR) { std::cout << __FILE__ << ":" << __LINE__ << ": " << __FUNCTION_NAME__ << "() -- ERROR: " << i << std::endl; } #define IPAACA_TODO(i) if (__ipaaca_static_option_log_level>=IPAACA_LOG_LEVEL_INFO) { std::cout << "[Info] " << __FILE_BASENAME__ << ":" << __LINE__ << ": " << __FUNCTION_NAME__ << "() -- TODO: " << i << std::endl; }
#define IPAACA_CRITICAL(i) if (__ipaaca_static_option_log_level>=IPAACA_LOG_LEVEL_CRITICAL) { std::cout << __FILE__ << ":" << __LINE__ << ": " << __FUNCTION_NAME__ << "() -- CRITICAL: " << i << std::endl; }
#define IPAACA_IMPLEMENT_ME if (__ipaaca_static_option_log_level>=IPAACA_LOG_LEVEL_INFO) { std::cout << __FILE__ << ":" << __LINE__ << ": " << __FUNCTION_NAME__ << "() -- IMPLEMENT_ME:" << std::endl; }
#define IPAACA_TODO(i) if (__ipaaca_static_option_log_level>=IPAACA_LOG_LEVEL_INFO) { std::cout << __FILE__ << ":" << __LINE__ << ": " << __FUNCTION_NAME__ << "() -- TODO: " << i << std::endl; }
#else #else
#define IPAACA_DEBUG(i) ; #define IPAACA_DEBUG(i) ;
#define IPAACA_INFO(i) ;
#define IPAACA_WARNING(i) ;
#define IPAACA_ERROR(i) ;
#define IPAACA_CRITICAL(i) ;
#define IPAACA_IMPLEMENT_ME ; #define IPAACA_IMPLEMENT_ME ;
#define IPAACA_TODO(i) ; #define IPAACA_TODO(i) ;
#endif #endif
// Always compile in info and above, even if debug messages disabled.
#ifdef IPAACA_EXPOSE_FULL_RSB_API // You can set __ipaaca_static_option_log_level (e.g. IPAACA_LOG_LEVEL_NONE for silence).
#include <rsc/runtime/TypeStringTools.h> #define IPAACA_INFO(i) if (__ipaaca_static_option_log_level>=IPAACA_LOG_LEVEL_INFO) { std::cout << "[Info] " << __FILE_BASENAME__ << ":" << __LINE__ << ": " << __FUNCTION_NAME__ << "() -- " << i << std::endl; }
#include <rsb/Factory.h> #define IPAACA_WARNING(i) if (__ipaaca_static_option_log_level>=IPAACA_LOG_LEVEL_WARNING) { std::cout << _IPAACA_LOG_COLOR_WARN << "[WARN] " << __FILE_BASENAME__ << ":" << __LINE__ << ": " << __FUNCTION_NAME__ << "() -- WARNING: " << i << _IPAACA_LOG_COLOR_NORMAL << std::endl; }
#include <rsb/Handler.h> #define IPAACA_ERROR(i) if (__ipaaca_static_option_log_level>=IPAACA_LOG_LEVEL_ERROR) { std::cout << _IPAACA_LOG_COLOR_ERROR << "[ERROR] " << __FILE_BASENAME__ << ":" << __LINE__ << ": " << __FUNCTION_NAME__ << "() -- ERROR: " << i << _IPAACA_LOG_COLOR_NORMAL << std::endl; }
#include <rsb/Event.h> #define IPAACA_CRITICAL(i) if (__ipaaca_static_option_log_level>=IPAACA_LOG_LEVEL_CRITICAL) { std::cout << _IPAACA_LOG_COLOR_ERROR << "[CRITICAL] " << __FILE_BASENAME__ << ":" << __LINE__ << ": " << __FUNCTION_NAME__ << "() -- CRITICAL: " << i << _IPAACA_LOG_COLOR_NORMAL << std::endl; }
#include <rsb/ParticipantConfig.h>
#include <rsb/converter/Repository.h>
#include <rsb/converter/ProtocolBufferConverter.h>
#include <rsb/converter/Converter.h>
#include <rsb/rsbexports.h>
#endif
// new json-based payload API, used in several classes // new json-based payload API, used in several classes
#define RAPIDJSON_HAS_STDSTRING 1 #define RAPIDJSON_HAS_STDSTRING 1
#include "rapidjson/document.h" #include "rapidjson/document.h"
#include "rapidjson/prettywriter.h" #include "rapidjson/prettywriter.h"
#include "rapidjson/filestream.h" #include "rapidjson/filereadstream.h"
#include "rapidjson/filewritestream.h"
#include <cstdio> #include <cstdio>
/// marking pure virtual functions for extra readability /// marking pure virtual functions for extra readability
...@@ -151,11 +230,12 @@ IU payload contents: Payload, PayloadEntryProxy ...@@ -151,11 +230,12 @@ IU payload contents: Payload, PayloadEntryProxy
#include <iostream> #include <iostream>
#include <fstream>
// for logger // for logger
#include <iomanip> #include <iomanip>
#ifdef WIN32 #if _WIN32 || _WIN64
// for Windows // for Windows
// time // time
#include <time.h> #include <time.h>
...@@ -172,7 +252,7 @@ IU payload contents: Payload, PayloadEntryProxy ...@@ -172,7 +252,7 @@ IU payload contents: Payload, PayloadEntryProxy
#include <cstdlib> #include <cstdlib>
#ifdef WIN32 #if _WIN32 || _WIN64
#include <rpc.h> #include <rpc.h>
#else #else
#include <uuid/uuid.h> #include <uuid/uuid.h>
...@@ -181,15 +261,12 @@ IU payload contents: Payload, PayloadEntryProxy ...@@ -181,15 +261,12 @@ IU payload contents: Payload, PayloadEntryProxy
#ifndef Q_MOC_RUN #ifndef Q_MOC_RUN
#include <boost/bind.hpp> #include <memory>
#include <boost/function.hpp> #include <functional>
#include <boost/shared_ptr.hpp> #include <chrono>
#include <boost/weak_ptr.hpp> #include <thread>
#include <boost/pointer_cast.hpp> #include <mutex>
#include <boost/lexical_cast.hpp> #include <condition_variable>
#include <boost/thread/recursive_mutex.hpp>
#include <boost/thread/thread.hpp>
#endif #endif
...@@ -204,10 +281,12 @@ IU payload contents: Payload, PayloadEntryProxy ...@@ -204,10 +281,12 @@ IU payload contents: Payload, PayloadEntryProxy
namespace ipaaca { namespace ipaaca {
#include <ipaaca/ipaaca-definitions.h> #include <ipaaca/ipaaca-definitions.h>
#include <ipaaca/ipaaca-forwards.h> #include <ipaaca/ipaaca-forwards.h>
#include <ipaaca/ipaaca-errors.h>
#include <ipaaca/ipaaca-initializer.h>
#include <ipaaca/ipaaca-locking.h> #include <ipaaca/ipaaca-locking.h>
#include <ipaaca/ipaaca-cmdline-parser.h>
#include <ipaaca/ipaaca-string-utils.h>
// Global static library variables (run-time default configuration) // Global static library variables (run-time default configuration)
// Actual initial values are set in ipaaca.cc // Actual initial values are set in ipaaca.cc
...@@ -230,14 +309,14 @@ IPAACA_MEMBER_VAR_EXPORT extern std::string __ipaaca_static_option_rsb_socketser ...@@ -230,14 +309,14 @@ IPAACA_MEMBER_VAR_EXPORT extern std::string __ipaaca_static_option_rsb_socketser
IPAACA_MEMBER_VAR_EXPORT Lock& logger_lock(); IPAACA_MEMBER_VAR_EXPORT Lock& logger_lock();
#ifdef WIN32 #if _WIN32 || _WIN64
#define LOG_IPAACA_CONSOLE(msg) { ipaaca::Locker logging_locker(ipaaca::logger_lock()); std::time_t result = std::time(NULL); std::cout << "[LOG] " << std::asctime(std::localtime(&result)) << " : " << msg << std::endl; } #define LOG_IPAACA_CONSOLE(msg) { ipaaca::Locker logging_locker(ipaaca::logger_lock()); std::time_t result = std::time(NULL); std::cout << "[LOG] " << std::asctime(std::localtime(&result)) << " : " << msg << std::endl; }
#else #else
// use normal gettimeofday() on POSIX // use normal gettimeofday() on POSIX
#define LOG_IPAACA_CONSOLE(msg) { ipaaca::Locker logging_locker(ipaaca::logger_lock()); timeval logging_tim; gettimeofday(&logging_tim, NULL); double logging_t1=logging_tim.tv_sec+(logging_tim.tv_usec/1000000.0); std::cout << "[LOG] " << std::setprecision(15) << logging_t1 << " : " << msg << std::endl; } #define LOG_IPAACA_CONSOLE(msg) { ipaaca::Locker logging_locker(ipaaca::logger_lock()); timeval logging_tim; gettimeofday(&logging_tim, NULL); double logging_t1=logging_tim.tv_sec+(logging_tim.tv_usec/1000000.0); std::cout << "[LOG] " << std::setprecision(15) << logging_t1 << " : " << msg << std::endl; }
#endif #endif
#ifdef WIN32 #if _WIN32 || _WIN64
#define IPAACA_SIMPLE_TIMER_BEGIN(N) ; #define IPAACA_SIMPLE_TIMER_BEGIN(N) ;
#define IPAACA_SIMPLE_TIMER_END(N, NAME) LOG_IPAACA_CONSOLE(NAME << " - time elapsed: Windows - IMPLEMENT ME") #define IPAACA_SIMPLE_TIMER_END(N, NAME) LOG_IPAACA_CONSOLE(NAME << " - time elapsed: Windows - IMPLEMENT ME")
#else #else
...@@ -252,16 +331,14 @@ IPAACA_MEMBER_VAR_EXPORT Lock& logger_lock(); ...@@ -252,16 +331,14 @@ IPAACA_MEMBER_VAR_EXPORT Lock& logger_lock();
LOG_IPAACA_CONSOLE(NAME << " - ̨́us elapsed: " << _ipaaca_timer_usecs_ ## N) LOG_IPAACA_CONSOLE(NAME << " - ̨́us elapsed: " << _ipaaca_timer_usecs_ ## N)
#endif #endif
#include <ipaaca/ipaaca-config.h>
#include <ipaaca/ipaaca-converters.h>
#include <ipaaca/ipaaca-backend.h>
#include <ipaaca/ipaaca-payload.h> #include <ipaaca/ipaaca-payload.h>
#include <ipaaca/ipaaca-buffers.h> #include <ipaaca/ipaaca-buffers.h>
#include <ipaaca/ipaaca-ius.h> #include <ipaaca/ipaaca-ius.h>
/// Full API (including RSB transport) is only exposed during
/// ipaaca compilation, user programs should use abstract API.
#ifdef IPAACA_EXPOSE_FULL_RSB_API
#include <ipaaca/ipaaca-internal.h>
#endif
} // of namespace ipaaca } // of namespace ipaaca
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* "Incremental Processing Architecture * "Incremental Processing Architecture
* for Artificial Conversational Agents". * for Artificial Conversational Agents".
* *
* Copyright (c) 2009-2015 Social Cognitive Systems Group * Copyright (c) 2009-2022 Social Cognitive Systems Group
* (formerly the Sociable Agents Group) * (formerly the Sociable Agents Group)
* CITEC, Bielefeld University * CITEC, Bielefeld University
* *
...@@ -67,8 +67,8 @@ class ComponentNotifier { ...@@ -67,8 +67,8 @@ class ComponentNotifier {
ComponentNotifier(const std::string& componentName, const std::string& componentFunction, const std::set<std::string>& sendCategories, const std::set<std::string>& receiveCategories); ComponentNotifier(const std::string& componentName, const std::string& componentFunction, const std::set<std::string>& sendCategories, const std::set<std::string>& receiveCategories);
ComponentNotifier(const std::string& componentName, const std::string& componentFunction, const std::set<std::string>& sendCategories, const std::set<std::string>& receiveCategories, ipaaca::OutputBuffer::ptr out_buf, ipaaca::InputBuffer::ptr in_buf); ComponentNotifier(const std::string& componentName, const std::string& componentFunction, const std::set<std::string>& sendCategories, const std::set<std::string>& receiveCategories, ipaaca::OutputBuffer::ptr out_buf, ipaaca::InputBuffer::ptr in_buf);
public: public:
static boost::shared_ptr<ComponentNotifier> create(const std::string& componentName, const std::string& componentFunction, const std::set<std::string>& sendCategories, const std::set<std::string>& receiveCategories); static std::shared_ptr<ComponentNotifier> create(const std::string& componentName, const std::string& componentFunction, const std::set<std::string>& sendCategories, const std::set<std::string>& receiveCategories);
static boost::shared_ptr<ComponentNotifier> create(const std::string& componentName, const std::string& componentFunction, const std::set<std::string>& sendCategories, const std::set<std::string>& receiveCategories, ipaaca::OutputBuffer::ptr out_buf, ipaaca::InputBuffer::ptr in_buf); static std::shared_ptr<ComponentNotifier> create(const std::string& componentName, const std::string& componentFunction, const std::set<std::string>& sendCategories, const std::set<std::string>& receiveCategories, ipaaca::OutputBuffer::ptr out_buf, ipaaca::InputBuffer::ptr in_buf);
public: public:
~ComponentNotifier(); ~ComponentNotifier();
protected: protected:
...@@ -91,7 +91,7 @@ class ComponentNotifier { ...@@ -91,7 +91,7 @@ class ComponentNotifier {
std::string send_categories; std::string send_categories;
std::string recv_categories; std::string recv_categories;
public: public:
typedef boost::shared_ptr<ComponentNotifier> ptr; typedef std::shared_ptr<ComponentNotifier> ptr;
}; };
......
// Copyright (C) 2011 Milo Yip // Tencent is pleased to support the open source community by making RapidJSON available.
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
// of this software and associated documentation files (the "Software"), to deal //
// in the Software without restriction, including without limitation the rights // Licensed under the MIT License (the "License"); you may not use this file except
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // in compliance with the License. You may obtain a copy of the License at
// copies of the Software, and to permit persons to whom the Software is //
// furnished to do so, subject to the following conditions: // http://opensource.org/licenses/MIT
// //
// The above copyright notice and this permission notice shall be included in // Unless required by applicable law or agreed to in writing, software distributed
// all copies or substantial portions of the Software. // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// // CONDITIONS OF ANY KIND, either express or implied. See the License for the
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // specific language governing permissions and limitations under the License.
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE #ifndef RAPIDJSON_ALLOCATORS_H_
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #define RAPIDJSON_ALLOCATORS_H_
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN #include "rapidjson.h"
// THE SOFTWARE. #include "internal/meta.h"
#ifndef RAPIDJSON_ALLOCATORS_H_ #include <memory>
#define RAPIDJSON_ALLOCATORS_H_
#if RAPIDJSON_HAS_CXX11
#include "rapidjson.h" #include <type_traits>
#endif
RAPIDJSON_NAMESPACE_BEGIN
RAPIDJSON_NAMESPACE_BEGIN
///////////////////////////////////////////////////////////////////////////////
// Allocator ///////////////////////////////////////////////////////////////////////////////
// Allocator
/*! \class rapidjson::Allocator
\brief Concept for allocating, resizing and freeing memory block. /*! \class rapidjson::Allocator
\brief Concept for allocating, resizing and freeing memory block.
Note that Malloc() and Realloc() are non-static but Free() is static.
Note that Malloc() and Realloc() are non-static but Free() is static.
So if an allocator need to support Free(), it needs to put its pointer in
the header of memory block. So if an allocator need to support Free(), it needs to put its pointer in
the header of memory block.
\code
concept Allocator { \code
static const bool kNeedFree; //!< Whether this allocator needs to call Free(). concept Allocator {
static const bool kNeedFree; //!< Whether this allocator needs to call Free().
// Allocate a memory block.
// \param size of the memory block in bytes. // Allocate a memory block.
// \returns pointer to the memory block. // \param size of the memory block in bytes.
void* Malloc(size_t size); // \returns pointer to the memory block.
void* Malloc(size_t size);
// Resize a memory block.
// \param originalPtr The pointer to current memory block. Null pointer is permitted. // Resize a memory block.
// \param originalSize The current size in bytes. (Design issue: since some allocator may not book-keep this, explicitly pass to it can save memory.) // \param originalPtr The pointer to current memory block. Null pointer is permitted.
// \param newSize the new size in bytes. // \param originalSize The current size in bytes. (Design issue: since some allocator may not book-keep this, explicitly pass to it can save memory.)
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize); // \param newSize the new size in bytes.
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize);
// Free a memory block.
// \param pointer to the memory block. Null pointer is permitted. // Free a memory block.
static void Free(void *ptr); // \param pointer to the memory block. Null pointer is permitted.
}; static void Free(void *ptr);
\endcode };
*/ \endcode
*/
///////////////////////////////////////////////////////////////////////////////
// CrtAllocator
/*! \def RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY
//! C-runtime library allocator. \ingroup RAPIDJSON_CONFIG
/*! This class is just wrapper for standard C library memory routines. \brief User-defined kDefaultChunkCapacity definition.
\note implements Allocator concept
*/ User can define this as any \c size that is a power of 2.
class CrtAllocator { */
public:
static const bool kNeedFree = true; #ifndef RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY
void* Malloc(size_t size) { return std::malloc(size); } #define RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY (64 * 1024)
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { (void)originalSize; return std::realloc(originalPtr, newSize); } #endif
static void Free(void *ptr) { std::free(ptr); }
};
///////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////// // CrtAllocator
// MemoryPoolAllocator
//! C-runtime library allocator.
//! Default memory allocator used by the parser and DOM. /*! This class is just wrapper for standard C library memory routines.
/*! This allocator allocate memory blocks from pre-allocated memory chunks. \note implements Allocator concept
*/
It does not free memory blocks. And Realloc() only allocate new memory. class CrtAllocator {
public:
The memory chunks are allocated by BaseAllocator, which is CrtAllocator by default. static const bool kNeedFree = true;
void* Malloc(size_t size) {
User may also supply a buffer as the first chunk. if (size) // behavior of malloc(0) is implementation defined.
return RAPIDJSON_MALLOC(size);
If the user-buffer is full then additional chunks are allocated by BaseAllocator. else
return NULL; // standardize to returning NULL.
The user-buffer is not deallocated by this allocator. }
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
\tparam BaseAllocator the allocator type for allocating memory chunks. Default is CrtAllocator. (void)originalSize;
\note implements Allocator concept if (newSize == 0) {
*/ RAPIDJSON_FREE(originalPtr);
template <typename BaseAllocator = CrtAllocator> return NULL;
class MemoryPoolAllocator { }
public: return RAPIDJSON_REALLOC(originalPtr, newSize);
static const bool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator) }
static void Free(void *ptr) RAPIDJSON_NOEXCEPT { RAPIDJSON_FREE(ptr); }
//! Constructor with chunkSize.
/*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize. bool operator==(const CrtAllocator&) const RAPIDJSON_NOEXCEPT {
\param baseAllocator The allocator for allocating memory chunks. return true;
*/ }
MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : bool operator!=(const CrtAllocator&) const RAPIDJSON_NOEXCEPT {
chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0) return false;
{ }
} };
//! Constructor with user-supplied buffer. ///////////////////////////////////////////////////////////////////////////////
/*! The user buffer will be used firstly. When it is full, memory pool allocates new chunk with chunk size. // MemoryPoolAllocator
The user buffer will not be deallocated when this allocator is destructed. //! Default memory allocator used by the parser and DOM.
/*! This allocator allocate memory blocks from pre-allocated memory chunks.
\param buffer User supplied buffer.
\param size Size of the buffer in bytes. It must at least larger than sizeof(ChunkHeader). It does not free memory blocks. And Realloc() only allocate new memory.
\param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
\param baseAllocator The allocator for allocating memory chunks. The memory chunks are allocated by BaseAllocator, which is CrtAllocator by default.
*/
MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : User may also supply a buffer as the first chunk.
chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(buffer), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
{ If the user-buffer is full then additional chunks are allocated by BaseAllocator.
RAPIDJSON_ASSERT(buffer != 0);
RAPIDJSON_ASSERT(size > sizeof(ChunkHeader)); The user-buffer is not deallocated by this allocator.
chunkHead_ = reinterpret_cast<ChunkHeader*>(buffer);
chunkHead_->capacity = size - sizeof(ChunkHeader); \tparam BaseAllocator the allocator type for allocating memory chunks. Default is CrtAllocator.
chunkHead_->size = 0; \note implements Allocator concept
chunkHead_->next = 0; */
} template <typename BaseAllocator = CrtAllocator>
class MemoryPoolAllocator {
//! Destructor. //! Chunk header for perpending to each chunk.
/*! This deallocates all memory chunks, excluding the user-supplied buffer. /*! Chunks are stored as a singly linked list.
*/ */
~MemoryPoolAllocator() { struct ChunkHeader {
Clear(); size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself).
RAPIDJSON_DELETE(ownBaseAllocator_); size_t size; //!< Current size of allocated memory in bytes.
} ChunkHeader *next; //!< Next chunk in the linked list.
};
//! Deallocates all memory chunks, excluding the user-supplied buffer.
void Clear() { struct SharedData {
while(chunkHead_ != 0 && chunkHead_ != userBuffer_) { ChunkHeader *chunkHead; //!< Head of the chunk linked-list. Only the head chunk serves allocation.
ChunkHeader* next = chunkHead_->next; BaseAllocator* ownBaseAllocator; //!< base allocator created by this object.
baseAllocator_->Free(chunkHead_); size_t refcount;
chunkHead_ = next; bool ownBuffer;
} };
}
static const size_t SIZEOF_SHARED_DATA = RAPIDJSON_ALIGN(sizeof(SharedData));
//! Computes the total capacity of allocated memory chunks. static const size_t SIZEOF_CHUNK_HEADER = RAPIDJSON_ALIGN(sizeof(ChunkHeader));
/*! \return total capacity in bytes.
*/ static inline ChunkHeader *GetChunkHead(SharedData *shared)
size_t Capacity() const { {
size_t capacity = 0; return reinterpret_cast<ChunkHeader*>(reinterpret_cast<uint8_t*>(shared) + SIZEOF_SHARED_DATA);
for (ChunkHeader* c = chunkHead_; c != 0; c = c->next) }
capacity += c->capacity; static inline uint8_t *GetChunkBuffer(SharedData *shared)
return capacity; {
} return reinterpret_cast<uint8_t*>(shared->chunkHead) + SIZEOF_CHUNK_HEADER;
}
//! Computes the memory blocks allocated.
/*! \return total used bytes. static const size_t kDefaultChunkCapacity = RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY; //!< Default chunk capacity.
*/
size_t Size() const { public:
size_t size = 0; static const bool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator)
for (ChunkHeader* c = chunkHead_; c != 0; c = c->next) static const bool kRefCounted = true; //!< Tell users that this allocator is reference counted on copy
size += c->size;
return size; //! Constructor with chunkSize.
} /*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
\param baseAllocator The allocator for allocating memory chunks.
//! Allocates a memory block. (concept Allocator) */
void* Malloc(size_t size) { explicit
size = RAPIDJSON_ALIGN(size); MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity) chunk_capacity_(chunkSize),
AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size); baseAllocator_(baseAllocator ? baseAllocator : RAPIDJSON_NEW(BaseAllocator)()),
shared_(static_cast<SharedData*>(baseAllocator_ ? baseAllocator_->Malloc(SIZEOF_SHARED_DATA + SIZEOF_CHUNK_HEADER) : 0))
void *buffer = reinterpret_cast<char *>(chunkHead_ + 1) + chunkHead_->size; {
chunkHead_->size += size; RAPIDJSON_ASSERT(baseAllocator_ != 0);
return buffer; RAPIDJSON_ASSERT(shared_ != 0);
} if (baseAllocator) {
shared_->ownBaseAllocator = 0;
//! Resizes a memory block (concept Allocator) }
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { else {
if (originalPtr == 0) shared_->ownBaseAllocator = baseAllocator_;
return Malloc(newSize); }
shared_->chunkHead = GetChunkHead(shared_);
// Do not shrink if new size is smaller than original shared_->chunkHead->capacity = 0;
if (originalSize >= newSize) shared_->chunkHead->size = 0;
return originalPtr; shared_->chunkHead->next = 0;
shared_->ownBuffer = true;
// Simply expand it if it is the last allocation and there is sufficient space shared_->refcount = 1;
if (originalPtr == (char *)(chunkHead_ + 1) + chunkHead_->size - originalSize) { }
size_t increment = static_cast<size_t>(newSize - originalSize);
increment = RAPIDJSON_ALIGN(increment); //! Constructor with user-supplied buffer.
if (chunkHead_->size + increment <= chunkHead_->capacity) { /*! The user buffer will be used firstly. When it is full, memory pool allocates new chunk with chunk size.
chunkHead_->size += increment;
return originalPtr; The user buffer will not be deallocated when this allocator is destructed.
}
} \param buffer User supplied buffer.
\param size Size of the buffer in bytes. It must at least larger than sizeof(ChunkHeader).
// Realloc process: allocate and copy memory, do not free original buffer. \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
void* newBuffer = Malloc(newSize); \param baseAllocator The allocator for allocating memory chunks.
RAPIDJSON_ASSERT(newBuffer != 0); // Do not handle out-of-memory explicitly. */
return std::memcpy(newBuffer, originalPtr, originalSize); MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
} chunk_capacity_(chunkSize),
baseAllocator_(baseAllocator),
//! Frees a memory block (concept Allocator) shared_(static_cast<SharedData*>(AlignBuffer(buffer, size)))
static void Free(void *ptr) { (void)ptr; } // Do nothing {
RAPIDJSON_ASSERT(size >= SIZEOF_SHARED_DATA + SIZEOF_CHUNK_HEADER);
private: shared_->chunkHead = GetChunkHead(shared_);
//! Copy constructor is not permitted. shared_->chunkHead->capacity = size - SIZEOF_SHARED_DATA - SIZEOF_CHUNK_HEADER;
MemoryPoolAllocator(const MemoryPoolAllocator& rhs) /* = delete */; shared_->chunkHead->size = 0;
//! Copy assignment operator is not permitted. shared_->chunkHead->next = 0;
MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) /* = delete */; shared_->ownBaseAllocator = 0;
shared_->ownBuffer = false;
//! Creates a new chunk. shared_->refcount = 1;
/*! \param capacity Capacity of the chunk in bytes. }
*/
void AddChunk(size_t capacity) { MemoryPoolAllocator(const MemoryPoolAllocator& rhs) RAPIDJSON_NOEXCEPT :
if (!baseAllocator_) chunk_capacity_(rhs.chunk_capacity_),
ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator()); baseAllocator_(rhs.baseAllocator_),
ChunkHeader* chunk = reinterpret_cast<ChunkHeader*>(baseAllocator_->Malloc(sizeof(ChunkHeader) + capacity)); shared_(rhs.shared_)
chunk->capacity = capacity; {
chunk->size = 0; RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
chunk->next = chunkHead_; ++shared_->refcount;
chunkHead_ = chunk; }
} MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) RAPIDJSON_NOEXCEPT
{
static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity. RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
++rhs.shared_->refcount;
//! Chunk header for perpending to each chunk. this->~MemoryPoolAllocator();
/*! Chunks are stored as a singly linked list. baseAllocator_ = rhs.baseAllocator_;
*/ chunk_capacity_ = rhs.chunk_capacity_;
struct ChunkHeader { shared_ = rhs.shared_;
size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself). return *this;
size_t size; //!< Current size of allocated memory in bytes. }
ChunkHeader *next; //!< Next chunk in the linked list.
}; #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
MemoryPoolAllocator(MemoryPoolAllocator&& rhs) RAPIDJSON_NOEXCEPT :
ChunkHeader *chunkHead_; //!< Head of the chunk linked-list. Only the head chunk serves allocation. chunk_capacity_(rhs.chunk_capacity_),
size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated. baseAllocator_(rhs.baseAllocator_),
void *userBuffer_; //!< User supplied buffer. shared_(rhs.shared_)
BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks. {
BaseAllocator* ownBaseAllocator_; //!< base allocator created by this object. RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
}; rhs.shared_ = 0;
}
RAPIDJSON_NAMESPACE_END MemoryPoolAllocator& operator=(MemoryPoolAllocator&& rhs) RAPIDJSON_NOEXCEPT
{
#endif // RAPIDJSON_ENCODINGS_H_ RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
this->~MemoryPoolAllocator();
baseAllocator_ = rhs.baseAllocator_;
chunk_capacity_ = rhs.chunk_capacity_;
shared_ = rhs.shared_;
rhs.shared_ = 0;
return *this;
}
#endif
//! Destructor.
/*! This deallocates all memory chunks, excluding the user-supplied buffer.
*/
~MemoryPoolAllocator() RAPIDJSON_NOEXCEPT {
if (!shared_) {
// do nothing if moved
return;
}
if (shared_->refcount > 1) {
--shared_->refcount;
return;
}
Clear();
BaseAllocator *a = shared_->ownBaseAllocator;
if (shared_->ownBuffer) {
baseAllocator_->Free(shared_);
}
RAPIDJSON_DELETE(a);
}
//! Deallocates all memory chunks, excluding the first/user one.
void Clear() RAPIDJSON_NOEXCEPT {
RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
for (;;) {
ChunkHeader* c = shared_->chunkHead;
if (!c->next) {
break;
}
shared_->chunkHead = c->next;
baseAllocator_->Free(c);
}
shared_->chunkHead->size = 0;
}
//! Computes the total capacity of allocated memory chunks.
/*! \return total capacity in bytes.
*/
size_t Capacity() const RAPIDJSON_NOEXCEPT {
RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
size_t capacity = 0;
for (ChunkHeader* c = shared_->chunkHead; c != 0; c = c->next)
capacity += c->capacity;
return capacity;
}
//! Computes the memory blocks allocated.
/*! \return total used bytes.
*/
size_t Size() const RAPIDJSON_NOEXCEPT {
RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
size_t size = 0;
for (ChunkHeader* c = shared_->chunkHead; c != 0; c = c->next)
size += c->size;
return size;
}
//! Whether the allocator is shared.
/*! \return true or false.
*/
bool Shared() const RAPIDJSON_NOEXCEPT {
RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
return shared_->refcount > 1;
}
//! Allocates a memory block. (concept Allocator)
void* Malloc(size_t size) {
RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
if (!size)
return NULL;
size = RAPIDJSON_ALIGN(size);
if (RAPIDJSON_UNLIKELY(shared_->chunkHead->size + size > shared_->chunkHead->capacity))
if (!AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size))
return NULL;
void *buffer = GetChunkBuffer(shared_) + shared_->chunkHead->size;
shared_->chunkHead->size += size;
return buffer;
}
//! Resizes a memory block (concept Allocator)
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
if (originalPtr == 0)
return Malloc(newSize);
RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
if (newSize == 0)
return NULL;
originalSize = RAPIDJSON_ALIGN(originalSize);
newSize = RAPIDJSON_ALIGN(newSize);
// Do not shrink if new size is smaller than original
if (originalSize >= newSize)
return originalPtr;
// Simply expand it if it is the last allocation and there is sufficient space
if (originalPtr == GetChunkBuffer(shared_) + shared_->chunkHead->size - originalSize) {
size_t increment = static_cast<size_t>(newSize - originalSize);
if (shared_->chunkHead->size + increment <= shared_->chunkHead->capacity) {
shared_->chunkHead->size += increment;
return originalPtr;
}
}
// Realloc process: allocate and copy memory, do not free original buffer.
if (void* newBuffer = Malloc(newSize)) {
if (originalSize)
std::memcpy(newBuffer, originalPtr, originalSize);
return newBuffer;
}
else
return NULL;
}
//! Frees a memory block (concept Allocator)
static void Free(void *ptr) RAPIDJSON_NOEXCEPT { (void)ptr; } // Do nothing
//! Compare (equality) with another MemoryPoolAllocator
bool operator==(const MemoryPoolAllocator& rhs) const RAPIDJSON_NOEXCEPT {
RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
return shared_ == rhs.shared_;
}
//! Compare (inequality) with another MemoryPoolAllocator
bool operator!=(const MemoryPoolAllocator& rhs) const RAPIDJSON_NOEXCEPT {
return !operator==(rhs);
}
private:
//! Creates a new chunk.
/*! \param capacity Capacity of the chunk in bytes.
\return true if success.
*/
bool AddChunk(size_t capacity) {
if (!baseAllocator_)
shared_->ownBaseAllocator = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator)();
if (ChunkHeader* chunk = static_cast<ChunkHeader*>(baseAllocator_->Malloc(SIZEOF_CHUNK_HEADER + capacity))) {
chunk->capacity = capacity;
chunk->size = 0;
chunk->next = shared_->chunkHead;
shared_->chunkHead = chunk;
return true;
}
else
return false;
}
static inline void* AlignBuffer(void* buf, size_t &size)
{
RAPIDJSON_NOEXCEPT_ASSERT(buf != 0);
const uintptr_t mask = sizeof(void*) - 1;
const uintptr_t ubuf = reinterpret_cast<uintptr_t>(buf);
if (RAPIDJSON_UNLIKELY(ubuf & mask)) {
const uintptr_t abuf = (ubuf + mask) & ~mask;
RAPIDJSON_ASSERT(size >= abuf - ubuf);
buf = reinterpret_cast<void*>(abuf);
size -= abuf - ubuf;
}
return buf;
}
size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated.
BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks.
SharedData *shared_; //!< The shared data of the allocator
};
namespace internal {
template<typename, typename = void>
struct IsRefCounted :
public FalseType
{ };
template<typename T>
struct IsRefCounted<T, typename internal::EnableIfCond<T::kRefCounted>::Type> :
public TrueType
{ };
}
template<typename T, typename A>
inline T* Realloc(A& a, T* old_p, size_t old_n, size_t new_n)
{
RAPIDJSON_NOEXCEPT_ASSERT(old_n <= SIZE_MAX / sizeof(T) && new_n <= SIZE_MAX / sizeof(T));
return static_cast<T*>(a.Realloc(old_p, old_n * sizeof(T), new_n * sizeof(T)));
}
template<typename T, typename A>
inline T *Malloc(A& a, size_t n = 1)
{
return Realloc<T, A>(a, NULL, 0, n);
}
template<typename T, typename A>
inline void Free(A& a, T *p, size_t n = 1)
{
static_cast<void>(Realloc<T, A>(a, p, n, 0));
}
#ifdef __GNUC__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++) // std::allocator can safely be inherited
#endif
template <typename T, typename BaseAllocator = CrtAllocator>
class StdAllocator :
public std::allocator<T>
{
typedef std::allocator<T> allocator_type;
#if RAPIDJSON_HAS_CXX11
typedef std::allocator_traits<allocator_type> traits_type;
#else
typedef allocator_type traits_type;
#endif
public:
typedef BaseAllocator BaseAllocatorType;
StdAllocator() RAPIDJSON_NOEXCEPT :
allocator_type(),
baseAllocator_()
{ }
StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT :
allocator_type(rhs),
baseAllocator_(rhs.baseAllocator_)
{ }
template<typename U>
StdAllocator(const StdAllocator<U, BaseAllocator>& rhs) RAPIDJSON_NOEXCEPT :
allocator_type(rhs),
baseAllocator_(rhs.baseAllocator_)
{ }
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
StdAllocator(StdAllocator&& rhs) RAPIDJSON_NOEXCEPT :
allocator_type(std::move(rhs)),
baseAllocator_(std::move(rhs.baseAllocator_))
{ }
#endif
#if RAPIDJSON_HAS_CXX11
using propagate_on_container_move_assignment = std::true_type;
using propagate_on_container_swap = std::true_type;
#endif
/* implicit */
StdAllocator(const BaseAllocator& allocator) RAPIDJSON_NOEXCEPT :
allocator_type(),
baseAllocator_(allocator)
{ }
~StdAllocator() RAPIDJSON_NOEXCEPT
{ }
template<typename U>
struct rebind {
typedef StdAllocator<U, BaseAllocator> other;
};
typedef typename traits_type::size_type size_type;
typedef typename traits_type::difference_type difference_type;
typedef typename traits_type::value_type value_type;
typedef typename traits_type::pointer pointer;
typedef typename traits_type::const_pointer const_pointer;
#if RAPIDJSON_HAS_CXX11
typedef typename std::add_lvalue_reference<value_type>::type &reference;
typedef typename std::add_lvalue_reference<typename std::add_const<value_type>::type>::type &const_reference;
pointer address(reference r) const RAPIDJSON_NOEXCEPT
{
return std::addressof(r);
}
const_pointer address(const_reference r) const RAPIDJSON_NOEXCEPT
{
return std::addressof(r);
}
size_type max_size() const RAPIDJSON_NOEXCEPT
{
return traits_type::max_size(*this);
}
template <typename ...Args>
void construct(pointer p, Args&&... args)
{
traits_type::construct(*this, p, std::forward<Args>(args)...);
}
void destroy(pointer p)
{
traits_type::destroy(*this, p);
}
#else // !RAPIDJSON_HAS_CXX11
typedef typename allocator_type::reference reference;
typedef typename allocator_type::const_reference const_reference;
pointer address(reference r) const RAPIDJSON_NOEXCEPT
{
return allocator_type::address(r);
}
const_pointer address(const_reference r) const RAPIDJSON_NOEXCEPT
{
return allocator_type::address(r);
}
size_type max_size() const RAPIDJSON_NOEXCEPT
{
return allocator_type::max_size();
}
void construct(pointer p, const_reference r)
{
allocator_type::construct(p, r);
}
void destroy(pointer p)
{
allocator_type::destroy(p);
}
#endif // !RAPIDJSON_HAS_CXX11
template <typename U>
U* allocate(size_type n = 1, const void* = 0)
{
return RAPIDJSON_NAMESPACE::Malloc<U>(baseAllocator_, n);
}
template <typename U>
void deallocate(U* p, size_type n = 1)
{
RAPIDJSON_NAMESPACE::Free<U>(baseAllocator_, p, n);
}
pointer allocate(size_type n = 1, const void* = 0)
{
return allocate<value_type>(n);
}
void deallocate(pointer p, size_type n = 1)
{
deallocate<value_type>(p, n);
}
#if RAPIDJSON_HAS_CXX11
using is_always_equal = std::is_empty<BaseAllocator>;
#endif
template<typename U>
bool operator==(const StdAllocator<U, BaseAllocator>& rhs) const RAPIDJSON_NOEXCEPT
{
return baseAllocator_ == rhs.baseAllocator_;
}
template<typename U>
bool operator!=(const StdAllocator<U, BaseAllocator>& rhs) const RAPIDJSON_NOEXCEPT
{
return !operator==(rhs);
}
//! rapidjson Allocator concept
static const bool kNeedFree = BaseAllocator::kNeedFree;
static const bool kRefCounted = internal::IsRefCounted<BaseAllocator>::Value;
void* Malloc(size_t size)
{
return baseAllocator_.Malloc(size);
}
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize)
{
return baseAllocator_.Realloc(originalPtr, originalSize, newSize);
}
static void Free(void *ptr) RAPIDJSON_NOEXCEPT
{
BaseAllocator::Free(ptr);
}
private:
template <typename, typename>
friend class StdAllocator; // access to StdAllocator<!T>.*
BaseAllocator baseAllocator_;
};
#if !RAPIDJSON_HAS_CXX17 // std::allocator<void> deprecated in C++17
template <typename BaseAllocator>
class StdAllocator<void, BaseAllocator> :
public std::allocator<void>
{
typedef std::allocator<void> allocator_type;
public:
typedef BaseAllocator BaseAllocatorType;
StdAllocator() RAPIDJSON_NOEXCEPT :
allocator_type(),
baseAllocator_()
{ }
StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT :
allocator_type(rhs),
baseAllocator_(rhs.baseAllocator_)
{ }
template<typename U>
StdAllocator(const StdAllocator<U, BaseAllocator>& rhs) RAPIDJSON_NOEXCEPT :
allocator_type(rhs),
baseAllocator_(rhs.baseAllocator_)
{ }
/* implicit */
StdAllocator(const BaseAllocator& baseAllocator) RAPIDJSON_NOEXCEPT :
allocator_type(),
baseAllocator_(baseAllocator)
{ }
~StdAllocator() RAPIDJSON_NOEXCEPT
{ }
template<typename U>
struct rebind {
typedef StdAllocator<U, BaseAllocator> other;
};
typedef typename allocator_type::value_type value_type;
private:
template <typename, typename>
friend class StdAllocator; // access to StdAllocator<!T>.*
BaseAllocator baseAllocator_;
};
#endif
#ifdef __GNUC__
RAPIDJSON_DIAG_POP
#endif
RAPIDJSON_NAMESPACE_END
#endif // RAPIDJSON_ENCODINGS_H_
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#ifndef RAPIDJSON_CURSORSTREAMWRAPPER_H_
#define RAPIDJSON_CURSORSTREAMWRAPPER_H_
#include "stream.h"
#if defined(__GNUC__)
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++)
#endif
#if defined(_MSC_VER) && _MSC_VER <= 1800
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(4702) // unreachable code
RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
#endif
RAPIDJSON_NAMESPACE_BEGIN
//! Cursor stream wrapper for counting line and column number if error exists.
/*!
\tparam InputStream Any stream that implements Stream Concept
*/
template <typename InputStream, typename Encoding = UTF8<> >
class CursorStreamWrapper : public GenericStreamWrapper<InputStream, Encoding> {
public:
typedef typename Encoding::Ch Ch;
CursorStreamWrapper(InputStream& is):
GenericStreamWrapper<InputStream, Encoding>(is), line_(1), col_(0) {}
// counting line and column number
Ch Take() {
Ch ch = this->is_.Take();
if(ch == '\n') {
line_ ++;
col_ = 0;
} else {
col_ ++;
}
return ch;
}
//! Get the error line number, if error exists.
size_t GetLine() const { return line_; }
//! Get the error column number, if error exists.
size_t GetColumn() const { return col_; }
private:
size_t line_; //!< Current Line
size_t col_; //!< Current Column
};
#if defined(_MSC_VER) && _MSC_VER <= 1800
RAPIDJSON_DIAG_POP
#endif
#if defined(__GNUC__)
RAPIDJSON_DIAG_POP
#endif
RAPIDJSON_NAMESPACE_END
#endif // RAPIDJSON_CURSORSTREAMWRAPPER_H_
Source diff could not be displayed: it is too large. Options to address this: view the blob.
// Copyright (C) 2011 Milo Yip // Tencent is pleased to support the open source community by making RapidJSON available.
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
// of this software and associated documentation files (the "Software"), to deal //
// in the Software without restriction, including without limitation the rights // Licensed under the MIT License (the "License"); you may not use this file except
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // in compliance with the License. You may obtain a copy of the License at
// copies of the Software, and to permit persons to whom the Software is //
// furnished to do so, subject to the following conditions: // http://opensource.org/licenses/MIT
// //
// The above copyright notice and this permission notice shall be included in // Unless required by applicable law or agreed to in writing, software distributed
// all copies or substantial portions of the Software. // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// // CONDITIONS OF ANY KIND, either express or implied. See the License for the
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // specific language governing permissions and limitations under the License.
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE #ifndef RAPIDJSON_ENCODEDSTREAM_H_
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #define RAPIDJSON_ENCODEDSTREAM_H_
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN #include "stream.h"
// THE SOFTWARE. #include "memorystream.h"
#ifndef RAPIDJSON_ENCODEDSTREAM_H_ #ifdef __GNUC__
#define RAPIDJSON_ENCODEDSTREAM_H_ RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++)
#include "rapidjson.h" #endif
#ifdef __GNUC__ #ifdef __clang__
RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++) RAPIDJSON_DIAG_OFF(padded)
#endif #endif
RAPIDJSON_NAMESPACE_BEGIN RAPIDJSON_NAMESPACE_BEGIN
//! Input byte stream wrapper with a statically bound encoding. //! Input byte stream wrapper with a statically bound encoding.
/*! /*!
\tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE. \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE.
\tparam InputByteStream Type of input byte stream. For example, FileReadStream. \tparam InputByteStream Type of input byte stream. For example, FileReadStream.
*/ */
template <typename Encoding, typename InputByteStream> template <typename Encoding, typename InputByteStream>
class EncodedInputStream { class EncodedInputStream {
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
public: public:
typedef typename Encoding::Ch Ch; typedef typename Encoding::Ch Ch;
EncodedInputStream(InputByteStream& is) : is_(is) { EncodedInputStream(InputByteStream& is) : is_(is) {
current_ = Encoding::TakeBOM(is_); current_ = Encoding::TakeBOM(is_);
} }
Ch Peek() const { return current_; } Ch Peek() const { return current_; }
Ch Take() { Ch c = current_; current_ = Encoding::Take(is_); return c; } Ch Take() { Ch c = current_; current_ = Encoding::Take(is_); return c; }
size_t Tell() const { return is_.Tell(); } size_t Tell() const { return is_.Tell(); }
// Not implemented // Not implemented
void Put(Ch) { RAPIDJSON_ASSERT(false); } void Put(Ch) { RAPIDJSON_ASSERT(false); }
void Flush() { RAPIDJSON_ASSERT(false); } void Flush() { RAPIDJSON_ASSERT(false); }
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
private: private:
EncodedInputStream(const EncodedInputStream&); EncodedInputStream(const EncodedInputStream&);
EncodedInputStream& operator=(const EncodedInputStream&); EncodedInputStream& operator=(const EncodedInputStream&);
InputByteStream& is_; InputByteStream& is_;
Ch current_; Ch current_;
}; };
//! Output byte stream wrapper with statically bound encoding. //! Specialized for UTF8 MemoryStream.
/*! template <>
\tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE. class EncodedInputStream<UTF8<>, MemoryStream> {
\tparam InputByteStream Type of input byte stream. For example, FileWriteStream. public:
*/ typedef UTF8<>::Ch Ch;
template <typename Encoding, typename OutputByteStream>
class EncodedOutputStream { EncodedInputStream(MemoryStream& is) : is_(is) {
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); if (static_cast<unsigned char>(is_.Peek()) == 0xEFu) is_.Take();
public: if (static_cast<unsigned char>(is_.Peek()) == 0xBBu) is_.Take();
typedef typename Encoding::Ch Ch; if (static_cast<unsigned char>(is_.Peek()) == 0xBFu) is_.Take();
}
EncodedOutputStream(OutputByteStream& os, bool putBOM = true) : os_(os) { Ch Peek() const { return is_.Peek(); }
if (putBOM) Ch Take() { return is_.Take(); }
Encoding::PutBOM(os_); size_t Tell() const { return is_.Tell(); }
}
// Not implemented
void Put(Ch c) { Encoding::Put(os_, c); } void Put(Ch) {}
void Flush() { os_.Flush(); } void Flush() {}
Ch* PutBegin() { return 0; }
// Not implemented size_t PutEnd(Ch*) { return 0; }
Ch Peek() const { RAPIDJSON_ASSERT(false); }
Ch Take() { RAPIDJSON_ASSERT(false); } MemoryStream& is_;
size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } private:
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } EncodedInputStream(const EncodedInputStream&);
EncodedInputStream& operator=(const EncodedInputStream&);
private: };
EncodedOutputStream(const EncodedOutputStream&);
EncodedOutputStream& operator=(const EncodedOutputStream&); //! Output byte stream wrapper with statically bound encoding.
/*!
OutputByteStream& os_; \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE.
}; \tparam OutputByteStream Type of input byte stream. For example, FileWriteStream.
*/
#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x template <typename Encoding, typename OutputByteStream>
class EncodedOutputStream {
//! Input stream wrapper with dynamically bound encoding and automatic encoding detection. RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
/*! public:
\tparam CharType Type of character for reading. typedef typename Encoding::Ch Ch;
\tparam InputByteStream type of input byte stream to be wrapped.
*/ EncodedOutputStream(OutputByteStream& os, bool putBOM = true) : os_(os) {
template <typename CharType, typename InputByteStream> if (putBOM)
class AutoUTFInputStream { Encoding::PutBOM(os_);
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); }
public:
typedef CharType Ch; void Put(Ch c) { Encoding::Put(os_, c); }
void Flush() { os_.Flush(); }
//! Constructor.
/*! // Not implemented
\param is input stream to be wrapped. Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;}
\param type UTF encoding type if it is not detected from the stream. Ch Take() { RAPIDJSON_ASSERT(false); return 0;}
*/ size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
AutoUTFInputStream(InputByteStream& is, UTFType type = kUTF8) : is_(&is), type_(type), hasBOM_(false) { Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
DetectType(); size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
static const TakeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Take) };
takeFunc_ = f[type_]; private:
current_ = takeFunc_(*is_); EncodedOutputStream(const EncodedOutputStream&);
} EncodedOutputStream& operator=(const EncodedOutputStream&);
UTFType GetType() const { return type_; } OutputByteStream& os_;
bool HasBOM() const { return hasBOM_; } };
Ch Peek() const { return current_; } #define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
Ch Take() { Ch c = current_; current_ = takeFunc_(*is_); return c; }
size_t Tell() const { return is_->Tell(); } //! Input stream wrapper with dynamically bound encoding and automatic encoding detection.
/*!
// Not implemented \tparam CharType Type of character for reading.
void Put(Ch) { RAPIDJSON_ASSERT(false); } \tparam InputByteStream type of input byte stream to be wrapped.
void Flush() { RAPIDJSON_ASSERT(false); } */
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } template <typename CharType, typename InputByteStream>
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } class AutoUTFInputStream {
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
private: public:
AutoUTFInputStream(const AutoUTFInputStream&); typedef CharType Ch;
AutoUTFInputStream& operator=(const AutoUTFInputStream&);
//! Constructor.
// Detect encoding type with BOM or RFC 4627 /*!
void DetectType() { \param is input stream to be wrapped.
// BOM (Byte Order Mark): \param type UTF encoding type if it is not detected from the stream.
// 00 00 FE FF UTF-32BE */
// FF FE 00 00 UTF-32LE AutoUTFInputStream(InputByteStream& is, UTFType type = kUTF8) : is_(&is), type_(type), hasBOM_(false) {
// FE FF UTF-16BE RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE);
// FF FE UTF-16LE DetectType();
// EF BB BF UTF-8 static const TakeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Take) };
takeFunc_ = f[type_];
const unsigned char* c = (const unsigned char *)is_->Peek4(); current_ = takeFunc_(*is_);
if (!c) }
return;
UTFType GetType() const { return type_; }
unsigned bom = c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24); bool HasBOM() const { return hasBOM_; }
hasBOM_ = false;
if (bom == 0xFFFE0000) { type_ = kUTF32BE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); } Ch Peek() const { return current_; }
else if (bom == 0x0000FEFF) { type_ = kUTF32LE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); } Ch Take() { Ch c = current_; current_ = takeFunc_(*is_); return c; }
else if ((bom & 0xFFFF) == 0xFFFE) { type_ = kUTF16BE; hasBOM_ = true; is_->Take(); is_->Take(); } size_t Tell() const { return is_->Tell(); }
else if ((bom & 0xFFFF) == 0xFEFF) { type_ = kUTF16LE; hasBOM_ = true; is_->Take(); is_->Take(); }
else if ((bom & 0xFFFFFF) == 0xBFBBEF) { type_ = kUTF8; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); } // Not implemented
void Put(Ch) { RAPIDJSON_ASSERT(false); }
// RFC 4627: Section 3 void Flush() { RAPIDJSON_ASSERT(false); }
// "Since the first two characters of a JSON text will always be ASCII Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
// characters [RFC0020], it is possible to determine whether an octet size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
// stream is UTF-8, UTF-16 (BE or LE), or UTF-32 (BE or LE) by looking
// at the pattern of nulls in the first four octets." private:
// 00 00 00 xx UTF-32BE AutoUTFInputStream(const AutoUTFInputStream&);
// 00 xx 00 xx UTF-16BE AutoUTFInputStream& operator=(const AutoUTFInputStream&);
// xx 00 00 00 UTF-32LE
// xx 00 xx 00 UTF-16LE // Detect encoding type with BOM or RFC 4627
// xx xx xx xx UTF-8 void DetectType() {
// BOM (Byte Order Mark):
if (!hasBOM_) { // 00 00 FE FF UTF-32BE
unsigned pattern = (c[0] ? 1 : 0) | (c[1] ? 2 : 0) | (c[2] ? 4 : 0) | (c[3] ? 8 : 0); // FF FE 00 00 UTF-32LE
switch (pattern) { // FE FF UTF-16BE
case 0x08: type_ = kUTF32BE; break; // FF FE UTF-16LE
case 0x0A: type_ = kUTF16BE; break; // EF BB BF UTF-8
case 0x01: type_ = kUTF32LE; break;
case 0x05: type_ = kUTF16LE; break; const unsigned char* c = reinterpret_cast<const unsigned char *>(is_->Peek4());
case 0x0F: type_ = kUTF8; break; if (!c)
default: break; // Use type defined by user. return;
}
} unsigned bom = static_cast<unsigned>(c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24));
hasBOM_ = false;
// Runtime check whether the size of character type is sufficient. It only perform checks with assertion. if (bom == 0xFFFE0000) { type_ = kUTF32BE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }
switch (type_) { else if (bom == 0x0000FEFF) { type_ = kUTF32LE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }
case kUTF8: else if ((bom & 0xFFFF) == 0xFFFE) { type_ = kUTF16BE; hasBOM_ = true; is_->Take(); is_->Take(); }
// Do nothing else if ((bom & 0xFFFF) == 0xFEFF) { type_ = kUTF16LE; hasBOM_ = true; is_->Take(); is_->Take(); }
break; else if ((bom & 0xFFFFFF) == 0xBFBBEF) { type_ = kUTF8; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); }
case kUTF16LE:
case kUTF16BE: // RFC 4627: Section 3
RAPIDJSON_ASSERT(sizeof(Ch) >= 2); // "Since the first two characters of a JSON text will always be ASCII
break; // characters [RFC0020], it is possible to determine whether an octet
case kUTF32LE: // stream is UTF-8, UTF-16 (BE or LE), or UTF-32 (BE or LE) by looking
case kUTF32BE: // at the pattern of nulls in the first four octets."
RAPIDJSON_ASSERT(sizeof(Ch) >= 4); // 00 00 00 xx UTF-32BE
break; // 00 xx 00 xx UTF-16BE
default: // xx 00 00 00 UTF-32LE
RAPIDJSON_ASSERT(false); // Invalid type // xx 00 xx 00 UTF-16LE
} // xx xx xx xx UTF-8
}
if (!hasBOM_) {
typedef Ch (*TakeFunc)(InputByteStream& is); int pattern = (c[0] ? 1 : 0) | (c[1] ? 2 : 0) | (c[2] ? 4 : 0) | (c[3] ? 8 : 0);
InputByteStream* is_; switch (pattern) {
UTFType type_; case 0x08: type_ = kUTF32BE; break;
Ch current_; case 0x0A: type_ = kUTF16BE; break;
TakeFunc takeFunc_; case 0x01: type_ = kUTF32LE; break;
bool hasBOM_; case 0x05: type_ = kUTF16LE; break;
}; case 0x0F: type_ = kUTF8; break;
default: break; // Use type defined by user.
//! Output stream wrapper with dynamically bound encoding and automatic encoding detection. }
/*! }
\tparam CharType Type of character for writing.
\tparam InputByteStream type of output byte stream to be wrapped. // Runtime check whether the size of character type is sufficient. It only perform checks with assertion.
*/ if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
template <typename CharType, typename OutputByteStream> if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
class AutoUTFOutputStream { }
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
public: typedef Ch (*TakeFunc)(InputByteStream& is);
typedef CharType Ch; InputByteStream* is_;
UTFType type_;
//! Constructor. Ch current_;
/*! TakeFunc takeFunc_;
\param os output stream to be wrapped. bool hasBOM_;
\param type UTF encoding type. };
\param putBOM Whether to write BOM at the beginning of the stream.
*/ //! Output stream wrapper with dynamically bound encoding and automatic encoding detection.
AutoUTFOutputStream(OutputByteStream& os, UTFType type, bool putBOM) : os_(&os), type_(type) { /*!
// RUntime check whether the size of character type is sufficient. It only perform checks with assertion. \tparam CharType Type of character for writing.
switch (type_) { \tparam OutputByteStream type of output byte stream to be wrapped.
case kUTF16LE: */
case kUTF16BE: template <typename CharType, typename OutputByteStream>
RAPIDJSON_ASSERT(sizeof(Ch) >= 2); class AutoUTFOutputStream {
break; RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
case kUTF32LE: public:
case kUTF32BE: typedef CharType Ch;
RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
break; //! Constructor.
case kUTF8: /*!
// Do nothing \param os output stream to be wrapped.
break; \param type UTF encoding type.
default: \param putBOM Whether to write BOM at the beginning of the stream.
RAPIDJSON_ASSERT(false); // Invalid UTFType */
} AutoUTFOutputStream(OutputByteStream& os, UTFType type, bool putBOM) : os_(&os), type_(type) {
RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE);
static const PutFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Put) };
putFunc_ = f[type_]; // Runtime check whether the size of character type is sufficient. It only perform checks with assertion.
if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
if (putBOM) if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
PutBOM();
} static const PutFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Put) };
putFunc_ = f[type_];
UTFType GetType() const { return type_; }
if (putBOM)
void Put(Ch c) { putFunc_(*os_, c); } PutBOM();
void Flush() { os_->Flush(); } }
// Not implemented UTFType GetType() const { return type_; }
Ch Peek() const { RAPIDJSON_ASSERT(false); }
Ch Take() { RAPIDJSON_ASSERT(false); } void Put(Ch c) { putFunc_(*os_, c); }
size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } void Flush() { os_->Flush(); }
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } // Not implemented
Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;}
private: Ch Take() { RAPIDJSON_ASSERT(false); return 0;}
AutoUTFOutputStream(const AutoUTFOutputStream&); size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
AutoUTFOutputStream& operator=(const AutoUTFOutputStream&); Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
void PutBOM() {
typedef void (*PutBOMFunc)(OutputByteStream&); private:
static const PutBOMFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(PutBOM) }; AutoUTFOutputStream(const AutoUTFOutputStream&);
f[type_](*os_); AutoUTFOutputStream& operator=(const AutoUTFOutputStream&);
}
void PutBOM() {
typedef void (*PutFunc)(OutputByteStream&, Ch); typedef void (*PutBOMFunc)(OutputByteStream&);
static const PutBOMFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(PutBOM) };
OutputByteStream* os_; f[type_](*os_);
UTFType type_; }
PutFunc putFunc_;
}; typedef void (*PutFunc)(OutputByteStream&, Ch);
#undef RAPIDJSON_ENCODINGS_FUNC OutputByteStream* os_;
UTFType type_;
RAPIDJSON_NAMESPACE_END PutFunc putFunc_;
};
#ifdef __GNUC__
RAPIDJSON_DIAG_POP #undef RAPIDJSON_ENCODINGS_FUNC
#endif
RAPIDJSON_NAMESPACE_END
#endif // RAPIDJSON_FILESTREAM_H_
#ifdef __clang__
RAPIDJSON_DIAG_POP
#endif
#ifdef __GNUC__
RAPIDJSON_DIAG_POP
#endif
#endif // RAPIDJSON_FILESTREAM_H_
// Copyright (C) 2011 Milo Yip // Tencent is pleased to support the open source community by making RapidJSON available.
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
// of this software and associated documentation files (the "Software"), to deal //
// in the Software without restriction, including without limitation the rights // Licensed under the MIT License (the "License"); you may not use this file except
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // in compliance with the License. You may obtain a copy of the License at
// copies of the Software, and to permit persons to whom the Software is //
// furnished to do so, subject to the following conditions: // http://opensource.org/licenses/MIT
// //
// The above copyright notice and this permission notice shall be included in // Unless required by applicable law or agreed to in writing, software distributed
// all copies or substantial portions of the Software. // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// // CONDITIONS OF ANY KIND, either express or implied. See the License for the
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // specific language governing permissions and limitations under the License.
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE #ifndef RAPIDJSON_ENCODINGS_H_
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #define RAPIDJSON_ENCODINGS_H_
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN #include "rapidjson.h"
// THE SOFTWARE.
#if defined(_MSC_VER) && !defined(__clang__)
#ifndef RAPIDJSON_ENCODINGS_H_ RAPIDJSON_DIAG_PUSH
#define RAPIDJSON_ENCODINGS_H_ RAPIDJSON_DIAG_OFF(4244) // conversion from 'type1' to 'type2', possible loss of data
RAPIDJSON_DIAG_OFF(4702) // unreachable code
#include "rapidjson.h" #elif defined(__GNUC__)
RAPIDJSON_DIAG_PUSH
#ifdef _MSC_VER RAPIDJSON_DIAG_OFF(effc++)
RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_OFF(overflow)
RAPIDJSON_DIAG_OFF(4244) // conversion from 'type1' to 'type2', possible loss of data #endif
RAPIDJSON_DIAG_OFF(4702) // unreachable code
#elif defined(__GNUC__) RAPIDJSON_NAMESPACE_BEGIN
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++) ///////////////////////////////////////////////////////////////////////////////
#endif // Encoding
RAPIDJSON_NAMESPACE_BEGIN /*! \class rapidjson::Encoding
\brief Concept for encoding of Unicode characters.
///////////////////////////////////////////////////////////////////////////////
// Encoding \code
concept Encoding {
/*! \class rapidjson::Encoding typename Ch; //! Type of character. A "character" is actually a code unit in unicode's definition.
\brief Concept for encoding of Unicode characters.
enum { supportUnicode = 1 }; // or 0 if not supporting unicode
\code
concept Encoding { //! \brief Encode a Unicode codepoint to an output stream.
typename Ch; //! Type of character. A "character" is actually a code unit in unicode's definition. //! \param os Output stream.
//! \param codepoint An unicode codepoint, ranging from 0x0 to 0x10FFFF inclusively.
enum { supportUnicode = 1 }; // or 0 if not supporting unicode template<typename OutputStream>
static void Encode(OutputStream& os, unsigned codepoint);
//! \brief Encode a Unicode codepoint to an output stream.
//! \param os Output stream. //! \brief Decode a Unicode codepoint from an input stream.
//! \param codepoint An unicode codepoint, ranging from 0x0 to 0x10FFFF inclusively. //! \param is Input stream.
template<typename OutputStream> //! \param codepoint Output of the unicode codepoint.
static void Encode(OutputStream& os, unsigned codepoint); //! \return true if a valid codepoint can be decoded from the stream.
template <typename InputStream>
//! \brief Decode a Unicode codepoint from an input stream. static bool Decode(InputStream& is, unsigned* codepoint);
//! \param is Input stream.
//! \param codepoint Output of the unicode codepoint. //! \brief Validate one Unicode codepoint from an encoded stream.
//! \return true if a valid codepoint can be decoded from the stream. //! \param is Input stream to obtain codepoint.
template <typename InputStream> //! \param os Output for copying one codepoint.
static bool Decode(InputStream& is, unsigned* codepoint); //! \return true if it is valid.
//! \note This function just validating and copying the codepoint without actually decode it.
//! \brief Validate one Unicode codepoint from an encoded stream. template <typename InputStream, typename OutputStream>
//! \param is Input stream to obtain codepoint. static bool Validate(InputStream& is, OutputStream& os);
//! \param os Output for copying one codepoint.
//! \return true if it is valid. // The following functions are deal with byte streams.
//! \note This function just validating and copying the codepoint without actually decode it.
template <typename InputStream, typename OutputStream> //! Take a character from input byte stream, skip BOM if exist.
static bool Validate(InputStream& is, OutputStream& os); template <typename InputByteStream>
static CharType TakeBOM(InputByteStream& is);
// The following functions are deal with byte streams.
//! Take a character from input byte stream.
//! Take a character from input byte stream, skip BOM if exist. template <typename InputByteStream>
template <typename InputByteStream> static Ch Take(InputByteStream& is);
static CharType TakeBOM(InputByteStream& is);
//! Put BOM to output byte stream.
//! Take a character from input byte stream. template <typename OutputByteStream>
template <typename InputByteStream> static void PutBOM(OutputByteStream& os);
static Ch Take(InputByteStream& is);
//! Put a character to output byte stream.
//! Put BOM to output byte stream. template <typename OutputByteStream>
template <typename OutputByteStream> static void Put(OutputByteStream& os, Ch c);
static void PutBOM(OutputByteStream& os); };
\endcode
//! Put a character to output byte stream. */
template <typename OutputByteStream>
static void Put(OutputByteStream& os, Ch c); ///////////////////////////////////////////////////////////////////////////////
}; // UTF8
\endcode
*/ //! UTF-8 encoding.
/*! http://en.wikipedia.org/wiki/UTF-8
/////////////////////////////////////////////////////////////////////////////// http://tools.ietf.org/html/rfc3629
// UTF8 \tparam CharType Code unit for storing 8-bit UTF-8 data. Default is char.
\note implements Encoding concept
//! UTF-8 encoding. */
/*! http://en.wikipedia.org/wiki/UTF-8 template<typename CharType = char>
http://tools.ietf.org/html/rfc3629 struct UTF8 {
\tparam CharType Code unit for storing 8-bit UTF-8 data. Default is char. typedef CharType Ch;
\note implements Encoding concept
*/ enum { supportUnicode = 1 };
template<typename CharType = char>
struct UTF8 { template<typename OutputStream>
typedef CharType Ch; static void Encode(OutputStream& os, unsigned codepoint) {
if (codepoint <= 0x7F)
enum { supportUnicode = 1 }; os.Put(static_cast<Ch>(codepoint & 0xFF));
else if (codepoint <= 0x7FF) {
template<typename OutputStream> os.Put(static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF)));
static void Encode(OutputStream& os, unsigned codepoint) { os.Put(static_cast<Ch>(0x80 | ((codepoint & 0x3F))));
if (codepoint <= 0x7F) }
os.Put(static_cast<Ch>(codepoint & 0xFF)); else if (codepoint <= 0xFFFF) {
else if (codepoint <= 0x7FF) { os.Put(static_cast<Ch>(0xE0 | ((codepoint >> 12) & 0xFF)));
os.Put(static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF))); os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
os.Put(static_cast<Ch>(0x80 | ((codepoint & 0x3F)))); os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F)));
} }
else if (codepoint <= 0xFFFF) { else {
os.Put(static_cast<Ch>(0xE0 | ((codepoint >> 12) & 0xFF))); RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F))); os.Put(static_cast<Ch>(0xF0 | ((codepoint >> 18) & 0xFF)));
os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F))); os.Put(static_cast<Ch>(0x80 | ((codepoint >> 12) & 0x3F)));
} os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
else { os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F)));
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); }
os.Put(static_cast<Ch>(0xF0 | ((codepoint >> 18) & 0xFF))); }
os.Put(static_cast<Ch>(0x80 | ((codepoint >> 12) & 0x3F)));
os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F))); template<typename OutputStream>
os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F))); static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
} if (codepoint <= 0x7F)
} PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF));
else if (codepoint <= 0x7FF) {
template <typename InputStream> PutUnsafe(os, static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF)));
static bool Decode(InputStream& is, unsigned* codepoint) { PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint & 0x3F))));
#define COPY() c = is.Take(); *codepoint = (*codepoint << 6) | ((unsigned char)c & 0x3Fu) }
#define TRANS(mask) result &= ((GetRange((unsigned char)c) & mask) != 0) else if (codepoint <= 0xFFFF) {
#define TAIL() COPY(); TRANS(0x70) PutUnsafe(os, static_cast<Ch>(0xE0 | ((codepoint >> 12) & 0xFF)));
Ch c = is.Take(); PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
if (!(c & 0x80)) { PutUnsafe(os, static_cast<Ch>(0x80 | (codepoint & 0x3F)));
*codepoint = (unsigned char)c; }
return true; else {
} RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
PutUnsafe(os, static_cast<Ch>(0xF0 | ((codepoint >> 18) & 0xFF)));
unsigned char type = GetRange((unsigned char)c); PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 12) & 0x3F)));
*codepoint = (0xFF >> type) & (unsigned char)c; PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
bool result = true; PutUnsafe(os, static_cast<Ch>(0x80 | (codepoint & 0x3F)));
switch (type) { }
case 2: TAIL(); return result; }
case 3: TAIL(); TAIL(); return result;
case 4: COPY(); TRANS(0x50); TAIL(); return result; template <typename InputStream>
case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result; static bool Decode(InputStream& is, unsigned* codepoint) {
case 6: TAIL(); TAIL(); TAIL(); return result; #define RAPIDJSON_COPY() c = is.Take(); *codepoint = (*codepoint << 6) | (static_cast<unsigned char>(c) & 0x3Fu)
case 10: COPY(); TRANS(0x20); TAIL(); return result; #define RAPIDJSON_TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result; #define RAPIDJSON_TAIL() RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x70)
default: return false; typename InputStream::Ch c = is.Take();
} if (!(c & 0x80)) {
#undef COPY *codepoint = static_cast<unsigned char>(c);
#undef TRANS return true;
#undef TAIL }
}
unsigned char type = GetRange(static_cast<unsigned char>(c));
template <typename InputStream, typename OutputStream> if (type >= 32) {
static bool Validate(InputStream& is, OutputStream& os) { *codepoint = 0;
#define COPY() os.Put(c = is.Take()) } else {
#define TRANS(mask) result &= ((GetRange((unsigned char)c) & mask) != 0) *codepoint = (0xFFu >> type) & static_cast<unsigned char>(c);
#define TAIL() COPY(); TRANS(0x70) }
Ch c; bool result = true;
COPY(); switch (type) {
if (!(c & 0x80)) case 2: RAPIDJSON_TAIL(); return result;
return true; case 3: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
case 4: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x50); RAPIDJSON_TAIL(); return result;
bool result = true; case 5: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x10); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
switch (GetRange((unsigned char)c)) { case 6: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
case 2: TAIL(); return result; case 10: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x20); RAPIDJSON_TAIL(); return result;
case 3: TAIL(); TAIL(); return result; case 11: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x60); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
case 4: COPY(); TRANS(0x50); TAIL(); return result; default: return false;
case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result; }
case 6: TAIL(); TAIL(); TAIL(); return result; #undef RAPIDJSON_COPY
case 10: COPY(); TRANS(0x20); TAIL(); return result; #undef RAPIDJSON_TRANS
case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result; #undef RAPIDJSON_TAIL
default: return false; }
}
#undef COPY template <typename InputStream, typename OutputStream>
#undef TRANS static bool Validate(InputStream& is, OutputStream& os) {
#undef TAIL #define RAPIDJSON_COPY() os.Put(c = is.Take())
} #define RAPIDJSON_TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
#define RAPIDJSON_TAIL() RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x70)
static unsigned char GetRange(unsigned char c) { Ch c;
// Referring to DFA of http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ RAPIDJSON_COPY();
// With new mapping 1 -> 0x10, 7 -> 0x20, 9 -> 0x40, such that AND operation can test multiple types. if (!(c & 0x80))
static const unsigned char type[] = { return true;
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, bool result = true;
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, switch (GetRange(static_cast<unsigned char>(c))) {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, case 2: RAPIDJSON_TAIL(); return result;
0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, case 3: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, case 4: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x50); RAPIDJSON_TAIL(); return result;
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, case 5: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x10); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, case 6: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, case 10: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x20); RAPIDJSON_TAIL(); return result;
10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8, case 11: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x60); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
}; default: return false;
return type[c]; }
} #undef RAPIDJSON_COPY
#undef RAPIDJSON_TRANS
template <typename InputByteStream> #undef RAPIDJSON_TAIL
static CharType TakeBOM(InputByteStream& is) { }
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
Ch c = Take(is); static unsigned char GetRange(unsigned char c) {
if ((unsigned char)c != 0xEFu) return c; // Referring to DFA of http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
c = is.Take(); // With new mapping 1 -> 0x10, 7 -> 0x20, 9 -> 0x40, such that AND operation can test multiple types.
if ((unsigned char)c != 0xBBu) return c; static const unsigned char type[] = {
c = is.Take(); 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
if ((unsigned char)c != 0xBFu) return c; 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
c = is.Take(); 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
return c; 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
} 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
template <typename InputByteStream> 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
static Ch Take(InputByteStream& is) { 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
return is.Take(); 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8,
} };
return type[c];
template <typename OutputByteStream> }
static void PutBOM(OutputByteStream& os) {
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); template <typename InputByteStream>
os.Put(0xEFu); os.Put(0xBBu); os.Put(0xBFu); static CharType TakeBOM(InputByteStream& is) {
} RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
typename InputByteStream::Ch c = Take(is);
template <typename OutputByteStream> if (static_cast<unsigned char>(c) != 0xEFu) return c;
static void Put(OutputByteStream& os, Ch c) { c = is.Take();
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); if (static_cast<unsigned char>(c) != 0xBBu) return c;
os.Put(static_cast<typename OutputByteStream::Ch>(c)); c = is.Take();
} if (static_cast<unsigned char>(c) != 0xBFu) return c;
}; c = is.Take();
return c;
/////////////////////////////////////////////////////////////////////////////// }
// UTF16
template <typename InputByteStream>
//! UTF-16 encoding. static Ch Take(InputByteStream& is) {
/*! http://en.wikipedia.org/wiki/UTF-16 RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
http://tools.ietf.org/html/rfc2781 return static_cast<Ch>(is.Take());
\tparam CharType Type for storing 16-bit UTF-16 data. Default is wchar_t. C++11 may use char16_t instead. }
\note implements Encoding concept
template <typename OutputByteStream>
\note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness. static void PutBOM(OutputByteStream& os) {
For streaming, use UTF16LE and UTF16BE, which handle endianness. RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
*/ os.Put(static_cast<typename OutputByteStream::Ch>(0xEFu));
template<typename CharType = wchar_t> os.Put(static_cast<typename OutputByteStream::Ch>(0xBBu));
struct UTF16 { os.Put(static_cast<typename OutputByteStream::Ch>(0xBFu));
typedef CharType Ch; }
RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 2);
template <typename OutputByteStream>
enum { supportUnicode = 1 }; static void Put(OutputByteStream& os, Ch c) {
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
template<typename OutputStream> os.Put(static_cast<typename OutputByteStream::Ch>(c));
static void Encode(OutputStream& os, unsigned codepoint) { }
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2); };
if (codepoint <= 0xFFFF) {
RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair ///////////////////////////////////////////////////////////////////////////////
os.Put(static_cast<typename OutputStream::Ch>(codepoint)); // UTF16
}
else { //! UTF-16 encoding.
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); /*! http://en.wikipedia.org/wiki/UTF-16
unsigned v = codepoint - 0x10000; http://tools.ietf.org/html/rfc2781
os.Put(static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800)); \tparam CharType Type for storing 16-bit UTF-16 data. Default is wchar_t. C++11 may use char16_t instead.
os.Put((v & 0x3FF) | 0xDC00); \note implements Encoding concept
}
} \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness.
For streaming, use UTF16LE and UTF16BE, which handle endianness.
template <typename InputStream> */
static bool Decode(InputStream& is, unsigned* codepoint) { template<typename CharType = wchar_t>
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2); struct UTF16 {
Ch c = is.Take(); typedef CharType Ch;
if (c < 0xD800 || c > 0xDFFF) { RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 2);
*codepoint = c;
return true; enum { supportUnicode = 1 };
}
else if (c <= 0xDBFF) { template<typename OutputStream>
*codepoint = (c & 0x3FF) << 10; static void Encode(OutputStream& os, unsigned codepoint) {
c = is.Take(); RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
*codepoint |= (c & 0x3FF); if (codepoint <= 0xFFFF) {
*codepoint += 0x10000; RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair
return c >= 0xDC00 && c <= 0xDFFF; os.Put(static_cast<typename OutputStream::Ch>(codepoint));
} }
return false; else {
} RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
unsigned v = codepoint - 0x10000;
template <typename InputStream, typename OutputStream> os.Put(static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
static bool Validate(InputStream& is, OutputStream& os) { os.Put(static_cast<typename OutputStream::Ch>((v & 0x3FF) | 0xDC00));
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2); }
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2); }
Ch c;
os.Put(c = is.Take());
if (c < 0xD800 || c > 0xDFFF) template<typename OutputStream>
return true; static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
else if (c <= 0xDBFF) { RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
os.Put(c = is.Take()); if (codepoint <= 0xFFFF) {
return c >= 0xDC00 && c <= 0xDFFF; RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair
} PutUnsafe(os, static_cast<typename OutputStream::Ch>(codepoint));
return false; }
} else {
}; RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
unsigned v = codepoint - 0x10000;
//! UTF-16 little endian encoding. PutUnsafe(os, static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
template<typename CharType = wchar_t> PutUnsafe(os, static_cast<typename OutputStream::Ch>((v & 0x3FF) | 0xDC00));
struct UTF16LE : UTF16<CharType> { }
template <typename InputByteStream> }
static CharType TakeBOM(InputByteStream& is) {
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); template <typename InputStream>
CharType c = Take(is); static bool Decode(InputStream& is, unsigned* codepoint) {
return (unsigned short)c == 0xFEFFu ? Take(is) : c; RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
} typename InputStream::Ch c = is.Take();
if (c < 0xD800 || c > 0xDFFF) {
template <typename InputByteStream> *codepoint = static_cast<unsigned>(c);
static CharType Take(InputByteStream& is) { return true;
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); }
CharType c = (unsigned char)is.Take(); else if (c <= 0xDBFF) {
c |= (unsigned char)is.Take() << 8; *codepoint = (static_cast<unsigned>(c) & 0x3FF) << 10;
return c; c = is.Take();
} *codepoint |= (static_cast<unsigned>(c) & 0x3FF);
*codepoint += 0x10000;
template <typename OutputByteStream> return c >= 0xDC00 && c <= 0xDFFF;
static void PutBOM(OutputByteStream& os) { }
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); return false;
os.Put(0xFFu); os.Put(0xFEu); }
}
template <typename InputStream, typename OutputStream>
template <typename OutputByteStream> static bool Validate(InputStream& is, OutputStream& os) {
static void Put(OutputByteStream& os, CharType c) { RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
os.Put(c & 0xFFu); typename InputStream::Ch c;
os.Put((c >> 8) & 0xFFu); os.Put(static_cast<typename OutputStream::Ch>(c = is.Take()));
} if (c < 0xD800 || c > 0xDFFF)
}; return true;
else if (c <= 0xDBFF) {
//! UTF-16 big endian encoding. os.Put(c = is.Take());
template<typename CharType = wchar_t> return c >= 0xDC00 && c <= 0xDFFF;
struct UTF16BE : UTF16<CharType> { }
template <typename InputByteStream> return false;
static CharType TakeBOM(InputByteStream& is) { }
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); };
CharType c = Take(is);
return (unsigned short)c == 0xFEFFu ? Take(is) : c; //! UTF-16 little endian encoding.
} template<typename CharType = wchar_t>
struct UTF16LE : UTF16<CharType> {
template <typename InputByteStream> template <typename InputByteStream>
static CharType Take(InputByteStream& is) { static CharType TakeBOM(InputByteStream& is) {
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
CharType c = (unsigned char)is.Take() << 8; CharType c = Take(is);
c |= (unsigned char)is.Take(); return static_cast<uint16_t>(c) == 0xFEFFu ? Take(is) : c;
return c; }
}
template <typename InputByteStream>
template <typename OutputByteStream> static CharType Take(InputByteStream& is) {
static void PutBOM(OutputByteStream& os) { RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); unsigned c = static_cast<uint8_t>(is.Take());
os.Put(0xFEu); os.Put(0xFFu); c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
} return static_cast<CharType>(c);
}
template <typename OutputByteStream>
static void Put(OutputByteStream& os, CharType c) { template <typename OutputByteStream>
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); static void PutBOM(OutputByteStream& os) {
os.Put((c >> 8) & 0xFFu); RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
os.Put(c & 0xFFu); os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
} os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
}; }
/////////////////////////////////////////////////////////////////////////////// template <typename OutputByteStream>
// UTF32 static void Put(OutputByteStream& os, CharType c) {
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
//! UTF-32 encoding. os.Put(static_cast<typename OutputByteStream::Ch>(static_cast<unsigned>(c) & 0xFFu));
/*! http://en.wikipedia.org/wiki/UTF-32 os.Put(static_cast<typename OutputByteStream::Ch>((static_cast<unsigned>(c) >> 8) & 0xFFu));
\tparam CharType Type for storing 32-bit UTF-32 data. Default is unsigned. C++11 may use char32_t instead. }
\note implements Encoding concept };
\note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness. //! UTF-16 big endian encoding.
For streaming, use UTF32LE and UTF32BE, which handle endianness. template<typename CharType = wchar_t>
*/ struct UTF16BE : UTF16<CharType> {
template<typename CharType = unsigned> template <typename InputByteStream>
struct UTF32 { static CharType TakeBOM(InputByteStream& is) {
typedef CharType Ch; RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 4); CharType c = Take(is);
return static_cast<uint16_t>(c) == 0xFEFFu ? Take(is) : c;
enum { supportUnicode = 1 }; }
template<typename OutputStream> template <typename InputByteStream>
static void Encode(OutputStream& os, unsigned codepoint) { static CharType Take(InputByteStream& is) {
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4); RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
os.Put(codepoint); c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take()));
} return static_cast<CharType>(c);
}
template <typename InputStream>
static bool Decode(InputStream& is, unsigned* codepoint) { template <typename OutputByteStream>
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4); static void PutBOM(OutputByteStream& os) {
Ch c = is.Take(); RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
*codepoint = c; os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
return c <= 0x10FFFF; os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
} }
template <typename InputStream, typename OutputStream> template <typename OutputByteStream>
static bool Validate(InputStream& is, OutputStream& os) { static void Put(OutputByteStream& os, CharType c) {
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4); RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
Ch c; os.Put(static_cast<typename OutputByteStream::Ch>((static_cast<unsigned>(c) >> 8) & 0xFFu));
os.Put(c = is.Take()); os.Put(static_cast<typename OutputByteStream::Ch>(static_cast<unsigned>(c) & 0xFFu));
return c <= 0x10FFFF; }
} };
};
///////////////////////////////////////////////////////////////////////////////
//! UTF-32 little endian enocoding. // UTF32
template<typename CharType = unsigned>
struct UTF32LE : UTF32<CharType> { //! UTF-32 encoding.
template <typename InputByteStream> /*! http://en.wikipedia.org/wiki/UTF-32
static CharType TakeBOM(InputByteStream& is) { \tparam CharType Type for storing 32-bit UTF-32 data. Default is unsigned. C++11 may use char32_t instead.
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); \note implements Encoding concept
CharType c = Take(is);
return (unsigned)c == 0x0000FEFFu ? Take(is) : c; \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness.
} For streaming, use UTF32LE and UTF32BE, which handle endianness.
*/
template <typename InputByteStream> template<typename CharType = unsigned>
static CharType Take(InputByteStream& is) { struct UTF32 {
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); typedef CharType Ch;
CharType c = (unsigned char)is.Take(); RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 4);
c |= (unsigned char)is.Take() << 8;
c |= (unsigned char)is.Take() << 16; enum { supportUnicode = 1 };
c |= (unsigned char)is.Take() << 24;
return c; template<typename OutputStream>
} static void Encode(OutputStream& os, unsigned codepoint) {
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4);
template <typename OutputByteStream> RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
static void PutBOM(OutputByteStream& os) { os.Put(codepoint);
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); }
os.Put(0xFFu); os.Put(0xFEu); os.Put(0x00u); os.Put(0x00u);
} template<typename OutputStream>
static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
template <typename OutputByteStream> RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4);
static void Put(OutputByteStream& os, CharType c) { RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); PutUnsafe(os, codepoint);
os.Put(c & 0xFFu); }
os.Put((c >> 8) & 0xFFu);
os.Put((c >> 16) & 0xFFu); template <typename InputStream>
os.Put((c >> 24) & 0xFFu); static bool Decode(InputStream& is, unsigned* codepoint) {
} RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);
}; Ch c = is.Take();
*codepoint = c;
//! UTF-32 big endian encoding. return c <= 0x10FFFF;
template<typename CharType = unsigned> }
struct UTF32BE : UTF32<CharType> {
template <typename InputByteStream> template <typename InputStream, typename OutputStream>
static CharType TakeBOM(InputByteStream& is) { static bool Validate(InputStream& is, OutputStream& os) {
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);
CharType c = Take(is); Ch c;
return (unsigned)c == 0x0000FEFFu ? Take(is) : c; os.Put(c = is.Take());
} return c <= 0x10FFFF;
}
template <typename InputByteStream> };
static CharType Take(InputByteStream& is) {
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); //! UTF-32 little endian enocoding.
CharType c = (unsigned char)is.Take() << 24; template<typename CharType = unsigned>
c |= (unsigned char)is.Take() << 16; struct UTF32LE : UTF32<CharType> {
c |= (unsigned char)is.Take() << 8; template <typename InputByteStream>
c |= (unsigned char)is.Take(); static CharType TakeBOM(InputByteStream& is) {
return c; RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
} CharType c = Take(is);
return static_cast<uint32_t>(c) == 0x0000FEFFu ? Take(is) : c;
template <typename OutputByteStream> }
static void PutBOM(OutputByteStream& os) {
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); template <typename InputByteStream>
os.Put(0x00u); os.Put(0x00u); os.Put(0xFEu); os.Put(0xFFu); static CharType Take(InputByteStream& is) {
} RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
unsigned c = static_cast<uint8_t>(is.Take());
template <typename OutputByteStream> c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
static void Put(OutputByteStream& os, CharType c) { c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 16;
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 24;
os.Put((c >> 24) & 0xFFu); return static_cast<CharType>(c);
os.Put((c >> 16) & 0xFFu); }
os.Put((c >> 8) & 0xFFu);
os.Put(c & 0xFFu); template <typename OutputByteStream>
} static void PutBOM(OutputByteStream& os) {
}; RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
/////////////////////////////////////////////////////////////////////////////// os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
// ASCII os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
//! ASCII encoding. }
/*! http://en.wikipedia.org/wiki/ASCII
\tparam CharType Code unit for storing 7-bit ASCII data. Default is char. template <typename OutputByteStream>
\note implements Encoding concept static void Put(OutputByteStream& os, CharType c) {
*/ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
template<typename CharType = char> os.Put(static_cast<typename OutputByteStream::Ch>(c & 0xFFu));
struct ASCII { os.Put(static_cast<typename OutputByteStream::Ch>((c >> 8) & 0xFFu));
typedef CharType Ch; os.Put(static_cast<typename OutputByteStream::Ch>((c >> 16) & 0xFFu));
os.Put(static_cast<typename OutputByteStream::Ch>((c >> 24) & 0xFFu));
enum { supportUnicode = 0 }; }
};
template<typename OutputStream>
static void Encode(OutputStream& os, unsigned codepoint) { //! UTF-32 big endian encoding.
RAPIDJSON_ASSERT(codepoint <= 0x7F); template<typename CharType = unsigned>
os.Put(static_cast<Ch>(codepoint & 0xFF)); struct UTF32BE : UTF32<CharType> {
} template <typename InputByteStream>
static CharType TakeBOM(InputByteStream& is) {
template <typename InputStream> RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
static bool Decode(InputStream& is, unsigned* codepoint) { CharType c = Take(is);
unsigned char c = static_cast<unsigned char>(is.Take()); return static_cast<uint32_t>(c) == 0x0000FEFFu ? Take(is) : c;
*codepoint = c; }
return c <= 0X7F;
} template <typename InputByteStream>
static CharType Take(InputByteStream& is) {
template <typename InputStream, typename OutputStream> RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
static bool Validate(InputStream& is, OutputStream& os) { unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 24;
unsigned char c = is.Take(); c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 16;
os.Put(c); c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
return c <= 0x7F; c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take()));
} return static_cast<CharType>(c);
}
template <typename InputByteStream>
static CharType TakeBOM(InputByteStream& is) { template <typename OutputByteStream>
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); static void PutBOM(OutputByteStream& os) {
Ch c = Take(is); RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
return c; os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
} os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
template <typename InputByteStream> os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
static Ch Take(InputByteStream& is) { }
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
return is.Take(); template <typename OutputByteStream>
} static void Put(OutputByteStream& os, CharType c) {
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
template <typename OutputByteStream> os.Put(static_cast<typename OutputByteStream::Ch>((c >> 24) & 0xFFu));
static void PutBOM(OutputByteStream& os) { os.Put(static_cast<typename OutputByteStream::Ch>((c >> 16) & 0xFFu));
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); os.Put(static_cast<typename OutputByteStream::Ch>((c >> 8) & 0xFFu));
(void)os; os.Put(static_cast<typename OutputByteStream::Ch>(c & 0xFFu));
} }
};
template <typename OutputByteStream>
static void Put(OutputByteStream& os, Ch c) { ///////////////////////////////////////////////////////////////////////////////
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); // ASCII
os.Put(static_cast<typename OutputByteStream::Ch>(c));
} //! ASCII encoding.
}; /*! http://en.wikipedia.org/wiki/ASCII
\tparam CharType Code unit for storing 7-bit ASCII data. Default is char.
/////////////////////////////////////////////////////////////////////////////// \note implements Encoding concept
// AutoUTF */
template<typename CharType = char>
//! Runtime-specified UTF encoding type of a stream. struct ASCII {
enum UTFType { typedef CharType Ch;
kUTF8 = 0, //!< UTF-8.
kUTF16LE = 1, //!< UTF-16 little endian. enum { supportUnicode = 0 };
kUTF16BE = 2, //!< UTF-16 big endian.
kUTF32LE = 3, //!< UTF-32 little endian. template<typename OutputStream>
kUTF32BE = 4 //!< UTF-32 big endian. static void Encode(OutputStream& os, unsigned codepoint) {
}; RAPIDJSON_ASSERT(codepoint <= 0x7F);
os.Put(static_cast<Ch>(codepoint & 0xFF));
//! Dynamically select encoding according to stream's runtime-specified UTF encoding type. }
/*! \note This class can be used with AutoUTFInputtStream and AutoUTFOutputStream, which provides GetType().
*/ template<typename OutputStream>
template<typename CharType> static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
struct AutoUTF { RAPIDJSON_ASSERT(codepoint <= 0x7F);
typedef CharType Ch; PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF));
}
enum { supportUnicode = 1 };
template <typename InputStream>
#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x static bool Decode(InputStream& is, unsigned* codepoint) {
uint8_t c = static_cast<uint8_t>(is.Take());
template<typename OutputStream> *codepoint = c;
RAPIDJSON_FORCEINLINE static void Encode(OutputStream& os, unsigned codepoint) { return c <= 0X7F;
typedef void (*EncodeFunc)(OutputStream&, unsigned); }
static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Encode) };
(*f[os.GetType()])(os, codepoint); template <typename InputStream, typename OutputStream>
} static bool Validate(InputStream& is, OutputStream& os) {
uint8_t c = static_cast<uint8_t>(is.Take());
template <typename InputStream> os.Put(static_cast<typename OutputStream::Ch>(c));
RAPIDJSON_FORCEINLINE static bool Decode(InputStream& is, unsigned* codepoint) { return c <= 0x7F;
typedef bool (*DecodeFunc)(InputStream&, unsigned*); }
static const DecodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Decode) };
return (*f[is.GetType()])(is, codepoint); template <typename InputByteStream>
} static CharType TakeBOM(InputByteStream& is) {
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
template <typename InputStream, typename OutputStream> uint8_t c = static_cast<uint8_t>(Take(is));
RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) { return static_cast<Ch>(c);
typedef bool (*ValidateFunc)(InputStream&, OutputStream&); }
static const ValidateFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Validate) };
return (*f[is.GetType()])(is, os); template <typename InputByteStream>
} static Ch Take(InputByteStream& is) {
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
#undef RAPIDJSON_ENCODINGS_FUNC return static_cast<Ch>(is.Take());
}; }
/////////////////////////////////////////////////////////////////////////////// template <typename OutputByteStream>
// Transcoder static void PutBOM(OutputByteStream& os) {
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
//! Encoding conversion. (void)os;
template<typename SourceEncoding, typename TargetEncoding> }
struct Transcoder {
//! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream. template <typename OutputByteStream>
template<typename InputStream, typename OutputStream> static void Put(OutputByteStream& os, Ch c) {
RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) { RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
unsigned codepoint; os.Put(static_cast<typename OutputByteStream::Ch>(c));
if (!SourceEncoding::Decode(is, &codepoint)) }
return false; };
TargetEncoding::Encode(os, codepoint);
return true; ///////////////////////////////////////////////////////////////////////////////
} // AutoUTF
//! Validate one Unicode codepoint from an encoded stream. //! Runtime-specified UTF encoding type of a stream.
template<typename InputStream, typename OutputStream> enum UTFType {
RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) { kUTF8 = 0, //!< UTF-8.
return Transcode(is, os); // Since source/target encoding is different, must transcode. kUTF16LE = 1, //!< UTF-16 little endian.
} kUTF16BE = 2, //!< UTF-16 big endian.
}; kUTF32LE = 3, //!< UTF-32 little endian.
kUTF32BE = 4 //!< UTF-32 big endian.
//! Specialization of Transcoder with same source and target encoding. };
template<typename Encoding>
struct Transcoder<Encoding, Encoding> { //! Dynamically select encoding according to stream's runtime-specified UTF encoding type.
template<typename InputStream, typename OutputStream> /*! \note This class can be used with AutoUTFInputtStream and AutoUTFOutputStream, which provides GetType().
RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) { */
os.Put(is.Take()); // Just copy one code unit. This semantic is different from primary template class. template<typename CharType>
return true; struct AutoUTF {
} typedef CharType Ch;
template<typename InputStream, typename OutputStream> enum { supportUnicode = 1 };
RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
return Encoding::Validate(is, os); // source/target encoding are the same #define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
}
}; template<typename OutputStream>
static RAPIDJSON_FORCEINLINE void Encode(OutputStream& os, unsigned codepoint) {
RAPIDJSON_NAMESPACE_END typedef void (*EncodeFunc)(OutputStream&, unsigned);
static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Encode) };
#if defined(__GNUC__) || defined(_MSV_VER) (*f[os.GetType()])(os, codepoint);
RAPIDJSON_DIAG_POP }
#endif
template<typename OutputStream>
#endif // RAPIDJSON_ENCODINGS_H_ static RAPIDJSON_FORCEINLINE void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
typedef void (*EncodeFunc)(OutputStream&, unsigned);
static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(EncodeUnsafe) };
(*f[os.GetType()])(os, codepoint);
}
template <typename InputStream>
static RAPIDJSON_FORCEINLINE bool Decode(InputStream& is, unsigned* codepoint) {
typedef bool (*DecodeFunc)(InputStream&, unsigned*);
static const DecodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Decode) };
return (*f[is.GetType()])(is, codepoint);
}
template <typename InputStream, typename OutputStream>
static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) {
typedef bool (*ValidateFunc)(InputStream&, OutputStream&);
static const ValidateFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Validate) };
return (*f[is.GetType()])(is, os);
}
#undef RAPIDJSON_ENCODINGS_FUNC
};
///////////////////////////////////////////////////////////////////////////////
// Transcoder
//! Encoding conversion.
template<typename SourceEncoding, typename TargetEncoding>
struct Transcoder {
//! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream.
template<typename InputStream, typename OutputStream>
static RAPIDJSON_FORCEINLINE bool Transcode(InputStream& is, OutputStream& os) {
unsigned codepoint;
if (!SourceEncoding::Decode(is, &codepoint))
return false;
TargetEncoding::Encode(os, codepoint);
return true;
}
template<typename InputStream, typename OutputStream>
static RAPIDJSON_FORCEINLINE bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
unsigned codepoint;
if (!SourceEncoding::Decode(is, &codepoint))
return false;
TargetEncoding::EncodeUnsafe(os, codepoint);
return true;
}
//! Validate one Unicode codepoint from an encoded stream.
template<typename InputStream, typename OutputStream>
static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) {
return Transcode(is, os); // Since source/target encoding is different, must transcode.
}
};
// Forward declaration.
template<typename Stream>
inline void PutUnsafe(Stream& stream, typename Stream::Ch c);
//! Specialization of Transcoder with same source and target encoding.
template<typename Encoding>
struct Transcoder<Encoding, Encoding> {
template<typename InputStream, typename OutputStream>
static RAPIDJSON_FORCEINLINE bool Transcode(InputStream& is, OutputStream& os) {
os.Put(is.Take()); // Just copy one code unit. This semantic is different from primary template class.
return true;
}
template<typename InputStream, typename OutputStream>
static RAPIDJSON_FORCEINLINE bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
PutUnsafe(os, is.Take()); // Just copy one code unit. This semantic is different from primary template class.
return true;
}
template<typename InputStream, typename OutputStream>
static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) {
return Encoding::Validate(is, os); // source/target encoding are the same
}
};
RAPIDJSON_NAMESPACE_END
#if defined(__GNUC__) || (defined(_MSC_VER) && !defined(__clang__))
RAPIDJSON_DIAG_POP
#endif
#endif // RAPIDJSON_ENCODINGS_H_
// Copyright (C) 2011 Milo Yip // Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Licensed under the MIT License (the "License"); you may not use this file except
// of this software and associated documentation files (the "Software"), to deal // in compliance with the License. You may obtain a copy of the License at
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // http://opensource.org/licenses/MIT
// all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // Unless required by applicable law or agreed to in writing, software distributed
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // CONDITIONS OF ANY KIND, either express or implied. See the License for the
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // specific language governing permissions and limitations under the License.
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef RAPIDJSON_ERROR_EN_H__ #ifndef RAPIDJSON_ERROR_EN_H_
#define RAPIDJSON_ERROR_EN_H__ #define RAPIDJSON_ERROR_EN_H_
#include "error.h" #include "error.h"
#ifdef __clang__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(switch-enum)
RAPIDJSON_DIAG_OFF(covered-switch-default)
#endif
RAPIDJSON_NAMESPACE_BEGIN RAPIDJSON_NAMESPACE_BEGIN
//! Maps error code of parsing into error message. //! Maps error code of parsing into error message.
...@@ -38,7 +38,7 @@ inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErro ...@@ -38,7 +38,7 @@ inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErro
case kParseErrorNone: return RAPIDJSON_ERROR_STRING("No error."); case kParseErrorNone: return RAPIDJSON_ERROR_STRING("No error.");
case kParseErrorDocumentEmpty: return RAPIDJSON_ERROR_STRING("The document is empty."); case kParseErrorDocumentEmpty: return RAPIDJSON_ERROR_STRING("The document is empty.");
case kParseErrorDocumentRootNotSingular: return RAPIDJSON_ERROR_STRING("The document root must not follow by other values."); case kParseErrorDocumentRootNotSingular: return RAPIDJSON_ERROR_STRING("The document root must not be followed by other values.");
case kParseErrorValueInvalid: return RAPIDJSON_ERROR_STRING("Invalid value."); case kParseErrorValueInvalid: return RAPIDJSON_ERROR_STRING("Invalid value.");
...@@ -61,11 +61,62 @@ inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErro ...@@ -61,11 +61,62 @@ inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErro
case kParseErrorTermination: return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error."); case kParseErrorTermination: return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error.");
case kParseErrorUnspecificSyntaxError: return RAPIDJSON_ERROR_STRING("Unspecific syntax error."); case kParseErrorUnspecificSyntaxError: return RAPIDJSON_ERROR_STRING("Unspecific syntax error.");
default: default: return RAPIDJSON_ERROR_STRING("Unknown error.");
return RAPIDJSON_ERROR_STRING("Unknown error."); }
}
//! Maps error code of validation into error message.
/*!
\ingroup RAPIDJSON_ERRORS
\param validateErrorCode Error code obtained from validator.
\return the error message.
\note User can make a copy of this function for localization.
Using switch-case is safer for future modification of error codes.
*/
inline const RAPIDJSON_ERROR_CHARTYPE* GetValidateError_En(ValidateErrorCode validateErrorCode) {
switch (validateErrorCode) {
case kValidateErrors: return RAPIDJSON_ERROR_STRING("One or more validation errors have occurred");
case kValidateErrorNone: return RAPIDJSON_ERROR_STRING("No error.");
case kValidateErrorMultipleOf: return RAPIDJSON_ERROR_STRING("Number '%actual' is not a multiple of the 'multipleOf' value '%expected'.");
case kValidateErrorMaximum: return RAPIDJSON_ERROR_STRING("Number '%actual' is greater than the 'maximum' value '%expected'.");
case kValidateErrorExclusiveMaximum: return RAPIDJSON_ERROR_STRING("Number '%actual' is greater than or equal to the 'exclusiveMaximum' value '%expected'.");
case kValidateErrorMinimum: return RAPIDJSON_ERROR_STRING("Number '%actual' is less than the 'minimum' value '%expected'.");
case kValidateErrorExclusiveMinimum: return RAPIDJSON_ERROR_STRING("Number '%actual' is less than or equal to the 'exclusiveMinimum' value '%expected'.");
case kValidateErrorMaxLength: return RAPIDJSON_ERROR_STRING("String '%actual' is longer than the 'maxLength' value '%expected'.");
case kValidateErrorMinLength: return RAPIDJSON_ERROR_STRING("String '%actual' is shorter than the 'minLength' value '%expected'.");
case kValidateErrorPattern: return RAPIDJSON_ERROR_STRING("String '%actual' does not match the 'pattern' regular expression.");
case kValidateErrorMaxItems: return RAPIDJSON_ERROR_STRING("Array of length '%actual' is longer than the 'maxItems' value '%expected'.");
case kValidateErrorMinItems: return RAPIDJSON_ERROR_STRING("Array of length '%actual' is shorter than the 'minItems' value '%expected'.");
case kValidateErrorUniqueItems: return RAPIDJSON_ERROR_STRING("Array has duplicate items at indices '%duplicates' but 'uniqueItems' is true.");
case kValidateErrorAdditionalItems: return RAPIDJSON_ERROR_STRING("Array has an additional item at index '%disallowed' that is not allowed by the schema.");
case kValidateErrorMaxProperties: return RAPIDJSON_ERROR_STRING("Object has '%actual' members which is more than 'maxProperties' value '%expected'.");
case kValidateErrorMinProperties: return RAPIDJSON_ERROR_STRING("Object has '%actual' members which is less than 'minProperties' value '%expected'.");
case kValidateErrorRequired: return RAPIDJSON_ERROR_STRING("Object is missing the following members required by the schema: '%missing'.");
case kValidateErrorAdditionalProperties: return RAPIDJSON_ERROR_STRING("Object has an additional member '%disallowed' that is not allowed by the schema.");
case kValidateErrorPatternProperties: return RAPIDJSON_ERROR_STRING("Object has 'patternProperties' that are not allowed by the schema.");
case kValidateErrorDependencies: return RAPIDJSON_ERROR_STRING("Object has missing property or schema dependencies, refer to following errors.");
case kValidateErrorEnum: return RAPIDJSON_ERROR_STRING("Property has a value that is not one of its allowed enumerated values.");
case kValidateErrorType: return RAPIDJSON_ERROR_STRING("Property has a type '%actual' that is not in the following list: '%expected'.");
case kValidateErrorOneOf: return RAPIDJSON_ERROR_STRING("Property did not match any of the sub-schemas specified by 'oneOf', refer to following errors.");
case kValidateErrorOneOfMatch: return RAPIDJSON_ERROR_STRING("Property matched more than one of the sub-schemas specified by 'oneOf'.");
case kValidateErrorAllOf: return RAPIDJSON_ERROR_STRING("Property did not match all of the sub-schemas specified by 'allOf', refer to following errors.");
case kValidateErrorAnyOf: return RAPIDJSON_ERROR_STRING("Property did not match any of the sub-schemas specified by 'anyOf', refer to following errors.");
case kValidateErrorNot: return RAPIDJSON_ERROR_STRING("Property matched the sub-schema specified by 'not'.");
default: return RAPIDJSON_ERROR_STRING("Unknown error.");
} }
} }
RAPIDJSON_NAMESPACE_END RAPIDJSON_NAMESPACE_END
#endif // RAPIDJSON_ERROR_EN_H__ #ifdef __clang__
RAPIDJSON_DIAG_POP
#endif
#endif // RAPIDJSON_ERROR_EN_H_
// Copyright (C) 2011 Milo Yip // Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Licensed under the MIT License (the "License"); you may not use this file except
// of this software and associated documentation files (the "Software"), to deal // in compliance with the License. You may obtain a copy of the License at
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // http://opensource.org/licenses/MIT
// all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // Unless required by applicable law or agreed to in writing, software distributed
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // CONDITIONS OF ANY KIND, either express or implied. See the License for the
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // specific language governing permissions and limitations under the License.
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef RAPIDJSON_ERROR_ERROR_H__ #ifndef RAPIDJSON_ERROR_ERROR_H_
#define RAPIDJSON_ERROR_ERROR_H__ #define RAPIDJSON_ERROR_ERROR_H_
#include "../rapidjson.h"
#ifdef __clang__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(padded)
#endif
/*! \file error.h */ /*! \file error.h */
...@@ -85,7 +86,7 @@ enum ParseErrorCode { ...@@ -85,7 +86,7 @@ enum ParseErrorCode {
kParseErrorNumberMissExponent, //!< Miss exponent in number. kParseErrorNumberMissExponent, //!< Miss exponent in number.
kParseErrorTermination, //!< Parsing was terminated. kParseErrorTermination, //!< Parsing was terminated.
kParseErrorUnspecificSyntaxError, //!< Unspecific syntax error. kParseErrorUnspecificSyntaxError //!< Unspecific syntax error.
}; };
//! Result of parsing (wraps ParseErrorCode) //! Result of parsing (wraps ParseErrorCode)
...@@ -103,7 +104,9 @@ enum ParseErrorCode { ...@@ -103,7 +104,9 @@ enum ParseErrorCode {
\see GenericReader::Parse, GenericDocument::Parse \see GenericReader::Parse, GenericDocument::Parse
*/ */
struct ParseResult { struct ParseResult {
//!! Unspecified boolean type
typedef bool (ParseResult::*BooleanType)() const;
public:
//! Default constructor, no error. //! Default constructor, no error.
ParseResult() : code_(kParseErrorNone), offset_(0) {} ParseResult() : code_(kParseErrorNone), offset_(0) {}
//! Constructor to set an error. //! Constructor to set an error.
...@@ -114,8 +117,8 @@ struct ParseResult { ...@@ -114,8 +117,8 @@ struct ParseResult {
//! Get the error offset, if \ref IsError(), 0 otherwise. //! Get the error offset, if \ref IsError(), 0 otherwise.
size_t Offset() const { return offset_; } size_t Offset() const { return offset_; }
//! Conversion to \c bool, returns \c true, iff !\ref IsError(). //! Explicit conversion to \c bool, returns \c true, iff !\ref IsError().
operator bool() const { return !IsError(); } operator BooleanType() const { return !IsError() ? &ParseResult::IsError : NULL; }
//! Whether the result is an error. //! Whether the result is an error.
bool IsError() const { return code_ != kParseErrorNone; } bool IsError() const { return code_ != kParseErrorNone; }
...@@ -123,6 +126,10 @@ struct ParseResult { ...@@ -123,6 +126,10 @@ struct ParseResult {
bool operator==(ParseErrorCode code) const { return code_ == code; } bool operator==(ParseErrorCode code) const { return code_ == code; }
friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; } friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; }
bool operator!=(const ParseResult& that) const { return !(*this == that); }
bool operator!=(ParseErrorCode code) const { return !(*this == code); }
friend bool operator!=(ParseErrorCode code, const ParseResult & err) { return err != code; }
//! Reset error code. //! Reset error code.
void Clear() { Set(kParseErrorNone); } void Clear() { Set(kParseErrorNone); }
//! Update error code and offset. //! Update error code and offset.
...@@ -145,6 +152,65 @@ private: ...@@ -145,6 +152,65 @@ private:
*/ */
typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorCode); typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorCode);
///////////////////////////////////////////////////////////////////////////////
// ValidateErrorCode
//! Error codes when validating.
/*! \ingroup RAPIDJSON_ERRORS
\see GenericSchemaValidator
*/
enum ValidateErrorCode {
kValidateErrors = -1, //!< Top level error code when kValidateContinueOnErrorsFlag set.
kValidateErrorNone = 0, //!< No error.
kValidateErrorMultipleOf, //!< Number is not a multiple of the 'multipleOf' value.
kValidateErrorMaximum, //!< Number is greater than the 'maximum' value.
kValidateErrorExclusiveMaximum, //!< Number is greater than or equal to the 'maximum' value.
kValidateErrorMinimum, //!< Number is less than the 'minimum' value.
kValidateErrorExclusiveMinimum, //!< Number is less than or equal to the 'minimum' value.
kValidateErrorMaxLength, //!< String is longer than the 'maxLength' value.
kValidateErrorMinLength, //!< String is longer than the 'maxLength' value.
kValidateErrorPattern, //!< String does not match the 'pattern' regular expression.
kValidateErrorMaxItems, //!< Array is longer than the 'maxItems' value.
kValidateErrorMinItems, //!< Array is shorter than the 'minItems' value.
kValidateErrorUniqueItems, //!< Array has duplicate items but 'uniqueItems' is true.
kValidateErrorAdditionalItems, //!< Array has additional items that are not allowed by the schema.
kValidateErrorMaxProperties, //!< Object has more members than 'maxProperties' value.
kValidateErrorMinProperties, //!< Object has less members than 'minProperties' value.
kValidateErrorRequired, //!< Object is missing one or more members required by the schema.
kValidateErrorAdditionalProperties, //!< Object has additional members that are not allowed by the schema.
kValidateErrorPatternProperties, //!< See other errors.
kValidateErrorDependencies, //!< Object has missing property or schema dependencies.
kValidateErrorEnum, //!< Property has a value that is not one of its allowed enumerated values
kValidateErrorType, //!< Property has a type that is not allowed by the schema..
kValidateErrorOneOf, //!< Property did not match any of the sub-schemas specified by 'oneOf'.
kValidateErrorOneOfMatch, //!< Property matched more than one of the sub-schemas specified by 'oneOf'.
kValidateErrorAllOf, //!< Property did not match all of the sub-schemas specified by 'allOf'.
kValidateErrorAnyOf, //!< Property did not match any of the sub-schemas specified by 'anyOf'.
kValidateErrorNot //!< Property matched the sub-schema specified by 'not'.
};
//! Function pointer type of GetValidateError().
/*! \ingroup RAPIDJSON_ERRORS
This is the prototype for \c GetValidateError_X(), where \c X is a locale.
User can dynamically change locale in runtime, e.g.:
\code
GetValidateErrorFunc GetValidateError = GetValidateError_En; // or whatever
const RAPIDJSON_ERROR_CHARTYPE* s = GetValidateError(validator.GetInvalidSchemaCode());
\endcode
*/
typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetValidateErrorFunc)(ValidateErrorCode);
RAPIDJSON_NAMESPACE_END RAPIDJSON_NAMESPACE_END
#endif // RAPIDJSON_ERROR_ERROR_H__ #ifdef __clang__
RAPIDJSON_DIAG_POP
#endif
#endif // RAPIDJSON_ERROR_ERROR_H_