1 // 2 // Copyright (c) ZeroC, Inc. All rights reserved. 3 // 4 5 #ifndef ICE_OUTPUT_STREAM_H 6 #define ICE_OUTPUT_STREAM_H 7 8 #include <Ice/CommunicatorF.h> 9 #include <Ice/InstanceF.h> 10 #include <Ice/Object.h> 11 #include <Ice/ValueF.h> 12 #include <Ice/ProxyF.h> 13 #include <Ice/Buffer.h> 14 #include <Ice/Protocol.h> 15 #include <Ice/SlicedDataF.h> 16 #include <Ice/StreamHelpers.h> 17 18 namespace Ice 19 { 20 21 class UserException; 22 23 /** 24 * Interface for output streams used to create a sequence of bytes from Slice types. 25 * \headerfile Ice/Ice.h 26 */ 27 class ICE_API OutputStream : public IceInternal::Buffer 28 { 29 public: 30 31 typedef size_t size_type; 32 33 /** 34 * Constructs an OutputStream using the latest encoding version, the default format for 35 * class encoding, and the process string converters. You can supply a communicator later 36 * by calling initialize(). 37 */ 38 OutputStream(); 39 40 /** 41 * Constructs a stream using the communicator's default encoding version. 42 * @param communicator The communicator to use for marshaling tasks. 43 */ 44 OutputStream(const CommunicatorPtr& communicator); 45 46 /** 47 * Constructs a stream using the given communicator and encoding version. 48 * @param communicator The communicator to use for marshaling tasks. 49 * @param version The encoding version used to encode the data. 50 */ 51 OutputStream(const CommunicatorPtr& communicator, const EncodingVersion& version); 52 53 /** 54 * Constructs a stream using the given communicator and encoding version. 55 * @param communicator The communicator to use for marshaling tasks. 56 * @param version The encoding version used to encode the data. 57 * @param bytes Application-supplied memory that the stream uses as its initial marshaling buffer. The 58 * stream will reallocate if the size of the marshaled data exceeds the application's buffer. 59 */ 60 OutputStream(const CommunicatorPtr& communicator, const EncodingVersion& version, 61 const std::pair<const Byte*, const Byte*>& bytes); 62 ~OutputStream()63 ~OutputStream() 64 { 65 // Inlined for performance reasons. 66 67 if(_currentEncaps != &_preAllocatedEncaps) 68 { 69 clear(); // Not inlined. 70 } 71 } 72 73 /** 74 * Initializes the stream to use the communicator's default encoding version, class 75 * encoding format and string converters. Use this method if you originally constructed 76 * the stream without a communicator. 77 * @param communicator The communicator to use for marshaling tasks. 78 */ 79 void initialize(const CommunicatorPtr& communicator); 80 81 /** 82 * Initializes the stream to use the given encoding version and the communicator's 83 * default class encoding format and string converters. Use this method if you 84 * originally constructed the stream without a communicator. 85 * @param communicator The communicator to use for marshaling tasks. 86 * @param version The encoding version used to encode the data. 87 */ 88 void initialize(const CommunicatorPtr& communicator, const EncodingVersion& version); 89 90 /** 91 * Releases any data retained by encapsulations. 92 */ 93 void clear(); 94 95 /// \cond INTERNAL 96 // 97 // Must return Instance*, because we don't hold an InstancePtr for 98 // optimization reasons (see comments below). 99 // instance()100 IceInternal::Instance* instance() const { return _instance; } // Inlined for performance reasons. 101 /// \endcond 102 103 /** 104 * Sets the class encoding format. 105 * @param format The encoding format. 106 */ 107 void setFormat(FormatType format); 108 109 /** 110 * Obtains the closure data associated with this stream. 111 * @return The data as a void pointer. 112 */ 113 void* getClosure() const; 114 115 /** 116 * Associates closure data with this stream. 117 * @param p The data as a void pointer. 118 * @return The previous closure data, or nil. 119 */ 120 void* setClosure(void* p); 121 122 /** 123 * Swaps the contents of one stream with another. 124 * 125 * @param other The other stream. 126 */ 127 void swap(OutputStream& other); 128 129 /// \cond INTERNAL 130 void resetEncapsulation(); 131 /// \endcond 132 133 /** 134 * Resizes the stream to a new size. 135 * 136 * @param sz The new size. 137 */ resize(Container::size_type sz)138 void resize(Container::size_type sz) 139 { 140 b.resize(sz); 141 } 142 143 /** 144 * Marks the start of a class instance. 145 * @param data Contains the marshaled form of unknown slices from this instance. If not nil, 146 * these slices will be marshaled with the instance. 147 */ startValue(const SlicedDataPtr & data)148 void startValue(const SlicedDataPtr& data) 149 { 150 assert(_currentEncaps && _currentEncaps->encoder); 151 _currentEncaps->encoder->startInstance(ValueSlice, data); 152 } 153 154 /** 155 * Marks the end of a class instance. 156 */ endValue()157 void endValue() 158 { 159 assert(_currentEncaps && _currentEncaps->encoder); 160 _currentEncaps->encoder->endInstance(); 161 } 162 163 /** 164 * Marks the start of an exception instance. 165 * @param data Contains the marshaled form of unknown slices from this instance. If not nil, 166 * these slices will be marshaled with the instance. 167 */ startException(const SlicedDataPtr & data)168 void startException(const SlicedDataPtr& data) 169 { 170 assert(_currentEncaps && _currentEncaps->encoder); 171 _currentEncaps->encoder->startInstance(ExceptionSlice, data); 172 } 173 174 /** 175 * Marks the end of an exception instance. 176 */ endException()177 void endException() 178 { 179 assert(_currentEncaps && _currentEncaps->encoder); 180 _currentEncaps->encoder->endInstance(); 181 } 182 183 /** 184 * Writes the start of an encapsulation using the default encoding version and 185 * class encoding format. 186 */ 187 void startEncapsulation(); 188 189 /** 190 * Writes the start of an encapsulation using the given encoding version and 191 * class encoding format. 192 * @param encoding The encoding version to use for the encapsulation. 193 * @param format The class format to use for the encapsulation. 194 */ startEncapsulation(const EncodingVersion & encoding,FormatType format)195 void startEncapsulation(const EncodingVersion& encoding, FormatType format) 196 { 197 IceInternal::checkSupportedEncoding(encoding); 198 199 Encaps* oldEncaps = _currentEncaps; 200 if(!oldEncaps) // First allocated encaps? 201 { 202 _currentEncaps = &_preAllocatedEncaps; 203 } 204 else 205 { 206 _currentEncaps = new Encaps(); 207 _currentEncaps->previous = oldEncaps; 208 } 209 _currentEncaps->format = format; 210 _currentEncaps->encoding = encoding; 211 _currentEncaps->start = b.size(); 212 213 write(Int(0)); // Placeholder for the encapsulation length. 214 write(_currentEncaps->encoding); 215 } 216 217 /** 218 * Ends the current encapsulation. 219 */ endEncapsulation()220 void endEncapsulation() 221 { 222 assert(_currentEncaps); 223 224 // Size includes size and version. 225 const Int sz = static_cast<Int>(b.size() - _currentEncaps->start); 226 write(sz, &(*(b.begin() + _currentEncaps->start))); 227 228 Encaps* oldEncaps = _currentEncaps; 229 _currentEncaps = _currentEncaps->previous; 230 if(oldEncaps == &_preAllocatedEncaps) 231 { 232 oldEncaps->reset(); 233 } 234 else 235 { 236 delete oldEncaps; 237 } 238 } 239 240 /** 241 * Writes an empty encapsulation using the given encoding version. 242 * @param encoding The encoding version to use for the encapsulation. 243 */ writeEmptyEncapsulation(const EncodingVersion & encoding)244 void writeEmptyEncapsulation(const EncodingVersion& encoding) 245 { 246 IceInternal::checkSupportedEncoding(encoding); 247 write(Int(6)); // Size 248 write(encoding); 249 } 250 251 /** 252 * Copies the marshaled form of an encapsulation to the buffer. 253 * @param v The start of the buffer. 254 * @param sz The number of bytes to copy. 255 */ writeEncapsulation(const Byte * v,Int sz)256 void writeEncapsulation(const Byte* v, Int sz) 257 { 258 if(sz < 6) 259 { 260 throwEncapsulationException(__FILE__, __LINE__); 261 } 262 263 Container::size_type position = b.size(); 264 resize(position + sz); 265 memcpy(&b[position], &v[0], sz); 266 } 267 268 /** 269 * Determines the current encoding version. 270 * 271 * @return The encoding version. 272 */ getEncoding()273 const EncodingVersion& getEncoding() const 274 { 275 return _currentEncaps ? _currentEncaps->encoding : _encoding; 276 } 277 278 /** 279 * Writes the start of a value or exception slice. 280 * 281 * @param typeId The Slice type ID for this slice. 282 * @param compactId The compact ID corresponding to the type, or -1 if no compact ID is used. 283 * @param last True if this is the last slice, false otherwise. 284 */ startSlice(const std::string & typeId,int compactId,bool last)285 void startSlice(const std::string& typeId, int compactId, bool last) 286 { 287 assert(_currentEncaps && _currentEncaps->encoder); 288 _currentEncaps->encoder->startSlice(typeId, compactId, last); 289 } 290 291 /** 292 * Marks the end of a value or exception slice. 293 */ endSlice()294 void endSlice() 295 { 296 assert(_currentEncaps && _currentEncaps->encoder); 297 _currentEncaps->encoder->endSlice(); 298 } 299 300 /** 301 * Encodes the state of class instances whose insertion was delayed during a previous 302 * call to write. This member function must only be called once. For backward 303 * compatibility with encoding version 1.0, this function must only be called when 304 * non-optional data members or parameters use class types. 305 */ 306 void writePendingValues(); 307 308 /** 309 * Writes a size value. 310 * @param v A non-negative integer. 311 */ writeSize(Int v)312 void writeSize(Int v) // Inlined for performance reasons. 313 { 314 assert(v >= 0); 315 if(v > 254) 316 { 317 write(Byte(255)); 318 write(v); 319 } 320 else 321 { 322 write(static_cast<Byte>(v)); 323 } 324 } 325 326 /** 327 * Replaces a size value at the given destination in the stream. This function 328 * does not change the stream's current position. 329 * @param v A non-negative integer representing the size. 330 * @param dest The buffer destination for the size. 331 */ rewriteSize(Int v,Container::iterator dest)332 void rewriteSize(Int v, Container::iterator dest) 333 { 334 assert(v >= 0); 335 if(v > 254) 336 { 337 *dest++ = Byte(255); 338 write(v, dest); 339 } 340 else 341 { 342 *dest = static_cast<Byte>(v); 343 } 344 } 345 346 /** 347 * Writes a placeholder value for the size and returns the starting position of the 348 * size value; after writing the data, call endSize to patch the placeholder with 349 * the actual size at the given position. 350 * @return The starting position of the size value. 351 */ startSize()352 size_type startSize() 353 { 354 size_type position = b.size(); 355 write(Int(0)); 356 return position; 357 } 358 359 /** 360 * Updates the size value at the given position to contain a size based on the 361 * stream's current position. 362 * @param position The starting position of the size value as returned by startSize. 363 */ endSize(size_type position)364 void endSize(size_type position) 365 { 366 rewrite(static_cast<Int>(b.size() - position) - 4, position); 367 } 368 369 /** 370 * Copies the specified blob of bytes to the stream without modification. 371 * @param v The bytes to be copied. 372 */ 373 void writeBlob(const std::vector<Byte>& v); 374 375 /** 376 * Copies the specified blob of bytes to the stream without modification. 377 * @param v The start of the buffer to be copied. 378 * @param sz The number of bytes to be copied. 379 */ writeBlob(const Byte * v,Container::size_type sz)380 void writeBlob(const Byte* v, Container::size_type sz) 381 { 382 if(sz > 0) 383 { 384 Container::size_type position = b.size(); 385 resize(position + sz); 386 memcpy(&b[position], &v[0], sz); 387 } 388 } 389 390 /** 391 * Writes a data value to the stream. 392 * @param v The data value to be written. 393 */ write(const T & v)394 template<typename T> void write(const T& v) 395 { 396 StreamHelper<T, StreamableTraits<T>::helper>::write(this, v); 397 } 398 399 /** 400 * Writes an optional data value to the stream. 401 * @param tag The tag ID. 402 * @param v The data value to be written (if any). 403 */ write(Int tag,const IceUtil::Optional<T> & v)404 template<typename T> void write(Int tag, const IceUtil::Optional<T>& v) 405 { 406 if(!v) 407 { 408 return; // Optional not set 409 } 410 411 if(writeOptional(tag, StreamOptionalHelper<T, 412 StreamableTraits<T>::helper, 413 StreamableTraits<T>::fixedLength>::optionalFormat)) 414 { 415 StreamOptionalHelper<T, 416 StreamableTraits<T>::helper, 417 StreamableTraits<T>::fixedLength>::write(this, *v); 418 } 419 } 420 421 /** 422 * Writes a sequence of data values to the stream. 423 * @param v The sequence to be written. 424 */ write(const std::vector<T> & v)425 template<typename T> void write(const std::vector<T>& v) 426 { 427 if(v.empty()) 428 { 429 writeSize(0); 430 } 431 else 432 { 433 write(&v[0], &v[0] + v.size()); 434 } 435 } 436 437 /** 438 * Writes a sequence of data values to the stream. 439 * @param begin The beginning of the sequence. 440 * @param end The end of the sequence. 441 */ write(const T * begin,const T * end)442 template<typename T> void write(const T* begin, const T* end) 443 { 444 writeSize(static_cast<Int>(end - begin)); 445 for(const T* p = begin; p != end; ++p) 446 { 447 write(*p); 448 } 449 } 450 451 #ifdef ICE_CPP11_MAPPING 452 453 /** 454 * Writes a list of mandatory data values. 455 */ writeAll(const T & v)456 template<typename T> void writeAll(const T& v) 457 { 458 write(v); 459 } 460 461 /** 462 * Writes a list of mandatory data values. 463 */ writeAll(const T & v,const Te &...ve)464 template<typename T, typename... Te> void writeAll(const T& v, const Te&... ve) 465 { 466 write(v); 467 writeAll(ve...); 468 } 469 470 /** 471 * Writes a list of mandatory data values. 472 */ 473 template<size_t I = 0, typename... Te> 474 typename std::enable_if<I == sizeof...(Te), void>::type writeAll(std::tuple<Te...>)475 writeAll(std::tuple<Te...>) 476 { 477 // Do nothing. Either tuple is empty or we are at the end. 478 } 479 480 /** 481 * Writes a list of mandatory data values. 482 */ 483 template<size_t I = 0, typename... Te> 484 typename std::enable_if<I < sizeof...(Te), void>::type 485 writeAll(std::tuple<Te...> tuple) 486 { 487 write(std::get<I>(tuple)); 488 writeAll<I + 1, Te...>(tuple); 489 } 490 491 /** 492 * Writes a list of optional data values. 493 */ 494 template<typename T> writeAll(std::initializer_list<int> tags,const IceUtil::Optional<T> & v)495 void writeAll(std::initializer_list<int> tags, const IceUtil::Optional<T>& v) 496 { 497 write(*(tags.begin() + tags.size() - 1), v); 498 } 499 500 /** 501 * Writes a list of optional data values. 502 */ 503 template<typename T, typename... Te> writeAll(std::initializer_list<int> tags,const IceUtil::Optional<T> & v,const IceUtil::Optional<Te> &...ve)504 void writeAll(std::initializer_list<int> tags, const IceUtil::Optional<T>& v, const IceUtil::Optional<Te>&... ve) 505 { 506 size_t index = tags.size() - sizeof...(ve) - 1; 507 write(*(tags.begin() + index), v); 508 writeAll(tags, ve...); 509 } 510 511 #endif 512 513 /** 514 * Writes the tag and format of an optional value. 515 * @param tag The optional tag ID. 516 * @param format The optional format. 517 * @return True if the current encoding version supports optional values, false otherwise. 518 * If true, the data associated with the optional value must be written next. 519 */ writeOptional(Int tag,OptionalFormat format)520 bool writeOptional(Int tag, OptionalFormat format) 521 { 522 assert(_currentEncaps); 523 if(_currentEncaps->encoder) 524 { 525 return _currentEncaps->encoder->writeOptional(tag, format); 526 } 527 else 528 { 529 return writeOptImpl(tag, format); 530 } 531 } 532 533 /** 534 * Writes a byte to the stream. 535 * @param v The byte to write. 536 */ write(Byte v)537 void write(Byte v) 538 { 539 b.push_back(v); 540 } 541 542 /** 543 * Writes a byte sequence to the stream. 544 * @param start The beginning of the sequence. 545 * @param end The end of the sequence. 546 */ 547 void write(const Byte* start, const Byte* end); 548 549 /** 550 * Writes a boolean to the stream. 551 * @param v The boolean to write. 552 */ write(bool v)553 void write(bool v) 554 { 555 b.push_back(static_cast<Byte>(v)); 556 } 557 558 /** 559 * Writes a byte sequence to the stream. 560 * @param v The sequence to be written. 561 */ 562 void write(const std::vector<bool>& v); 563 564 /** 565 * Writes a byte sequence to the stream. 566 * @param begin The beginning of the sequence. 567 * @param end The end of the sequence. 568 */ 569 void write(const bool* begin, const bool* end); 570 571 /** 572 * Writes a short to the stream. 573 * @param v The short to write. 574 */ 575 void write(Short v); 576 577 /** 578 * Writes a short sequence to the stream. 579 * @param begin The beginning of the sequence. 580 * @param end The end of the sequence. 581 */ 582 void write(const Short* begin, const Short* end); 583 584 /** 585 * Writes an int to the stream. 586 * @param v The int to write. 587 */ write(Int v)588 void write(Int v) // Inlined for performance reasons. 589 { 590 Container::size_type position = b.size(); 591 resize(position + sizeof(Int)); 592 write(v, &b[position]); 593 } 594 595 /** 596 * Overwrites a 32-bit integer value at the given destination in the stream. 597 * This function does not change the stream's current position. 598 * @param v The integer value to be written. 599 * @param dest The buffer destination for the integer value. 600 */ write(Int v,Container::iterator dest)601 void write(Int v, Container::iterator dest) 602 { 603 #ifdef ICE_BIG_ENDIAN 604 const Byte* src = reinterpret_cast<const Byte*>(&v) + sizeof(Int) - 1; 605 *dest++ = *src--; 606 *dest++ = *src--; 607 *dest++ = *src--; 608 *dest = *src; 609 #else 610 const Byte* src = reinterpret_cast<const Byte*>(&v); 611 *dest++ = *src++; 612 *dest++ = *src++; 613 *dest++ = *src++; 614 *dest = *src; 615 #endif 616 } 617 618 /** 619 * Writes an int sequence to the stream. 620 * @param begin The beginning of the sequence. 621 * @param end The end of the sequence. 622 */ 623 void write(const Int* begin, const Int* end); 624 625 /** 626 * Writes a long to the stream. 627 * @param v The long to write. 628 */ 629 void write(Long v); 630 631 /** 632 * Writes a long sequence to the stream. 633 * @param begin The beginning of the sequence. 634 * @param end The end of the sequence. 635 */ 636 void write(const Long* begin, const Long* end); 637 638 /** 639 * Writes a float to the stream. 640 * @param v The float to write. 641 */ 642 void write(Float v); 643 644 /** 645 * Writes a float sequence to the stream. 646 * @param begin The beginning of the sequence. 647 * @param end The end of the sequence. 648 */ 649 void write(const Float* begin, const Float* end); 650 651 /** 652 * Writes a double to the stream. 653 * @param v The double to write. 654 */ 655 void write(Double v); 656 657 /** 658 * Writes a double sequence to the stream. 659 * @param begin The beginning of the sequence. 660 * @param end The end of the sequence. 661 */ 662 void write(const Double* begin, const Double* end); 663 664 /** 665 * Writes a string to the stream. 666 * @param v The string to write. 667 * @param convert Determines whether the string is processed by the narrow string converter, 668 * if one has been configured. The default behavior is to convert the strings. 669 */ 670 void write(const std::string& v, bool convert = true) 671 { 672 Int sz = static_cast<Int>(v.size()); 673 if(convert && sz > 0) 674 { 675 writeConverted(v.data(), static_cast<size_t>(sz)); 676 } 677 else 678 { 679 writeSize(sz); 680 if(sz > 0) 681 { 682 Container::size_type position = b.size(); 683 resize(position + sz); 684 memcpy(&b[position], v.data(), sz); 685 } 686 } 687 } 688 689 /** 690 * Writes a string to the stream. 691 * @param vdata The string to write. 692 * @param vsize The size of the string. 693 * @param convert Determines whether the string is processed by the narrow string converter, 694 * if one has been configured. The default behavior is to convert the strings. 695 */ 696 void write(const char* vdata, size_t vsize, bool convert = true) 697 { 698 Int sz = static_cast<Int>(vsize); 699 if(convert && sz > 0) 700 { 701 writeConverted(vdata, vsize); 702 } 703 else 704 { 705 writeSize(sz); 706 if(sz > 0) 707 { 708 Container::size_type position = b.size(); 709 resize(position + sz); 710 memcpy(&b[position], vdata, vsize); 711 } 712 } 713 } 714 715 /** 716 * Writes a string to the stream. 717 * @param vdata The null-terminated string to write. 718 * @param convert Determines whether the string is processed by the narrow string converter, 719 * if one has been configured. The default behavior is to convert the strings. 720 */ 721 void write(const char* vdata, bool convert = true) 722 { 723 write(vdata, strlen(vdata), convert); 724 } 725 726 /** 727 * Writes a string sequence to the stream. 728 * @param begin The beginning of the sequence. 729 * @param end The end of the sequence. 730 * @param convert Determines whether the string is processed by the narrow string converter, 731 * if one has been configured. The default behavior is to convert the strings. 732 */ 733 void write(const std::string* begin, const std::string* end, bool convert = true); 734 735 /** 736 * Writes a wide string to the stream. 737 * @param v The wide string to write. 738 */ 739 void write(const std::wstring& v); 740 741 /** 742 * Writes a wide string sequence to the stream. 743 * @param begin The beginning of the sequence. 744 * @param end The end of the sequence. 745 */ 746 void write(const std::wstring* begin, const std::wstring* end); 747 748 #ifdef ICE_CPP11_MAPPING 749 /** 750 * Writes a proxy to the stream. 751 * @param v The proxy to be written. 752 */ 753 void writeProxy(const ::std::shared_ptr<ObjectPrx>& v); 754 755 /** 756 * Writes a proxy to the stream. 757 * @param v The proxy to be written. 758 */ 759 template<typename T, typename ::std::enable_if<::std::is_base_of<ObjectPrx, T>::value>::type* = nullptr> write(const::std::shared_ptr<T> & v)760 void write(const ::std::shared_ptr<T>& v) 761 { 762 writeProxy(::std::static_pointer_cast<ObjectPrx>(v)); 763 } 764 #else 765 /** 766 * Writes a proxy to the stream. 767 * @param v The proxy to be written. 768 */ 769 void write(const ObjectPrx& v); 770 771 /** 772 * Writes a proxy to the stream. 773 * @param v The proxy to be written. 774 */ write(const IceInternal::ProxyHandle<T> & v)775 template<typename T> void write(const IceInternal::ProxyHandle<T>& v) 776 { 777 write(ObjectPrx(upCast(v.get()))); 778 } 779 #endif 780 781 #ifdef ICE_CPP11_MAPPING // C++11 mapping 782 /** 783 * Writes a value instance to the stream. 784 * @param v The value to be written. 785 */ 786 template<typename T, typename ::std::enable_if<::std::is_base_of<Value, T>::value>::type* = nullptr> write(const::std::shared_ptr<T> & v)787 void write(const ::std::shared_ptr<T>& v) 788 { 789 initEncaps(); 790 _currentEncaps->encoder->write(v); 791 } 792 #else // C++98 mapping 793 /** 794 * Writes a value instance to the stream. 795 * @param v The value to be written. 796 */ write(const ObjectPtr & v)797 void write(const ObjectPtr& v) 798 { 799 initEncaps(); 800 _currentEncaps->encoder->write(v); 801 } 802 803 /** 804 * Writes a value instance to the stream. 805 * @param v The value to be written. 806 */ write(const IceInternal::Handle<T> & v)807 template<typename T> void write(const IceInternal::Handle<T>& v) 808 { 809 write(ObjectPtr(upCast(v.get()))); 810 } 811 #endif 812 813 /** 814 * Writes an enumerator to the stream. 815 * @param v The enumerator to be written. 816 * @param maxValue The maximum value of all enumerators in this enumeration. 817 */ 818 void writeEnum(Int v, Int maxValue); 819 820 /** 821 * Writes an exception to the stream. 822 * @param v The exception to be written. 823 */ 824 void writeException(const UserException& v); 825 826 /** 827 * Obtains the current position of the stream. 828 * @return The current position. 829 */ pos()830 size_type pos() 831 { 832 return b.size(); 833 } 834 835 /** 836 * Overwrite a 32-bit integer value at the given position in the stream. 837 * This function does not change the stream's current position. 838 * @param v The value to be written. 839 * @param pos The buffer position for the value. 840 */ rewrite(Int v,size_type pos)841 void rewrite(Int v, size_type pos) 842 { 843 write(v, b.begin() + pos); 844 } 845 846 /** 847 * Indicates that marshaling is complete. This function must only be called once. 848 * @param v Filled with a copy of the encoded data. 849 */ 850 void finished(std::vector<Byte>& v); 851 852 /** 853 * Indicates that marshaling is complete. This function must only be called once. 854 * @return A pair of pointers into the internal marshaling buffer. These pointers are 855 * valid for the lifetime of the stream. 856 */ 857 std::pair<const Byte*, const Byte*> finished(); 858 859 /// \cond INTERNAL 860 OutputStream(IceInternal::Instance*, const EncodingVersion&); 861 void initialize(IceInternal::Instance*, const EncodingVersion&); 862 863 // Optionals 864 bool writeOptImpl(Int, OptionalFormat); 865 /// \endcond 866 867 private: 868 869 // 870 // String 871 // 872 void writeConverted(const char*, size_t); 873 874 // 875 // We can't throw this exception from inline functions from within 876 // this file, because we cannot include the header with the 877 // exceptions. Doing so would screw up the whole include file 878 // ordering. 879 // 880 void throwEncapsulationException(const char*, int); 881 882 // 883 // Optimization. The instance may not be deleted while a 884 // stack-allocated stream still holds it. 885 // 886 IceInternal::Instance* _instance; 887 888 // 889 // The public stream API needs to attach data to a stream. 890 // 891 void* _closure; 892 893 class Encaps; 894 enum SliceType { NoSlice, ValueSlice, ExceptionSlice }; 895 896 typedef std::vector<ValuePtr> ValueList; 897 898 class ICE_API EncapsEncoder : private ::IceUtil::noncopyable 899 { 900 public: 901 902 virtual ~EncapsEncoder(); 903 904 virtual void write(const ValuePtr&) = 0; 905 virtual void write(const UserException&) = 0; 906 907 virtual void startInstance(SliceType, const SlicedDataPtr&) = 0; 908 virtual void endInstance() = 0; 909 virtual void startSlice(const std::string&, int, bool) = 0; 910 virtual void endSlice() = 0; 911 writeOptional(Int,OptionalFormat)912 virtual bool writeOptional(Int, OptionalFormat) 913 { 914 return false; 915 } 916 writePendingValues()917 virtual void writePendingValues() 918 { 919 } 920 921 protected: 922 EncapsEncoder(OutputStream * stream,Encaps * encaps)923 EncapsEncoder(OutputStream* stream, Encaps* encaps) : _stream(stream), _encaps(encaps), _typeIdIndex(0) 924 { 925 } 926 927 Int registerTypeId(const std::string&); 928 929 OutputStream* _stream; 930 Encaps* _encaps; 931 932 typedef std::map<ValuePtr, Int> PtrToIndexMap; 933 typedef std::map<std::string, Int> TypeIdMap; 934 935 // Encapsulation attributes for value marshaling. 936 PtrToIndexMap _marshaledMap; 937 938 private: 939 940 // Encapsulation attributes for value marshaling. 941 TypeIdMap _typeIdMap; 942 Int _typeIdIndex; 943 }; 944 945 class ICE_API EncapsEncoder10 : public EncapsEncoder 946 { 947 public: 948 EncapsEncoder10(OutputStream * stream,Encaps * encaps)949 EncapsEncoder10(OutputStream* stream, Encaps* encaps) : 950 EncapsEncoder(stream, encaps), _sliceType(NoSlice), _valueIdIndex(0) 951 { 952 } 953 954 virtual void write(const ValuePtr&); 955 virtual void write(const UserException&); 956 957 virtual void startInstance(SliceType, const SlicedDataPtr&); 958 virtual void endInstance(); 959 virtual void startSlice(const std::string&, int, bool); 960 virtual void endSlice(); 961 962 virtual void writePendingValues(); 963 964 private: 965 966 Int registerValue(const ValuePtr&); 967 968 // Instance attributes 969 SliceType _sliceType; 970 971 // Slice attributes 972 Container::size_type _writeSlice; // Position of the slice data members 973 974 // Encapsulation attributes for value marshaling. 975 Int _valueIdIndex; 976 PtrToIndexMap _toBeMarshaledMap; 977 }; 978 979 class ICE_API EncapsEncoder11 : public EncapsEncoder 980 { 981 public: 982 EncapsEncoder11(OutputStream * stream,Encaps * encaps)983 EncapsEncoder11(OutputStream* stream, Encaps* encaps) : 984 EncapsEncoder(stream, encaps), _preAllocatedInstanceData(0), _current(0), _valueIdIndex(1) 985 { 986 } 987 988 virtual void write(const ValuePtr&); 989 virtual void write(const UserException&); 990 991 virtual void startInstance(SliceType, const SlicedDataPtr&); 992 virtual void endInstance(); 993 virtual void startSlice(const std::string&, int, bool); 994 virtual void endSlice(); 995 996 virtual bool writeOptional(Int, OptionalFormat); 997 998 private: 999 1000 void writeSlicedData(const SlicedDataPtr&); 1001 void writeInstance(const ValuePtr&); 1002 1003 struct InstanceData 1004 { InstanceDataInstanceData1005 InstanceData(InstanceData* p) : previous(p), next(0) 1006 { 1007 if(previous) 1008 { 1009 previous->next = this; 1010 } 1011 } 1012 ~InstanceDataInstanceData1013 ~InstanceData() 1014 { 1015 if(next) 1016 { 1017 delete next; 1018 } 1019 } 1020 1021 // Instance attributes 1022 SliceType sliceType; 1023 bool firstSlice; 1024 1025 // Slice attributes 1026 Byte sliceFlags; 1027 Container::size_type writeSlice; // Position of the slice data members 1028 Container::size_type sliceFlagsPos; // Position of the slice flags 1029 PtrToIndexMap indirectionMap; 1030 ValueList indirectionTable; 1031 1032 InstanceData* previous; 1033 InstanceData* next; 1034 }; 1035 InstanceData _preAllocatedInstanceData; 1036 InstanceData* _current; 1037 1038 Int _valueIdIndex; // The ID of the next value to marhsal 1039 }; 1040 1041 class Encaps : private ::IceUtil::noncopyable 1042 { 1043 1044 public: 1045 Encaps()1046 Encaps() : format(ICE_ENUM(FormatType, DefaultFormat)), encoder(0), previous(0) 1047 { 1048 // Inlined for performance reasons. 1049 } ~Encaps()1050 ~Encaps() 1051 { 1052 // Inlined for performance reasons. 1053 delete encoder; 1054 } reset()1055 void reset() 1056 { 1057 // Inlined for performance reasons. 1058 delete encoder; 1059 encoder = 0; 1060 1061 previous = 0; 1062 } 1063 1064 Container::size_type start; 1065 EncodingVersion encoding; 1066 FormatType format; 1067 1068 EncapsEncoder* encoder; 1069 1070 Encaps* previous; 1071 }; 1072 1073 // 1074 // The encoding version to use when there's no encapsulation to 1075 // read from or write to. This is for example used to read message 1076 // headers or when the user is using the streaming API with no 1077 // encapsulation. 1078 // 1079 EncodingVersion _encoding; 1080 1081 FormatType _format; 1082 1083 Encaps* _currentEncaps; 1084 1085 void initEncaps(); 1086 1087 Encaps _preAllocatedEncaps; 1088 }; 1089 1090 } // End namespace Ice 1091 1092 #endif 1093