* #39226: Switch back to pjsip rev 4710

Rev 4716 introduces errors when building for android (miltiple definitions)
diff --git a/jni/pjproject-android/.svn/pristine/c5/c5d1820cd0fecc10721dbc1b8b529b04f5228a56.svn-base b/jni/pjproject-android/.svn/pristine/c5/c5d1820cd0fecc10721dbc1b8b529b04f5228a56.svn-base
new file mode 100644
index 0000000..c086b01
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/c5/c5d1820cd0fecc10721dbc1b8b529b04f5228a56.svn-base
@@ -0,0 +1,689 @@
+/* $Id$ */
+/*
+ * 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:
+    /**
+     * Read this object from a container node.
+     *
+     * @param node		Container to read values from.
+     */
+    virtual void readObject(const ContainerNode &node) throw(Error) = 0;
+
+    /**
+     * Write this object to a container node.
+     *
+     * @param node		Container to write values to.
+     */
+    virtual void writeObject(ContainerNode &node) const 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) throw(Error) = 0;
+
+    /**
+     * Load this document from string.
+     *
+     * @param input	The string.
+     */
+    virtual void   	loadString(const string &input) throw(Error) = 0;
+
+    /**
+     * Write this document to a file.
+     *
+     * @param filename	The file name.
+     */
+    virtual void   	saveFile(const string &filename) throw(Error) = 0;
+
+    /**
+     * Write this document to string.
+     *
+     * @return		The string document.
+     */
+    virtual string 	saveString() 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 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 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 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 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 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
+					 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 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
+				      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
+				  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) 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) 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) 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) 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)
+					  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) 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)
+					  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)
+				      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 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 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 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 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 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
+					 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 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
+				      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
+				  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) 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) 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) 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) 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)
+					  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) 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)
+					  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)
+				      throw(Error);
+
+public:
+    /* internal data */
+    container_node_op *op;		/**< Method table.	*/
+    container_node_internal_data data;	/**< Internal 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*)
+				      throw(Error);
+    float		(*readNumber)(const ContainerNode*,
+				      const string&)
+				      throw(Error);
+    bool		(*readBool)(const ContainerNode*,
+				    const string&)
+				    throw(Error);
+    string		(*readString)(const ContainerNode*,
+				      const string&)
+				      throw(Error);
+    StringVector	(*readStringVector)(const ContainerNode*,
+					    const string&)
+					    throw(Error);
+    ContainerNode	(*readContainer)(const ContainerNode*,
+					 const string &)
+					 throw(Error);
+    ContainerNode	(*readArray)(const ContainerNode*,
+				     const string &)
+				     throw(Error);
+    void		(*writeNumber)(ContainerNode*,
+				       const string &name,
+        		               float num)
+        		               throw(Error);
+    void		(*writeBool)(ContainerNode*,
+				     const string &name,
+        			     bool value)
+        			     throw(Error);
+    void		(*writeString)(ContainerNode*,
+				       const string &name,
+        			       const string &value)
+        			       throw(Error);
+    void		(*writeStringVector)(ContainerNode*,
+					     const string &name,
+        				     const StringVector &value)
+					     throw(Error);
+    ContainerNode 	(*writeNewContainer)(ContainerNode*,
+					     const string &name)
+					     throw(Error);
+    ContainerNode 	(*writeNewArray)(ContainerNode*,
+				         const string &name)
+					 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__ */