// bslx_genericinstream.h -*-C++-*- #ifndef INCLUDED_BSLX_GENERICINSTREAM #define INCLUDED_BSLX_GENERICINSTREAM #include <bsls_ident.h> BSLS_IDENT("$Id: $") //@PURPOSE: Unexternalization of fundamental types from a parameterized stream. // //@CLASSES: // bslx::GenericInStream: parameterized input stream for fundamental types // //@SEE_ALSO: bslx_streambufinstream, bslx_genericoutstream // //@DESCRIPTION: This component implements a parameterized input stream // class, 'bslx::GenericInStream', that provides platform-independent input // methods ("unexternalization") on values, and arrays of values, of // fundamental types, and on 'bsl::string'. // // The 'bslx::GenericInStream' type reads from a compliant user-supplied buffer // (see {Generic Byte-Format Parser}) directly, with no data copying or // assumption of ownership. The user must therefore make sure that the // lifetime and visibility of the buffer is sufficient to satisfy the needs of // the input stream. // // This component is intended to be used in conjunction with the // 'bslx_genericoutstream' "externalization" component. Each input method of // 'bslx::GenericInStream' reads either a value or a homogeneous array of // values of a fundamental type, in a format that was written by the // corresponding 'bslx::GenericOutStream' method. In general, the user of // this component cannot rely on being able to read data that was written by // any mechanism other than 'bslx::GenericOutStream'. // // The supported types and required content are listed in the 'bslx' // package-level documentation under "Supported Types". // // Note that input streams can be *invalidated* explicitly and queried for // *validity*. Reading from an initially invalid stream has no effect. // Attempting to read beyond the end of a stream will automatically invalidate // the stream. Whenever an inconsistent value is detected, the stream should // be invalidated explicitly. // ///Generic Byte-Format Parser ///-------------------------- // The class 'bslx::GenericInStream' is parameterized by a buffered stream // class, 'STREAMBUF', which, given the declarations: //.. // char c; // int len; // const char *s; // STREAMBUF *sb; //.. // must make the following expressions syntactically valid, with the assert // statements highlighting the expected return values: //.. // STREAMBUF::traits_type::int_type eof = STREAMBUF::traits_type::eof(); // assert(eof != sb->sbumpc()); // assert(eof != sb->sgetc()); // assert(len == sb->sgetn(s, len)); //.. // Suitable choices for 'STREAMBUF' include any class that implements the // 'bsl::basic_streambuf' protocol. // // The class 'bslx::StreambufInStream' is a 'typedef' for // 'bslx::GenericInStream<bsl::streambuf>'. // ///Usage ///----- // This section illustrates intended use of this component. The first example // depicts usage with a 'bsl::stringbuf'. The second example replaces the // 'bsl::stringbuf' with a user-defined 'STREAMBUF'. // ///Example 1: Basic Unexternalization /// - - - - - - - - - - - - - - - - - // Suppose we wish to implement a (deliberately simple) 'MyPerson' class as a // value-semantic object that supports BDEX externalization and // unexternalization. In addition to whatever data and methods that we choose // to put into our design, we must supply three methods having specific names // and signatures in order to comply with the BDEX protocol: a class method // 'maxSupportedBdexVersion', an accessor (i.e., a 'const' method) // 'bdexStreamOut', and a manipulator (i.e., a non-'const' method) // 'bdexStreamIn'. This example shows how to implement those three methods. // // In this example we will not worry overly about "good design" of the // 'MyPerson' component, and we will declare but not implement illustrative // methods and free operators, except for the three required BDEX methods, // which are implemented in full. In particular, we will not make explicit use // of 'bslma' allocators; a more complete design would do so: // // First, we implement 'MyPerson': //.. // class MyPerson { // bsl::string d_firstName; // bsl::string d_lastName; // int d_age; // // friend bool operator==(const MyPerson&, const MyPerson&); // // public: // // CLASS METHODS // static int maxSupportedBdexVersion(int versionSelector); // // Return the maximum valid BDEX format version, as indicated by // // the specified 'versionSelector', to be passed to the // // 'bdexStreamOut' method. Note that it is highly recommended that // // 'versionSelector' be formatted as "YYYYMMDD", a date // // representation. Also note that 'versionSelector' should be a // // *compile*-time-chosen value that selects a format version // // supported by both externalizer and unexternalizer. See the // // 'bslx' package-level documentation for more information on BDEX // // streaming of value-semantic types and containers. // // // CREATORS // MyPerson(); // // Create a default person. // // MyPerson(const char *firstName, const char *lastName, int age); // // Create a person having the specified 'firstName', 'lastName', // // and 'age'. // // MyPerson(const MyPerson& original); // // Create a person having the value of the specified 'original' // // person. // // ~MyPerson(); // // Destroy this object. // // // MANIPULATORS // MyPerson& operator=(const MyPerson& rhs); // // Assign to this person the value of the specified 'rhs' person, // // and return a reference to this person. // // template <class STREAM> // STREAM& bdexStreamIn(STREAM& stream, int version); // // Assign to this object the value read from the specified input // // 'stream' using the specified 'version' format, and return a // // reference to 'stream'. If 'stream' is initially invalid, this // // operation has no effect. If 'version' is not supported, this // // object is unaltered and 'stream' is invalidated, but otherwise // // unmodified. If 'version' is supported but 'stream' becomes // // invalid during this operation, this object has an undefined, but // // valid, state. Note that no version is read from 'stream'. See // // the 'bslx' package-level documentation for more information on // // BDEX streaming of value-semantic types and containers. // // //... // // // ACCESSORS // int age() const; // // Return the age of this person. // // template <class STREAM> // STREAM& bdexStreamOut(STREAM& stream, int version) const; // // Write the value of this object, using the specified 'version' // // format, to the specified output 'stream', and return a reference // // to 'stream'. If 'stream' is initially invalid, this operation // // has no effect. If 'version' is not supported, 'stream' is // // invalidated, but otherwise unmodified. Note that 'version' is // // not written to 'stream'. See the 'bslx' package-level // // documentation for more information on BDEX streaming of // // value-semantic types and containers. // // const bsl::string& firstName() const; // // Return the first name of this person. // // const bsl::string& lastName() const; // // Return the last name of this person. // // //... // // }; // // // FREE OPERATORS // bool operator==(const MyPerson& lhs, const MyPerson& rhs); // // Return 'true' if the specified 'lhs' and 'rhs' person objects have // // the same value, and 'false' otherwise. Two person objects have the // // same value if they have the same first name, last name, and age. // // bool operator!=(const MyPerson& lhs, const MyPerson& rhs); // // Return 'true' if the specified 'lhs' and 'rhs' person objects do not // // have the same value, and 'false' otherwise. Two person objects // // differ in value if they differ in first name, last name, or age. // // // ======================================================================== // // INLINE FUNCTION DEFINITIONS // // ======================================================================== // // // CLASS METHODS // inline // int MyPerson::maxSupportedBdexVersion(int /* versionSelector */) { // return 1; // } // // // CREATORS // inline // MyPerson::MyPerson() // : d_firstName("") // , d_lastName("") // , d_age(0) // { // } // // inline // MyPerson::MyPerson(const char *firstName, const char *lastName, int age) // : d_firstName(firstName) // , d_lastName(lastName) // , d_age(age) // { // } // // inline // MyPerson::~MyPerson() // { // } // // template <class STREAM> // STREAM& MyPerson::bdexStreamIn(STREAM& stream, int version) // { // if (stream) { // switch (version) { // switch on the 'bslx' version // case 1: { // stream.getString(d_firstName); // if (!stream) { // d_firstName = "stream error"; // *might* be corrupted; // // value for testing // return stream; // RETURN // } // stream.getString(d_lastName); // if (!stream) { // d_lastName = "stream error"; // *might* be corrupted; // // value for testing // return stream; // RETURN // } // stream.getInt32(d_age); // if (!stream) { // d_age = 999; // *might* be corrupted; value for testing // return stream; // RETURN // } // } break; // default: { // stream.invalidate(); // } // } // } // return stream; // } // // // ACCESSORS // inline // int MyPerson::age() const // { // return d_age; // } // // template <class STREAM> // STREAM& MyPerson::bdexStreamOut(STREAM& stream, int version) const // { // switch (version) { // case 1: { // stream.putString(d_firstName); // stream.putString(d_lastName); // stream.putInt32(d_age); // } break; // default: { // stream.invalidate(); // } break; // } // return stream; // } // // inline // const bsl::string& MyPerson::firstName() const // { // return d_firstName; // } // // inline // const bsl::string& MyPerson::lastName() const // { // return d_lastName; // } // // // FREE OPERATORS // inline // bool operator==(const MyPerson& lhs, const MyPerson& rhs) // { // return lhs.d_firstName == rhs.d_firstName && // lhs.d_lastName == rhs.d_lastName && // lhs.d_age == rhs.d_age; // } // // inline // bool operator!=(const MyPerson& lhs, const MyPerson& rhs) // { // return !(lhs == rhs); // } //.. // Then, we can exercise the new 'MyPerson' value-semantic class by // externalizing and reconstituting an object. First, create a 'MyPerson' // 'janeSmith1' and a 'bslx::GenericOutStream' 'outStream1': //.. // MyPerson janeSmith1("Jane", "Smith", 42); // bsl::stringbuf buffer1; // bslx::GenericOutStream<bsl::stringbuf> outStream1(&buffer1, 20131127); // const int VERSION1 = 1; // outStream1.putVersion(VERSION1); // janeSmith1.bdexStreamOut(outStream1, VERSION1); // assert(outStream1.isValid()); //.. // Next, create a 'MyPerson' 'janeCopy1' initialized to the default value, and // assert that 'janeCopy1' is different from 'janeSmith1': //.. // MyPerson janeCopy1; // assert(janeCopy1 != janeSmith1); //.. // Then, create a 'bslx::GenericInStream' 'inStream1' initialized with the // buffer from the 'bslx::GenericOutStream' object 'outStream1' and // unexternalize this data into 'janeCopy1': //.. // bslx::GenericInStream<bsl::stringbuf> inStream1(&buffer1); // int version1; // inStream1.getVersion(version1); // janeCopy1.bdexStreamIn(inStream1, version1); // assert(inStream1.isValid()); //.. // Finally, 'assert' the obtained values are as expected and display the // results to 'bsl::stdout': //.. // assert(version1 == VERSION1); // assert(janeCopy1 == janeSmith1); // // if (janeCopy1 == janeSmith1) { // bsl::cout << "Successfully serialized and de-serialized Jane Smith:" // << "\n\tFirstName: " << janeCopy1.firstName() // << "\n\tLastName : " << janeCopy1.lastName() // << "\n\tAge : " << janeCopy1.age() << bsl::endl; // } // else { // bsl::cout << "Serialization unsuccessful. 'janeCopy1' holds:" // << "\n\tFirstName: " << janeCopy1.firstName() // << "\n\tLastName : " << janeCopy1.lastName() // << "\n\tAge : " << janeCopy1.age() << bsl::endl; // } //.. // ///Example 2: Sample 'STREAMBUF' Implementation /// - - - - - - - - - - - - - - - - - - - - - - // For this example, we will implement 'MyStreamBuf', a minimal 'STREAMBUF' to // to be used with 'bslx::GenericInStream' and 'bslx::GenericOutStream'. The // implementation will consist of only what is required of the type. For // comparison, we will reuse 'MyPerson' and repeat part of {Example 1} to // demonstrate how to use 'bslx::GenericInStream'. // // First, we implement 'MyStreamBuf' (which, for brevity, simply uses the // default allocator): //.. // class MyStreamBuf { // // This class implements a very basic stream buffer suitable for use in // // 'bslx::GenericOutStream' and 'bslx::GenericInStream'. // // // DATA // bsl::deque<char> d_buffer; // the input and output buffer // // private: // // NOT IMPLEMENTED // MyStreamBuf(const MyStreamBuf&); // MyStreamBuf& operator=(const MyStreamBuf&); // // public: // // TYPES // struct traits_type { // static int eof() { return -1; } // }; // // // CREATORS // MyStreamBuf(); // // Create an empty stream buffer. // // ~MyStreamBuf(); // // Destroy this stream buffer. // // // MANIPULATORS // int pubsync(); // // Return 0. // // int sbumpc(); // // Read the next character in this buffer. Return the value of the // // character on success, and 'traits_type::eof()' otherwise. // // int sgetc(); // // Peek at the next character in this buffer. Return the value of // // the character on success, and 'traits_type::eof()' otherwise. // // bsl::streamsize sgetn(char *s, bsl::streamsize length); // // Load the specified 'length' characters into the specified // // address 's', and return the number of characters read. // // int sputc(char c); // // Write the specified character 'c' to this buffer. Return 'c' on // // success, and 'traits_type::eof()' otherwise. // // bsl::streamsize sputn(const char *s, bsl::streamsize length); // // Write the specified 'length' characters at the specified address // // 's' to this buffer, and return the number of characters written. // }; // // // ======================================================================== // // INLINE FUNCTION DEFINITIONS // // ======================================================================== // // // CREATORS // MyStreamBuf::MyStreamBuf() // : d_buffer() // { // } // // MyStreamBuf::~MyStreamBuf() // { // } // // // MANIPULATORS // int MyStreamBuf::pubsync() // { // // In this implementation, there is nothing to be done except return // // success. // // return 0; // } // // int MyStreamBuf::sbumpc() // { // if (!d_buffer.empty()) { // const int rv = static_cast<int>(d_buffer.front()); // d_buffer.pop_front(); // return rv; // RETURN // } // return traits_type::eof(); // } // // int MyStreamBuf::sgetc() // { // if (!d_buffer.empty()) { // return static_cast<int>(d_buffer.front()); // RETURN // } // return traits_type::eof(); // } // // bsl::streamsize MyStreamBuf::sgetn(char *s, bsl::streamsize length) // { // for (bsl::streamsize i = 0; i < length; ++i) { // if (d_buffer.empty()) { // return i; // RETURN // } // s[i] = d_buffer.front(); // d_buffer.pop_front(); // } // return length; // } // // int MyStreamBuf::sputc(char c) // { // d_buffer.push_back(c); // return static_cast<int>(c); // } // // bsl::streamsize MyStreamBuf::sputn(const char *s, // bsl::streamsize length) // { // for (bsl::streamsize i = 0; i < length; ++i) { // d_buffer.push_back(s[i]); // } // return length; // } //.. // Then, we create a 'MyPerson' 'janeSmith2' and a 'bslx::GenericOutStream' // 'outStream2': //.. // MyPerson janeSmith2("Jane", "Smith", 42); // MyStreamBuf buffer2; // bslx::GenericOutStream<MyStreamBuf> outStream2(&buffer2, 20131127); // const int VERSION2 = 1; // outStream2.putVersion(VERSION2); // janeSmith2.bdexStreamOut(outStream2, VERSION2); // assert(outStream2.isValid()); //.. // Next, create a 'MyPerson' 'janeCopy2' initialized to the default value, and // assert that 'janeCopy2' is different from 'janeSmith2': //.. // MyPerson janeCopy2; // assert(janeCopy2 != janeSmith2); //.. // Then, create a 'bslx::GenericInStream' 'inStream2' initialized with the // buffer from the 'bslx::GenericOutStream' object 'outStream2' and // unexternalize this data into 'janeCopy2': //.. // bslx::GenericInStream<MyStreamBuf> inStream2(&buffer2); // int version2; // inStream2.getVersion(version2); // janeCopy2.bdexStreamIn(inStream2, version2); // assert(inStream2.isValid()); //.. // Finally, 'assert' the obtained values are as expected: //.. // assert(version2 == VERSION2); // assert(janeCopy2 == janeSmith2); //.. #include <bslscm_version.h> #include <bslx_instreamfunctions.h> #include <bsls_assert.h> #include <bsls_performancehint.h> #include <bsls_platform.h> #include <bsls_types.h> #include <bsl_cstddef.h> #include <bsl_string.h> #include <bsl_vector.h> namespace BloombergLP { namespace bslx { // ===================== // class GenericInStream // ===================== template <class STREAMBUF> class GenericInStream { // This class provides input methods to unexternalize values, and C-style // arrays of values, of the fundamental integral and floating-point types, // as well as 'bsl::string' values, using a byte format documented in the // 'bslx_byteoutstream' component. In particular, each 'get' method of // this class is guaranteed to read stream data written by the // corresponding 'put' method of 'bslx::GenericOutStream'. Note that // attempting to read beyond the end of a stream will automatically // invalidate the stream. See the 'bslx' package-level documentation for // the definition of the BDEX 'InStream' protocol. // PRIVATE TYPES enum { // Enumerate the platform-independent sizes (in bytes) of data types in // wire format. Note that the wire format size may differ from the // size in memory. k_SIZEOF_INT64 = 8, k_SIZEOF_INT56 = 7, k_SIZEOF_INT48 = 6, k_SIZEOF_INT40 = 5, k_SIZEOF_INT32 = 4, k_SIZEOF_INT24 = 3, k_SIZEOF_INT16 = 2, k_SIZEOF_INT8 = 1, k_SIZEOF_FLOAT64 = 8, k_SIZEOF_FLOAT32 = 4 }; // DATA STREAMBUF *d_streamBuf; // held stream to read from bool d_validFlag; // stream validity flag; 'true' if stream is in // valid state, 'false' otherwise // NOT IMPLEMENTED GenericInStream(const GenericInStream&); GenericInStream& operator=(const GenericInStream&); private: // PRIVATE MANIPULATORS void validate(); // Put this output stream into a valid state. This function has no // effect if this stream is already valid. public: // CREATORS GenericInStream(STREAMBUF *streamBuf); // Create an input byte stream that reads its input from the specified // 'streamBuf'. ~GenericInStream(); // Destroy this object. // MANIPULATORS GenericInStream& getLength(int& length); // If the most-significant bit of the one byte of this stream at the // current cursor location is set, assign to the specified 'length' the // four-byte, two's complement integer (in host byte order) comprised // of the four bytes of this stream at the current cursor location (in // network byte order) with the most-significant bit unset; otherwise, // assign to 'length' the one-byte, two's complement integer comprised // of the one byte of this stream at the current cursor location. // Update the cursor location and return a reference to this stream. // If this stream is initially invalid, this operation has no effect. // If this function otherwise fails to extract a valid value, this // stream is marked invalid and the value of 'length' is undefined. // Note that the value will be zero-extended. GenericInStream& getVersion(int& version); // Assign to the specified 'version' the one-byte, two's complement // unsigned integer comprised of the one byte of this stream at the // current cursor location, update the cursor location, and return a // reference to this stream. If this stream is initially invalid, this // operation has no effect. If this function otherwise fails to // extract a valid value, this stream is marked invalid and the value // of 'version' is undefined. Note that the value will be // zero-extended. void invalidate(); // Put this input stream in an invalid state. This function has no // effect if this stream is already invalid. Note that this function // should be called whenever a value extracted from this stream is // determined to be invalid, inconsistent, or otherwise incorrect. // *** scalar integer values *** GenericInStream& getInt64(bsls::Types::Int64& variable); // Assign to the specified 'variable' the eight-byte, two's complement // integer (in host byte order) comprised of the eight bytes of this // stream at the current cursor location (in network byte order), // update the cursor location, and return a reference to this stream. // If this stream is initially invalid, this operation has no effect. // If this function otherwise fails to extract a valid value, this // stream is marked invalid and the value of 'variable' is undefined. // Note that the value will be sign-extended. GenericInStream& getUint64(bsls::Types::Uint64& variable); // Assign to the specified 'variable' the eight-byte, two's complement // unsigned integer (in host byte order) comprised of the eight bytes // of this stream at the current cursor location (in network byte // order), update the cursor location, and return a reference to this // stream. If this stream is initially invalid, this operation has no // effect. If this function otherwise fails to extract a valid value, // this stream is marked invalid and the value of 'variable' is // undefined. Note that the value will be zero-extended. GenericInStream& getInt56(bsls::Types::Int64& variable); // Assign to the specified 'variable' the seven-byte, two's complement // integer (in host byte order) comprised of the seven bytes of this // stream at the current cursor location (in network byte order), // update the cursor location, and return a reference to this stream. // If this stream is initially invalid, this operation has no effect. // If this function otherwise fails to extract a valid value, this // stream is marked invalid and the value of 'variable' is undefined. // Note that the value will be sign-extended. GenericInStream& getUint56(bsls::Types::Uint64& variable); // Assign to the specified 'variable' the seven-byte, two's complement // unsigned integer (in host byte order) comprised of the seven bytes // of this stream at the current cursor location (in network byte // order), update the cursor location, and return a reference to this // stream. If this stream is initially invalid, this operation has no // effect. If this function otherwise fails to extract a valid value, // this stream is marked invalid and the value of 'variable' is // undefined. Note that the value will be zero-extended. GenericInStream& getInt48(bsls::Types::Int64& variable); // Assign to the specified 'variable' the six-byte, two's complement // integer (in host byte order) comprised of the six bytes of this // stream at the current cursor location (in network byte order), // update the cursor location, and return a reference to this stream. // If this stream is initially invalid, this operation has no effect. // If this function otherwise fails to extract a valid value, this // stream is marked invalid and the value of 'variable' is undefined. // Note that the value will be sign-extended. GenericInStream& getUint48(bsls::Types::Uint64& variable); // Assign to the specified 'variable' the six-byte, two's complement // unsigned integer (in host byte order) comprised of the six bytes of // this stream at the current cursor location (in network byte order), // update the cursor location, and return a reference to this stream. // If this stream is initially invalid, this operation has no effect. // If this function otherwise fails to extract a valid value, this // stream is marked invalid and the value of 'variable' is undefined. // Note that the value will be zero-extended. GenericInStream& getInt40(bsls::Types::Int64& variable); // Assign to the specified 'variable' the five-byte, two's complement // integer (in host byte order) comprised of the five bytes of this // stream at the current cursor location (in network byte order), // update the cursor location, and return a reference to this stream. // If this stream is initially invalid, this operation has no effect. // If this function otherwise fails to extract a valid value, this // stream is marked invalid and the value of 'variable' is undefined. // Note that the value will be sign-extended. GenericInStream& getUint40(bsls::Types::Uint64& variable); // Assign to the specified 'variable' the five-byte, two's complement // unsigned integer (in host byte order) comprised of the five bytes of // this stream at the current cursor location (in network byte order), // update the cursor location, and return a reference to this stream. // If this stream is initially invalid, this operation has no effect. // If this function otherwise fails to extract a valid value, this // stream is marked invalid and the value of 'variable' is undefined. // Note that the value will be zero-extended. GenericInStream& getInt32(int& variable); // Assign to the specified 'variable' the four-byte, two's complement // integer (in host byte order) comprised of the four bytes of this // stream at the current cursor location (in network byte order), // update the cursor location, and return a reference to this stream. // If this stream is initially invalid, this operation has no effect. // If this function otherwise fails to extract a valid value, this // stream is marked invalid and the value of 'variable' is undefined. // Note that the value will be sign-extended. GenericInStream& getUint32(unsigned int& variable); // Assign to the specified 'variable' the four-byte, two's complement // unsigned integer (in host byte order) comprised of the four bytes of // this stream at the current cursor location (in network byte order), // update the cursor location, and return a reference to this stream. // If this stream is initially invalid, this operation has no effect. // If this function otherwise fails to extract a valid value, this // stream is marked invalid and the value of 'variable' is undefined. // Note that the value will be zero-extended. GenericInStream& getInt24(int& variable); // Assign to the specified 'variable' the three-byte, two's complement // integer (in host byte order) comprised of the three bytes of this // stream at the current cursor location (in network byte order), // update the cursor location, and return a reference to this stream. // If this stream is initially invalid, this operation has no effect. // If this function otherwise fails to extract a valid value, this // stream is marked invalid and the value of 'variable' is undefined. // Note that the value will be sign-extended. GenericInStream& getUint24(unsigned int& variable); // Assign to the specified 'variable' the three-byte, two's complement // unsigned integer (in host byte order) comprised of the three bytes // of this stream at the current cursor location (in network byte // order), update the cursor location, and return a reference to this // stream. If this stream is initially invalid, this operation has no // effect. If this function otherwise fails to extract a valid value, // this stream is marked invalid and the value of 'variable' is // undefined. Note that the value will be zero-extended. GenericInStream& getInt16(short& variable); // Assign to the specified 'variable' the two-byte, two's complement // integer (in host byte order) comprised of the two bytes of this // stream at the current cursor location (in network byte order), // update the cursor location, and return a reference to this stream. // If this stream is initially invalid, this operation has no effect. // If this function otherwise fails to extract a valid value, this // stream is marked invalid and the value of 'variable' is undefined. // Note that the value will be sign-extended. GenericInStream& getUint16(unsigned short& variable); // Assign to the specified 'variable' the two-byte, two's complement // unsigned integer (in host byte order) comprised of the two bytes of // this stream at the current cursor location (in network byte order), // update the cursor location, and return a reference to this stream. // If this stream is initially invalid, this operation has no effect. // If this function otherwise fails to extract a valid value, this // stream is marked invalid and the value of 'variable' is undefined. // Note that the value will be zero-extended. GenericInStream& getInt8(char& variable); GenericInStream& getInt8(signed char& variable); // Assign to the specified 'variable' the one-byte, two's complement // integer comprised of the one byte of this stream at the current // cursor location, update the cursor location, and return a reference // to this stream. If this stream is initially invalid, this operation // has no effect. If this function otherwise fails to extract a valid // value, this stream is marked invalid and the value of 'variable' is // undefined. Note that the value will be sign-extended. GenericInStream& getUint8(char& variable); GenericInStream& getUint8(unsigned char& variable); // Assign to the specified 'variable' the one-byte, two's complement // unsigned integer comprised of the one byte of this stream at the // current cursor location, update the cursor location, and return a // reference to this stream. If this stream is initially invalid, this // operation has no effect. If this function otherwise fails to // extract a valid value, this stream is marked invalid and the value // of 'variable' is undefined. Note that the value will be // zero-extended. // *** scalar floating-point values *** GenericInStream& getFloat64(double& variable); // Assign to the specified 'variable' the eight-byte IEEE // double-precision floating-point number (in host byte order) // comprised of the eight bytes of this stream at the current cursor // location (in network byte order), update the cursor location, and // return a reference to this stream. If this stream is initially // invalid, this operation has no effect. If this function otherwise // fails to extract a valid value, this stream is marked invalid and // the value of 'variable' is undefined. GenericInStream& getFloat32(float& variable); // Assign to the specified 'variable' the four-byte IEEE // single-precision floating-point number (in host byte order) // comprised of the four bytes of this stream at the current cursor // location (in network byte order), update the cursor location, and // return a reference to this stream. If this stream is initially // invalid, this operation has no effect. If this function otherwise // fails to extract a valid value, this stream is marked invalid and // the value of 'variable' is undefined. // *** string values *** GenericInStream& getString(bsl::string& variable); // Assign to the specified 'variable' the string comprised of the // length of the string (see 'getLength') and the string data (see // 'getUint8'), update the cursor location, and return a reference to // this stream. If this stream is initially invalid, this operation // has no effect. If this function otherwise fails to extract a valid // value, this stream is marked invalid and the value of 'variable' is // undefined. // *** arrays of integer values *** GenericInStream& getArrayInt64(bsls::Types::Int64 *variables, int numVariables); // Assign to the specified 'variables' the consecutive eight-byte, // two's complement integers (in host byte order) comprised of each of // the specified 'numVariables' eight-byte sequences of this stream at // the current cursor location (in network byte order), update the // cursor location, and return a reference to this stream. If this // stream is initially invalid, this operation has no effect. If this // function otherwise fails to extract a valid value, this stream is // marked invalid and the value of 'variables' is undefined. The // behavior is undefined unless '0 <= numVariables' and 'variables' has // sufficient capacity. Note that each of the values will be // sign-extended. GenericInStream& getArrayUint64(bsls::Types::Uint64 *variables, int numVariables); // Assign to the specified 'variables' the consecutive eight-byte, // two's complement unsigned integers (in host byte order) comprised of // each of the specified 'numVariables' eight-byte sequences of this // stream at the current cursor location (in network byte order), // update the cursor location, and return a reference to this stream. // If this stream is initially invalid, this operation has no effect. // If this function otherwise fails to extract a valid value, this // stream is marked invalid and the value of 'variables' is undefined. // The behavior is undefined unless '0 <= numVariables' and 'variables' // has sufficient capacity. Note that each of the values will be // zero-extended. GenericInStream& getArrayInt56(bsls::Types::Int64 *variables, int numVariables); // Assign to the specified 'variables' the consecutive seven-byte, // two's complement integers (in host byte order) comprised of each of // the specified 'numVariables' seven-byte sequences of this stream at // the current cursor location (in network byte order), update the // cursor location, and return a reference to this stream. If this // stream is initially invalid, this operation has no effect. If this // function otherwise fails to extract a valid value, this stream is // marked invalid and the value of 'variables' is undefined. The // behavior is undefined unless '0 <= numVariables' and 'variables' has // sufficient capacity. Note that each of the values will be // sign-extended. GenericInStream& getArrayUint56(bsls::Types::Uint64 *variables, int numVariables); // Assign to the specified 'variables' the consecutive seven-byte, // two's complement unsigned integers (in host byte order) comprised of // each of the specified 'numVariables' seven-byte sequences of this // stream at the current cursor location (in network byte order), // update the cursor location, and return a reference to this stream. // If this stream is initially invalid, this operation has no effect. // If this function otherwise fails to extract a valid value, this // stream is marked invalid and the value of 'variables' is undefined. // The behavior is undefined unless '0 <= numVariables' and 'variables' // has sufficient capacity. Note that each of the values will be // zero-extended. GenericInStream& getArrayInt48(bsls::Types::Int64 *variables, int numVariables); // Assign to the specified 'variables' the consecutive six-byte, two's // complement integers (in host byte order) comprised of each of the // specified 'numVariables' six-byte sequences of this stream at the // current cursor location (in network byte order), update the cursor // location, and return a reference to this stream. If this stream is // initially invalid, this operation has no effect. If this function // otherwise fails to extract a valid value, this stream is marked // invalid and the value of 'variables' is undefined. The behavior is // undefined unless '0 <= numVariables' and 'variables' has sufficient // capacity. Note that each of the values will be sign-extended. GenericInStream& getArrayUint48(bsls::Types::Uint64 *variables, int numVariables); // Assign to the specified 'variables' the consecutive six-byte, two's // complement unsigned integers (in host byte order) comprised of each // of the specified 'numVariables' six-byte sequences of this stream at // the current cursor location (in network byte order), update the // cursor location, and return a reference to this stream. If this // stream is initially invalid, this operation has no effect. If this // function otherwise fails to extract a valid value, this stream is // marked invalid and the value of 'variables' is undefined. The // behavior is undefined unless '0 <= numVariables' and 'variables' has // sufficient capacity. Note that each of the values will be // zero-extended. GenericInStream& getArrayInt40(bsls::Types::Int64 *variables, int numVariables); // Assign to the specified 'variables' the consecutive five-byte, two's // complement integers (in host byte order) comprised of each of the // specified 'numVariables' five-byte sequences of this stream at the // current cursor location (in network byte order), update the cursor // location, and return a reference to this stream. If this stream is // initially invalid, this operation has no effect. If this function // otherwise fails to extract a valid value, this stream is marked // invalid and the value of 'variables' is undefined. The behavior is // undefined unless '0 <= numVariables' and 'variables' has sufficient // capacity. Note that each of the values will be sign-extended. GenericInStream& getArrayUint40(bsls::Types::Uint64 *variables, int numVariables); // Assign to the specified 'variables' the consecutive five-byte, two's // complement unsigned integers (in host byte order) comprised of each // of the specified 'numVariables' five-byte sequences of this stream // at the current cursor location (in network byte order), update the // cursor location, and return a reference to this stream. If this // stream is initially invalid, this operation has no effect. If this // function otherwise fails to extract a valid value, this stream is // marked invalid and the value of 'variables' is undefined. The // behavior is undefined unless '0 <= numVariables' and 'variables' has // sufficient capacity. Note that each of the values will be // zero-extended. GenericInStream& getArrayInt32(int *variables, int numVariables); // Assign to the specified 'variables' the consecutive four-byte, two's // complement integers (in host byte order) comprised of each of the // specified 'numVariables' four-byte sequences of this stream at the // current cursor location (in network byte order), update the cursor // location, and return a reference to this stream. If this stream is // initially invalid, this operation has no effect. If this function // otherwise fails to extract a valid value, this stream is marked // invalid and the value of 'variables' is undefined. The behavior is // undefined unless '0 <= numVariables' and 'variables' has sufficient // capacity. Note that each of the values will be sign-extended. GenericInStream& getArrayUint32(unsigned int *variables, int numVariables); // Assign to the specified 'variables' the consecutive four-byte, two's // complement unsigned integers (in host byte order) comprised of each // of the specified 'numVariables' four-byte sequences of this stream // at the current cursor location (in network byte order), update the // cursor location, and return a reference to this stream. If this // stream is initially invalid, this operation has no effect. If this // function otherwise fails to extract a valid value, this stream is // marked invalid and the value of 'variables' is undefined. The // behavior is undefined unless '0 <= numVariables' and 'variables' has // sufficient capacity. Note that each of the values will be // zero-extended. GenericInStream& getArrayInt24(int *variables, int numVariables); // Assign to the specified 'variables' the consecutive three-byte, // two's complement integers (in host byte order) comprised of each of // the specified 'numVariables' three-byte sequences of this stream at // the current cursor location (in network byte order), update the // cursor location, and return a reference to this stream. If this // stream is initially invalid, this operation has no effect. If this // function otherwise fails to extract a valid value, this stream is // marked invalid and the value of 'variables' is undefined. The // behavior is undefined unless '0 <= numValues' and 'variables' has // sufficient capacity. Note that each of the values will be // sign-extended. GenericInStream& getArrayUint24(unsigned int *variables, int numVariables); // Assign to the specified 'variables' the consecutive three-byte, // two's complement unsigned integers (in host byte order) comprised of // each of the specified 'numVariables' three-byte sequences of this // stream at the current cursor location (in network byte order), // update the cursor location, and return a reference to this stream. // If this stream is initially invalid, this operation has no effect. // If this function otherwise fails to extract a valid value, this // stream is marked invalid and the value of 'variables' is undefined. // The behavior is undefined unless '0 <= numVariables' and 'variables' // has sufficient capacity. Note that each of the values will be // zero-extended. GenericInStream& getArrayInt16(short *variables, int numVariables); // Assign to the specified 'variables' the consecutive two-byte, two's // complement integers (in host byte order) comprised of each of the // specified 'numVariables' two-byte sequences of this stream at the // current cursor location (in network byte order), update the cursor // location, and return a reference to this stream. If this stream is // initially invalid, this operation has no effect. If this function // otherwise fails to extract a valid value, this stream is marked // invalid and the value of 'variables' is undefined. The behavior is // undefined unless '0 <= numVariables' and 'variables' has sufficient // capacity. Note that each of the values will be sign-extended. GenericInStream& getArrayUint16(unsigned short *variables, int numVariables); // Assign to the specified 'variables' the consecutive two-byte, two's // complement unsigned integers (in host byte order) comprised of each // of the specified 'numVariables' two-byte sequences of this stream at // the current cursor location (in network byte order), update the // cursor location, and return a reference to this stream. If this // stream is initially invalid, this operation has no effect. If this // function otherwise fails to extract a valid value, this stream is // marked invalid and the value of 'variables' is undefined. The // behavior is undefined unless '0 <= numVariables' and 'variables' has // sufficient capacity. Note that each of the values will be // zero-extended. GenericInStream& getArrayInt8(char *variables, int numVariables); GenericInStream& getArrayInt8(signed char *variables, int numVariables); // Assign to the specified 'variables' the consecutive one-byte, two's // complement integers comprised of each of the specified // 'numVariables' one-byte sequences of this stream at the current // cursor location, update the cursor location, and return a reference // to this stream. If this stream is initially invalid, this operation // has no effect. If this function otherwise fails to extract a valid // value, this stream is marked invalid and the value of 'variables' is // undefined. The behavior is undefined unless '0 <= numVariables' and // 'variables' has sufficient capacity. Note that each of the values // will be sign-extended. GenericInStream& getArrayUint8(char *variables, int numVariables); GenericInStream& getArrayUint8(unsigned char *variables, int numVariables); // Assign to the specified 'variables' the consecutive one-byte, two's // complement unsigned integers comprised of each of the specified // 'numVariables' one-byte sequences of this stream at the current // cursor location, update the cursor location, and return a reference // to this stream. If this stream is initially invalid, this operation // has no effect. If this function otherwise fails to extract a valid // value, this stream is marked invalid and the value of 'variables' is // undefined. The behavior is undefined unless '0 <= numVariables' and // 'variables' has sufficient capacity. Note that each of the values // will be zero-extended. // *** arrays of floating-point values *** GenericInStream& getArrayFloat64(double *variables, int numVariables); // Assign to the specified 'variables' the consecutive eight-byte IEEE // double-precision floating-point numbers (in host byte order) // comprised of each of the specified 'numVariables' eight-byte // sequences of this stream at the current cursor location (in network // byte order), update the cursor location, and return a reference to // this stream. If this stream is initially invalid, this operation // has no effect. If this function otherwise fails to extract a valid // value, this stream is marked invalid and the value of 'variables' is // undefined. The behavior is undefined unless '0 <= numVariables' and // 'variables' has sufficient capacity. GenericInStream& getArrayFloat32(float *variables, int numVariables); // Assign to the specified 'variables' the consecutive four-byte IEEE // single-precision floating-point numbers (in host byte order) // comprised of each of the specified 'numVariables' four-byte // sequences of this stream at the current cursor location (in network // byte order), update the cursor location, and return a reference to // this stream. If this stream is initially invalid, this operation // has no effect. If this function otherwise fails to extract a valid // value, this stream is marked invalid and the value of 'variables' is // undefined. The behavior is undefined unless '0 <= numVariables' and // 'variables' has sufficient capacity. // ACCESSORS operator const void *() const; // Return a non-zero value if this stream is valid, and 0 otherwise. // An invalid stream is a stream in which insufficient or invalid data // was detected during an extraction operation. Note that an empty // stream will be valid unless an extraction attempt or explicit // invalidation causes it to be otherwise. bool isValid() const; // Return 'true' if this stream is valid, and 'false' otherwise. An // invalid stream is a stream in which insufficient or invalid data was // detected during an extraction operation. Note that an empty stream // will be valid unless an extraction attempt or explicit invalidation // causes it to be otherwise. }; // FREE OPERATORS template <class STREAMBUF, class TYPE> GenericInStream<STREAMBUF>& operator>>(GenericInStream<STREAMBUF>& stream, TYPE& value); // Read the specified 'value' from the specified input 'stream' following // the requirements of the BDEX protocol (see the 'bslx' package-level // documentation), and return a reference to 'stream'. The behavior is // undefined unless 'TYPE' is BDEX-compliant. // ============================================================================ // INLINE DEFINITIONS // ============================================================================ // --------------------- // class GenericInStream // --------------------- // PRIVATE MANIPULATORS template <class STREAMBUF> inline void GenericInStream<STREAMBUF>::validate() { d_validFlag = true; } // CREATORS template <class STREAMBUF> inline GenericInStream<STREAMBUF>::GenericInStream(STREAMBUF *streamBuf) : d_streamBuf(streamBuf) , d_validFlag(true) { BSLS_ASSERT_SAFE(streamBuf); } template <class STREAMBUF> inline GenericInStream<STREAMBUF>::~GenericInStream() { } // MANIPULATORS template <class STREAMBUF> inline GenericInStream<STREAMBUF>& GenericInStream<STREAMBUF>::getLength(int& length) { if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid())) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } invalidate(); const int current = d_streamBuf->sgetc(); if (STREAMBUF::traits_type::eof() != current) { validate(); if (127 < current) { // If 'length > 127', 'length' is stored as 4 bytes with top bit // set. getInt32(length); length &= 0x7fffffff; // Clear top bit. } else { // If 'length <= 127', 'length' is stored as one byte. char tmp = 0; getInt8(tmp); length = tmp; } } return *this; } template <class STREAMBUF> inline GenericInStream<STREAMBUF>& GenericInStream<STREAMBUF>::getVersion(int& version) { if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid())) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } unsigned char tmp; getUint8(tmp); version = tmp; return *this; } template <class STREAMBUF> inline void GenericInStream<STREAMBUF>::invalidate() { d_validFlag = false; } // *** scalar integer values *** template <class STREAMBUF> inline GenericInStream<STREAMBUF>& GenericInStream<STREAMBUF>::getInt64(bsls::Types::Int64& variable) { if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid())) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } invalidate(); if (sizeof variable > k_SIZEOF_INT64) { const int current = d_streamBuf->sgetc(); if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY( STREAMBUF::traits_type::eof() == current)) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } variable = 0x80 & current ? -1 : 0; // sign extend } #ifdef BSLS_PLATFORM_IS_LITTLE_ENDIAN char *bytes = reinterpret_cast<char *>(&variable); char rawBytes[k_SIZEOF_INT64]; if (k_SIZEOF_INT64 == d_streamBuf->sgetn(rawBytes, k_SIZEOF_INT64)) { validate(); bytes[7] = rawBytes[0]; bytes[6] = rawBytes[1]; bytes[5] = rawBytes[2]; bytes[4] = rawBytes[3]; bytes[3] = rawBytes[4]; bytes[2] = rawBytes[5]; bytes[1] = rawBytes[6]; bytes[0] = rawBytes[7]; } #else char *bytes = reinterpret_cast<char *>(&variable) + sizeof variable - k_SIZEOF_INT64; if (k_SIZEOF_INT64 == d_streamBuf->sgetn(bytes, k_SIZEOF_INT64)) { validate(); } #endif return *this; } template <class STREAMBUF> inline GenericInStream<STREAMBUF>& GenericInStream<STREAMBUF>::getUint64(bsls::Types::Uint64& variable) { if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid())) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } invalidate(); if (sizeof variable > k_SIZEOF_INT64) { variable = 0; // zero-extend } #ifdef BSLS_PLATFORM_IS_LITTLE_ENDIAN char *bytes = reinterpret_cast<char *>(&variable); char rawBytes[k_SIZEOF_INT64]; if (k_SIZEOF_INT64 == d_streamBuf->sgetn(rawBytes, k_SIZEOF_INT64)) { validate(); bytes[7] = rawBytes[0]; bytes[6] = rawBytes[1]; bytes[5] = rawBytes[2]; bytes[4] = rawBytes[3]; bytes[3] = rawBytes[4]; bytes[2] = rawBytes[5]; bytes[1] = rawBytes[6]; bytes[0] = rawBytes[7]; } #else char *bytes = reinterpret_cast<char *>(&variable) + sizeof variable - k_SIZEOF_INT64; if (k_SIZEOF_INT64 == d_streamBuf->sgetn(bytes, k_SIZEOF_INT64)) { validate(); } #endif return *this; } template <class STREAMBUF> inline GenericInStream<STREAMBUF>& GenericInStream<STREAMBUF>::getInt56(bsls::Types::Int64& variable) { if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid())) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } invalidate(); const int current = d_streamBuf->sgetc(); if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY( STREAMBUF::traits_type::eof() == current)) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } variable = 0x80 & current ? -1 : 0; // sign extend #ifdef BSLS_PLATFORM_IS_LITTLE_ENDIAN char *bytes = reinterpret_cast<char *>(&variable); char rawBytes[k_SIZEOF_INT56]; if (k_SIZEOF_INT56 == d_streamBuf->sgetn(rawBytes, k_SIZEOF_INT56)) { validate(); bytes[6] = rawBytes[0]; bytes[5] = rawBytes[1]; bytes[4] = rawBytes[2]; bytes[3] = rawBytes[3]; bytes[2] = rawBytes[4]; bytes[1] = rawBytes[5]; bytes[0] = rawBytes[6]; } #else char *bytes = reinterpret_cast<char *>(&variable) + sizeof variable - k_SIZEOF_INT56; if (k_SIZEOF_INT56 == d_streamBuf->sgetn(bytes, k_SIZEOF_INT56)) { validate(); } #endif return *this; } template <class STREAMBUF> inline GenericInStream<STREAMBUF>& GenericInStream<STREAMBUF>::getUint56(bsls::Types::Uint64& variable) { if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid())) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } invalidate(); variable = 0; // zero-extend #ifdef BSLS_PLATFORM_IS_LITTLE_ENDIAN char *bytes = reinterpret_cast<char *>(&variable); char rawBytes[k_SIZEOF_INT56]; if (k_SIZEOF_INT56 == d_streamBuf->sgetn(rawBytes, k_SIZEOF_INT56)) { validate(); bytes[6] = rawBytes[0]; bytes[5] = rawBytes[1]; bytes[4] = rawBytes[2]; bytes[3] = rawBytes[3]; bytes[2] = rawBytes[4]; bytes[1] = rawBytes[5]; bytes[0] = rawBytes[6]; } #else char *bytes = reinterpret_cast<char *>(&variable) + sizeof variable - k_SIZEOF_INT56; if (k_SIZEOF_INT56 == d_streamBuf->sgetn(bytes, k_SIZEOF_INT56)) { validate(); } #endif return *this; } template <class STREAMBUF> inline GenericInStream<STREAMBUF>& GenericInStream<STREAMBUF>::getInt48(bsls::Types::Int64& variable) { if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid())) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } invalidate(); const int current = d_streamBuf->sgetc(); if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY( STREAMBUF::traits_type::eof() == current)) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } variable = 0x80 & current ? -1 : 0; // sign extend #ifdef BSLS_PLATFORM_IS_LITTLE_ENDIAN char *bytes = reinterpret_cast<char *>(&variable); char rawBytes[k_SIZEOF_INT48]; if (k_SIZEOF_INT48 == d_streamBuf->sgetn(rawBytes, k_SIZEOF_INT48)) { validate(); bytes[5] = rawBytes[0]; bytes[4] = rawBytes[1]; bytes[3] = rawBytes[2]; bytes[2] = rawBytes[3]; bytes[1] = rawBytes[4]; bytes[0] = rawBytes[5]; } #else char *bytes = reinterpret_cast<char *>(&variable) + sizeof variable - k_SIZEOF_INT48; if (k_SIZEOF_INT48 == d_streamBuf->sgetn(bytes, k_SIZEOF_INT48)) { validate(); } #endif return *this; } template <class STREAMBUF> inline GenericInStream<STREAMBUF>& GenericInStream<STREAMBUF>::getUint48(bsls::Types::Uint64& variable) { if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid())) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } invalidate(); variable = 0; // zero-extend #ifdef BSLS_PLATFORM_IS_LITTLE_ENDIAN char *bytes = reinterpret_cast<char *>(&variable); char rawBytes[k_SIZEOF_INT48]; if (k_SIZEOF_INT48 == d_streamBuf->sgetn(rawBytes, k_SIZEOF_INT48)) { validate(); bytes[5] = rawBytes[0]; bytes[4] = rawBytes[1]; bytes[3] = rawBytes[2]; bytes[2] = rawBytes[3]; bytes[1] = rawBytes[4]; bytes[0] = rawBytes[5]; } #else char *bytes = reinterpret_cast<char *>(&variable) + sizeof variable - k_SIZEOF_INT48; if (k_SIZEOF_INT48 == d_streamBuf->sgetn(bytes, k_SIZEOF_INT48)) { validate(); } #endif return *this; } template <class STREAMBUF> inline GenericInStream<STREAMBUF>& GenericInStream<STREAMBUF>::getInt40(bsls::Types::Int64& variable) { if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid())) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } invalidate(); const int current = d_streamBuf->sgetc(); if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY( STREAMBUF::traits_type::eof() == current)) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } variable = 0x80 & current ? -1 : 0; // sign extend #ifdef BSLS_PLATFORM_IS_LITTLE_ENDIAN char *bytes = reinterpret_cast<char *>(&variable); char rawBytes[k_SIZEOF_INT40]; if (k_SIZEOF_INT40 == d_streamBuf->sgetn(rawBytes, k_SIZEOF_INT40)) { validate(); bytes[4] = rawBytes[0]; bytes[3] = rawBytes[1]; bytes[2] = rawBytes[2]; bytes[1] = rawBytes[3]; bytes[0] = rawBytes[4]; } #else char *bytes = reinterpret_cast<char *>(&variable) + sizeof variable - k_SIZEOF_INT40; if (k_SIZEOF_INT40 == d_streamBuf->sgetn(bytes, k_SIZEOF_INT40)) { validate(); } #endif return *this; } template <class STREAMBUF> inline GenericInStream<STREAMBUF>& GenericInStream<STREAMBUF>::getUint40(bsls::Types::Uint64& variable) { if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid())) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } invalidate(); variable = 0; // zero-extend #ifdef BSLS_PLATFORM_IS_LITTLE_ENDIAN char *bytes = reinterpret_cast<char *>(&variable); char rawBytes[k_SIZEOF_INT40]; if (k_SIZEOF_INT40 == d_streamBuf->sgetn(rawBytes, k_SIZEOF_INT40)) { validate(); bytes[4] = rawBytes[0]; bytes[3] = rawBytes[1]; bytes[2] = rawBytes[2]; bytes[1] = rawBytes[3]; bytes[0] = rawBytes[4]; } #else char *bytes = reinterpret_cast<char *>(&variable) + sizeof variable - k_SIZEOF_INT40; if (k_SIZEOF_INT40 == d_streamBuf->sgetn(bytes, k_SIZEOF_INT40)) { validate(); } #endif return *this; } template <class STREAMBUF> inline GenericInStream<STREAMBUF>& GenericInStream<STREAMBUF>::getInt32(int& variable) { if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid())) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } invalidate(); if (sizeof variable > k_SIZEOF_INT32) { const int current = d_streamBuf->sgetc(); if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY( STREAMBUF::traits_type::eof() == current)) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } variable = 0x80 & current ? -1 : 0; // sign extend } #ifdef BSLS_PLATFORM_IS_LITTLE_ENDIAN char *bytes = reinterpret_cast<char *>(&variable); char rawBytes[k_SIZEOF_INT32]; if (k_SIZEOF_INT32 == d_streamBuf->sgetn(rawBytes, k_SIZEOF_INT32)) { validate(); bytes[3] = rawBytes[0]; bytes[2] = rawBytes[1]; bytes[1] = rawBytes[2]; bytes[0] = rawBytes[3]; } #else char *bytes = reinterpret_cast<char *>(&variable) + sizeof variable - k_SIZEOF_INT32; if (k_SIZEOF_INT32 == d_streamBuf->sgetn(bytes, k_SIZEOF_INT32)) { validate(); } #endif return *this; } template <class STREAMBUF> inline GenericInStream<STREAMBUF>& GenericInStream<STREAMBUF>::getUint32(unsigned int& variable) { if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid())) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } invalidate(); if (sizeof variable > k_SIZEOF_INT32) { variable = 0; // zero-extend } #ifdef BSLS_PLATFORM_IS_LITTLE_ENDIAN char *bytes = reinterpret_cast<char *>(&variable); char rawBytes[k_SIZEOF_INT32]; if (k_SIZEOF_INT32 == d_streamBuf->sgetn(rawBytes, k_SIZEOF_INT32)) { validate(); bytes[3] = rawBytes[0]; bytes[2] = rawBytes[1]; bytes[1] = rawBytes[2]; bytes[0] = rawBytes[3]; } #else char *bytes = reinterpret_cast<char *>(&variable) + sizeof variable - k_SIZEOF_INT32; if (k_SIZEOF_INT32 == d_streamBuf->sgetn(bytes, k_SIZEOF_INT32)) { validate(); } #endif return *this; } template <class STREAMBUF> inline GenericInStream<STREAMBUF>& GenericInStream<STREAMBUF>::getInt24(int& variable) { if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid())) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } invalidate(); const int current = d_streamBuf->sgetc(); if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY( STREAMBUF::traits_type::eof() == current)) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } variable = 0x80 & current ? -1 : 0; // sign extend #ifdef BSLS_PLATFORM_IS_LITTLE_ENDIAN char *bytes = reinterpret_cast<char *>(&variable); char rawBytes[k_SIZEOF_INT24]; if (k_SIZEOF_INT24 == d_streamBuf->sgetn(rawBytes, k_SIZEOF_INT24)) { validate(); bytes[2] = rawBytes[0]; bytes[1] = rawBytes[1]; bytes[0] = rawBytes[2]; } #else char *bytes = reinterpret_cast<char *>(&variable) + sizeof variable - k_SIZEOF_INT24; if (k_SIZEOF_INT24 == d_streamBuf->sgetn(bytes, k_SIZEOF_INT24)) { validate(); } #endif return *this; } template <class STREAMBUF> inline GenericInStream<STREAMBUF>& GenericInStream<STREAMBUF>::getUint24(unsigned int& variable) { if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid())) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } invalidate(); variable = 0; // zero-extend #ifdef BSLS_PLATFORM_IS_LITTLE_ENDIAN char *bytes = reinterpret_cast<char *>(&variable); char rawBytes[k_SIZEOF_INT24]; if (k_SIZEOF_INT24 == d_streamBuf->sgetn(rawBytes, k_SIZEOF_INT24)) { validate(); bytes[2] = rawBytes[0]; bytes[1] = rawBytes[1]; bytes[0] = rawBytes[2]; } #else char *bytes = reinterpret_cast<char *>(&variable) + sizeof variable - k_SIZEOF_INT24; if (k_SIZEOF_INT24 == d_streamBuf->sgetn(bytes, k_SIZEOF_INT24)) { validate(); } #endif return *this; } template <class STREAMBUF> inline GenericInStream<STREAMBUF>& GenericInStream<STREAMBUF>::getInt16(short& variable) { if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid())) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } invalidate(); if (sizeof variable > k_SIZEOF_INT16) { const int current = d_streamBuf->sgetc(); if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY( STREAMBUF::traits_type::eof() == current)) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } variable = 0x80 & current ? -1 : 0; // sign extend } #ifdef BSLS_PLATFORM_IS_LITTLE_ENDIAN char *bytes = reinterpret_cast<char *>(&variable); char rawBytes[k_SIZEOF_INT16]; if (k_SIZEOF_INT16 == d_streamBuf->sgetn(rawBytes, k_SIZEOF_INT16)) { validate(); bytes[1] = rawBytes[0]; bytes[0] = rawBytes[1]; } #else char *bytes = reinterpret_cast<char *>(&variable) + sizeof variable - k_SIZEOF_INT16; if (k_SIZEOF_INT16 == d_streamBuf->sgetn(bytes, k_SIZEOF_INT16)) { validate(); } #endif return *this; } template <class STREAMBUF> inline GenericInStream<STREAMBUF>& GenericInStream<STREAMBUF>::getUint16(unsigned short& variable) { if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid())) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } invalidate(); if (sizeof variable > k_SIZEOF_INT16) { variable = 0; // zero-extend } #ifdef BSLS_PLATFORM_IS_LITTLE_ENDIAN char *bytes = reinterpret_cast<char *>(&variable); char rawBytes[k_SIZEOF_INT16]; if (k_SIZEOF_INT16 == d_streamBuf->sgetn(rawBytes, k_SIZEOF_INT16)) { validate(); bytes[1] = rawBytes[0]; bytes[0] = rawBytes[1]; } #else char *bytes = reinterpret_cast<char *>(&variable) + sizeof variable - k_SIZEOF_INT16; if (k_SIZEOF_INT16 == d_streamBuf->sgetn(bytes, k_SIZEOF_INT16)) { validate(); } #endif return *this; } template <class STREAMBUF> inline GenericInStream<STREAMBUF>& GenericInStream<STREAMBUF>::getInt8(char& variable) { if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid())) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } invalidate(); const int current = d_streamBuf->sbumpc(); if (STREAMBUF::traits_type::eof() != current) { validate(); variable = static_cast<char>(current); } return *this; } template <class STREAMBUF> inline GenericInStream<STREAMBUF>& GenericInStream<STREAMBUF>::getInt8(signed char& variable) { return getInt8(reinterpret_cast<char&>(variable)); } template <class STREAMBUF> inline GenericInStream<STREAMBUF>& GenericInStream<STREAMBUF>::getUint8(char& variable) { return getInt8(variable); } template <class STREAMBUF> inline GenericInStream<STREAMBUF>& GenericInStream<STREAMBUF>::getUint8(unsigned char& variable) { return getInt8(reinterpret_cast<char&>(variable)); } // *** scalar floating-point values *** template <class STREAMBUF> inline GenericInStream<STREAMBUF>& GenericInStream<STREAMBUF>::getFloat64(double& variable) { if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid())) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } invalidate(); if (sizeof variable > k_SIZEOF_FLOAT64) { variable = 0; // zero-fill mantissa } #ifdef BSLS_PLATFORM_IS_LITTLE_ENDIAN char *bytes = reinterpret_cast<char *>(&variable); char rawBytes[k_SIZEOF_FLOAT64]; if (k_SIZEOF_FLOAT64 == d_streamBuf->sgetn(rawBytes, k_SIZEOF_FLOAT64)) { validate(); bytes[sizeof variable - 1] = rawBytes[0]; bytes[sizeof variable - 2] = rawBytes[1]; bytes[sizeof variable - 3] = rawBytes[2]; bytes[sizeof variable - 4] = rawBytes[3]; bytes[sizeof variable - 5] = rawBytes[4]; bytes[sizeof variable - 6] = rawBytes[5]; bytes[sizeof variable - 7] = rawBytes[6]; bytes[sizeof variable - 8] = rawBytes[7]; } #else char *bytes = reinterpret_cast<char *>(&variable); if (k_SIZEOF_FLOAT64 == d_streamBuf->sgetn(bytes, k_SIZEOF_FLOAT64)) { validate(); } #endif return *this; } template <class STREAMBUF> inline GenericInStream<STREAMBUF>& GenericInStream<STREAMBUF>::getFloat32(float& variable) { if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid())) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } invalidate(); if (sizeof variable > k_SIZEOF_FLOAT32) { variable = 0; // zero-fill mantissa } #ifdef BSLS_PLATFORM_IS_LITTLE_ENDIAN char *bytes = reinterpret_cast<char *>(&variable); char rawBytes[k_SIZEOF_FLOAT32]; if (k_SIZEOF_FLOAT32 == d_streamBuf->sgetn(rawBytes, k_SIZEOF_FLOAT32)) { validate(); bytes[sizeof variable - 1] = rawBytes[0]; bytes[sizeof variable - 2] = rawBytes[1]; bytes[sizeof variable - 3] = rawBytes[2]; bytes[sizeof variable - 4] = rawBytes[3]; } #else char *bytes = reinterpret_cast<char *>(&variable); if (k_SIZEOF_FLOAT32 == d_streamBuf->sgetn(bytes, k_SIZEOF_FLOAT32)) { validate(); } #endif return *this; } // *** string values *** template <class STREAMBUF> GenericInStream<STREAMBUF>& GenericInStream<STREAMBUF>::getString(bsl::string& variable) { if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid())) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } int length = 0; getLength(length); if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid())) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } // 'length' could be corrupt or invalid, so we limit the initial 'resize' // to something that can accommodate the preponderance of strings that will // arise in practice. The remaining portion of a string longer than 16M is // read in via a second pass. enum { k_INITIAL_ALLOCATION_SIZE = 16 * 1024 * 1024 }; const int initialLength = length < k_INITIAL_ALLOCATION_SIZE ? length : k_INITIAL_ALLOCATION_SIZE; variable.resize(initialLength); if (0 == length) { return *this; // RETURN } getArrayUint8(&variable.front(), initialLength); if (isValid() && length > initialLength) { variable.resize(length); getArrayUint8(&variable[initialLength], length - initialLength); } return *this; } // *** arrays of integer values *** template <class STREAMBUF> GenericInStream<STREAMBUF>& GenericInStream<STREAMBUF>::getArrayInt64(bsls::Types::Int64 *variables, int numVariables) { BSLS_ASSERT(variables); BSLS_ASSERT(0 <= numVariables); if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY( !isValid() || 0 == numVariables)) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } const bsls::Types::Int64 *end = variables + numVariables; for (; variables != end; ++variables) { getInt64(*variables); } return *this; } template <class STREAMBUF> GenericInStream<STREAMBUF>& GenericInStream<STREAMBUF>::getArrayUint64(bsls::Types::Uint64 *variables, int numVariables) { BSLS_ASSERT(variables); BSLS_ASSERT(0 <= numVariables); if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY( !isValid() || 0 == numVariables)) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } const bsls::Types::Uint64 *end = variables + numVariables; for (; variables != end; ++variables) { getUint64(*variables); } return *this; } template <class STREAMBUF> GenericInStream<STREAMBUF>& GenericInStream<STREAMBUF>::getArrayInt56(bsls::Types::Int64 *variables, int numVariables) { BSLS_ASSERT(variables); BSLS_ASSERT(0 <= numVariables); if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY( !isValid() || 0 == numVariables)) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } const bsls::Types::Int64 *end = variables + numVariables; for (; variables != end; ++variables) { getInt56(*variables); } return *this; } template <class STREAMBUF> GenericInStream<STREAMBUF>& GenericInStream<STREAMBUF>::getArrayUint56(bsls::Types::Uint64 *variables, int numVariables) { BSLS_ASSERT(variables); BSLS_ASSERT(0 <= numVariables); if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY( !isValid() || 0 == numVariables)) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } const bsls::Types::Uint64 *end = variables + numVariables; for (; variables != end; ++variables) { getUint56(*variables); } return *this; } template <class STREAMBUF> GenericInStream<STREAMBUF>& GenericInStream<STREAMBUF>::getArrayInt48(bsls::Types::Int64 *variables, int numVariables) { BSLS_ASSERT(variables); BSLS_ASSERT(0 <= numVariables); if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY( !isValid() || 0 == numVariables)) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } const bsls::Types::Int64 *end = variables + numVariables; for (; variables != end; ++variables) { getInt48(*variables); } return *this; } template <class STREAMBUF> GenericInStream<STREAMBUF>& GenericInStream<STREAMBUF>::getArrayUint48(bsls::Types::Uint64 *variables, int numVariables) { BSLS_ASSERT(variables); BSLS_ASSERT(0 <= numVariables); if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY( !isValid() || 0 == numVariables)) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } const bsls::Types::Uint64 *end = variables + numVariables; for (; variables != end; ++variables) { getUint48(*variables); } return *this; } template <class STREAMBUF> GenericInStream<STREAMBUF>& GenericInStream<STREAMBUF>::getArrayInt40(bsls::Types::Int64 *variables, int numVariables) { BSLS_ASSERT(variables); BSLS_ASSERT(0 <= numVariables); if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY( !isValid() || 0 == numVariables)) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } const bsls::Types::Int64 *end = variables + numVariables; for (; variables != end; ++variables) { getInt40(*variables); } return *this; } template <class STREAMBUF> GenericInStream<STREAMBUF>& GenericInStream<STREAMBUF>::getArrayUint40(bsls::Types::Uint64 *variables, int numVariables) { BSLS_ASSERT(variables); BSLS_ASSERT(0 <= numVariables); if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY( !isValid() || 0 == numVariables)) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } const bsls::Types::Uint64 *end = variables + numVariables; for (; variables != end; ++variables) { getUint40(*variables); } return *this; } template <class STREAMBUF> GenericInStream<STREAMBUF>& GenericInStream<STREAMBUF>::getArrayInt32(int *variables, int numVariables) { BSLS_ASSERT(variables); BSLS_ASSERT(0 <= numVariables); if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY( !isValid() || 0 == numVariables)) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } const int *end = variables + numVariables; for (; variables != end; ++variables) { getInt32(*variables); } return *this; } template <class STREAMBUF> GenericInStream<STREAMBUF>& GenericInStream<STREAMBUF>::getArrayUint32(unsigned int *variables, int numVariables) { BSLS_ASSERT(variables); BSLS_ASSERT(0 <= numVariables); if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY( !isValid() || 0 == numVariables)) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } const unsigned int *end = variables + numVariables; for (; variables != end; ++variables) { getUint32(*variables); } return *this; } template <class STREAMBUF> GenericInStream<STREAMBUF>& GenericInStream<STREAMBUF>::getArrayInt24(int *variables, int numVariables) { BSLS_ASSERT(variables); BSLS_ASSERT(0 <= numVariables); if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY( !isValid() || 0 == numVariables)) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } const int *end = variables + numVariables; for (; variables != end; ++variables) { getInt24(*variables); } return *this; } template <class STREAMBUF> GenericInStream<STREAMBUF>& GenericInStream<STREAMBUF>::getArrayUint24(unsigned int *variables, int numVariables) { BSLS_ASSERT(variables); BSLS_ASSERT(0 <= numVariables); if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY( !isValid() || 0 == numVariables)) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } const unsigned int *end = variables + numVariables; for (; variables != end; ++variables) { getUint24(*variables); } return *this; } template <class STREAMBUF> GenericInStream<STREAMBUF>& GenericInStream<STREAMBUF>::getArrayInt16(short *variables, int numVariables) { BSLS_ASSERT(variables); BSLS_ASSERT(0 <= numVariables); if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY( !isValid() || 0 == numVariables)) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } const short *end = variables + numVariables; for (; variables != end; ++variables) { getInt16(*variables); } return *this; } template <class STREAMBUF> GenericInStream<STREAMBUF>& GenericInStream<STREAMBUF>::getArrayUint16(unsigned short *variables, int numVariables) { BSLS_ASSERT(variables); BSLS_ASSERT(0 <= numVariables); if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY( !isValid() || 0 == numVariables)) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } const unsigned short *end = variables + numVariables; for (; variables != end; ++variables) { getUint16(*variables); } return *this; } template <class STREAMBUF> GenericInStream<STREAMBUF>& GenericInStream<STREAMBUF>::getArrayInt8(char *variables, int numVariables) { BSLS_ASSERT(variables); BSLS_ASSERT(0 <= numVariables); if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY( !isValid() || 0 == numVariables)) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } const char *end = variables + numVariables; for (; variables != end; ++variables) { getInt8(*variables); } return *this; } template <class STREAMBUF> inline GenericInStream<STREAMBUF>& GenericInStream<STREAMBUF>::getArrayInt8(signed char *variables, int numVariables) { BSLS_ASSERT_SAFE(variables); BSLS_ASSERT_SAFE(0 <= numVariables); return getArrayInt8(reinterpret_cast<char *>(variables), numVariables); } template <class STREAMBUF> inline GenericInStream<STREAMBUF>& GenericInStream<STREAMBUF>::getArrayUint8(char *variables, int numVariables) { BSLS_ASSERT_SAFE(variables); BSLS_ASSERT_SAFE(0 <= numVariables); return getArrayInt8(variables, numVariables); } template <class STREAMBUF> inline GenericInStream<STREAMBUF>& GenericInStream<STREAMBUF>::getArrayUint8(unsigned char *variables, int numVariables) { BSLS_ASSERT_SAFE(variables); BSLS_ASSERT_SAFE(0 <= numVariables); return getArrayInt8(reinterpret_cast<char *>(variables), numVariables); } // *** arrays of floating-point values *** template <class STREAMBUF> GenericInStream<STREAMBUF>& GenericInStream<STREAMBUF>::getArrayFloat64(double *variables, int numVariables) { BSLS_ASSERT(variables); BSLS_ASSERT(0 <= numVariables); if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY( !isValid() || 0 == numVariables)) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } const double *end = variables + numVariables; for (; variables != end; ++variables) { getFloat64(*variables); } return *this; } template <class STREAMBUF> GenericInStream<STREAMBUF>& GenericInStream<STREAMBUF>::getArrayFloat32(float *variables, int numVariables) { BSLS_ASSERT(variables); BSLS_ASSERT(0 <= numVariables); if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY( !isValid() || 0 == numVariables)) { BSLS_PERFORMANCEHINT_UNLIKELY_HINT; return *this; // RETURN } const float *end = variables + numVariables; for (; variables != end; ++variables) { getFloat32(*variables); } return *this; } // ACCESSORS template <class STREAMBUF> inline GenericInStream<STREAMBUF>::operator const void *() const { return isValid() ? this : 0; } template <class STREAMBUF> inline bool GenericInStream<STREAMBUF>::isValid() const { return d_validFlag; } template <class STREAMBUF, class TYPE> inline GenericInStream<STREAMBUF>& operator>>(GenericInStream<STREAMBUF>& stream, TYPE& value) { return InStreamFunctions::bdexStreamIn(stream, value); } } // close package namespace } // close enterprise namespace #endif // ---------------------------------------------------------------------------- // Copyright 2014 Bloomberg Finance L.P. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ----------------------------- END-OF-FILE ----------------------------------