123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715 |
- /*
- * Copyright (C) 2013 Teluu Inc. (http://www.teluu.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
- #ifndef __PJSUA2_PERSISTENT_HPP__
- #define __PJSUA2_PERSISTENT_HPP__
- /**
- * @file pjsua2/persistent.hpp
- * @brief PJSUA2 Persistent Services
- */
- #include <pjsua2/types.hpp>
- #include <string>
- #include <vector>
- /** PJSUA2 API is inside pj namespace */
- namespace pj
- {
- /**
- * @defgroup PJSUA2_PERSISTENT Persistent API
- * @ingroup PJSUA2_Ref
- * @{
- * The persistent API provides functionality to read/write data from/to
- * a document (string or file). The data can be simple data types such
- * as boolean, number, string, and string arrays, or a user defined object.
- * Currently the implementation supports reading and writing from/to JSON
- * document, but the framework allows application to extend the API to
- * support other document formats.
- */
- using std::string;
- using std::vector;
- /* Forward declaration for ContainerNode */
- class ContainerNode;
- /**
- * This is the abstract base class of objects that can be serialized to/from
- * persistent document.
- */
- class PersistentObject
- {
- public:
- /**
- * Virtual destructor
- */
- virtual ~PersistentObject()
- {}
- /**
- * Read this object from a container node.
- *
- * @param node Container to read values from.
- */
- virtual void readObject(const ContainerNode &node) PJSUA2_THROW(Error) = 0;
- /**
- * Write this object to a container node.
- *
- * @param node Container to write values to.
- */
- virtual void writeObject(ContainerNode &node) const PJSUA2_THROW(Error) = 0;
- };
- /**
- * This a the abstract base class for a persistent document. A document
- * is created either by loading from a string or a file, or by constructing
- * it manually when writing data to it. The document then can be saved
- * to either string or to a file. A document contains one root ContainerNode
- * where all data are stored under.
- *
- * Document is read and written serially, hence the order of reading must be
- * the same as the order of writing. The PersistentDocument class provides
- * API to read and write to the root node, but for more flexible operations
- * application can use the ContainerNode methods instead. Indeed the read
- * and write API in PersistentDocument is just a shorthand which calls the
- * relevant methods in the ContainerNode. As a tip, normally application only
- * uses the readObject() and writeObject() methods declared here to read/write
- * top level objects, and use the macros that are explained in ContainerNode
- * documentation to read/write more detailed data.
- */
- class PersistentDocument
- {
- public:
- /**
- * Virtual destructor
- */
- virtual ~PersistentDocument()
- {}
- /**
- * Load this document from a file.
- *
- * @param filename The file name.
- */
- virtual void loadFile(const string &filename)
- PJSUA2_THROW(Error) = 0;
- /**
- * Load this document from string.
- *
- * @param input The string.
- */
- virtual void loadString(const string &input)
- PJSUA2_THROW(Error) = 0;
- /**
- * Write this document to a file.
- *
- * @param filename The file name.
- */
- virtual void saveFile(const string &filename)
- PJSUA2_THROW(Error) = 0;
- /**
- * Write this document to string.
- *
- * @return The string document.
- */
- virtual string saveString() PJSUA2_THROW(Error) = 0;
- /**
- * Get the root container node for this document
- *
- * @return The root node.
- */
- virtual ContainerNode & getRootContainer() const = 0;
- /*
- * Shorthand functions for reading and writing from/to the root container
- */
- /**
- * Determine if there is unread element. If yes, then app can use one of
- * the readXxx() functions to read it.
- *
- * @return True if there is.
- */
- bool hasUnread() const;
- /**
- * Get the name of the next unread element. It will throw Error if there
- * is no more element to read.
- *
- * @return The name of the next element .
- */
- string unreadName() const PJSUA2_THROW(Error);
- /**
- * Read an integer value from the document and return the value.
- * This will throw Error if the current element is not a number.
- * The read position will be advanced to the next element.
- *
- * @param name If specified, then the function will check if the
- * name of the next element matches the specified
- * name and throw Error if it doesn't match.
- *
- * @return The value.
- */
- int readInt(const string &name="") const
- PJSUA2_THROW(Error);
- /**
- * Read a float value from the document and return the value.
- * This will throw Error if the current element is not a number.
- * The read position will be advanced to the next element.
- *
- * @param name If specified, then the function will check if the
- * name of the next element matches the specified
- * name and throw Error if it doesn't match.
- *
- * @return The value.
- */
- float readNumber(const string &name="") const
- PJSUA2_THROW(Error);
- /**
- * Read a boolean value from the container and return the value.
- * This will throw Error if the current element is not a boolean.
- * The read position will be advanced to the next element.
- *
- * @param name If specified, then the function will check if the
- * name of the next element matches the specified
- * name and throw Error if it doesn't match.
- *
- * @return The value.
- */
- bool readBool(const string &name="") const
- PJSUA2_THROW(Error);
- /**
- * Read a string value from the container and return the value.
- * This will throw Error if the current element is not a string.
- * The read position will be advanced to the next element.
- *
- * @param name If specified, then the function will check if the
- * name of the next element matches the specified
- * name and throw Error if it doesn't match.
- *
- * @return The value.
- */
- string readString(const string &name="") const
- PJSUA2_THROW(Error);
- /**
- * Read a string array from the container. This will throw Error
- * if the current element is not a string array. The read position
- * will be advanced to the next element.
- *
- * @param name If specified, then the function will check if the
- * name of the next element matches the specified
- * name and throw Error if it doesn't match.
- *
- * @return The value.
- */
- StringVector readStringVector(const string &name="") const
- PJSUA2_THROW(Error);
- /**
- * Read the specified object from the container. This is equal to
- * calling PersistentObject.readObject(ContainerNode);
- *
- * @param obj The object to read.
- */
- void readObject(PersistentObject &obj) const
- PJSUA2_THROW(Error);
- /**
- * Read a container from the container. This will throw Error if the
- * current element is not an object. The read position will be advanced
- * to the next element.
- *
- * @param name If specified, then the function will check if the
- * name of the next element matches the specified
- * name and throw Error if it doesn't match.
- *
- * @return Container object.
- */
- ContainerNode readContainer(const string &name="") const
- PJSUA2_THROW(Error);
- /**
- * Read array container from the container. This will throw Error if the
- * current element is not an array. The read position will be advanced
- * to the next element.
- *
- * @param name If specified, then the function will check if the
- * name of the next element matches the specified
- * name and throw Error if it doesn't match.
- *
- * @return Container object.
- */
- ContainerNode readArray(const string &name="") const
- PJSUA2_THROW(Error);
- /**
- * Write a number value to the container.
- *
- * @param name The name for the value in the container.
- * @param num The value to be written.
- */
- void writeNumber(const string &name,
- float num) PJSUA2_THROW(Error);
- /**
- * Write a number value to the container.
- *
- * @param name The name for the value in the container.
- * @param num The value to be written.
- */
- void writeInt(const string &name,
- int num) PJSUA2_THROW(Error);
- /**
- * Write a boolean value to the container.
- *
- * @param name The name for the value in the container.
- * @param value The value to be written.
- */
- void writeBool(const string &name,
- bool value) PJSUA2_THROW(Error);
- /**
- * Write a string value to the container.
- *
- * @param name The name for the value in the container.
- * @param value The value to be written.
- */
- void writeString(const string &name,
- const string &value) PJSUA2_THROW(Error);
- /**
- * Write string vector to the container.
- *
- * @param name The name for the value in the container.
- * @param arr The vector to be written.
- */
- void writeStringVector(const string &name,
- const StringVector &arr)
- PJSUA2_THROW(Error);
- /**
- * Write an object to the container. This is equal to calling
- * PersistentObject.writeObject(ContainerNode);
- *
- * @param obj The object to be written
- */
- void writeObject(const PersistentObject &obj)
- PJSUA2_THROW(Error);
- /**
- * Create and write an empty Object node that can be used as parent
- * for subsequent write operations.
- *
- * @param name The name for the new container in the container.
- *
- * @return A sub-container.
- */
- ContainerNode writeNewContainer(const string &name)
- PJSUA2_THROW(Error);
- /**
- * Create and write an empty array node that can be used as parent
- * for subsequent write operations.
- *
- * @param name The name for the array.
- *
- * @return A sub-container.
- */
- ContainerNode writeNewArray(const string &name)
- PJSUA2_THROW(Error);
- };
- /**
- * Forward declaration of container_node_op.
- */
- struct container_node_op;
- /**
- * Internal data for ContainerNode. See ContainerNode implementation notes
- * for more info.
- */
- struct container_node_internal_data
- {
- void *doc; /**< The document. */
- void *data1; /**< Internal data 1 */
- void *data2; /**< Internal data 2 */
- };
- /**
- * A container node is a placeholder for storing other data elements, which
- * could be boolean, number, string, array of strings, or another container.
- * Each data in the container is basically a name/value pair, with a type
- * internally associated with it so that written data can be read in the
- * correct type. Data is read and written serially, hence the order of
- * reading must be the same as the order of writing.
- *
- * Application can read data from it by using the various read methods, and
- * write data to it using the various write methods. Alternatively, it
- * may be more convenient to use the provided macros below to read and write
- * the data, because these macros set the name automatically:
- * - NODE_READ_BOOL(node,item)
- * - NODE_READ_UNSIGNED(node,item)
- * - NODE_READ_INT(node,item)
- * - NODE_READ_FLOAT(node,item)
- * - NODE_READ_NUM_T(node,type,item)
- * - NODE_READ_STRING(node,item)
- * - NODE_READ_STRINGV(node,item)
- * - NODE_READ_OBJ(node,item)
- * - NODE_WRITE_BOOL(node,item)
- * - NODE_WRITE_UNSIGNED(node,item)
- * - NODE_WRITE_INT(node,item)
- * - NODE_WRITE_FLOAT(node,item)
- * - NODE_WRITE_NUM_T(node,type,item)
- * - NODE_WRITE_STRING(node,item)
- * - NODE_WRITE_STRINGV(node,item)
- * - NODE_WRITE_OBJ(node,item)
- *
- * Implementation notes:
- *
- * The ContainerNode class is subclass-able, but not in the usual C++ way.
- * With the usual C++ inheritance, some methods will be made pure virtual
- * and must be implemented by the actual class. However, doing so will
- * require dynamic instantiation of the ContainerNode class, which means
- * we will need to pass around the class as pointer, for example as the
- * return value of readContainer() and writeNewContainer() methods. Then
- * we will need to establish who needs or how to delete these objects, or
- * use shared pointer mechanism, each of which is considered too inconvenient
- * or complicated for the purpose.
- *
- * So hence we use C style "inheritance", where the methods are declared in
- * container_node_op and the data in container_node_internal_data structures.
- * An implementation of ContainerNode class will need to set up these members
- * with values that makes sense to itself. The methods in container_node_op
- * contains the pointer to the actual implementation of the operation, which
- * would be specific according to the format of the document. The methods in
- * this ContainerNode class are just thin wrappers which call the
- * implementation in the container_node_op structure.
- *
- */
- class ContainerNode
- {
- public:
- /**
- * Determine if there is unread element. If yes, then app can use one of
- * the readXxx() functions to read it.
- */
- bool hasUnread() const;
- /**
- * Get the name of the next unread element.
- */
- string unreadName() const PJSUA2_THROW(Error);
- /**
- * Read an integer value from the document and return the value.
- * This will throw Error if the current element is not a number.
- * The read position will be advanced to the next element.
- *
- * @param name If specified, then the function will check if the
- * name of the next element matches the specified
- * name and throw Error if it doesn't match.
- *
- * @return The value.
- */
- int readInt(const string &name="") const
- PJSUA2_THROW(Error);
- /**
- * Read a number value from the document and return the value.
- * This will throw Error if the current element is not a number.
- * The read position will be advanced to the next element.
- *
- * @param name If specified, then the function will check if the
- * name of the next element matches the specified
- * name and throw Error if it doesn't match.
- *
- * @return The value.
- */
- float readNumber(const string &name="") const
- PJSUA2_THROW(Error);
- /**
- * Read a boolean value from the container and return the value.
- * This will throw Error if the current element is not a boolean.
- * The read position will be advanced to the next element.
- *
- * @param name If specified, then the function will check if the
- * name of the next element matches the specified
- * name and throw Error if it doesn't match.
- *
- * @return The value.
- */
- bool readBool(const string &name="") const
- PJSUA2_THROW(Error);
- /**
- * Read a string value from the container and return the value.
- * This will throw Error if the current element is not a string.
- * The read position will be advanced to the next element.
- *
- * @param name If specified, then the function will check if the
- * name of the next element matches the specified
- * name and throw Error if it doesn't match.
- *
- * @return The value.
- */
- string readString(const string &name="") const
- PJSUA2_THROW(Error);
- /**
- * Read a string array from the container. This will throw Error
- * if the current element is not a string array. The read position
- * will be advanced to the next element.
- *
- * @param name If specified, then the function will check if the
- * name of the next element matches the specified
- * name and throw Error if it doesn't match.
- *
- * @return The value.
- */
- StringVector readStringVector(const string &name="") const
- PJSUA2_THROW(Error);
- /**
- * Read the specified object from the container. This is equal to
- * calling PersistentObject.readObject(ContainerNode);
- *
- * @param obj The object to read.
- */
- void readObject(PersistentObject &obj) const
- PJSUA2_THROW(Error);
- /**
- * Read a container from the container. This will throw Error if the
- * current element is not a container. The read position will be advanced
- * to the next element.
- *
- * @param name If specified, then the function will check if the
- * name of the next element matches the specified
- * name and throw Error if it doesn't match.
- *
- * @return Container object.
- */
- ContainerNode readContainer(const string &name="") const
- PJSUA2_THROW(Error);
- /**
- * Read array container from the container. This will throw Error if the
- * current element is not an array. The read position will be advanced
- * to the next element.
- *
- * @param name If specified, then the function will check if the
- * name of the next element matches the specified
- * name and throw Error if it doesn't match.
- *
- * @return Container object.
- */
- ContainerNode readArray(const string &name="") const
- PJSUA2_THROW(Error);
- /**
- * Write a number value to the container.
- *
- * @param name The name for the value in the container.
- * @param num The value to be written.
- */
- void writeNumber(const string &name,
- float num) PJSUA2_THROW(Error);
- /**
- * Write a number value to the container.
- *
- * @param name The name for the value in the container.
- * @param num The value to be written.
- */
- void writeInt(const string &name,
- int num) PJSUA2_THROW(Error);
- /**
- * Write a boolean value to the container.
- *
- * @param name The name for the value in the container.
- * @param value The value to be written.
- */
- void writeBool(const string &name,
- bool value) PJSUA2_THROW(Error);
- /**
- * Write a string value to the container.
- *
- * @param name The name for the value in the container.
- * @param value The value to be written.
- */
- void writeString(const string &name,
- const string &value) PJSUA2_THROW(Error);
- /**
- * Write string vector to the container.
- *
- * @param name The name for the value in the container.
- * @param arr The vector to be written.
- */
- void writeStringVector(const string &name,
- const StringVector &arr)
- PJSUA2_THROW(Error);
- /**
- * Write an object to the container. This is equal to calling
- * PersistentObject.writeObject(ContainerNode);
- *
- * @param obj The object to be written
- */
- void writeObject(const PersistentObject &obj)
- PJSUA2_THROW(Error);
- /**
- * Create and write an empty Object node that can be used as parent
- * for subsequent write operations.
- *
- * @param name The name for the new container in the container.
- *
- * @return A sub-container.
- */
- ContainerNode writeNewContainer(const string &name)
- PJSUA2_THROW(Error);
- /**
- * Create and write an empty array node that can be used as parent
- * for subsequent write operations.
- *
- * @param name The name for the array.
- *
- * @return A sub-container.
- */
- ContainerNode writeNewArray(const string &name)
- PJSUA2_THROW(Error);
- public:
- /* internal data */
- container_node_op *op; /**< Method table. */
- container_node_internal_data data; /**< Internal data */
- ContainerNode()
- : op(NULL)
- {
- pj_bzero(&data, sizeof(data));
- }
- };
- /**
- * Pointer to actual ContainerNode implementation. See ContainerNode
- * implementation notes for more info.
- */
- //! @cond Doxygen_Suppress
- struct container_node_op
- {
- bool (*hasUnread)(const ContainerNode*);
- string (*unreadName)(const ContainerNode*)
- PJSUA2_THROW(Error);
- float (*readNumber)(const ContainerNode*,
- const string&)
- PJSUA2_THROW(Error);
- bool (*readBool)(const ContainerNode*,
- const string&)
- PJSUA2_THROW(Error);
- string (*readString)(const ContainerNode*,
- const string&)
- PJSUA2_THROW(Error);
- StringVector (*readStringVector)(const ContainerNode*,
- const string&)
- PJSUA2_THROW(Error);
- ContainerNode (*readContainer)(const ContainerNode*,
- const string &)
- PJSUA2_THROW(Error);
- ContainerNode (*readArray)(const ContainerNode*,
- const string &)
- PJSUA2_THROW(Error);
- void (*writeNumber)(ContainerNode*,
- const string &name,
- float num)
- PJSUA2_THROW(Error);
- void (*writeBool)(ContainerNode*,
- const string &name,
- bool value)
- PJSUA2_THROW(Error);
- void (*writeString)(ContainerNode*,
- const string &name,
- const string &value)
- PJSUA2_THROW(Error);
- void (*writeStringVector)(ContainerNode*,
- const string &name,
- const StringVector &value)
- PJSUA2_THROW(Error);
- ContainerNode (*writeNewContainer)(ContainerNode*,
- const string &name)
- PJSUA2_THROW(Error);
- ContainerNode (*writeNewArray)(ContainerNode*,
- const string &name)
- PJSUA2_THROW(Error);
- };
- /*
- * Convenient macros.
- */
- #define NODE_READ_BOOL(node,item) item = node.readBool(#item)
- #define NODE_READ_UNSIGNED(node,item) item = (unsigned)node.readNumber(#item)
- #define NODE_READ_INT(node,item) item = (int) node.readNumber(#item)
- #define NODE_READ_FLOAT(node,item) item = node.readNumber(#item)
- #define NODE_READ_NUM_T(node,T,item) item = (T)(int)node.readNumber(#item)
- #define NODE_READ_STRING(node,item) item = node.readString(#item)
- #define NODE_READ_STRINGV(node,item) item = node.readStringVector(#item)
- #define NODE_READ_OBJ(node,item) node.readObject(item)
- #define NODE_WRITE_BOOL(node,item) node.writeBool(#item, item)
- #define NODE_WRITE_UNSIGNED(node,item) node.writeNumber(#item, (float)item)
- #define NODE_WRITE_INT(node,item) node.writeNumber(#item, (float)item)
- #define NODE_WRITE_NUM_T(node,T,item) node.writeNumber(#item, (float)item)
- #define NODE_WRITE_FLOAT(node,item) node.writeNumber(#item, item)
- #define NODE_WRITE_STRING(node,item) node.writeString(#item, item)
- #define NODE_WRITE_STRINGV(node,item) node.writeStringVector(#item, item)
- #define NODE_WRITE_OBJ(node,item) node.writeObject(item)
- //! @endcond
- /**
- * @} PJSUA2
- */
- } // namespace pj
- #endif /* __PJSUA2_PERSISTENT_HPP__ */
|