Ignore:
Timestamp:
Nov 27, 2013 9:37:32 AM (10 years ago)
Author:
nanang
Message:

Re #1519: Added presence API in pjsua2.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/branches/projects/pjsua2/pjsip/include/pjsua2/persistent.hpp

    r4644 r4657  
    334334                                      throw(Error); 
    335335}; 
     336 
     337 
     338/** 
     339 * Forward declaration of container_node_op. 
     340 */ 
     341struct container_node_op; 
     342 
     343 
     344/** 
     345 * Internal data for ContainerNode. See ContainerNode implementation notes 
     346 * for more info. 
     347 */ 
     348struct container_node_internal_data 
     349{ 
     350    void        *doc; 
     351    void        *data1; 
     352    void        *data2; 
     353}; 
     354 
     355/** 
     356 * A container node is a placeholder for storing other data elements, which 
     357 * could be boolean, number, string, array of strings, or another container. 
     358 * Each data in the container is basically a name/value pair, with a type 
     359 * internally associated with it so that written data can be read in the 
     360 * correct type. Data is read and written serially, hence the order of 
     361 * reading must be the same as the order of writing. 
     362 * 
     363 * Application can read data from it by using the various read methods, and 
     364 * write data to it using the various write methods. Alternatively, it 
     365 * may be more convenient to use the provided macros below to read and write 
     366 * the data, because these macros set the name automatically: 
     367 *      - NODE_READ_BOOL(node,item) 
     368 *      - NODE_READ_UNSIGNED(node,item) 
     369 *      - NODE_READ_INT(node,item) 
     370 *      - NODE_READ_FLOAT(node,item) 
     371 *      - NODE_READ_NUM_T(node,type,item) 
     372 *      - NODE_READ_STRING(node,item) 
     373 *      - NODE_READ_STRINGV(node,item) 
     374 *      - NODE_READ_OBJ(node,item) 
     375 *      - NODE_WRITE_BOOL(node,item) 
     376 *      - NODE_WRITE_UNSIGNED(node,item) 
     377 *      - NODE_WRITE_INT(node,item) 
     378 *      - NODE_WRITE_FLOAT(node,item) 
     379 *      - NODE_WRITE_NUM_T(node,type,item) 
     380 *      - NODE_WRITE_STRING(node,item) 
     381 *      - NODE_WRITE_STRINGV(node,item) 
     382 *      - NODE_WRITE_OBJ(node,item) 
     383 * 
     384 * Implementation notes: 
     385 * 
     386 * The ContainerNode class is subclass-able, but not in the usual C++ way. 
     387 * With the usual C++ inheritance, some methods will be made pure virtual 
     388 * and must be implemented by the actual class. However, doing so will 
     389 * require dynamic instantiation of the ContainerNode class, which means 
     390 * we will need to pass around the class as pointer, for example as the 
     391 * return value of readContainer() and writeNewContainer() methods. Then 
     392 * we will need to establish who needs or how to delete these objects, or 
     393 * use shared pointer mechanism, each of which is considered too inconvenient 
     394 * or complicated for the purpose. 
     395 * 
     396 * So hence we use C style "inheritance", where the methods are declared in 
     397 * container_node_op and the data in container_node_internal_data structures. 
     398 * An implementation of ContainerNode class will need to set up these members 
     399 * with values that makes sense to itself. The methods in container_node_op 
     400 * contains the pointer to the actual implementation of the operation, which 
     401 * would be specific according to the format of the document. The methods in 
     402 * this ContainerNode class are just thin wrappers which call the 
     403 * implementation in the container_node_op structure. 
     404 * 
     405 */ 
     406class ContainerNode 
     407{ 
     408public: 
     409    /** 
     410     * Determine if there is unread element. If yes, then app can use one of 
     411     * the readXxx() functions to read it. 
     412     */ 
     413    bool                hasUnread() const; 
     414 
     415    /** 
     416     * Get the name of the next unread element. 
     417     */ 
     418    string              unreadName() const throw(Error); 
     419 
     420    /** 
     421     * Read an integer value from the document and return the value. 
     422     * This will throw Error if the current element is not a number. 
     423     * The read position will be advanced to the next element. 
     424     * 
     425     * @param name      If specified, then the function will check if the 
     426     *                  name of the next element matches the specified 
     427     *                  name and throw Error if it doesn't match. 
     428     * 
     429     * @return          The value. 
     430     */ 
     431    int                 readInt(const string &name="") const throw(Error); 
     432 
     433    /** 
     434     * Read a number value from the document and return the value. 
     435     * This will throw Error if the current element is not a number. 
     436     * The read position will be advanced to the next element. 
     437     * 
     438     * @param name      If specified, then the function will check if the 
     439     *                  name of the next element matches the specified 
     440     *                  name and throw Error if it doesn't match. 
     441     * 
     442     * @return          The value. 
     443     */ 
     444    float               readNumber(const string &name="") const throw(Error); 
     445 
     446    /** 
     447     * Read a boolean value from the container and return the value. 
     448     * This will throw Error if the current element is not a boolean. 
     449     * The read position will be advanced to the next element. 
     450     * 
     451     * @param name      If specified, then the function will check if the 
     452     *                  name of the next element matches the specified 
     453     *                  name and throw Error if it doesn't match. 
     454     * 
     455     * @return          The value. 
     456     */ 
     457    bool                readBool(const string &name="") const throw(Error); 
     458 
     459    /** 
     460     * Read a string value from the container and return the value. 
     461     * This will throw Error if the current element is not a string. 
     462     * The read position will be advanced to the next element. 
     463     * 
     464     * @param name      If specified, then the function will check if the 
     465     *                  name of the next element matches the specified 
     466     *                  name and throw Error if it doesn't match. 
     467     * 
     468     * @return          The value. 
     469     */ 
     470    string              readString(const string &name="") const throw(Error); 
     471 
     472    /** 
     473     * Read a string array from the container. This will throw Error 
     474     * if the current element is not a string array. The read position 
     475     * will be advanced to the next element. 
     476     * 
     477     * @param name      If specified, then the function will check if the 
     478     *                  name of the next element matches the specified 
     479     *                  name and throw Error if it doesn't match. 
     480     * 
     481     * @return          The value. 
     482     */ 
     483    StringVector        readStringVector(const string &name="") const 
     484                                         throw(Error); 
     485 
     486    /** 
     487     * Read the specified object from the container. This is equal to 
     488     * calling PersistentObject.readObject(ContainerNode); 
     489     * 
     490     * @param obj       The object to read. 
     491     */ 
     492    void                readObject(PersistentObject &obj) const throw(Error); 
     493 
     494    /** 
     495     * Read a container from the container. This will throw Error if the 
     496     * current element is not a container. The read position will be advanced 
     497     * to the next element. 
     498     * 
     499     * @param name      If specified, then the function will check if the 
     500     *                  name of the next element matches the specified 
     501     *                  name and throw Error if it doesn't match. 
     502     * 
     503     * @return          Container object. 
     504     */ 
     505    ContainerNode       readContainer(const string &name="") const 
     506                                      throw(Error); 
     507 
     508    /** 
     509     * Read array container from the container. This will throw Error if the 
     510     * current element is not an array. The read position will be advanced 
     511     * to the next element. 
     512     * 
     513     * @param name      If specified, then the function will check if the 
     514     *                  name of the next element matches the specified 
     515     *                  name and throw Error if it doesn't match. 
     516     * 
     517     * @return          Container object. 
     518     */ 
     519    ContainerNode       readArray(const string &name="") const 
     520                                  throw(Error); 
     521 
     522    /** 
     523     * Write a number value to the container. 
     524     * 
     525     * @param name      The name for the value in the container. 
     526     * @param value     The value to be written. 
     527     */ 
     528    void                writeNumber(const string &name, 
     529                                    float num) throw(Error); 
     530 
     531    /** 
     532     * Write a number value to the container. 
     533     * 
     534     * @param name      The name for the value in the container. 
     535     * @param value     The value to be written. 
     536     */ 
     537    void                writeInt(const string &name, 
     538                                 int num) throw(Error); 
     539 
     540    /** 
     541     * Write a boolean value to the container. 
     542     * 
     543     * @param name      The name for the value in the container. 
     544     * @param value     The value to be written. 
     545     */ 
     546    void                writeBool(const string &name, 
     547                                  bool value) throw(Error); 
     548 
     549    /** 
     550     * Write a string value to the container. 
     551     * 
     552     * @param name      The name for the value in the container. 
     553     * @param value     The value to be written. 
     554     */ 
     555    void                writeString(const string &name, 
     556                                    const string &value) throw(Error); 
     557 
     558    /** 
     559     * Write string vector to the container. 
     560     * 
     561     * @param name      The name for the value in the container. 
     562     * @param array     The vector to be written. 
     563     */ 
     564    void                writeStringVector(const string &name, 
     565                                          const StringVector &value) 
     566                                          throw(Error); 
     567 
     568    /** 
     569     * Write an object to the container. This is equal to calling 
     570     * PersistentObject.writeObject(ContainerNode); 
     571     * 
     572     * @param obj       The object to be written 
     573     */ 
     574    void                writeObject(const PersistentObject &obj) throw(Error); 
     575 
     576    /** 
     577     * Create and write an empty Object node that can be used as parent 
     578     * for subsequent write operations. 
     579     * 
     580     * @param name      The name for the new container in the container. 
     581     * 
     582     * @return          A sub-container. 
     583     */ 
     584    ContainerNode       writeNewContainer(const string &name) 
     585                                          throw(Error); 
     586 
     587    /** 
     588     * Create and write an empty array node that can be used as parent 
     589     * for subsequent write operations. 
     590     * 
     591     * @param name      The name for the array. 
     592     * 
     593     * @return          A sub-container. 
     594     */ 
     595    ContainerNode       writeNewArray(const string &name) 
     596                                      throw(Error); 
     597 
     598public: 
     599    /* internal data */ 
     600    container_node_op *op; 
     601    container_node_internal_data data; 
     602}; 
     603 
    336604 
    337605/** 
     
    387655}; 
    388656 
    389 /** 
    390  * Internal data for ContainerNode. See ContainerNode implementation notes 
    391  * for more info. 
    392  */ 
    393 struct container_node_internal_data 
    394 { 
    395     void        *doc; 
    396     void        *data1; 
    397     void        *data2; 
    398 }; 
    399  
    400 /** 
    401  * A container node is a placeholder for storing other data elements, which 
    402  * could be boolean, number, string, array of strings, or another container. 
    403  * Each data in the container is basically a name/value pair, with a type 
    404  * internally associated with it so that written data can be read in the 
    405  * correct type. Data is read and written serially, hence the order of 
    406  * reading must be the same as the order of writing. 
    407  * 
    408  * Application can read data from it by using the various read methods, and 
    409  * write data to it using the various write methods. Alternatively, it 
    410  * may be more convenient to use the provided macros below to read and write 
    411  * the data, because these macros set the name automatically: 
    412  *      - NODE_READ_BOOL(node,item) 
    413  *      - NODE_READ_UNSIGNED(node,item) 
    414  *      - NODE_READ_INT(node,item) 
    415  *      - NODE_READ_FLOAT(node,item) 
    416  *      - NODE_READ_NUM_T(node,type,item) 
    417  *      - NODE_READ_STRING(node,item) 
    418  *      - NODE_READ_STRINGV(node,item) 
    419  *      - NODE_READ_OBJ(node,item) 
    420  *      - NODE_WRITE_BOOL(node,item) 
    421  *      - NODE_WRITE_UNSIGNED(node,item) 
    422  *      - NODE_WRITE_INT(node,item) 
    423  *      - NODE_WRITE_FLOAT(node,item) 
    424  *      - NODE_WRITE_NUM_T(node,type,item) 
    425  *      - NODE_WRITE_STRING(node,item) 
    426  *      - NODE_WRITE_STRINGV(node,item) 
    427  *      - NODE_WRITE_OBJ(node,item) 
    428  * 
    429  * Implementation notes: 
    430  * 
    431  * The ContainerNode class is subclass-able, but not in the usual C++ way. 
    432  * With the usual C++ inheritance, some methods will be made pure virtual 
    433  * and must be implemented by the actual class. However, doing so will 
    434  * require dynamic instantiation of the ContainerNode class, which means 
    435  * we will need to pass around the class as pointer, for example as the 
    436  * return value of readContainer() and writeNewContainer() methods. Then 
    437  * we will need to establish who needs or how to delete these objects, or 
    438  * use shared pointer mechanism, each of which is considered too inconvenient 
    439  * or complicated for the purpose. 
    440  * 
    441  * So hence we use C style "inheritance", where the methods are declared in 
    442  * container_node_op and the data in container_node_internal_data structures. 
    443  * An implementation of ContainerNode class will need to set up these members 
    444  * with values that makes sense to itself. The methods in container_node_op 
    445  * contains the pointer to the actual implementation of the operation, which 
    446  * would be specific according to the format of the document. The methods in 
    447  * this ContainerNode class are just thin wrappers which call the 
    448  * implementation in the container_node_op structure. 
    449  * 
    450  */ 
    451 class ContainerNode 
    452 { 
    453 public: 
    454     /** 
    455      * Determine if there is unread element. If yes, then app can use one of 
    456      * the readXxx() functions to read it. 
    457      */ 
    458     bool                hasUnread() const; 
    459  
    460     /** 
    461      * Get the name of the next unread element. 
    462      */ 
    463     string              unreadName() const throw(Error); 
    464  
    465     /** 
    466      * Read an integer value from the document and return the value. 
    467      * This will throw Error if the current element is not a number. 
    468      * The read position will be advanced to the next element. 
    469      * 
    470      * @param name      If specified, then the function will check if the 
    471      *                  name of the next element matches the specified 
    472      *                  name and throw Error if it doesn't match. 
    473      * 
    474      * @return          The value. 
    475      */ 
    476     int                 readInt(const string &name="") const throw(Error); 
    477  
    478     /** 
    479      * Read a number value from the document and return the value. 
    480      * This will throw Error if the current element is not a number. 
    481      * The read position will be advanced to the next element. 
    482      * 
    483      * @param name      If specified, then the function will check if the 
    484      *                  name of the next element matches the specified 
    485      *                  name and throw Error if it doesn't match. 
    486      * 
    487      * @return          The value. 
    488      */ 
    489     float               readNumber(const string &name="") const throw(Error); 
    490  
    491     /** 
    492      * Read a boolean value from the container and return the value. 
    493      * This will throw Error if the current element is not a boolean. 
    494      * The read position will be advanced to the next element. 
    495      * 
    496      * @param name      If specified, then the function will check if the 
    497      *                  name of the next element matches the specified 
    498      *                  name and throw Error if it doesn't match. 
    499      * 
    500      * @return          The value. 
    501      */ 
    502     bool                readBool(const string &name="") const throw(Error); 
    503  
    504     /** 
    505      * Read a string value from the container and return the value. 
    506      * This will throw Error if the current element is not a string. 
    507      * The read position will be advanced to the next element. 
    508      * 
    509      * @param name      If specified, then the function will check if the 
    510      *                  name of the next element matches the specified 
    511      *                  name and throw Error if it doesn't match. 
    512      * 
    513      * @return          The value. 
    514      */ 
    515     string              readString(const string &name="") const throw(Error); 
    516  
    517     /** 
    518      * Read a string array from the container. This will throw Error 
    519      * if the current element is not a string array. The read position 
    520      * will be advanced to the next element. 
    521      * 
    522      * @param name      If specified, then the function will check if the 
    523      *                  name of the next element matches the specified 
    524      *                  name and throw Error if it doesn't match. 
    525      * 
    526      * @return          The value. 
    527      */ 
    528     StringVector        readStringVector(const string &name="") const 
    529                                          throw(Error); 
    530  
    531     /** 
    532      * Read the specified object from the container. This is equal to 
    533      * calling PersistentObject.readObject(ContainerNode); 
    534      * 
    535      * @param obj       The object to read. 
    536      */ 
    537     void                readObject(PersistentObject &obj) const throw(Error); 
    538  
    539     /** 
    540      * Read a container from the container. This will throw Error if the 
    541      * current element is not a container. The read position will be advanced 
    542      * to the next element. 
    543      * 
    544      * @param name      If specified, then the function will check if the 
    545      *                  name of the next element matches the specified 
    546      *                  name and throw Error if it doesn't match. 
    547      * 
    548      * @return          Container object. 
    549      */ 
    550     ContainerNode       readContainer(const string &name="") const 
    551                                       throw(Error); 
    552  
    553     /** 
    554      * Read array container from the container. This will throw Error if the 
    555      * current element is not an array. The read position will be advanced 
    556      * to the next element. 
    557      * 
    558      * @param name      If specified, then the function will check if the 
    559      *                  name of the next element matches the specified 
    560      *                  name and throw Error if it doesn't match. 
    561      * 
    562      * @return          Container object. 
    563      */ 
    564     ContainerNode       readArray(const string &name="") const 
    565                                   throw(Error); 
    566  
    567     /** 
    568      * Write a number value to the container. 
    569      * 
    570      * @param name      The name for the value in the container. 
    571      * @param value     The value to be written. 
    572      */ 
    573     void                writeNumber(const string &name, 
    574                                     float num) throw(Error); 
    575  
    576     /** 
    577      * Write a number value to the container. 
    578      * 
    579      * @param name      The name for the value in the container. 
    580      * @param value     The value to be written. 
    581      */ 
    582     void                writeInt(const string &name, 
    583                                  int num) throw(Error); 
    584  
    585     /** 
    586      * Write a boolean value to the container. 
    587      * 
    588      * @param name      The name for the value in the container. 
    589      * @param value     The value to be written. 
    590      */ 
    591     void                writeBool(const string &name, 
    592                                   bool value) throw(Error); 
    593  
    594     /** 
    595      * Write a string value to the container. 
    596      * 
    597      * @param name      The name for the value in the container. 
    598      * @param value     The value to be written. 
    599      */ 
    600     void                writeString(const string &name, 
    601                                     const string &value) throw(Error); 
    602  
    603     /** 
    604      * Write string vector to the container. 
    605      * 
    606      * @param name      The name for the value in the container. 
    607      * @param array     The vector to be written. 
    608      */ 
    609     void                writeStringVector(const string &name, 
    610                                           const StringVector &value) 
    611                                           throw(Error); 
    612  
    613     /** 
    614      * Write an object to the container. This is equal to calling 
    615      * PersistentObject.writeObject(ContainerNode); 
    616      * 
    617      * @param obj       The object to be written 
    618      */ 
    619     void                writeObject(const PersistentObject &obj) throw(Error); 
    620  
    621     /** 
    622      * Create and write an empty Object node that can be used as parent 
    623      * for subsequent write operations. 
    624      * 
    625      * @param name      The name for the new container in the container. 
    626      * 
    627      * @return          A sub-container. 
    628      */ 
    629     ContainerNode       writeNewContainer(const string &name) 
    630                                           throw(Error); 
    631  
    632     /** 
    633      * Create and write an empty array node that can be used as parent 
    634      * for subsequent write operations. 
    635      * 
    636      * @param name      The name for the array. 
    637      * 
    638      * @return          A sub-container. 
    639      */ 
    640     ContainerNode       writeNewArray(const string &name) 
    641                                       throw(Error); 
    642  
    643 public: 
    644     /* internal data */ 
    645     container_node_op *op; 
    646     container_node_internal_data data; 
    647 }; 
    648657 
    649658/* 
     
    660669 
    661670#define NODE_WRITE_BOOL(node,item)      node.writeBool(#item, item) 
    662 #define NODE_WRITE_UNSIGNED(node,item)  node.writeNumber(#item, item) 
    663 #define NODE_WRITE_INT(node,item)       node.writeNumber(#item, item) 
    664 #define NODE_WRITE_NUM_T(node,T,item)   node.writeNumber(#item, (int)item) 
     671#define NODE_WRITE_UNSIGNED(node,item)  node.writeNumber(#item, (float)item) 
     672#define NODE_WRITE_INT(node,item)       node.writeNumber(#item, (float)item) 
     673#define NODE_WRITE_NUM_T(node,T,item)   node.writeNumber(#item, (float)item) 
    665674#define NODE_WRITE_FLOAT(node,item)     node.writeNumber(#item, item) 
    666675#define NODE_WRITE_STRING(node,item)    node.writeString(#item, item) 
Note: See TracChangeset for help on using the changeset viewer.