// bdlsb_fixedmemoutput.h -*-C++-*- #ifndef INCLUDED_BDLSB_FIXEDMEMOUTPUT #define INCLUDED_BDLSB_FIXEDMEMOUTPUT #include <bsls_ident.h> BSLS_IDENT("$Id: $") //@PURPOSE: Provide a basic output stream buffer using a client buffer. // //@CLASSES: // bdlsb::FixedMemOutput: basic output stream buffer using client memory // //@SEE_ALSO: bdlsb_fixedmemoutstreambuf // //@DESCRIPTION: This component implements the output portion of the // 'bsl::basic_streambuf' protocol using a client-supplied memory buffer. // Method names 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. The only difference between this component and // 'bdlsb_fixedmemoutstreambuf' is that the class 'bdlsb::FixedMemOutput' does // *not* derive from a 'bsl::streambuf' and does not support locales. This is // advantageous for performance reasons, as the overhead of the initialization // and virtual function calls of a 'bsl::streambuf' can be undesirable. The // 'bdlsb::FixedMemOutput' is designed to be used by generic template code that // must be instantiated on a type that matches the interface of // 'bsl::streambuf', but does not require an actual 'bsl::streambuf', in // particular 'bslx_genericoutstream'. // ///Usage ///----- // This section illustrates intended use of this component. // ///Example 1: Basic Use of 'bdlsb::FixedMemOutput' ///- - - - - - - - - - - - - - - - - - - - - - - - // This example demonstrates instantiating a template, bslx::GenericOutStream', // on a 'bdlsb::FixedMemOutput' object and using the 'bslx::GenericOutStream' // object to stream out some data. // // First, we create an object of our stream buffer: //.. // enum { k_STREAMBUF_CAPACITY = 30 }; // // char buffer[k_STREAMBUF_CAPACITY]; // bdlsb::FixedMemOutput streamBuf(buffer, k_STREAMBUF_CAPACITY); //.. // Then, we create an instance of 'bslx::GenericOutStream' using 'streamBuf', // with an arbitrary value for its 'versionSelector', and externalize some // values: //.. // bslx::GenericOutStream<bdlsb::FixedMemOutput> outStream(&streamBuf, // 20150707); // outStream.putInt32(1); // outStream.putInt32(2); // outStream.putInt8('c'); // outStream.putString(bsl::string("hello")); //.. // Finally, we compare the contents of the buffer to the expected value: //.. // assert(15 == streamBuf.length()); // assert( 0 == bsl::memcmp(streamBuf.data(), // "\x00\x00\x00\x01\x00\x00\x00\x02""c\x05""hello", // 15)); //.. #include <bdlscm_version.h> #include <bsls_assert.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> // 'bsl::streamsize' #include <bsl_iosfwd.h> #include <bsl_locale.h> #include <bsl_streambuf.h> namespace BloombergLP { namespace bdlsb { // ============== // FixedMemOutput // ============== class FixedMemOutput { // This class, like 'bdlsb::FixedMemOutStreamBuf', implements the output // functionality of the 'basic_streambuf' interface, using client-supplied // 'char *' memory. It has an identical interface to // 'bdlsb::FixedMemOutStreamBuf' but does *not* inherit from // 'bsl::streambuf'. Thus, it is suitable for use as template parameter to // 'bslx::GenericOutStream' (but not to 'bslx::StreambufOutStream'). Note // that this class is not designed to be derived from. public: // TYPES typedef char char_type; typedef bsl::char_traits<char>::int_type int_type; typedef bsl::char_traits<char>::pos_type pos_type; typedef bsl::char_traits<char>::off_type off_type; typedef bsl::char_traits<char> traits_type; private: // PRIVATE TYPE typedef bsls::Types::IntPtr IntPtr; // PRIVATE DATA MEMBERS char *d_buffer_p; // output buffer bsl::streamsize d_capacity; // length of output buffer pos_type d_pos; // output cursor // NOT IMPLEMENTED FixedMemOutput(const FixedMemOutput&); FixedMemOutput& operator=(const FixedMemOutput&); public: // CREATORS FixedMemOutput(char *buffer, bsl::streamsize length); // Create an empty stream buffer that uses the specified character // 'buffer' of the specified 'length'. The behavior is undefined // unless 'length == 0' or 'length > 0 && buffer != 0'. // Note that 'buffer' is held but not owned. //! ~FixedMemOutput(); // Destroy this stream buffer. Note that this method's definition is // compiler generated. // MANIPULATORS char *data(); // Return a pointer providing modifiable access to the character buffer // held by this stream buffer (supplied at construction). // *** 27.5.2.2.1 locales: *** bsl::locale pubimbue(const bsl::locale& loc); // Associate the specified locale 'loc' to this stream buffer. // Operation has no effect, because locales are not supported by this // component. Return default constructed bsl::locale object. // *** 27.5.2.2.2 buffer and positioning: *** FixedMemOutput *pubsetbuf(char *buffer, bsl::streamsize length); // Reset the internal buffer of this stream to the specified 'buffer' // of the specified 'length'. Note that the next write operation will // start at the beginning of 'buffer'. pos_type pubseekoff(off_type offset, bsl::ios_base::seekdir fixedPosition, bsl::ios_base::openmode which = bsl::ios_base::in | bsl::ios_base::out); // Set the position indicator to the relative specified 'offset' from // the base position indicated by the specified 'fixedPosition' 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::out' 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 | bsl::ios_base::out); // 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::out' or if position is less then zero or greater // than the value returned by 'length'. int pubsync(); // Synchronizes the controlled character sequence (the buffers) with // the associated character sequence. Operation has no effect, because // the stream is always kept in sync (no buffered output). Return 0. // *** 27.5.2.2.5 Put area: *** int_type sputc(char c); // Write the specified character 'c' to this buffer. Return 'c', or // 'traits_type::eof()' if the end of the write buffer is reached. bsl::streamsize sputn(const char *s, bsl::streamsize length); // Write the specified 'length' characters at the specified address 's' // to this buffer. Return the number of characters written, which is // either 'length' or the distance from the current write position to // the end of the write buffer, whichever is smaller, and move the // write cursor position by this amount. // ACCESSORS bsl::streamsize capacity() const; // Return the size in bytes of the buffer held by this stream buffer. const char *data() const; // Return a pointer providing non-modifiable access to the character // buffer held by this stream buffer (supplied at construction). bsl::streamsize length() const; // Return the number of characters from the beginning of the buffer to // the current write position. // *** 27.5.2.2.1 locales: *** bsl::locale getloc() const; // Return the current default locale. Operation has no effect, because // locales are not supported by this component. Return default // constructed bsl::locale object. }; // ============================================================================ // INLINE DEFINITIONS // ============================================================================ // -------------- // FixedMemOutput // -------------- // CREATORS inline FixedMemOutput::FixedMemOutput(char *buffer, bsl::streamsize length) : d_buffer_p(buffer) , d_capacity(length) , d_pos(0) { BSLS_ASSERT(buffer || 0 == length); BSLS_ASSERT(0 <= length); } // MANIPULATORS inline char *FixedMemOutput::data() { return d_buffer_p; } inline bsl::locale FixedMemOutput::pubimbue(const bsl::locale&) { return bsl::locale(); } inline FixedMemOutput *FixedMemOutput::pubsetbuf(char *buffer, bsl::streamsize length) { BSLS_ASSERT(buffer || 0 == length); BSLS_ASSERT(0 <= length); d_buffer_p = buffer; d_capacity = length; d_pos = 0; return this; } inline int FixedMemOutput::pubsync() { // Nothing to do, the buffer is always up to date. return 0; } inline FixedMemOutput::int_type FixedMemOutput::sputc(char c) { if (d_pos >= d_capacity) { return traits_type::eof(); // RETURN } d_buffer_p[static_cast<IntPtr>(d_pos)] = c; d_pos += 1; return traits_type::to_int_type(c); } inline bsl::streamsize FixedMemOutput::sputn(const char *s, bsl::streamsize length) { BSLS_ASSERT(s); BSLS_ASSERT(0 <= length); pos_type current = d_pos; d_pos += length; if (d_pos > d_capacity) { d_pos = d_capacity; length = static_cast<bsl::streamsize>(d_capacity - current); } bsl::memcpy(d_buffer_p + static_cast<IntPtr>(current), s, length); return length; } // ACCESSORS inline bsl::streamsize FixedMemOutput::capacity() const { return d_capacity; } inline const char *FixedMemOutput::data() const { return d_buffer_p; } inline bsl::locale FixedMemOutput::getloc() const { return bsl::locale(); } inline bsl::streamsize FixedMemOutput::length() const { return bsl::streamsize(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 ----------------------------------