- Timestamp:
- Nov 27, 2013 9:37:32 AM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/branches/projects/pjsua2/pjsip/include/pjsua2/persistent.hpp
r4644 r4657 334 334 throw(Error); 335 335 }; 336 337 338 /** 339 * Forward declaration of container_node_op. 340 */ 341 struct container_node_op; 342 343 344 /** 345 * Internal data for ContainerNode. See ContainerNode implementation notes 346 * for more info. 347 */ 348 struct 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 */ 406 class ContainerNode 407 { 408 public: 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 598 public: 599 /* internal data */ 600 container_node_op *op; 601 container_node_internal_data data; 602 }; 603 336 604 337 605 /** … … 387 655 }; 388 656 389 /**390 * Internal data for ContainerNode. See ContainerNode implementation notes391 * for more info.392 */393 struct container_node_internal_data394 {395 void *doc;396 void *data1;397 void *data2;398 };399 400 /**401 * A container node is a placeholder for storing other data elements, which402 * 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 type404 * internally associated with it so that written data can be read in the405 * correct type. Data is read and written serially, hence the order of406 * reading must be the same as the order of writing.407 *408 * Application can read data from it by using the various read methods, and409 * write data to it using the various write methods. Alternatively, it410 * may be more convenient to use the provided macros below to read and write411 * 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 virtual433 * and must be implemented by the actual class. However, doing so will434 * require dynamic instantiation of the ContainerNode class, which means435 * we will need to pass around the class as pointer, for example as the436 * return value of readContainer() and writeNewContainer() methods. Then437 * we will need to establish who needs or how to delete these objects, or438 * use shared pointer mechanism, each of which is considered too inconvenient439 * or complicated for the purpose.440 *441 * So hence we use C style "inheritance", where the methods are declared in442 * container_node_op and the data in container_node_internal_data structures.443 * An implementation of ContainerNode class will need to set up these members444 * with values that makes sense to itself. The methods in container_node_op445 * contains the pointer to the actual implementation of the operation, which446 * would be specific according to the format of the document. The methods in447 * this ContainerNode class are just thin wrappers which call the448 * implementation in the container_node_op structure.449 *450 */451 class ContainerNode452 {453 public:454 /**455 * Determine if there is unread element. If yes, then app can use one of456 * 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 the471 * name of the next element matches the specified472 * 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 the484 * name of the next element matches the specified485 * 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 the497 * name of the next element matches the specified498 * 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 the510 * name of the next element matches the specified511 * 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 Error519 * if the current element is not a string array. The read position520 * will be advanced to the next element.521 *522 * @param name If specified, then the function will check if the523 * name of the next element matches the specified524 * name and throw Error if it doesn't match.525 *526 * @return The value.527 */528 StringVector readStringVector(const string &name="") const529 throw(Error);530 531 /**532 * Read the specified object from the container. This is equal to533 * 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 the541 * current element is not a container. The read position will be advanced542 * to the next element.543 *544 * @param name If specified, then the function will check if the545 * name of the next element matches the specified546 * name and throw Error if it doesn't match.547 *548 * @return Container object.549 */550 ContainerNode readContainer(const string &name="") const551 throw(Error);552 553 /**554 * Read array container from the container. This will throw Error if the555 * current element is not an array. The read position will be advanced556 * to the next element.557 *558 * @param name If specified, then the function will check if the559 * name of the next element matches the specified560 * name and throw Error if it doesn't match.561 *562 * @return Container object.563 */564 ContainerNode readArray(const string &name="") const565 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 calling615 * PersistentObject.writeObject(ContainerNode);616 *617 * @param obj The object to be written618 */619 void writeObject(const PersistentObject &obj) throw(Error);620 621 /**622 * Create and write an empty Object node that can be used as parent623 * 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 parent634 * 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 };648 657 649 658 /* … … 660 669 661 670 #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) 665 674 #define NODE_WRITE_FLOAT(node,item) node.writeNumber(#item, item) 666 675 #define NODE_WRITE_STRING(node,item) node.writeString(#item, item)
Note: See TracChangeset
for help on using the changeset viewer.