// bdlsb_fixedmeminput.h -*-C++-*- #ifndef INCLUDED_BDLSB_FIXEDMEMINPUT #define INCLUDED_BDLSB_FIXEDMEMINPUT #include <bsls_ident.h> BSLS_IDENT("$Id: $") //@PURPOSE: Provide a basic input stream buffer using a client buffer. // //@CLASSES: // bdlsb::FixedMemInput: basic input stream buffer using client memory // //@SEE_ALSO: bdlsb_fixedmeminstreambuf // //@DESCRIPTION: This component provides a mechanism, 'bdlsb::FixedMemInput', // that implements the input portion of the 'bsl::basic_streambuf' protocol // using a client-supplied memory buffer. Method names necessarily correspond // to the protocol-specified method names. Clients supply the character buffer // at stream buffer construction, and can later reinitialize the stream buffer // with a different character buffer by calling the 'pubsetbuf' method. This // component provides none of the output-related functionality of // 'bsl::basic_streambuf' nor does it use locales in any way. The only // difference between this component and 'bdlsb::FixedMemInStreamBuf' is that // the class 'bdlsb::FixedMemInput' does *not* derive from a 'bsl::streambuf', // and is generally more efficient (at initialization and due to the lack of // virtual functions). It is especially designed for streaming a very small // amount of information from a fixed-length buffer using a // 'bslx_genericinstream'. // ///Usage ///----- // This section illustrates intended use of this component. // ///Example 1: Basic Use of 'bdlsb::FixedMemInput' /// - - - - - - - - - - - - - - - - - - - - - - - // The 'bdlsb::FixedMemInput' class is intended to be used as a template // parameter to the 'bslx::GenericInStream' class. Such specialization // provides user with performance efficient way to unexternalize BDEX encoded // data from an existing character buffer. // // See the 'bslx_genericinstream' component usage example for a more practical // example of using 'bslx' streams. // // This example demonstrates instantiating a template, 'bslx::GenericInStream', // on a 'bdlsb::FixedMemInput' object and using the 'bslx::GenericInStream' // object to stream in some data. // // First, create 'bslx::ByteOutStream' 'outStream' and externalize some user // data to it. Note that this code only prepares the character buffer that is // used to illustrate the purpose of the 'bdlsb::FixedMemInput' class. //.. // bslx::ByteOutStream outStream(20131127); // // unsigned int MAGIC = 0x1812; // // outStream.putUint32(MAGIC); // outStream.putInt32(83); // outStream.putString(bsl::string("test")); // assert(outStream.isValid()); //.. // Next, create a 'bdlsb::FixedMemInput' stream buffer initialized with the // buffer from the 'bslx::ByteOutStream' object 'outStream': //.. // bdlsb::FixedMemInput streamBuffer(outStream.data(), outStream.length()); //.. // Then, create the 'bslx::GenericInStream' stream parameterized with // 'bdlsb::FixedMemInput': //.. // bslx::GenericInStream<bdlsb::FixedMemInput> inStream(&streamBuffer); //.. // Now, use resulting 'inStream' to unexternalize user data: //.. // unsigned int magic; // int key; // bsl::string value; // // inStream.getUint32(magic); // inStream.getInt32(key); // inStream.getString(value); // assert(inStream.isValid()); //.. // Finally, verify that the data from the supplied buffer was unexternalized // correctly: //.. // assert(MAGIC == magic); // assert(83 == key); // assert("test" == value); //.. #include <bdlscm_version.h> #include <bsls_assert.h> #include <bsls_performancehint.h> #include <bsls_platform.h> #include <bsls_review.h> #include <bsls_types.h> #include <bsl_algorithm.h> #include <bsl_cstdlib.h> #include <bsl_cstring.h> #include <bsl_ios.h> #include <bsl_iosfwd.h> namespace BloombergLP { namespace bdlsb { // =================== // class FixedMemInput // =================== class FixedMemInput { // This class, like 'bdlsb::FixedMemInStreamBuf', implements the input // functionality of the 'basic_streambuf' interface, using client-supplied // 'char *' memory. It has an interface identical to // 'bdlsb::FixedMemInStreamBuf' but does *not* inherit from // 'bsl::streambuf'. This implementation is advantageous for performance // reasons, as the overhead of the initialization and virtual function // calls of a 'bsl::streambuf' can be undesirable. It is especially // designed for streaming a very small amount of information from a // fixed-length buffer using a 'bslx_genericinstream' when the number of // characters read from the input is guaranteed not to exceed the length of // the buffer. Note that this class is not designed to be derived from. public: // TYPES typedef char char_type; typedef bsl::char_traits<char> traits_type; typedef traits_type::int_type int_type; typedef traits_type::pos_type pos_type; typedef traits_type::off_type off_type; private: // PRIVATE DATA MEMBERS const char *d_buffer_p; // buffer (held, not owned) bsl::size_t d_bufferSize; // buffer size (not length of stream) bsl::size_t d_pos; // current read position private: // NOT IMPLEMENTED FixedMemInput(const FixedMemInput&); FixedMemInput& operator=(const FixedMemInput&); public: // CREATORS FixedMemInput(const char *buffer, bsl::size_t length); // Create a 'FixedMemInput' using the specified 'buffer' of the // specified 'length'. The position indicator is set to the beginning // of the 'buffer'. The behavior is undefined unless // 'buffer != 0 && length > 0' or 'length == 0'. Note that 'buffer' is // held but not owned. //! ~FixedMemInput(); // Destroy this stream buffer. Note that this trivial destructor is // generated by the compiler. // MANIPULATORS bsl::streamsize in_avail(); // Return the number of characters available from the current read // position in this stream buffer. // *** 27.5.2.2.2 buffer and positioning: *** FixedMemInput *pubsetbuf(const char *buffer, bsl::streamsize length); // Reinitialize this stream buffer to use the specified character // 'buffer' having the specified 'length'. Return a pointer providing // modifiable access to this stream buffer. The behaviour is undefined // unless 'buffer != 0 && length > 0' or 'length == 0'. Upon // reinitialization for use of the new buffer, the position indicator // is set to the beginning of the 'buffer'. Note that 'buffer' is // held but not owned. pos_type pubseekoff(off_type offset, bsl::ios_base::seekdir way, bsl::ios_base::openmode which = bsl::ios_base::in); // Set the position indicator to the relative specified 'offset' from // the base position indicated by the specified 'way' and return the // resulting absolute position on success or pos_type(-1) on failure. // Optionally specify 'which' area of the stream buffer. The seek // operation will fail if 'which' does not include the flag // 'bsl::ios_base::in' or if the resulting absolute position is less // than zero or greater than the value returned by 'length'. pos_type pubseekpos(pos_type position, bsl::ios_base::openmode which = bsl::ios_base::in); // Set the position indicator to the specified 'position' and return // the resulting absolute position on success or pos_type(-1) on // failure. Optionally specify 'which' area of the stream buffer. The // 'seekpos' operation will fail if 'which' does not include the flag // 'bsl::ios_base::in' or if position is less then zero or greater // than the value returned by 'length'. // *** 27.5.2.2.3 Get area: *** int_type sbumpc(); // Return the character at the current read position from this buffer, // or 'traits_type::eof()' if the end of the buffer is reached and // advance read position indicator. int_type sgetc(); // Return the character at the current read position from this buffer, // or 'traits_type::eof()' if the end of the buffer is reached. bsl::streamsize sgetn(char_type *destination, bsl::streamsize length); // Read the specified 'length' characters to the specified // 'destination'. Return the number of characters successfully read // from this buffer, which is either equal to the 'length' parameter or // equal to the distance from the current read position to the end of // the input buffer, whichever is smaller, and move the read cursor // position by this amount. The behavior is undefined unless '0 <= // length'. int_type snextc(); // Advance the current read position and return the character at the // resulting position from this buffer, or 'traits_type::eof()' if the // end of the buffer is reached. // *** 27.5.2.2.4 Putback: *** int_type sputbackc(char c); // Move the current read position back one character if the current // read position is not at the beginning of the buffer and the previous // position contains the specified character 'c', and return that // character. Otherwise, return 'traits_type::eof()' and do not move // the current read position. int_type sungetc(); // Move the current read position back one character if the current // read position is not at the beginning of the buffer, and return the // character at the resulting current read position from this buffer. // Return 'traits_type::eof()' otherwise. // ACCESSORS bsl::size_t capacity() const; // Return the size for the buffer held by this buffer, in bytes, // supplied at construction. const char *data() const; // Return the address of the non-modifiable character buffer held by // this stream buffer. bsl::size_t length() const; // Return the number of characters that can be successfully read from // this stream buffer before reading 'traits_type::eof()' -- i.e., the // number of characters between the current read position and the end // of this buffer. }; // ============================================================================ // INLINE DEFINITIONS // ============================================================================ // ------------------- // class FixedMemInput // ------------------- // CREATORS inline FixedMemInput::FixedMemInput(const char *buffer, bsl::size_t length) : d_buffer_p(const_cast<char *>(buffer)) , d_bufferSize(length) , d_pos(0) { BSLS_ASSERT(buffer || 0 == length); } // MANIPULATORS inline bsl::streamsize FixedMemInput::in_avail() { if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(d_pos == d_bufferSize)) { return bsl::streamsize(-1); // RETURN } return static_cast<bsl::streamsize>(d_bufferSize - d_pos); } inline FixedMemInput *FixedMemInput::pubsetbuf(const char *buffer, bsl::streamsize length) { BSLS_ASSERT(buffer || 0 == length); BSLS_ASSERT(0 <= length); d_buffer_p = buffer; d_bufferSize = static_cast<bsl::size_t>(length); d_pos = 0; return this; } inline FixedMemInput::int_type FixedMemInput::sbumpc() { if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(d_pos >= d_bufferSize)) { return traits_type::eof(); // RETURN } const int_type i = traits_type::to_int_type(d_buffer_p[d_pos]); d_pos += 1; return i; } inline FixedMemInput::int_type FixedMemInput::sgetc() { if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(d_pos >= d_bufferSize)) { return traits_type::eof(); // RETURN } //return traits_type::to_int_type(d_buffer_p[static_cast<IntPtr>(d_pos)]); return traits_type::to_int_type(d_buffer_p[d_pos]); } inline bsl::streamsize FixedMemInput::sgetn(char *destination, bsl::streamsize length) { BSLS_ASSERT(0 <= length); const bsl::size_t current = d_pos; d_pos += static_cast<bsl::size_t>(length); if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY((d_pos > d_bufferSize) || (d_pos < current) )) { d_pos = d_bufferSize; length = static_cast<bsl::streamsize>(d_bufferSize - current); } bsl::memcpy(destination, d_buffer_p+current, length); return length; } inline FixedMemInput::int_type FixedMemInput::snextc() { if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(d_pos >= d_bufferSize)) { return traits_type::eof(); // RETURN } d_pos += 1; return sgetc(); } inline FixedMemInput::int_type FixedMemInput::sputbackc(char c) { if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(0 == d_pos) || BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(c != d_buffer_p[d_pos-1])) { return traits_type::eof(); // RETURN } d_pos -= 1; return traits_type::to_int_type(c); } inline FixedMemInput::int_type FixedMemInput::sungetc() { if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(0 == d_pos)) { return traits_type::eof(); // RETURN } d_pos -= 1; return traits_type::to_int_type(d_buffer_p[d_pos]); } // ACCESSORS inline bsl::size_t FixedMemInput::capacity() const { return d_bufferSize; } inline const char *FixedMemInput::data() const { return d_buffer_p; } inline bsl::size_t FixedMemInput::length() const { return (d_bufferSize - d_pos); } } // close package namespace } // close enterprise namespace #endif // ---------------------------------------------------------------------------- // Copyright 2015 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 ----------------------------------