BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bslx_genericoutstream.h
Go to the documentation of this file.
1/// @file bslx_genericoutstream.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslx_genericoutstream.h -*-C++-*-
8#ifndef INCLUDED_BSLX_GENERICOUTSTREAM
9#define INCLUDED_BSLX_GENERICOUTSTREAM
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslx_genericoutstream bslx_genericoutstream
15/// @brief Externalization of fundamental types to a parameterized stream.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslx
19/// @{
20/// @addtogroup bslx_genericoutstream
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslx_genericoutstream-purpose"> Purpose</a>
25/// * <a href="#bslx_genericoutstream-classes"> Classes </a>
26/// * <a href="#bslx_genericoutstream-description"> Description </a>
27/// * <a href="#bslx_genericoutstream-generic-byte-format-generator"> Generic Byte-Format Generator </a>
28/// * <a href="#bslx_genericoutstream-versioning"> Versioning </a>
29/// * <a href="#bslx_genericoutstream-usage"> Usage </a>
30/// * <a href="#bslx_genericoutstream-example-1-basic-externalization"> Example 1: Basic Externalization </a>
31/// * <a href="#bslx_genericoutstream-example-2-sample-streambuf-implementation"> Example 2: Sample STREAMBUF Implementation </a>
32///
33/// # Purpose {#bslx_genericoutstream-purpose}
34/// Externalization of fundamental types to a parameterized stream.
35///
36/// # Classes {#bslx_genericoutstream-classes}
37///
38/// - bslx::GenericOutStream: parameterized output stream for fundamentals
39///
40/// @see bslx_streambufoutstream, bslx_genericinstream
41///
42/// # Description {#bslx_genericoutstream-description}
43/// This component implements a parameterized output stream
44/// class, `bslx::GenericOutStream`, that provides platform-independent output
45/// methods ("externalization") on values, and arrays of values, of fundamental
46/// types, and on `bsl::string`.
47///
48/// This component is intended to be used in conjunction with the
49/// @ref bslx_genericinstream "unexternalization" component. Each output method of
50/// `bslx::GenericOutStream` writes either a value or a homogeneous array of
51/// values of a fundamental type, in a format that is readable by the
52/// corresponding `bslx::GenericInStream` method. In general, the user cannot
53/// rely on any other mechanism to read data written by `bslx::GenericOutStream`
54/// unless that mechanism explicitly states its ability to do so.
55///
56/// The supported types and required content are listed in the `bslx`
57/// package-level documentation under "Supported Types".
58///
59/// Note that the values are stored in big-endian (i.e., network byte order)
60/// format.
61///
62/// Note that output streams can be *invalidated* explicitly and queried for
63/// *validity*. Writing to an initially invalid stream has no effect. Whenever
64/// an output operation fails, the stream should be invalidated explicitly.
65///
66/// ## Generic Byte-Format Generator {#bslx_genericoutstream-generic-byte-format-generator}
67///
68///
69/// The class `bslx::GenericOutStream` is parameterized by a buffered stream
70/// class, `STREAMBUF`, which, given the declarations:
71/// @code
72/// char c;
73/// int len;
74/// const char *s;
75/// STREAMBUF *sb;
76/// @endcode
77/// must make the following expressions syntactically valid, with the assert
78/// statements highlighting the expected return values:
79/// @code
80/// STREAMBUF::traits_type::int_type eof = STREAMBUF::traits_type::eof();
81/// assert(eof != sb->sputc(c));
82/// assert(len == sb->sputn(s, len));
83/// assert( 0 == sb->pubsync());
84/// @endcode
85/// Suitable choices for `STREAMBUF` include any class that implements the
86/// `bsl::basic_streambuf` protocol.
87///
88/// The class `bslx::StreambufOutStream` is a `typedef` of
89/// `bslx::GenericOutStream<bsl::streambuf>`.
90///
91/// ## Versioning {#bslx_genericoutstream-versioning}
92///
93///
94/// BDEX provides two concepts that support versioning the BDEX serialization
95/// format of a type: `version` and `versionSelector`. A `version` is a 1-based
96/// integer indicating one of the supported formats (e.g., format 1, format 2,
97/// etc.). A `versionSelector` is a value that is mapped to a `version` for a
98/// type by the type's implementation of `maxSupportedBdexVersion`.
99///
100/// Selecting a value for a `versionSelector` is required at two different
101/// points: (1) when implementing a new `version` format within the
102/// `bdexStreamIn` and `bdexStreamOut` methods of a type, and (2) when
103/// implementing code that constructs a BDEX `OutStream`. In both cases, the
104/// value should be a *compile*-time-selected value.
105///
106/// When a new `version` format is implemented within the `bdexStreamIn` and
107/// `bdexStreamOut` methods of a type, a new mapping in
108/// `maxSupportedBdexVersion` should be created to expose this new `version`
109/// with a `versionSelector`. A simple - and the recommended - approach is to
110/// use a value having the pattern "YYYYMMDD", where "YYYYMMDD" corresponds to
111/// the "go-live" date of the corresponding `version` format.
112///
113/// When constructing an `OutStream`, a simple approach is to use the current
114/// date as a *compile*-time constant value. In combination with the
115/// recommended selection of `versionSelector` values for
116/// `maxSupportedBdexVersion`, this will result in consistent and predictable
117/// behavior while externalizing types. Note that this recommendation is chosen
118/// for its simplicity: to ensure the largest possible audience for an
119/// externalized representation, clients can select the minimum date value that
120/// will result in the desired version of all types externalized with
121/// `operator<<` being selected.
122///
123/// See the `bslx` package-level documentation for more detailed information
124/// about versioning.
125///
126/// ## Usage {#bslx_genericoutstream-usage}
127///
128///
129/// This section illustrates intended use of this component. The first example
130/// depicts usage with a `bsl::stringbuf`. The second example replaces the
131/// `bsl::stringbuf` with a user-defined `STREAMBUF`.
132///
133/// ### Example 1: Basic Externalization {#bslx_genericoutstream-example-1-basic-externalization}
134///
135///
136/// A `bslx::GenericOutStream` can be used to externalize values in a
137/// platform-neutral way. Writing out fundamental C++ types and `bsl::string`
138/// requires no additional work on the part of the client; the client can simply
139/// use the stream directly. The following code serializes a few representative
140/// values using a `bslx::GenericOutStream`, compares the contents of this
141/// stream to the expected value, and then writes the contents of this stream's
142/// buffer to `stdout`.
143///
144/// First, we create a `bslx::GenericOutStream`, with an arbitrary value for its
145/// `versionSelector`, and externalize some values:
146/// @code
147/// bsl::stringbuf buffer1;
148/// bslx::GenericOutStream<bsl::stringbuf> outStream1(&buffer1, 20131127);
149/// outStream1.putInt32(1);
150/// outStream1.putInt32(2);
151/// outStream1.putInt8('c');
152/// outStream1.putString(bsl::string("hello"));
153/// @endcode
154/// Then, we compare the contents of the buffer to the expected value:
155/// @code
156/// bsl::string theChars = buffer1.str();
157/// assert(15 == theChars.size());
158/// assert( 0 == bsl::memcmp(theChars.data(),
159/// "\x00\x00\x00\x01\x00\x00\x00\x02""c\x05""hello",
160/// 15));
161/// @endcode
162/// Finally, we print the buffer's contents to `bsl::cout`.
163/// @code
164/// for (bsl::size_t i = 0; i < theChars.size(); ++i) {
165/// if (bsl::isalnum(static_cast<unsigned char>(theChars[i]))) {
166/// bsl::cout << "nextByte (char): " << theChars[i] << bsl::endl;
167/// }
168/// else {
169/// bsl::cout << "nextByte (int): "
170/// << static_cast<int>(theChars[i])
171/// << bsl::endl;
172/// }
173/// }
174/// @endcode
175/// Executing the above code results in the following output:
176/// @code
177/// nextByte (int): 0
178/// nextByte (int): 0
179/// nextByte (int): 0
180/// nextByte (int): 1
181/// nextByte (int): 0
182/// nextByte (int): 0
183/// nextByte (int): 0
184/// nextByte (int): 2
185/// nextByte (char): c
186/// nextByte (int): 5
187/// nextByte (char): h
188/// nextByte (char): e
189/// nextByte (char): l
190/// nextByte (char): l
191/// nextByte (char): o
192/// @endcode
193/// See the @ref bslx_genericinstream component usage example for a more practical
194/// example of using `bslx` streams.
195///
196/// ### Example 2: Sample STREAMBUF Implementation {#bslx_genericoutstream-example-2-sample-streambuf-implementation}
197///
198///
199/// For this example, we will implement `MyOutStreamBuf`, a minimal `STREAMBUF`
200/// to be used with `bslx::GenericOutStream`. The implementation will consist
201/// of only what is required of the type and two accessors to verify correct
202/// functionality (`data` and `length`).
203///
204/// First, we implement `MyOutStreamBuf` (which, for brevity, simply uses the
205/// default allocator):
206/// @code
207/// class MyOutStreamBuf {
208/// // This class implements a very basic stream buffer suitable for use in
209/// // 'bslx::GenericOutStream'.
210///
211/// // DATA
212/// bsl::string d_buffer; // output buffer
213///
214/// private:
215/// // NOT IMPLEMENTED
216/// MyOutStreamBuf(const MyOutStreamBuf&);
217/// MyOutStreamBuf& operator=(const MyOutStreamBuf&);
218///
219/// public:
220/// // TYPES
221/// struct traits_type {
222/// static int eof() { return -1; }
223/// };
224///
225/// // CREATORS
226/// MyOutStreamBuf();
227/// // Create an empty stream buffer.
228///
229/// ~MyOutStreamBuf();
230/// // Destroy this stream buffer.
231///
232/// // MANIPULATORS
233/// int pubsync();
234/// // Return 0.
235///
236/// int sputc(char c);
237/// // Write the specified character 'c' to this buffer. Return 'c' on
238/// // success, and 'traits_type::eof()' otherwise.
239///
240/// bsl::streamsize sputn(const char *s, bsl::streamsize length);
241/// // Write the specified 'length' characters at the specified address
242/// // 's' to this buffer, and return the number of characters written.
243///
244/// // ACCESSORS
245/// const char *data() const;
246/// // Return the address of the non-modifiable character buffer held
247/// // by this stream buffer.
248///
249/// bsl::streamsize size() const;
250/// // Return the number of characters from the beginning of the buffer
251/// // to the current write position.
252/// };
253///
254/// // ========================================================================
255/// // INLINE FUNCTION DEFINITIONS
256/// // ========================================================================
257///
258/// // CREATORS
259/// MyOutStreamBuf::MyOutStreamBuf()
260/// : d_buffer()
261/// {
262/// }
263///
264/// MyOutStreamBuf::~MyOutStreamBuf()
265/// {
266/// }
267///
268/// // MANIPULATORS
269/// int MyOutStreamBuf::pubsync()
270/// {
271/// // In this implementation, there is nothing to be done except return
272/// // success.
273///
274/// return 0;
275/// }
276///
277/// int MyOutStreamBuf::sputc(char c)
278/// {
279/// d_buffer += c;
280/// return static_cast<int>(c);
281/// }
282///
283/// bsl::streamsize MyOutStreamBuf::sputn(const char *s,
284/// bsl::streamsize length)
285/// {
286/// d_buffer.append(s, length);
287/// return length;
288/// }
289///
290/// // ACCESSORS
291/// const char *MyOutStreamBuf::data() const
292/// {
293/// return d_buffer.data();
294/// }
295///
296/// bsl::streamsize MyOutStreamBuf::size() const
297/// {
298/// return d_buffer.size();
299/// }
300/// @endcode
301/// Then, we create `buffer2`, an instance of `MyOutStreamBuf`, and a
302/// `bslx::GenericOutStream` using `buffer2`, with an arbitrary value for its
303/// `versionSelector`, and externalize some values:
304/// @code
305/// MyOutStreamBuf buffer2;
306/// bslx::GenericOutStream<MyOutStreamBuf> outStream2(&buffer2, 20131127);
307/// outStream2.putInt32(1);
308/// outStream2.putInt32(2);
309/// outStream2.putInt8('c');
310/// outStream2.putString(bsl::string("hello"));
311/// @endcode
312/// Finally, we compare the contents of the buffer to the expected value:
313/// @code
314/// assert(15 == buffer2.size());
315/// assert( 0 == bsl::memcmp(buffer2.data(),
316/// "\x00\x00\x00\x01\x00\x00\x00\x02""c\x05""hello",
317/// 15));
318/// @endcode
319/// @}
320/** @} */
321/** @} */
322
323/** @addtogroup bsl
324 * @{
325 */
326/** @addtogroup bslx
327 * @{
328 */
329/** @addtogroup bslx_genericoutstream
330 * @{
331 */
332
333#include <bslscm_version.h>
334
336
337#include <bsls_assert.h>
338#include <bsls_performancehint.h>
339#include <bsls_platform.h>
340#include <bsls_types.h>
341
342#include <bsl_cstddef.h>
343#include <bsl_string.h>
344#include <bsl_vector.h>
345
346
347namespace bslx {
348
349 // ======================
350 // class GenericOutStream
351 // ======================
352
353/// This class provides output methods to externalize values, and C-style
354/// arrays of values, of the fundamental integral and floating-point types,
355/// as well as `bsl::string` values. In particular, each `put` method of
356/// this class is guaranteed to write stream data that can be read by the
357/// corresponding `get` method of `bslx::GenericInStream`. See the `bslx`
358/// package-level documentation for the definition of the BDEX `OutStream`
359/// protocol.
360///
361/// See @ref bslx_genericoutstream
362template <class STREAMBUF>
364
365 // PRIVATE TYPES
366 enum {
367 // Enumerate the platform-independent sizes (in bytes) of data types in
368 // wire format. Note that the wire format size may differ from the
369 // size in memory.
370
371 k_SIZEOF_INT64 = 8,
372 k_SIZEOF_INT56 = 7,
373 k_SIZEOF_INT48 = 6,
374 k_SIZEOF_INT40 = 5,
375 k_SIZEOF_INT32 = 4,
376 k_SIZEOF_INT24 = 3,
377 k_SIZEOF_INT16 = 2,
378 k_SIZEOF_INT8 = 1,
379 k_SIZEOF_FLOAT64 = 8,
380 k_SIZEOF_FLOAT32 = 4
381 };
382
383 // DATA
384 STREAMBUF *d_streamBuf; // held stream to write to
385
386 int d_versionSelector; // 'versionSelector' to use with
387 // 'operator<<' as per the 'bslx'
388 // package-level documentation
389
390 int d_validFlag; // stream validity flag; 'true' if stream is
391 // in valid state, 'false' otherwise
392
393 private:
394 // NOT IMPLEMENTED
396 GenericOutStream& operator=(const GenericOutStream&);
397
398 private:
399 // PRIVATE MANIPULATORS
400
401 /// Put this output stream into a valid state. This function has no
402 /// effect if this stream is already valid.
403 void validate();
404
405 public:
406 // CREATORS
407
408 /// Create an output byte stream that writes its output to the specified
409 /// `streamBuf` and uses the specified (*compile*-time-defined) `versionSelector` as needed (see {Versioning}).
410 ///
411 /// \note Note that the
412 /// `versionSelector` is expected to be formatted as "YYYYMMDD", a date
413 /// representation.
414 GenericOutStream(STREAMBUF *streamBuf, int versionSelector);
415
416 /// Destroy this object.
418
419 // MANIPULATORS
420
421 /// If this stream is valid, invoke the `pubsync` method on the
422 /// underlying stream supplied at construction of this object;
423 /// otherwise, this function has no effect.
425
426 /// Put this output stream in an invalid state. This function has no
427 /// effect if this stream is already invalid.
428 void invalidate();
429
430 /// If the specified `length` is less than 128, write to the stream
431 /// supplied at construction the one-byte integer comprised of the
432 /// least-significant one byte of the `length`; otherwise, write to the
433 /// stream the four-byte, two's complement integer (in network byte
434 /// order) comprised of the least-significant four bytes of the `length`
435 /// (in host byte order) with the most-significant bit set. Return a
436 /// reference to this stream. If this stream is initially invalid, this operation has no effect.
437 ///
438 /// \pre The behavior is undefined unless
439 /// `0 <= length`.
440 GenericOutStream& putLength(int length);
441
442 /// Write to the stream supplied at construction the one-byte, two's
443 /// complement unsigned integer comprised of the least-significant one
444 /// byte of the specified `version`, and return a reference to this
445 /// stream. If this stream is initially invalid, this operation has no
446 /// effect.
447 GenericOutStream& putVersion(int version);
448
449 // *** scalar integer values ***
450
451 /// Write to the stream supplied at construction the eight-byte, two's
452 /// complement integer (in network byte order) comprised of the
453 /// least-significant eight bytes of the specified `value` (in host byte
454 /// order), and return a reference to this stream. If this stream is
455 /// initially invalid, this operation has no effect.
457
458 /// Write to the stream supplied at construction the eight-byte, two's
459 /// complement unsigned integer (in network byte order) comprised of the
460 /// least-significant eight bytes of the specified `value` (in host byte
461 /// order), and return a reference to this stream. If this stream is
462 /// initially invalid, this operation has no effect.
464
465 /// Write to the stream supplied at construction the seven-byte, two's
466 /// complement integer (in network byte order) comprised of the
467 /// least-significant seven bytes of the specified `value` (in host byte
468 /// order), and return a reference to this stream. If this stream is
469 /// initially invalid, this operation has no effect.
471
472 /// Write to the stream supplied at construction the seven-byte, two's
473 /// complement unsigned integer (in network byte order) comprised of the
474 /// least-significant seven bytes of the specified `value` (in host byte
475 /// order), and return a reference to this stream. If this stream is
476 /// initially invalid, this operation has no effect.
478
479 /// Write to the stream supplied at construction the six-byte, two's
480 /// complement integer (in network byte order) comprised of the
481 /// least-significant six bytes of the specified `value` (in host byte
482 /// order), and return a reference to this stream. If this stream is
483 /// initially invalid, this operation has no effect.
485
486 /// Write to the stream supplied at construction the six-byte, two's
487 /// complement unsigned integer (in network byte order) comprised of the
488 /// least-significant six bytes of the specified `value` (in host byte
489 /// order), and return a reference to this stream. If this stream is
490 /// initially invalid, this operation has no effect.
492
493 /// Write to the stream supplied at construction the five-byte, two's
494 /// complement integer (in network byte order) comprised of the
495 /// least-significant five bytes of the specified `value` (in host byte
496 /// order), and return a reference to this stream. If this stream is
497 /// initially invalid, this operation has no effect.
499
500 /// Write to the stream supplied at construction the five-byte, two's
501 /// complement unsigned integer (in network byte order) comprised of the
502 /// least-significant five bytes of the specified `value` (in host byte
503 /// order), and return a reference to this stream. If this stream is
504 /// initially invalid, this operation has no effect.
506
507 /// Write to the stream supplied at construction the four-byte, two's
508 /// complement integer (in network byte order) comprised of the
509 /// least-significant four bytes of the specified `value` (in host byte
510 /// order), and return a reference to this stream. If this stream is
511 /// initially invalid, this operation has no effect.
512 GenericOutStream& putInt32(int value);
513
514 /// Write to the stream supplied at construction the four-byte, two's
515 /// complement unsigned integer (in network byte order) comprised of the
516 /// least-significant four bytes of the specified `value` (in host byte
517 /// order), and return a reference to this stream. If this stream is
518 /// initially invalid, this operation has no effect.
519 GenericOutStream& putUint32(unsigned int value);
520
521 /// Write to the stream supplied at construction the three-byte, two's
522 /// complement integer (in network byte order) comprised of the
523 /// least-significant three bytes of the specified `value` (in host byte
524 /// order), and return a reference to this stream. If this stream is
525 /// initially invalid, this operation has no effect.
526 GenericOutStream& putInt24(int value);
527
528 /// Write to the stream supplied at construction the three-byte, two's
529 /// complement unsigned integer (in network byte order) comprised of the
530 /// least-significant three bytes of the specified `value` (in host byte
531 /// order), and return a reference to this stream. If this stream is
532 /// initially invalid, this operation has no effect.
533 GenericOutStream& putUint24(unsigned int value);
534
535 /// Write to the stream supplied at construction the two-byte, two's
536 /// complement integer (in network byte order) comprised of the
537 /// least-significant two bytes of the specified `value` (in host byte
538 /// order), and return a reference to this stream. If this stream is
539 /// initially invalid, this operation has no effect.
540 GenericOutStream& putInt16(int value);
541
542 /// Write to the stream supplied at construction the two-byte, two's
543 /// complement unsigned integer (in network byte order) comprised of the
544 /// least-significant two bytes of the specified `value` (in host byte
545 /// order), and return a reference to this stream. If this stream is
546 /// initially invalid, this operation has no effect.
547 GenericOutStream& putUint16(unsigned int value);
548
549 /// Write to the stream supplied at construction the one-byte, two's
550 /// complement integer comprised of the least-significant one byte of
551 /// the specified `value`, and return a reference to this stream. If
552 /// this stream is initially invalid, this operation has no effect.
553 GenericOutStream& putInt8(int value);
554
555 /// Write to the stream supplied at construction the one-byte, two's
556 /// complement unsigned integer comprised of the least-significant one
557 /// byte of the specified `value`, and return a reference to this
558 /// stream. If this stream is initially invalid, this operation has no
559 /// effect.
560 GenericOutStream& putUint8(unsigned int value);
561
562 // *** scalar floating-point values ***
563
564 /// Write to the stream supplied at construction the eight-byte IEEE
565 /// double-precision floating-point number (in network byte order)
566 /// comprised of the most-significant eight bytes of the specified
567 /// `value` (in host byte order), and return a reference to this stream.
568 /// If this stream is initially invalid, this operation has no effect.
569 ///
570 /// \note Note that for non-conforming platforms, this operation may be lossy.
571 GenericOutStream& putFloat64(double value);
572
573 /// Write to the stream supplied at construction the four-byte IEEE
574 /// single-precision floating-point number (in network byte order)
575 /// comprised of the most-significant four bytes of the specified
576 /// `value` (in host byte order), and return a reference to this stream.
577 /// If this stream is initially invalid, this operation has no effect.
578 ///
579 /// \note Note that for non-conforming platforms, this operation may be lossy.
580 GenericOutStream& putFloat32(float value);
581
582 // *** string values ***
583
584 /// Write to the stream supplied at construction the length of the
585 /// specified `value` (see `putLength`) and an array of one-byte, two's
586 /// complement unsigned integers comprised of the least-significant one
587 /// byte of each character in the `value`, and return a reference to
588 /// this stream. If this stream is initially invalid, this operation
589 /// has no effect.
591
592 // *** arrays of integer values ***
593
594 /// Write to the stream supplied at construction the consecutive
595 /// eight-byte, two's complement integers (in network byte order)
596 /// comprised of the least-significant eight bytes of each of the
597 /// specified `numValues` leading entries in the specified `values` (in
598 /// host byte order), and return a reference to this stream. If this
599 /// stream is initially invalid, this operation has no effect.
600 ///
601 /// \pre The behavior is undefined unless `0 <= numValues` and `values` has
602 /// sufficient contents.
604 int numValues);
605
606 /// Write to the stream supplied at construction the consecutive
607 /// eight-byte, two's complement unsigned integers (in network byte
608 /// order) comprised of the least-significant eight bytes of each of the
609 /// specified `numValues` leading entries in the specified `values` (in
610 /// host byte order), and return a reference to this stream. If this
611 /// stream is initially invalid, this operation has no effect.
612 ///
613 /// \pre The behavior is undefined unless `0 <= numValues` and `values` has
614 /// sufficient contents.
616 int numValues);
617
618 /// Write to the stream supplied at construction the consecutive
619 /// seven-byte, two's complement integers (in network byte order)
620 /// comprised of the least-significant seven bytes of each of the
621 /// specified `numValues` leading entries in the specified `values` (in
622 /// host byte order), and return a reference to this stream. If this
623 /// stream is initially invalid, this operation has no effect.
624 ///
625 /// \pre The behavior is undefined unless `0 <= numValues` and `values` has
626 /// sufficient contents.
628 int numValues);
629
630 /// Write to the stream supplied at construction the consecutive
631 /// seven-byte, two's complement unsigned integers (in network byte
632 /// order) comprised of the least-significant seven bytes of each of the
633 /// specified `numValues` leading entries in the specified `values` (in
634 /// host byte order), and return a reference to this stream. If this
635 /// stream is initially invalid, this operation has no effect.
636 ///
637 /// \pre The behavior is undefined unless `0 <= numValues` and `values` has
638 /// sufficient contents.
640 int numValues);
641
642 /// Write to the stream supplied at construction the consecutive
643 /// six-byte, two's complement integers (in network byte order)
644 /// comprised of the least-significant six bytes of each of the
645 /// specified `numValues` leading entries in the specified `values` (in
646 /// host byte order), and return a reference to this stream. If this
647 /// stream is initially invalid, this operation has no effect.
648 ///
649 /// \pre The behavior is undefined unless `0 <= numValues` and `values` has
650 /// sufficient contents.
652 int numValues);
653
654 /// Write to the stream supplied at construction the consecutive
655 /// six-byte, two's complement unsigned integers (in network byte order)
656 /// comprised of the least-significant six bytes of each of the
657 /// specified `numValues` leading entries in the specified `values` (in
658 /// host byte order), and return a reference to this stream. If this
659 /// stream is initially invalid, this operation has no effect.
660 ///
661 /// \pre The behavior is undefined unless `0 <= numValues` and `values` has
662 /// sufficient contents.
664 int numValues);
665
666 /// Write to the stream supplied at construction the consecutive
667 /// five-byte, two's complement integers (in network byte order)
668 /// comprised of the least-significant five bytes of each of the
669 /// specified `numValues` leading entries in the specified `values` (in
670 /// host byte order), and return a reference to this stream. If this
671 /// stream is initially invalid, this operation has no effect.
672 ///
673 /// \pre The behavior is undefined unless `0 <= numValues` and `values` has
674 /// sufficient contents.
676 int numValues);
677
678 /// Write to the stream supplied at construction the consecutive
679 /// five-byte, two's complement unsigned integers (in network byte
680 /// order) comprised of the least-significant five bytes of each of the
681 /// specified `numValues` leading entries in the specified `values` (in
682 /// host byte order), and return a reference to this stream. If this
683 /// stream is initially invalid, this operation has no effect.
684 ///
685 /// \pre The behavior is undefined unless `0 <= numValues` and `values` has
686 /// sufficient contents.
688 int numValues);
689
690 /// Write to the stream supplied at construction the consecutive
691 /// four-byte, two's complement integers (in network byte order)
692 /// comprised of the least-significant four bytes of each of the
693 /// specified `numValues` leading entries in the specified `values` (in
694 /// host byte order), and return a reference to this stream. If this
695 /// stream is initially invalid, this operation has no effect.
696 ///
697 /// \pre The behavior is undefined unless `0 <= numValues` and `values` has
698 /// sufficient contents.
699 GenericOutStream& putArrayInt32(const int *values, int numValues);
700
701 /// Write to the stream supplied at construction the consecutive
702 /// four-byte, two's complement unsigned integers (in network byte
703 /// order) comprised of the least-significant four bytes of each of the
704 /// specified `numValues` leading entries in the specified `values` (in
705 /// host byte order), and return a reference to this stream. If this
706 /// stream is initially invalid, this operation has no effect.
707 ///
708 /// \pre The behavior is undefined unless `0 <= numValues` and `values` has
709 /// sufficient contents.
710 GenericOutStream& putArrayUint32(const unsigned int *values,
711 int numValues);
712
713 /// Write to the stream supplied at construction the consecutive
714 /// three-byte, two's complement integers (in network byte order)
715 /// comprised of the least-significant three bytes of each of the
716 /// specified `numValues` leading entries in the specified `values` (in
717 /// host byte order), and return a reference to this stream. If this
718 /// stream is initially invalid, this operation has no effect.
719 ///
720 /// \pre The behavior is undefined unless `0 <= numValues` and `values` has
721 /// sufficient contents.
722 GenericOutStream& putArrayInt24(const int *values, int numValues);
723
724 /// Write to the stream supplied at construction the consecutive
725 /// three-byte, two's complement unsigned integers (in network byte
726 /// order) comprised of the least-significant three bytes of each of the
727 /// specified `numValues` leading entries in the specified `values` (in
728 /// host byte order), and return a reference to this stream. If this
729 /// stream is initially invalid, this operation has no effect.
730 ///
731 /// \pre The behavior is undefined unless `0 <= numValues` and `values` has
732 /// sufficient contents.
733 GenericOutStream& putArrayUint24(const unsigned int *values,
734 int numValues);
735
736 /// Write to the stream supplied at construction the consecutive
737 /// two-byte, two's complement integers (in network byte order)
738 /// comprised of the least-significant two bytes of each of the
739 /// specified `numValues` leading entries in the specified `values` (in
740 /// host byte order), and return a reference to this stream. If this
741 /// stream is initially invalid, this operation has no effect.
742 ///
743 /// \pre The behavior is undefined unless `0 <= numValues` and `values` has
744 /// sufficient contents.
745 GenericOutStream& putArrayInt16(const short *values, int numValues);
746
747 /// Write to the stream supplied at construction the consecutive
748 /// two-byte, two's complement unsigned integers (in network byte order)
749 /// comprised of the least-significant two bytes of each of the
750 /// specified `numValues` leading entries in the specified `values` (in
751 /// host byte order), and return a reference to this stream. If this
752 /// stream is initially invalid, this operation has no effect.
753 ///
754 /// \pre The behavior is undefined unless `0 <= numValues` and `values` has
755 /// sufficient contents.
756 GenericOutStream& putArrayUint16(const unsigned short *values,
757 int numValues);
758
759 /// Write to the stream supplied at construction the consecutive
760 /// one-byte, two's complement integers comprised of the
761 /// least-significant one byte of each of the specified `numValues`
762 /// leading entries in the specified `values`, and return a reference to
763 /// this stream. If this stream is initially invalid, this operation has no effect.
764 ///
765 /// \pre The behavior is undefined unless `0 <= numValues`
766 /// and `values` has sufficient contents.
767 GenericOutStream& putArrayInt8(const char *values, int numValues);
768 GenericOutStream& putArrayInt8(const signed char *values, int numValues);
769
770 /// Write to the stream supplied at construction the consecutive
771 /// one-byte, two's complement unsigned integers comprised of the
772 /// least-significant one byte of each of the specified `numValues`
773 /// leading entries in the specified `values`, and return a reference to
774 /// this stream. If this stream is initially invalid, this operation has no effect.
775 ///
776 /// \pre The behavior is undefined unless `0 <= numValues`
777 /// and `values` has sufficient contents.
778 GenericOutStream& putArrayUint8(const char *values,
779 int numValues);
780 GenericOutStream& putArrayUint8(const unsigned char *values,
781 int numValues);
782
783 // *** arrays of floating-point values ***
784
785 /// Write to the stream supplied at construction the consecutive
786 /// eight-byte IEEE double-precision floating-point numbers (in network
787 /// byte order) comprised of the most-significant eight bytes of each of
788 /// the specified `numValues` leading entries in the specified `values`
789 /// (in host byte order), and return a reference to this stream. If
790 /// this stream is initially invalid, this operation has no effect.
791 ///
792 /// \pre The behavior is undefined unless `0 <= numValues` and `values` has sufficient contents.
793 ///
794 /// \note Note that for non-conforming platforms, this
795 /// operation may be lossy.
796 GenericOutStream& putArrayFloat64(const double *values, int numValues);
797
798 /// Write to the stream supplied at construction the consecutive
799 /// four-byte IEEE single-precision floating-point numbers (in network
800 /// byte order) comprised of the most-significant four bytes of each of
801 /// the specified `numValues` leading entries in the specified `values`
802 /// (in host byte order), and return a reference to this stream. If
803 /// this stream is initially invalid, this operation has no effect.
804 ///
805 /// \pre The behavior is undefined unless `0 <= numValues` and `values` has sufficient contents.
806 ///
807 /// \note Note that for non-conforming platforms, this
808 /// operation may be lossy.
809 GenericOutStream& putArrayFloat32(const float *values, int numValues);
810
811 // ACCESSORS
812
813 /// Return a non-zero value if this stream is valid, and 0 otherwise.
814 /// An invalid stream is a stream for which an output operation was
815 /// detected to have failed or `invalidate` was called.
816 operator const void *() const;
817
818 /// Return the `versionSelector` to be used with `operator<<` for BDEX
819 /// streaming as per the `bslx` package-level documentation.
820 int bdexVersionSelector() const;
821
822 /// Return `true` if this stream is valid, and `false` otherwise. An
823 /// invalid stream is a stream for which an output operation was
824 /// detected to have failed or `invalidate` was called.
825 bool isValid() const;
826};
827
828// FREE OPERATORS
829
830/// Write the specified `value` to the specified output `stream` following
831/// the requirements of the BDEX protocol (see the `bslx` package-level
832/// documentation), and return a reference to `stream`.
833///
834/// \pre The behavior is undefined unless `TYPE` is BDEX-compliant.
835template <class STREAMBUF, class TYPE>
837operator<<(GenericOutStream<STREAMBUF>& stream, const TYPE& value);
838
839// ============================================================================
840// INLINE DEFINITIONS
841// ============================================================================
842
843 // ----------------------
844 // class GenericOutStream
845 // ----------------------
846
847// PRIVATE MANIPULATORS
848template <class STREAMBUF>
849inline
851{
852 d_validFlag = true;
853}
854
855// CREATORS
856template <class STREAMBUF>
857inline
859 int versionSelector)
860: d_streamBuf(streamBuf)
861, d_versionSelector(versionSelector)
862, d_validFlag(true)
863{
864 BSLS_ASSERT_SAFE(streamBuf);
865}
866
867template <class STREAMBUF>
868inline
872
873// MANIPULATORS
874template <class STREAMBUF>
875inline
877{
878 if (isValid()) {
879 invalidate();
880 if (0 == d_streamBuf->pubsync()) {
881 validate();
882 }
883 }
884 return *this;
885}
886
887template <class STREAMBUF>
888inline
890{
891 d_validFlag = false;
892}
893
894template <class STREAMBUF>
895inline
898{
899 BSLS_ASSERT_SAFE(0 <= length);
900
901 if (length > 127) {
902 putInt32(length | (1 << 31));
903 }
904 else {
905 putInt8(length);
906 }
907 return *this;
908}
909
910template <class STREAMBUF>
911inline
914{
915 return putUint8(version);
916}
917
918 // *** scalar integer values ***
919
920template <class STREAMBUF>
921inline
924{
927 return *this; // RETURN
928 }
929
930 invalidate();
931
932#if BSLS_PLATFORM_IS_LITTLE_ENDIAN
933 const char *rawBytes = reinterpret_cast<char *>(&value);
934 char bytes[k_SIZEOF_INT64];
935
936 bytes[0] = rawBytes[7];
937 bytes[1] = rawBytes[6];
938 bytes[2] = rawBytes[5];
939 bytes[3] = rawBytes[4];
940 bytes[4] = rawBytes[3];
941 bytes[5] = rawBytes[2];
942 bytes[6] = rawBytes[1];
943 bytes[7] = rawBytes[0];
944#else
945 const char *bytes =
946 reinterpret_cast<char *>(&value) + sizeof value - k_SIZEOF_INT64;
947#endif
948
949 if (k_SIZEOF_INT64 == d_streamBuf->sputn(bytes, k_SIZEOF_INT64)) {
950 validate();
951 }
952
953 return *this;
954}
955
956template <class STREAMBUF>
957inline
960{
961 return putInt64(static_cast<bsls::Types::Int64>(value));
962}
963
964template <class STREAMBUF>
965inline
968{
971 return *this; // RETURN
972 }
973
974 invalidate();
975
976#if BSLS_PLATFORM_IS_LITTLE_ENDIAN
977 const char *rawBytes = reinterpret_cast<char *>(&value);
978 char bytes[k_SIZEOF_INT56];
979
980 bytes[0] = rawBytes[6];
981 bytes[1] = rawBytes[5];
982 bytes[2] = rawBytes[4];
983 bytes[3] = rawBytes[3];
984 bytes[4] = rawBytes[2];
985 bytes[5] = rawBytes[1];
986 bytes[6] = rawBytes[0];
987#else
988 const char *bytes =
989 reinterpret_cast<char *>(&value) + sizeof value - k_SIZEOF_INT56;
990#endif
991
992 if (k_SIZEOF_INT56 == d_streamBuf->sputn(bytes, k_SIZEOF_INT56)) {
993 validate();
994 }
995
996 return *this;
997}
998
999template <class STREAMBUF>
1000inline
1003{
1004 return putInt56(static_cast<bsls::Types::Int64>(value));
1005}
1006
1007template <class STREAMBUF>
1008inline
1011{
1012 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid())) {
1014 return *this; // RETURN
1015 }
1016
1017 invalidate();
1018
1019#if BSLS_PLATFORM_IS_LITTLE_ENDIAN
1020 const char *rawBytes = reinterpret_cast<char *>(&value);
1021 char bytes[k_SIZEOF_INT48];
1022
1023 bytes[0] = rawBytes[5];
1024 bytes[1] = rawBytes[4];
1025 bytes[2] = rawBytes[3];
1026 bytes[3] = rawBytes[2];
1027 bytes[4] = rawBytes[1];
1028 bytes[5] = rawBytes[0];
1029#else
1030 const char *bytes =
1031 reinterpret_cast<char *>(&value) + sizeof value - k_SIZEOF_INT48;
1032#endif
1033
1034 if (k_SIZEOF_INT48 == d_streamBuf->sputn(bytes, k_SIZEOF_INT48)) {
1035 validate();
1036 }
1037
1038 return *this;
1039}
1040
1041template <class STREAMBUF>
1042inline
1045{
1046 return putInt48(static_cast<bsls::Types::Int64>(value));
1047}
1048
1049template <class STREAMBUF>
1050inline
1053{
1054 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid())) {
1056 return *this; // RETURN
1057 }
1058
1059 invalidate();
1060
1061#if BSLS_PLATFORM_IS_LITTLE_ENDIAN
1062 const char *rawBytes = reinterpret_cast<char *>(&value);
1063 char bytes[k_SIZEOF_INT40];
1064
1065 bytes[0] = rawBytes[4];
1066 bytes[1] = rawBytes[3];
1067 bytes[2] = rawBytes[2];
1068 bytes[3] = rawBytes[1];
1069 bytes[4] = rawBytes[0];
1070#else
1071 const char *bytes =
1072 reinterpret_cast<char *>(&value) + sizeof value - k_SIZEOF_INT40;
1073#endif
1074
1075 if (k_SIZEOF_INT40 == d_streamBuf->sputn(bytes, k_SIZEOF_INT40)) {
1076 validate();
1077 }
1078
1079 return *this;
1080}
1081
1082template <class STREAMBUF>
1083inline
1086{
1087 return putInt40(static_cast<bsls::Types::Int64>(value));
1088}
1089
1090template <class STREAMBUF>
1091inline
1094{
1095 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid())) {
1097 return *this; // RETURN
1098 }
1099
1100 invalidate();
1101
1102#if BSLS_PLATFORM_IS_LITTLE_ENDIAN
1103 const char *rawBytes = reinterpret_cast<char *>(&value);
1104 char bytes[k_SIZEOF_INT32];
1105
1106 bytes[0] = rawBytes[3];
1107 bytes[1] = rawBytes[2];
1108 bytes[2] = rawBytes[1];
1109 bytes[3] = rawBytes[0];
1110#else
1111 const char *bytes =
1112 reinterpret_cast<char *>(&value) + sizeof value - k_SIZEOF_INT32;
1113#endif
1114
1115 if (k_SIZEOF_INT32 == d_streamBuf->sputn(bytes, k_SIZEOF_INT32)) {
1116 validate();
1117 }
1118
1119 return *this;
1120}
1121
1122template <class STREAMBUF>
1123inline
1126{
1127 return putInt32(static_cast<int>(value));
1128}
1129
1130template <class STREAMBUF>
1131inline
1134{
1135 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid())) {
1137 return *this; // RETURN
1138 }
1139
1140 invalidate();
1141
1142#if BSLS_PLATFORM_IS_LITTLE_ENDIAN
1143 const char *rawBytes = reinterpret_cast<char *>(&value);
1144 char bytes[k_SIZEOF_INT24];
1145
1146 bytes[0] = rawBytes[2];
1147 bytes[1] = rawBytes[1];
1148 bytes[2] = rawBytes[0];
1149#else
1150 const char *bytes =
1151 reinterpret_cast<char *>(&value) + sizeof value - k_SIZEOF_INT24;
1152#endif
1153
1154 if (k_SIZEOF_INT24 == d_streamBuf->sputn(bytes, k_SIZEOF_INT24)) {
1155 validate();
1156 }
1157
1158 return *this;
1159}
1160
1161template <class STREAMBUF>
1162inline
1165{
1166 return putInt24(static_cast<int>(value));
1167}
1168
1169template <class STREAMBUF>
1170inline
1173{
1174 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid())) {
1176 return *this; // RETURN
1177 }
1178
1179 invalidate();
1180
1181#if BSLS_PLATFORM_IS_LITTLE_ENDIAN
1182 const char *rawBytes = reinterpret_cast<char *>(&value);
1183 char bytes[k_SIZEOF_INT16];
1184
1185 bytes[0] = rawBytes[1];
1186 bytes[1] = rawBytes[0];
1187#else
1188 const char *bytes =
1189 reinterpret_cast<char *>(&value) + sizeof value - k_SIZEOF_INT16;
1190#endif
1191
1192 if (k_SIZEOF_INT16 == d_streamBuf->sputn(bytes, k_SIZEOF_INT16)) {
1193 validate();
1194 }
1195
1196 return *this;
1197}
1198
1199template <class STREAMBUF>
1200inline
1203{
1204 return putInt16(static_cast<int>(value));
1205}
1206
1207template <class STREAMBUF>
1208inline
1211{
1212 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid())) {
1214 return *this; // RETURN
1215 }
1216
1217 invalidate();
1218
1219 if (STREAMBUF::traits_type::eof() !=
1220 d_streamBuf->sputc(static_cast<char>(value))) {
1221 validate();
1222 }
1223
1224 return *this;
1225}
1226
1227template <class STREAMBUF>
1228inline
1231{
1232 return putInt8(static_cast<int>(value));
1233}
1234
1235 // *** scalar floating-point values ***
1236
1237template <class STREAMBUF>
1238inline
1241{
1242 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid())) {
1244 return *this; // RETURN
1245 }
1246
1247 invalidate();
1248
1249#if BSLS_PLATFORM_IS_LITTLE_ENDIAN
1250 const char *rawBytes = reinterpret_cast<char *>(&value);
1251 char bytes[k_SIZEOF_FLOAT64];
1252
1253 bytes[0] = rawBytes[sizeof value - 1];
1254 bytes[1] = rawBytes[sizeof value - 2];
1255 bytes[2] = rawBytes[sizeof value - 3];
1256 bytes[3] = rawBytes[sizeof value - 4];
1257 bytes[4] = rawBytes[sizeof value - 5];
1258 bytes[5] = rawBytes[sizeof value - 6];
1259 bytes[6] = rawBytes[sizeof value - 7];
1260 bytes[7] = rawBytes[sizeof value - 8];
1261#else
1262 const char *bytes = reinterpret_cast<char *>(&value);
1263#endif
1264
1265 if (k_SIZEOF_FLOAT64 == d_streamBuf->sputn(bytes, k_SIZEOF_FLOAT64)) {
1266 validate();
1267 }
1268
1269 return *this;
1270}
1271
1272template <class STREAMBUF>
1273inline
1276{
1277 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid())) {
1279 return *this; // RETURN
1280 }
1281
1282 invalidate();
1283
1284#if BSLS_PLATFORM_IS_LITTLE_ENDIAN
1285 const char *rawBytes = reinterpret_cast<char *>(&value);
1286 char bytes[k_SIZEOF_FLOAT32];
1287
1288 bytes[0] = rawBytes[sizeof value - 1];
1289 bytes[1] = rawBytes[sizeof value - 2];
1290 bytes[2] = rawBytes[sizeof value - 3];
1291 bytes[3] = rawBytes[sizeof value - 4];
1292#else
1293 const char *bytes = reinterpret_cast<char *>(&value);
1294#endif
1295
1296 if (k_SIZEOF_FLOAT32 == d_streamBuf->sputn(bytes, k_SIZEOF_FLOAT32)) {
1297 validate();
1298 }
1299
1300 return *this;
1301}
1302
1303 // *** string values ***
1304
1305template <class STREAMBUF>
1306inline
1309{
1310 putLength(static_cast<int>(value.length()));
1311 return putArrayUint8(value.data(), static_cast<int>(value.length()));
1312}
1313
1314 // *** arrays of integer values ***
1315
1316template <class STREAMBUF>
1319 int numValues)
1320{
1321 BSLS_ASSERT(values);
1322 BSLS_ASSERT(0 <= numValues);
1323
1324 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid() || 0 == numValues)) {
1326 return *this; // RETURN
1327 }
1328
1329 const bsls::Types::Int64 *end = values + numValues;
1330 for (; values != end; ++values) {
1331 putInt64(*values);
1332 }
1333
1334 return *this;
1335}
1336
1337template <class STREAMBUF>
1340 const bsls::Types::Uint64 *values,
1341 int numValues)
1342{
1343 BSLS_ASSERT(values);
1344 BSLS_ASSERT(0 <= numValues);
1345
1346 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid() || 0 == numValues)) {
1348 return *this; // RETURN
1349 }
1350
1351 const bsls::Types::Uint64 *end = values + numValues;
1352 for (; values != end; ++values) {
1353 putUint64(*values);
1354 }
1355
1356 return *this;
1357}
1358
1359template <class STREAMBUF>
1362 int numValues)
1363{
1364 BSLS_ASSERT(values);
1365 BSLS_ASSERT(0 <= numValues);
1366
1367 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid() || 0 == numValues)) {
1369 return *this; // RETURN
1370 }
1371
1372 const bsls::Types::Int64 *end = values + numValues;
1373 for (; values != end; ++values) {
1374 putInt56(*values);
1375 }
1376
1377 return *this;
1378}
1379
1380template <class STREAMBUF>
1383 const bsls::Types::Uint64 *values,
1384 int numValues)
1385{
1386 BSLS_ASSERT(values);
1387 BSLS_ASSERT(0 <= numValues);
1388
1389 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid() || 0 == numValues)) {
1391 return *this; // RETURN
1392 }
1393
1394 const bsls::Types::Uint64 *end = values + numValues;
1395 for (; values != end; ++values) {
1396 putUint56(*values);
1397 }
1398
1399 return *this;
1400}
1401
1402template <class STREAMBUF>
1405 int numValues)
1406{
1407 BSLS_ASSERT(values);
1408 BSLS_ASSERT(0 <= numValues);
1409
1410 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid() || 0 == numValues)) {
1412 return *this; // RETURN
1413 }
1414
1415 const bsls::Types::Int64 *end = values + numValues;
1416 for (; values != end; ++values) {
1417 putInt48(*values);
1418 }
1419
1420 return *this;
1421}
1422
1423template <class STREAMBUF>
1426 const bsls::Types::Uint64 *values,
1427 int numValues)
1428{
1429 BSLS_ASSERT(values);
1430 BSLS_ASSERT(0 <= numValues);
1431
1432 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid() || 0 == numValues)) {
1434 return *this; // RETURN
1435 }
1436
1437 const bsls::Types::Uint64 *end = values + numValues;
1438 for (; values != end; ++values) {
1439 putUint48(*values);
1440 }
1441
1442 return *this;
1443}
1444
1445template <class STREAMBUF>
1448 int numValues)
1449{
1450 BSLS_ASSERT(values);
1451 BSLS_ASSERT(0 <= numValues);
1452
1453 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid() || 0 == numValues)) {
1455 return *this; // RETURN
1456 }
1457
1458 const bsls::Types::Int64 *end = values + numValues;
1459 for (; values != end; ++values) {
1460 putInt40(*values);
1461 }
1462
1463 return *this;
1464}
1465
1466template <class STREAMBUF>
1469 const bsls::Types::Uint64 *values,
1470 int numValues)
1471{
1472 BSLS_ASSERT(values);
1473 BSLS_ASSERT(0 <= numValues);
1474
1475 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid() || 0 == numValues)) {
1477 return *this; // RETURN
1478 }
1479
1480 const bsls::Types::Uint64 *end = values + numValues;
1481 for (; values != end; ++values) {
1482 putUint40(*values);
1483 }
1484
1485 return *this;
1486}
1487
1488template <class STREAMBUF>
1490GenericOutStream<STREAMBUF>::putArrayInt32(const int *values, int numValues)
1491{
1492 BSLS_ASSERT(values);
1493 BSLS_ASSERT(0 <= numValues);
1494
1495 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid() || 0 == numValues)) {
1497 return *this; // RETURN
1498 }
1499
1500 const int *end = values + numValues;
1501 for (; values != end; ++values) {
1502 putInt32(*values);
1503 }
1504
1505 return *this;
1506}
1507
1508template <class STREAMBUF>
1511 int numValues)
1512{
1513 BSLS_ASSERT(values);
1514 BSLS_ASSERT(0 <= numValues);
1515
1516 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid() || 0 == numValues)) {
1518 return *this; // RETURN
1519 }
1520
1521 const unsigned int *end = values + numValues;
1522 for (; values != end; ++values) {
1523 putUint32(*values);
1524 }
1525
1526 return *this;
1527}
1528
1529template <class STREAMBUF>
1531GenericOutStream<STREAMBUF>::putArrayInt24(const int *values, int numValues)
1532{
1533 BSLS_ASSERT(values);
1534 BSLS_ASSERT(0 <= numValues);
1535
1536 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid() || 0 == numValues)) {
1538 return *this; // RETURN
1539 }
1540
1541 const int *end = values + numValues;
1542 for (; values != end; ++values) {
1543 putInt24(*values);
1544 }
1545
1546 return *this;
1547}
1548
1549template <class STREAMBUF>
1552 int numValues)
1553{
1554 BSLS_ASSERT(values);
1555 BSLS_ASSERT(0 <= numValues);
1556
1557 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid() || 0 == numValues)) {
1559 return *this; // RETURN
1560 }
1561
1562 const unsigned int *end = values + numValues;
1563 for (; values != end; ++values) {
1564 putUint24(*values);
1565 }
1566
1567 return *this;
1568}
1569
1570template <class STREAMBUF>
1572GenericOutStream<STREAMBUF>::putArrayInt16(const short *values, int numValues)
1573{
1574 BSLS_ASSERT(values);
1575 BSLS_ASSERT(0 <= numValues);
1576
1577 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid() || 0 == numValues)) {
1579 return *this; // RETURN
1580 }
1581
1582 const short *end = values + numValues;
1583 for (; values != end; ++values) {
1584 putInt16(*values);
1585 }
1586
1587 return *this;
1588}
1589
1590template <class STREAMBUF>
1593 int numValues)
1594{
1595 BSLS_ASSERT(values);
1596 BSLS_ASSERT(0 <= numValues);
1597
1598 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid() || 0 == numValues)) {
1600 return *this; // RETURN
1601 }
1602
1603 const unsigned short *end = values + numValues;
1604 for (; values != end; ++values) {
1605 putUint16(*values);
1606 }
1607
1608 return *this;
1609}
1610
1611template <class STREAMBUF>
1612inline
1614GenericOutStream<STREAMBUF>::putArrayInt8(const char *values, int numValues)
1615{
1616 BSLS_ASSERT_SAFE(values);
1617 BSLS_ASSERT_SAFE(0 <= numValues);
1618
1619 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid() || 0 == numValues)) {
1621 return *this; // RETURN
1622 }
1623
1624 invalidate();
1625
1626 if (numValues == d_streamBuf->sputn(values, numValues)) {
1627 validate();
1628 }
1629
1630 return *this;
1631}
1632
1633template <class STREAMBUF>
1634inline
1637 int numValues)
1638{
1639 BSLS_ASSERT_SAFE(values);
1640 BSLS_ASSERT_SAFE(0 <= numValues);
1641
1642 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid() || 0 == numValues)) {
1644 return *this; // RETURN
1645 }
1646
1647 invalidate();
1648
1649 if (numValues == d_streamBuf->sputn(reinterpret_cast<const char *>(values),
1650 numValues)) {
1651 validate();
1652 }
1653
1654 return *this;
1655}
1656
1657template <class STREAMBUF>
1658inline
1660GenericOutStream<STREAMBUF>::putArrayUint8(const char *values, int numValues)
1661{
1662 BSLS_ASSERT_SAFE(values);
1663 BSLS_ASSERT_SAFE(0 <= numValues);
1664
1665 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid() || 0 == numValues)) {
1667 return *this; // RETURN
1668 }
1669
1670 invalidate();
1671
1672 if (numValues == d_streamBuf->sputn(values, numValues)) {
1673 validate();
1674 }
1675
1676 return *this;
1677}
1678
1679template <class STREAMBUF>
1680inline
1683 int numValues)
1684{
1685 BSLS_ASSERT_SAFE(values);
1686 BSLS_ASSERT_SAFE(0 <= numValues);
1687
1688 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid() || 0 == numValues)) {
1690 return *this; // RETURN
1691 }
1692
1693 invalidate();
1694
1695 if (numValues == d_streamBuf->sputn(reinterpret_cast<const char *>(values),
1696 numValues)) {
1697 validate();
1698 }
1699
1700 return *this;
1701}
1702
1703 // *** arrays of floating-point values ***
1704
1705template <class STREAMBUF>
1708 int numValues)
1709{
1710 BSLS_ASSERT(values);
1711 BSLS_ASSERT(0 <= numValues);
1712
1713 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid() || 0 == numValues)) {
1715 return *this; // RETURN
1716 }
1717
1718 const double *end = values + numValues;
1719 for (; values != end; ++values) {
1720 putFloat64(*values);
1721 }
1722
1723 return *this;
1724}
1725
1726template <class STREAMBUF>
1729 int numValues)
1730{
1731 BSLS_ASSERT(values);
1732 BSLS_ASSERT(0 <= numValues);
1733
1734 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValid() || 0 == numValues)) {
1736 return *this; // RETURN
1737 }
1738
1739 const float *end = values + numValues;
1740 for (; values != end; ++values) {
1741 putFloat32(*values);
1742 }
1743
1744 return *this;
1745}
1746
1747// ACCESSORS
1748template <class STREAMBUF>
1749inline
1751{
1752 return isValid() ? this : 0;
1753}
1754
1755template <class STREAMBUF>
1756inline
1758{
1759 return d_versionSelector;
1760}
1761
1762template <class STREAMBUF>
1763inline
1765{
1766 return d_validFlag;
1767}
1768
1769// FREE OPERATORS
1770template <class STREAMBUF, class TYPE>
1771inline
1773operator<<(GenericOutStream<STREAMBUF>& stream, const TYPE& value)
1774{
1775 return OutStreamFunctions::bdexStreamOut(stream, value);
1776}
1777
1778} // close package namespace
1779
1780
1781#endif
1782
1783// ----------------------------------------------------------------------------
1784// Copyright 2014 Bloomberg Finance L.P.
1785//
1786// Licensed under the Apache License, Version 2.0 (the "License");
1787// you may not use this file except in compliance with the License.
1788// You may obtain a copy of the License at
1789//
1790// http://www.apache.org/licenses/LICENSE-2.0
1791//
1792// Unless required by applicable law or agreed to in writing, software
1793// distributed under the License is distributed on an "AS IS" BASIS,
1794// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1795// See the License for the specific language governing permissions and
1796// limitations under the License.
1797// ----------------------------- END-OF-FILE ----------------------------------
1798
1799/** @} */
1800/** @} */
1801/** @} */
Definition bslstl_string.h:1252
size_type length() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:7301
CHAR_TYPE * data() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:7177
Definition bslx_genericoutstream.h:363
GenericOutStream & putFloat32(float value)
Definition bslx_genericoutstream.h:1275
GenericOutStream & putInt32(int value)
Definition bslx_genericoutstream.h:1093
GenericOutStream & putInt56(bsls::Types::Int64 value)
Definition bslx_genericoutstream.h:967
GenericOutStream & putLength(int length)
Definition bslx_genericoutstream.h:897
GenericOutStream & putUint56(bsls::Types::Uint64 value)
Definition bslx_genericoutstream.h:1002
GenericOutStream & putArrayInt64(const bsls::Types::Int64 *values, int numValues)
Definition bslx_genericoutstream.h:1318
GenericOutStream & putArrayInt16(const short *values, int numValues)
Definition bslx_genericoutstream.h:1572
GenericOutStream & putUint40(bsls::Types::Uint64 value)
Definition bslx_genericoutstream.h:1085
int bdexVersionSelector() const
Definition bslx_genericoutstream.h:1757
GenericOutStream & putArrayUint48(const bsls::Types::Uint64 *values, int numValues)
Definition bslx_genericoutstream.h:1425
GenericOutStream & putArrayUint32(const unsigned int *values, int numValues)
Definition bslx_genericoutstream.h:1510
GenericOutStream & putUint64(bsls::Types::Uint64 value)
Definition bslx_genericoutstream.h:959
GenericOutStream & putArrayUint40(const bsls::Types::Uint64 *values, int numValues)
Definition bslx_genericoutstream.h:1468
GenericOutStream & putInt64(bsls::Types::Int64 value)
Definition bslx_genericoutstream.h:923
GenericOutStream & putArrayInt48(const bsls::Types::Int64 *values, int numValues)
Definition bslx_genericoutstream.h:1404
GenericOutStream & putVersion(int version)
Definition bslx_genericoutstream.h:913
GenericOutStream & putUint16(unsigned int value)
Definition bslx_genericoutstream.h:1202
GenericOutStream & putArrayInt24(const int *values, int numValues)
Definition bslx_genericoutstream.h:1531
GenericOutStream & putInt16(int value)
Definition bslx_genericoutstream.h:1172
GenericOutStream & putArrayUint56(const bsls::Types::Uint64 *values, int numValues)
Definition bslx_genericoutstream.h:1382
GenericOutStream & putString(const bsl::string &value)
Definition bslx_genericoutstream.h:1308
GenericOutStream & putInt24(int value)
Definition bslx_genericoutstream.h:1133
GenericOutStream & putInt8(int value)
Definition bslx_genericoutstream.h:1210
GenericOutStream & putInt40(bsls::Types::Int64 value)
Definition bslx_genericoutstream.h:1052
GenericOutStream & putUint24(unsigned int value)
Definition bslx_genericoutstream.h:1164
GenericOutStream & putArrayInt32(const int *values, int numValues)
Definition bslx_genericoutstream.h:1490
bool isValid() const
Definition bslx_genericoutstream.h:1764
GenericOutStream & putArrayFloat64(const double *values, int numValues)
Definition bslx_genericoutstream.h:1707
GenericOutStream & putInt48(bsls::Types::Int64 value)
Definition bslx_genericoutstream.h:1010
GenericOutStream & putArrayUint16(const unsigned short *values, int numValues)
Definition bslx_genericoutstream.h:1592
void invalidate()
Definition bslx_genericoutstream.h:889
GenericOutStream & putArrayUint64(const bsls::Types::Uint64 *values, int numValues)
Definition bslx_genericoutstream.h:1339
GenericOutStream & putArrayUint24(const unsigned int *values, int numValues)
Definition bslx_genericoutstream.h:1551
GenericOutStream & putFloat64(double value)
Definition bslx_genericoutstream.h:1240
~GenericOutStream()
Destroy this object.
Definition bslx_genericoutstream.h:869
GenericOutStream & flush()
Definition bslx_genericoutstream.h:876
GenericOutStream & putUint48(bsls::Types::Uint64 value)
Definition bslx_genericoutstream.h:1044
GenericOutStream & putArrayFloat32(const float *values, int numValues)
Definition bslx_genericoutstream.h:1728
GenericOutStream & putArrayInt8(const char *values, int numValues)
Definition bslx_genericoutstream.h:1614
GenericOutStream & putUint32(unsigned int value)
Definition bslx_genericoutstream.h:1125
GenericOutStream & putUint8(unsigned int value)
Definition bslx_genericoutstream.h:1230
GenericOutStream & putArrayInt56(const bsls::Types::Int64 *values, int numValues)
Definition bslx_genericoutstream.h:1361
GenericOutStream & putArrayInt40(const bsls::Types::Int64 *values, int numValues)
Definition bslx_genericoutstream.h:1447
GenericOutStream & putArrayUint8(const char *values, int numValues)
Definition bslx_genericoutstream.h:1660
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1976
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1917
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
#define BSLS_PERFORMANCEHINT_UNLIKELY_HINT
Definition bsls_performancehint.h:484
#define BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(expr)
Definition bsls_performancehint.h:452
STREAM & bdexStreamOut(STREAM &stream, const TYPE &value)
Definition bslx_outstreamfunctions.h:1004
Definition bslx_byteinstream.h:377
bsl::ostream & operator<<(bsl::ostream &stream, const ByteInStream &object)
unsigned long long Uint64
Definition bsls_types.h:139
long long Int64
Definition bsls_types.h:134