BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslstl_stringbuf.h
Go to the documentation of this file.
1/// @file bslstl_stringbuf.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslstl_stringbuf.h -*-C++-*-
8#ifndef INCLUDED_BSLSTL_STRINGBUF
9#define INCLUDED_BSLSTL_STRINGBUF
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslstl_stringbuf bslstl_stringbuf
15/// @brief Provide a C++03-compatible `stringbuf` class.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslstl
19/// @{
20/// @addtogroup bslstl_stringbuf
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslstl_stringbuf-purpose"> Purpose</a>
25/// * <a href="#bslstl_stringbuf-classes"> Classes </a>
26/// * <a href="#bslstl_stringbuf-description"> Description </a>
27/// * <a href="#bslstl_stringbuf-memory-allocation"> Memory Allocation </a>
28/// * <a href="#bslstl_stringbuf-bslma-style-allocators"> bslma-Style Allocators </a>
29/// * <a href="#bslstl_stringbuf-usage"> Usage </a>
30/// * <a href="#bslstl_stringbuf-example-1-basic-operations"> Example 1: Basic Operations </a>
31///
32/// # Purpose {#bslstl_stringbuf-purpose}
33/// Provide a C++03-compatible `stringbuf` class.
34///
35/// # Classes {#bslstl_stringbuf-classes}
36///
37/// - bsl::stringbuf: C++03-compatible `stringbuf` class
38/// - bsl::StringBufContainer: wrapper for @ref basic_stringbuf
39///
40/// **Canonical header:** bsl_sstream.h
41///
42/// @see bslstl_stringstream, bslstl_ostringstream, bslstl_istringstream
43///
44/// # Description {#bslstl_stringbuf-description}
45/// This component is for internal use only. Please include
46/// `<bsl_sstream.h>` instead.
47///
48/// This component defines a class template, `bsl::basic_stringbuf`, that
49/// implements a standard string buffer, providing an unformatted character
50/// input sequence and an unformatted character output sequence that
51/// may be initialized or accessed using a string value (see 27.8.2 [stringbuf]
52/// of the C++11 standard). This component also defines two standard aliases,
53/// `bsl::stringbuf` and `bsl::wstringbuf`, that refer to specializations of the
54/// `bsl::basic_stringbuf` template for `char` and `wchar_t` types,
55/// respectively. As with any stream buffer class, `bsl::basic_stringbuf` is
56/// rarely used directly. Stream buffers provide low-level unformatted
57/// input/output. They are usually plugged into `std::basic_stream` classes to
58/// provide higher-level formatted input and output via `operator>>` and
59/// `operator<<`. `bsl::basic_stringbuf` is used in the
60/// `bsl::basic_stringstream` family of classes and users should prefer those
61/// classes over direct use of `bsl::basic_stringbuf`.
62///
63/// `bsl::basic_stringbuf` derives from `std::basic_streambuf` and implements
64/// the necessary protected virtual methods. In this way `bsl::basic_stringbuf`
65/// customizes the behavior of `std::basic_streambuf` to redirect the reading
66/// and writing of characters to an internally-maintained sequence of characters
67/// that can be initialized or accessed using a `bsl::basic_string`. Note that
68/// although the standard mandates functions that access and modify the
69/// buffered sequence using a @ref basic_string , it does not mandate that a
70/// @ref basic_stringbuf internally store this buffer in a @ref basic_string ; this
71/// implementation currently uses a @ref basic_string as its internal buffer, but
72/// that is subject to change without warning.
73///
74/// The `bsl::stringbuf` template has three parameters, `CHAR_TYPE`,
75/// `CHAR_TRAITS`, and `ALLOCATOR`. The `CHAR_TYPE` and `CHAR_TRAITS`
76/// parameters respectively define the character type for the stream buffer and
77/// a type providing a set of operations the stream buffer will use to
78/// manipulate characters of that type, which must meet the character traits
79/// requirements defined by the C++11 standard, 21.2 [char.traits]. The
80/// `ALLOCATOR` template parameter is described in the "Memory Allocation"
81/// section below.
82///
83/// ## Memory Allocation {#bslstl_stringbuf-memory-allocation}
84///
85///
86/// The type supplied as a stream buffer's `ALLOCATOR` template parameter
87/// determines how that stream buffer will allocate memory. The
88/// @ref basic_stringbuf template supports allocators meeting the requirements
89/// of the C++11 standard, 17.6.3.5 [allocator.requirements]; in addition, it
90/// supports scoped-allocators derived from the `bslma::Allocator` memory
91/// allocation protocol. Clients intending to use `bslma`-style allocators
92/// should use `bsl::allocator`, which provides a C++11 standard-compatible
93/// adapter for a `bslma::Allocator` object. Note that the standard aliases
94/// `bsl::stringbuf` and `bsl::wstringbuf` both use `bsl::allocator`.
95///
96/// ### bslma-Style Allocators {#bslstl_stringbuf-bslma-style-allocators}
97///
98///
99/// If the type supplied for the `ALLOCATOR` template parameter of a `stringbuf`
100/// instantiation is `bsl::allocator`, then objects of that stream buffer type
101/// will conform to the standard behavior of a `bslma`-allocator-enabled type.
102/// Such a stream buffer accepts an optional `bslma::Allocator` argument at
103/// construction. If the address of a `bslma::Allocator` object is explicitly
104/// supplied at construction, it will be used to supply memory for the stream
105/// buffer throughout its lifetime; otherwise, the stream buffer will use the
106/// default allocator installed at the time of the stream buffer's construction
107/// (see @ref bslma_default ).
108///
109/// ## Usage {#bslstl_stringbuf-usage}
110///
111///
112/// This section illustrates intended use of this component.
113///
114/// ### Example 1: Basic Operations {#bslstl_stringbuf-example-1-basic-operations}
115///
116///
117/// The following example demonstrates the use of `bsl::stringbuf` to read and
118/// write character data from and to a `bsl::string` object.
119///
120/// Suppose we want to implement a simplified converter from `unsigned int` to
121/// `bsl::string` and back. First, we define the prototypes of two conversion
122/// functions:
123/// @code
124/// bsl::string toString(unsigned int from);
125/// unsigned int fromString(const bsl::string& from);
126/// @endcode
127/// Then, we use `bsl::stringbuf` to implement the `toString` function. We
128/// write all digits into `bsl::stringbuf` individually using `sputc` methods
129/// and then return the resulting `bsl::string` object:
130/// @code
131/// #include <algorithm>
132///
133/// bsl::string toString(unsigned int from)
134/// {
135/// bsl::stringbuf out;
136///
137/// for (; from != 0; from /= 10) {
138/// out.sputc('0' + from % 10);
139/// }
140///
141/// bsl::string result(out.str());
142/// std::reverse(result.begin(), result.end());
143/// return result;
144/// }
145/// @endcode
146/// Now, we implement the `fromString` function that converts from
147/// `bsl::string` to `unsigned int` by using `bsl::stringbuf` to read individual
148/// digits from the string object:
149/// @code
150/// unsigned int fromString(const bsl::string& from)
151/// {
152/// unsigned int result = 0;
153///
154/// for (bsl::stringbuf in(from); in.in_avail(); ) {
155/// result = result * 10 + (in.sbumpc() - '0');
156/// }
157///
158/// return result;
159/// }
160/// @endcode
161/// Finally, we verify that the result of the round-trip conversion is identical
162/// to the original value:
163/// @code
164/// unsigned int orig = 92872498;
165/// unsigned int result = fromString(toString(orig));
166///
167/// assert(orig == result);
168/// @endcode
169/// @}
170/** @} */
171/** @} */
172
173/** @addtogroup bsl
174 * @{
175 */
176/** @addtogroup bslstl
177 * @{
178 */
179/** @addtogroup bslstl_stringbuf
180 * @{
181 */
182
183#include <bslscm_version.h>
184
185#include <bslstl_iosfwd.h>
186#include <bslstl_string.h>
187#include <bslstl_stringview.h>
188
189#include <bslalg_swaputil.h>
190
191#include <bslma_isstdallocator.h>
192#include <bslma_bslallocator.h>
194
195#include <bslmf_enableif.h>
196#include <bslmf_issame.h>
197#include <bslmf_movableref.h>
198
199#include <bsls_assert.h>
201#include <bsls_keyword.h>
202#include <bsls_libraryfeatures.h>
203#include <bsls_platform.h>
204
205#include <algorithm>
206#include <cstddef>
207#include <ios>
208#include <istream>
209#include <ostream>
210#include <streambuf>
211
212#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_STREAM_MOVE
213# include <utility>
214#endif
215#include <limits.h> // for 'INT_MAX', 'INT_MIN'
216
217#ifndef BDE_OMIT_INTERNAL_DEPRECATED
218#ifndef BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
219#include <bslalg_typetraits.h>
220#endif // BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
221#endif // BDE_OMIT_INTERNAL_DEPRECATED
222
223
224// 'BSLS_ASSERT' filename fix -- See @ref bsls_assertimputil
225#ifdef BSLS_ASSERTIMPUTIL_AVOID_STRING_CONSTANTS
226extern const char s_bslstl_stringbuf_h[];
227#undef BSLS_ASSERTIMPUTIL_FILE
228#define BSLS_ASSERTIMPUTIL_FILE BloombergLP::s_bslstl_stringbuf_h
229#endif
230}
231
232namespace bsl {
233
234using std::ios_base;
235
236 // =====================
237 // class basic_stringbuf
238 // =====================
239
240/// This class implements a standard stream buffer providing an unformatted
241/// character input sequence and an unformatted character output sequence
242/// that may be initialized or accessed using a string value.
243template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
245 : public std::basic_streambuf<CHAR_TYPE, CHAR_TRAITS> {
246
247 private:
248 // PRIVATE TYPES
249 typedef std::basic_streambuf<CHAR_TYPE, CHAR_TRAITS> BaseType;
252
253 typedef BloombergLP::bslmf::MovableRefUtil MoveUtil;
254
255 public:
256 // TYPES
257 typedef CHAR_TYPE char_type;
258 typedef CHAR_TRAITS traits_type;
259 typedef ALLOCATOR allocator_type;
260 typedef typename traits_type::int_type int_type;
261 typedef typename traits_type::off_type off_type;
262 typedef typename traits_type::pos_type pos_type;
263
264 private:
265 // DATA
266 StringType d_str; // internal character sequence buffer
267
268 off_type d_endHint;
269 // offset to one past the last known good
270 // character in `d_str` (Note that to enable
271 // efficient buffering, `d_str` may be resized
272 // beyond the last written character, so
273 // `d_str.size()` may not accurately report
274 // the current length of the character
275 // sequence available for input. Extending
276 // the size of `d_str` and updating `epptr`
277 // (the end-of-output pointer) allows the
278 // parent stream type to write additional
279 // characters without `overflow`. However,
280 // care must be taken to refresh the cached
281 // `d_endHint` value as the parent stream will
282 // update the current output position `pptr`,
283 // without calling a method on this type.)
284
285 ios_base::openmode d_mode; // `stringbuf` open mode (`in`, `out`, or both)
286
287 private:
288 // NOT IMPLEMENTED
289 basic_stringbuf(const basic_stringbuf&); // = delete
290 basic_stringbuf& operator=(const basic_stringbuf&); // = delete
291
292 private:
293 // PRIVATE MANIPULATORS
294
295 /// Update the input pointers (`eback`, `gptr`, `egptr`) of this string
296 /// buffer, setting the beginning of the input sequence, `eback`, to the
297 /// address of the first character of the internal string
298 /// representation, `d_str`, the current position of the input sequence,
299 /// `gptr`, to the specified `currentInputPosition`, and the address
300 /// past the end of the accessible sequence, `egptr`, to the last
301 /// character in `d_ptr` (`&d_ptr[0] + d_endHint`). Return the offset
302 /// of the current position of the input sequence from the start of the
303 /// sequence. The behavior is undefined unless this buffer is in input
304 /// mode and `currentInputPosition` is within the range of accessible
305 /// characters in `d_ptr`.
306 pos_type updateInputPointers(char_type *currentInputPosition);
307
308 /// Update the output pointers (`pback`, `pptr`, `epptr`) of this string
309 /// buffer, setting the beginning of the output sequence, `pback`, to
310 /// the address of the first character of the internal string
311 /// representation, `d_str`, the current position of the output
312 /// sequence, `pptr`, to the specified `currentOutputPosition`, and the
313 /// address past the end of the accessible sequence, `epptr`, to one
314 /// past the last character in `d_ptr` (`&d_ptr[0] + d_ptr.size()`).
315 /// Return the offset of the current position of the output sequence
316 /// from the start of the sequence. The behavior is undefined unless
317 /// this buffer is in output mode, and `currentOutputPosition` is within
318 /// the range of accessible characters in `d_ptr`.
319 pos_type updateOutputPointers(char_type *currentOutputPosition);
320
321 /// Update the input and output positions of this string buffer object
322 /// according to the current state of the internal string representation
323 /// `d_ptr`. Optionally specify an `inputOffset` indicating the current
324 /// input position's offset from the beginning of the sequence.
325 /// Optionally specify an `outputOffset` indicating the current output
326 /// position's offset from the beginning of the sequence. If this
327 /// buffer is in output mode, set the beginning of the output sequence,
328 /// `pback`, to the address of the first character of `d_ptr`, the
329 /// current output position, `pptr`, to `pback + outputOffset`, and the
330 /// end of the output sequence, `epptr`, to one past the last character
331 /// in `d_str` (`&d_ptr[0] + d_ptr.size()`). If this buffer is in input
332 /// mode, set the beginning of the input sequence, `eback`, to the
333 /// address of the first character of `d_ptr`, the current input
334 /// position, `gptr`, to `eback + inputOffset`, and the end of the input
335 /// sequence, `egptr`, to the last written character in `d_str`
336 /// (`&d_ptr[0] + d_endHint`).
337 void updateStreamPositions(off_type inputOffset = 0,
338 off_type outputOffset = 0);
339
340 /// Attempt to expand the sequence of characters available for input
341 /// (i.e., update the end of input buffer position, `egptr`) to
342 /// incorporate additional characters that may have been written (as
343 /// output) to the stream. Return `true` if the input buffer was
344 /// successfully extended, and `false` otherwise. Note that the input
345 /// area as described by `eback`, `gptr`, and `egptr` may become out of
346 /// sync with the characters actually available in the buffer as the
347 /// parent @ref basic_streambuf type may perform writes into the output
348 /// area (using `pbase`, `pptr`, and `epptr`) without calling any
349 /// methods of this object.
350 bool extendInputArea();
351
352 // PRIVATE ACCESSORS
353
354 /// Return the number of characters currently in the buffer. Note this
355 /// may not be `d_str.size()`, as this implementation resizes `d_str`
356 /// beyond the number of written characters to provide more efficient
357 /// buffering, and it also may not be `d_endHint`, as that value may
358 /// currently be stale (as writes may have been performed through the
359 /// parent @ref basic_streambuf type without calling a method on this
360 /// object).
361 pos_type streamSize() const;
362
363 /// Return `true` if pointers form a valid range
364 /// (`first <= middle <= last`) and `first == d_str.data()` and
365 /// `middle` and `last` are in the range
366 /// `[d_str.data() .. d_str.data() + d_str.size()]`, or all arguments
367 /// are 0, and `false` otherwise. Note that this function is called in
368 /// defensive (i.e., "DEBUG" or "SAFE") build modes only.
369 bool arePointersValid(const char_type *first,
370 const char_type *middle,
371 const char_type *last) const;
372
373 protected:
374 // PROTECTED MANIPULATORS
375
376 /// Set the current input position or the current output position (or
377 /// both) to the specified `offset` from the specified `whence`
378 /// location. Optionally specify a `modeBitMask` indicating whether to
379 /// set the current input position, current output position, or both.
380 /// If `whence` is `ios_base::beg`, set the current position to the
381 /// indicated `offset` from the beginning of the stream; if `whence` is
382 /// `ios_base::end`, set the current position to the indicated `offset`
383 /// from the end of the stream; and if `whence` is `ios_base::cur`, set
384 /// the current input or output position to the indicated `offset` from
385 /// its current position. If `whence` is `ios_base::cur`, then
386 /// `modeBitMask` may be either `ios_base::in` or `ios_base::out`, but
387 /// not both. Return the offset of the new position on success, and
388 /// `pos_type(off_type(-1))` otherwise.
389 virtual pos_type seekoff(
390 off_type offset,
391 ios_base::seekdir whence,
392 ios_base::openmode modeBitMask = ios_base::in | ios_base::out);
393
394 /// Set the current input position or the current output position (or
395 /// both) to the specified `absoluteOffset` from the beginning of the
396 /// stream. Optionally specify a `modeBitMask` indicating whether to
397 /// set the current input position, current output position, or both.
398 /// Return the offset of the new position on success, and
399 /// `pos_type(off_type(-1))` otherwise.
400 virtual pos_type seekpos(
401 pos_type absoluteOffset,
402 ios_base::openmode modeBitMask = ios_base::in | ios_base::out);
403
404 /// Read up to the specified `numCharacters` from this `stringbuf`
405 /// object and store them in the specified `result` array. Return the
406 /// number of characters loaded into `result`. Note that if fewer than
407 /// `numCharacters` characters are available in the buffer, all
408 /// available characters are loaded into `result`. The behavior is
409 /// undefined unless `result` refers to a contiguous sequence of at
410 /// least `numCharacters` characters.
411 virtual std::streamsize xsgetn(char_type *result,
412 std::streamsize numCharacters);
413
414 /// Return the character at the current input position, if a character
415 /// is available, and `traits_type::eof()` otherwise. Update the end
416 /// of the input area, `egptr`, if additional characters are available
417 /// (as may occur if additional characters have been written to the
418 /// string buffer). Note that this operation is similar to `uflow`,
419 /// but does not advance the current input position.
420 virtual int_type underflow();
421
422 /// Return the character at the current input position and advance the
423 /// input position by 1. If no character is available at the current
424 /// input position, return `traits_type::eof()`. Update the end of the
425 /// input area, `egptr`, if additional characters are available (as may
426 /// occur if additional characters have been written to the string
427 /// buffer). Note that this operation is similar to `underflow`, but
428 /// advances the current input position.
429 virtual int_type uflow();
430
431 /// Put back the specified `character` into the input sequence so that
432 /// the next character read from the input sequence will be
433 /// `character`. If `character` is either `traits_type::eof()` or is
434 /// the same as the previously read character from the input sequence,
435 /// then adjust the current input position, `gptr`, back one position.
436 /// If `character` is neither `traits_type::eof()` nor the character
437 /// previously read from the input sequence, but this string buffer was
438 /// opened for writing (`ios_base::out`), then adjust the input
439 /// sequence back one position and write `character` to that position.
440 /// Return the character that was put back on success and
441 /// `traits_type::eof()` if either the input position is currently at
442 /// the beginning of the sequence or if the previous character in the
443 /// input sequence is not `character` and this buffer was not opened
444 /// for writing.
445 virtual int_type pbackfail(int_type character = traits_type::eof());
446
447 /// Append the specified `numCharacters` from the specified
448 /// `inputString` to the output sequence starting at the current output
449 /// position (`pptr`). Update the current output position of this
450 /// string buffer to refer to the last appended character. Return the
451 /// number of characters that were appended. The behavior is undefined
452 /// unless `inputString` refers to a contiguous sequence of at least
453 /// `numCharacters` characters.
454 virtual std::streamsize xsputn(const char_type *inputString,
455 std::streamsize numCharacters);
456
457 /// Append the specified `character` to the output sequence of this
458 /// stream buffer at the current output position (`pptr`), and advance
459 /// the output position by one. This operation may update the end of
460 /// output area (`epptr`) to allow for additional writes (e.g., by the
461 /// base @ref basic_streambuf type) to the output sequence without calling
462 /// a method on this type. Return the written character on success, and
463 /// `traits_type::eof()` if `character` is `traits_type::eof()` or this
464 /// stream buffer was not opened for writing.
465 virtual int_type overflow(int_type character = traits_type::eof());
466
467 public:
468 // CREATORS
469
470 explicit
472 explicit
473 basic_stringbuf(ios_base::openmode modeBitMask,
475 explicit
476 basic_stringbuf(const StringType& initialString,
478 /// Create a @ref basic_stringbuf object. Optionally specify a
479 /// `modeBitMask` indicating whether this buffer may be read from,
480 /// written to, or both. If `modeBitMask` is not supplied, this buffer
481 /// is created with `ios_base::in | ios_base::out`. Optionally specify
482 /// an `initialString` indicating the initial sequence of characters
483 /// that this buffer will access or manipulate. If `initialString` is
484 /// not supplied, the initial sequence of characters will be empty.
485 /// Optionally specify the `allocator` used to supply memory. If
486 /// `allocator` is not supplied, a default-constructed object of the
487 /// (template parameter) `ALLOCATOR` type is used. If the `ALLOCATOR`
488 /// argument is of type `bsl::allocator` (the default), then
489 /// `allocator`, if supplied, shall be convertible to
490 /// `bslma::Allocator *`. If the `ALLOCATOR` argument is of type
491 /// `bsl::allocator` and `allocator` is not supplied, the currently
492 /// installed default allocator will be used to supply memory.
493 basic_stringbuf(const StringType& initialString,
494 ios_base::openmode modeBitMask,
496
497 explicit
498 basic_stringbuf(BloombergLP::bslmf::MovableRef<StringType>
499 initialString);
500 basic_stringbuf(BloombergLP::bslmf::MovableRef<StringType>
501 initialString,
503 basic_stringbuf(BloombergLP::bslmf::MovableRef<StringType>
504 initialString,
505 ios_base::openmode modeBitMask);
506 /// Create a @ref basic_stringbuf object. Use the specified
507 /// `initialString` indicating the initial sequence of characters that
508 /// this buffer will access or manipulate. Optionally specify a
509 /// `modeBitMask` indicating whether this buffer may be read from,
510 /// written to, or both. If `modeBitMask` is not supplied, this buffer
511 /// is created with `ios_base::in | ios_base::out`. Optionally specify
512 /// the `allocator` used to supply memory. If `allocator` is not
513 /// supplied, the allocator in `initialString` is used. `initialString`
514 /// is left in a valid but unspecified state.
515 basic_stringbuf(BloombergLP::bslmf::MovableRef<StringType>
516 initialString,
517 ios_base::openmode modeBitMask,
519
520 /// Create a @ref basic_stringbuf object. Use the specified
521 /// `initialString` indicating the initial sequence of characters that
522 /// this buffer will access or manipulate. Optionally specify the
523 /// `allocator` used to supply memory. If `allocator` is not supplied,
524 /// a default-constructed object of the (template parameter) `ALLOCATOR`
525 /// type is used. If the `ALLOCATOR` argument is of type
526 /// `bsl::allocator` (the default), then `allocator`, if supplied, shall
527 /// be convertible to `bslma::Allocator *`. If the `ALLOCATOR` argument
528 /// is of type `bsl::allocator` and `allocator` is not supplied, the
529 /// currently installed default allocator will be used to supply memory.
530 template <class SALLOC>
531 explicit
534 initialString,
536 typename bsl::enable_if<
537 !bsl::is_same<ALLOCATOR, SALLOC>::value, void *>::type = 0)
538
539 : BaseType()
540 , d_str(initialString.data(), initialString.size(), allocator)
541 , d_endHint(initialString.size())
542 , d_mode(ios_base::in | ios_base::out)
543 {
544 // Note: implemented inline due to Sun CC compilation error.
545 updateStreamPositions();
546 }
547
548 /// Create a @ref basic_stringbuf object. Use the specified
549 /// `initialString` indicating the initial sequence of characters that
550 /// this buffer will access or manipulate. Use the specified
551 /// `modeBitMask` to indicate whether this buffer may be read from,
552 /// written to, or both. Optionally specify the `allocator` used to
553 /// supply memory. If `allocator` is not supplied, a
554 /// default-constructed object of the (template parameter) `ALLOCATOR`
555 /// type is used. If the `ALLOCATOR` argument is of type
556 /// `bsl::allocator` (the default), then `allocator`, if supplied, shall
557 /// be convertible to `bslma::Allocator *`. If the `ALLOCATOR` argument
558 /// is of type `bsl::allocator` and `allocator` is not supplied, the
559 /// currently installed default allocator will be used to supply memory.
560 ///
561 /// Note: implemented inline due to Sun CC compilation error.
562 template <class SALLOC>
565 initialString,
566 ios_base::openmode modeBitMask,
568 typename bsl::enable_if<
569 !bsl::is_same<ALLOCATOR, SALLOC>::value, void *>::type = 0)
570 : BaseType()
571 , d_str(initialString.data(), initialString.size(), allocator)
572 , d_endHint(initialString.size())
573 , d_mode(modeBitMask)
574 {
575 updateStreamPositions(0, d_mode & ios_base::ate ? d_endHint : 0);
576 }
577
578#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_STREAM_MOVE
580 /// Create a @ref basic_stringbuf object having the same value as the
581 /// specified `original` object by moving the contents of `original` to
582 /// the newly-created object. Optionally specify the `allocator` used
583 /// to supply memory. `original` is left in a valid but unspecified
584 /// state.
587#endif
588
589 /// Destroy this object.
591
592 // MANIPULATORS
593
594#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_STREAM_MOVE
595 /// Assign to this object the value of the specified `rhs`, and return a
596 /// reference providing modifiable access to this object. The contents
597 /// of `rhs` are move-assigned to this object. `rhs` is left in a valid
598 /// but unspecified state.
599 basic_stringbuf& operator=(basic_stringbuf&& rhs);
600#endif
601
602 /// Reset the internally buffered sequence of characters to the
603 /// specified `value`. Update the beginning and end of both the input
604 /// and output sequences to be the beginning and end of the updated
605 /// buffer, update the current input position to be the beginning of the
606 /// updated buffer, and update the current output position to be the end
607 /// of the updated buffer. If `value` is passed by `MovableRef`, then
608 /// it is left in an unspecified but valid state.
609 ///
610 void str(const StringType& value);
611 /// Note: implemented inline due to Sun CC compilation error.
612 void str(BloombergLP::bslmf::MovableRef<StringType> value);
613 template <class SALLOC>
614 typename
617 {
618 d_str.assign(value.data(), value.size());
619 d_endHint = d_str.size();
620 updateStreamPositions(0, d_mode & ios_base::ate ? d_endHint : 0);
621 }
622
623#ifdef BSLS_COMPILERFEATURES_SUPPORT_REF_QUALIFIERS
624 /// Return the currently buffered sequence of characters. If this
625 /// object was created only in input mode, the resultant `StringType`
626 /// contains the character sequence in the range `[eback(), egptr())`.
627 /// If `modeBitMask & ios_base::out` specified at construction is
628 /// nonzero then the resultant `StringType` contains the character
629 /// sequence in the range `[pbase(), high_mark)`, where @ref high_mark
630 /// represents the position one past the highest initialized character
631 /// in the buffer. Otherwise this object has been created in neither
632 /// input nor output mode and a zero length `StringType` is returned.
633 /// This object is left in an empty state.
634 StringType str() &&;
635#endif
636
637#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY
638 /// Efficiently exchange the value of this object with the value of the
639 /// specified `other` object. This method provides the no-throw
640 /// exception-safety guarantee if `*this` and `other` allocators compare
641 /// equal. The behavior is undefined unless either `*this` and `other`
642 /// allocators compare equal or `propagate_on_container_swap` is `true`.
643 /// Note that this function is only available for C++11 (and later)
644 /// language standards because it requires that `swap` be provided on
645 /// the (platform supplied) base class for this type.
646 void swap(basic_stringbuf& other);
647#endif // BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY
648
649 // ACCESSORS
650
651 /// Return the allocator used by the underlying string to supply memory.
653
654 /// Return the currently buffered sequence of characters. If this
655 /// object was created only in input mode, the resultant `StringType`
656 /// contains the character sequence in the range `[eback(), egptr())`.
657 /// If `modeBitMask & ios_base::out` specified at construction is
658 /// nonzero then the resultant `StringType` contains the character
659 /// sequence in the range `[pbase(), high_mark)`, where @ref high_mark
660 /// represents the position one past the highest initialized character
661 /// in the buffer. Otherwise this object has been created in neither
662 /// input nor output mode and a zero length `StringType` is returned.
663#ifdef BSLS_COMPILERFEATURES_SUPPORT_REF_QUALIFIERS
664 StringType str() const &;
665#else
666 StringType str() const;
667#endif
668
669#ifndef BSLS_PLATFORM_CMP_SUN
670 // To be enabled once DRQS 168075157 is resolved
671
672 /// Return the currently buffered sequence of characters in a
673 /// @ref basic_string that uses the specified `allocator`. If this object
674 /// was created only in input mode, the resultant @ref basic_string
675 /// contains the character sequence in the range `[eback(), egptr())`.
676 /// If `modeBitMask & ios_base::out` specified at construction is
677 /// nonzero then the resultant @ref basic_string contains the character
678 /// sequence in the range `[pbase(), high_mark)`, where @ref high_mark
679 /// represents the position one past the highest initialized character
680 /// in the buffer. Otherwise this object has been created in neither
681 /// input nor output mode and a zero length @ref basic_string is returned.
682 ///
683 /// Note: implemented inline due to Sun CC compilation error.
684 template <class SALLOC>
685 typename bsl::enable_if<
686 bsl::IsStdAllocator<SALLOC>::value,
688 str(const SALLOC& allocator) const
689 {
691 }
692#endif
693
694 /// Return a @ref string_view containing the currently buffered sequence of
695 /// characters. If this object was created only in input mode, the
696 /// resultant `ViewType` contains the character sequence in the range
697 /// `[eback(), egptr())`. If `modeBitMask & ios_base::out` specified at
698 /// construction is nonzero then the resultant `StringType` contains the
699 /// character sequence in the range `[pbase(), high_mark)`, where
700 /// @ref high_mark represents the position one past the highest initialized
701 /// character in the buffer. Otherwise this object has been created in
702 /// neither input nor output mode and a zero length `ViewType` is
703 /// returned.
704 ViewType view() const BSLS_KEYWORD_NOEXCEPT;
705};
706
707// FREE FUNCTIONS
708#if defined(BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY) \
709 && defined(BSLS_LIBRARYFEATURES_HAS_CPP11_STREAM_MOVE)
710/// Efficiently exchange the values of the specified `a` and `b` objects.
711/// This method provides the no-throw exception-safety guarantee if `a` and
712/// `b` allocators compare equal. Note that this function is only available
713/// for C++11 (and later) language standards.
714template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
717#endif
718
719// STANDARD TYPEDEFS
723
724 // =========================
725 // struct StringBufContainer
726 // =========================
727
728/// This class enables the implementation of string-stream types by
729/// providing a trivial type containing a @ref basic_stringbuf that is suitable
730/// as a (`private`) base class for a string-stream. Inheriting from
731/// `StringBufContainer` allows the string-stream to ensure that the
732/// contained @ref basic_stringbuf is initialized before initializing other
733/// base classes or data members without potentially overriding `virtual`
734/// methods in the @ref basic_stringbuf type. Note that implementations of
735/// string-stream types must pass the address of a string-buffer to their
736/// `public` base class (e.g., @ref basic_stream ), so the string-stream must
737/// ensure (using `private` inheritance) that the string-buffer is
738/// initialized before constructing the `public` base class. If a
739/// string-stream implementation were to directly inherit from
740/// @ref basic_streambuf , then `virtual` methods defined in that string-stream
741/// (e.g., `underflow`) might incorrectly override those in the
742/// @ref basic_stringbuf implementation.
743///
744/// See @ref bslstl_stringbuf
745template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
747
748 private:
749 // PRIVATE TYPES
752
753 typedef BloombergLP::bslmf::MovableRefUtil MoveUtil;
754
755 // DATA
756 StreamBufType d_bufObj; // contained 'basic_stringbuf'
757
758 private:
759 // NOT IMPLEMENTED
760 StringBufContainer(const StringBufContainer&); // = delete
761 StringBufContainer& operator=(const StringBufContainer&); // = delete
762
763 public:
764 // CREATORS
765 explicit
767 : d_bufObj(allocator)
768 {
769 }
770
771 StringBufContainer(ios_base::openmode modeBitMask,
772 const ALLOCATOR& allocator)
773 : d_bufObj(modeBitMask, allocator)
774 {
775 }
776
777 StringBufContainer(const StringType& initialString,
778 const ALLOCATOR& allocator)
779 : d_bufObj(initialString, allocator)
780 {
781 }
782
783 StringBufContainer(const StringType& initialString,
784 ios_base::openmode modeBitMask,
785 const ALLOCATOR& allocator)
786 : d_bufObj(initialString, modeBitMask, allocator)
787 {
788 }
789
791 BloombergLP::bslmf::MovableRef<StringType> initialString,
792 ios_base::openmode modeBitMask,
793 const ALLOCATOR& allocator)
794 : d_bufObj(MoveUtil::move(initialString), modeBitMask, allocator)
795 {
796 }
797
799 BloombergLP::bslmf::MovableRef<StringType> initialString,
800 ios_base::openmode modeBitMask)
801 : d_bufObj(MoveUtil::move(initialString), modeBitMask)
802 {
803 }
804
805 template <class STRING_ITER>
806 StringBufContainer(STRING_ITER first,
807 STRING_ITER last,
808 ios_base::openmode modeBitMask,
809 const ALLOCATOR& allocator)
810 : d_bufObj(modeBitMask, allocator)
811 {
812 StringType tempStr(first, last, allocator);
813 d_bufObj.str(MoveUtil::move(tempStr));
814 }
815
816#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_STREAM_MOVE
817 /// Create a `StringBufContainer` object having the same value as the
818 /// specified `original` object by moving the contents of `original` to
819 /// the newly-created object. `original` is left in a valid but
820 /// unspecified state.
822 : d_bufObj(std::move(original.d_bufObj))
823 {
824 }
825
826 /// Create a `StringBufContainer` object using the specified `allocator` to
827 /// supply memory and having the same value as the specified `original`
828 /// object by moving the contents of `original` to the newly-created object.
829 /// `original` is left in a valid but unspecified state.
830 StringBufContainer(StringBufContainer&& original,
831 const ALLOCATOR& allocator)
832 : d_bufObj(std::move(original.d_bufObj), allocator)
833 {
834 }
835#endif
836
838
839 // MANIPULATORS
840
841#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_STREAM_MOVE
842 /// Assign to this object the value of the specified `rhs`, and return a
843 /// reference providing modifiable access to this object. The contents
844 /// of `rhs` are move-assigned to this object. `rhs` is left in a valid
845 /// but unspecified state.
846 StringBufContainer& operator=(StringBufContainer&& rhs)
847 {
848 d_bufObj = std::move(rhs.d_bufObj);
849
850 return *this;
851 }
852#endif
853
854#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY
855 /// Efficiently exchange the value of this object with the value of the
856 /// specified `other` object.
858 {
859 d_bufObj.swap(other.d_bufObj);
860 }
861#endif // BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY
862
863 // ACCESSORS
865 {
866 return const_cast<StreamBufType *>(&d_bufObj);
867 }
868};
869
870// ============================================================================
871// TEMPLATE FUNCTION DEFINITIONS
872// ============================================================================
873
874 // ---------------------
875 // class basic_stringbuf
876 // ---------------------
877
878// PRIVATE MANIPULATORS
879template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
881basic_stringbuf<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>::
882 updateInputPointers(char_type *currentInputPosition)
883{
884 BSLS_ASSERT(d_mode & ios_base::in);
885 BSLS_ASSERT(&d_str[0] <= currentInputPosition);
886 BSLS_ASSERT(currentInputPosition <=
887 &d_str[0] + static_cast<std::ptrdiff_t>(streamSize()));
888
889 char_type *dataPtr = &d_str[0];
890
891 this->setg(dataPtr,
892 currentInputPosition,
893 dataPtr + static_cast<std::ptrdiff_t>(streamSize()));
894 return pos_type(currentInputPosition - dataPtr);
895}
896
897template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
899basic_stringbuf<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>::
900 updateOutputPointers(char_type *currentOutputPosition)
901{
902 BSLS_ASSERT(d_mode & ios_base::out);
903 BSLS_ASSERT(&d_str[0] <= currentOutputPosition);
904 BSLS_ASSERT(currentOutputPosition <= &d_str[0] + d_str.size());
905
906 char_type *dataPtr = &d_str[0];
907 std::size_t dataSize = d_str.size();
908
909 pos_type outputPos = currentOutputPosition - dataPtr;
910 this->setp(dataPtr, dataPtr + dataSize);
911 pos_type bumpAmount = outputPos;
912 while (bumpAmount > INT_MAX) {
913 this->pbump(INT_MAX);
914 bumpAmount -= INT_MAX;
915 }
916 if (bumpAmount) {
917 this->pbump(int(bumpAmount));
918 }
919 return outputPos;
920}
921
922template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
923void basic_stringbuf<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>::
924 updateStreamPositions(off_type inputOffset, off_type outputOffset)
925{
926 // Extend the internal buffer to the full capacity of the string to allow
927 // us to use the full capacity for buffering output.
928
929 d_str.resize(d_str.capacity());
930 char_type *dataPtr = &d_str[0];
931
932 if (d_mode & ios_base::out) {
933 // Update the output position.
934
935 std::size_t dataSize = d_str.size();
936 this->setp(dataPtr, dataPtr + dataSize);
937 off_type bumpAmount = outputOffset;
938 while (bumpAmount < INT_MIN) {
939 this->pbump(INT_MIN);
940 bumpAmount -= INT_MIN;
941 }
942 while (bumpAmount > INT_MAX) {
943 this->pbump(INT_MAX);
944 bumpAmount -= INT_MAX;
945 }
946 if (bumpAmount) {
947 this->pbump(int(bumpAmount));
948 }
949 }
950
951 if (d_mode & ios_base::in) {
952 // Update the input position.
953
954 this->setg(dataPtr,
955 dataPtr + inputOffset,
956 dataPtr + static_cast<std::ptrdiff_t>(streamSize()));
957 }
958}
959
960template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
961bool basic_stringbuf<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>::extendInputArea()
962{
963 // Try to extend into written buffer.
964
965 if (d_mode & ios_base::out && this->pptr() > this->egptr()) {
966 d_endHint = streamSize();
967 updateInputPointers(this->gptr());
968 return true; // RETURN
969 }
970
971 return false;
972}
973
974// PRIVATE ACCESSORS
975template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
977 basic_stringbuf<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>::streamSize() const
978{
979 pos_type size = std::max<off_type>(d_endHint,
980 this->pptr() - this->pbase());
981
982 BSLS_ASSERT(size <= off_type(d_str.size()));
983
984 return size;
985}
986
987template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
988bool basic_stringbuf<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>::arePointersValid(
989 const char_type *first,
990 const char_type *middle,
991 const char_type *last) const
992{
993 const bool isNull = first == 0;
994 const char_type *bufferBegin = isNull ? 0 : d_str.data();
995 const char_type *bufferEnd = isNull ? 0 : d_str.data() + d_str.size();
996 return first == bufferBegin
997 && last <= bufferEnd
998 && first <= middle
999 && middle <= last;
1000}
1001
1002// PROTECTED MANIPULATORS
1003template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
1006 off_type offset,
1007 ios_base::seekdir whence,
1008 ios_base::openmode modeBitMask)
1009{
1010 // If `whence` is `ios_base::cur` (the current position), `modeBitMask`
1011 // may not be both input and output mode.
1012
1013 if (((modeBitMask & (ios_base::in | ios_base::out)) ==
1014 (ios_base::in | ios_base::out))
1015 && whence == ios_base::cur) {
1016 return pos_type(off_type(-1)); // RETURN
1017 }
1018
1019 pos_type newPos = pos_type(off_type(-1));
1020
1021 // Set the current input position.
1022
1023 if ((modeBitMask & ios_base::in) && (d_mode & ios_base::in)) {
1024 char_type *inputPtr = 0;
1025
1026 switch (whence) {
1027 case ios_base::beg: {
1028 inputPtr = this->eback() + offset;
1029 } break;
1030 case ios_base::cur: {
1031 inputPtr = this->gptr() + offset;
1032 } break;
1033 case ios_base::end: {
1034 inputPtr = this->eback()
1035 + static_cast<std::ptrdiff_t>(streamSize())
1036 + offset;
1037 } break;
1038 default: {
1039 BSLS_ASSERT_OPT(false && "invalid seekdir argument");
1040 }
1041 }
1042
1043 if (inputPtr < this->eback()
1044 || inputPtr >
1045 this->eback() + static_cast<std::ptrdiff_t>(streamSize())) {
1046 // 'inputPtr' is outside the valid range of the string buffer.
1047
1048 return pos_type(off_type(-1)); // RETURN
1049 }
1050
1051 newPos = updateInputPointers(inputPtr);
1052 }
1053
1054 // Set the current output position.
1055
1056 if ((modeBitMask & ios_base::out) && (d_mode & ios_base::out)) {
1057 char_type *outputPtr = 0;
1058
1059 switch (whence) {
1060 case ios_base::beg: {
1061 outputPtr = this->pbase() + offset;
1062 } break;
1063 case ios_base::cur: {
1064 outputPtr = this->pptr() + offset;
1065 } break;
1066 case ios_base::end: {
1067 outputPtr = this->pbase()
1068 + static_cast<std::ptrdiff_t>(streamSize())
1069 + offset;
1070 } break;
1071 default:
1072 BSLS_ASSERT_OPT(false && "invalid seekdir argument");
1073 }
1074
1075 if (outputPtr < this->pbase()
1076 || outputPtr >
1077 this->pbase() + static_cast<std::ptrdiff_t>(streamSize())) {
1078 // 'outputPtr' is outside the valid range of the string buffer.
1079
1080 return pos_type(off_type(-1)); // RETURN
1081 }
1082
1083 newPos = updateOutputPointers(outputPtr);
1084 }
1085
1086 return newPos;
1087}
1088
1089template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
1090inline
1093 pos_type absoluteOffset,
1094 ios_base::openmode modeBitMask)
1095{
1096 return basic_stringbuf::seekoff(off_type(absoluteOffset),
1097 ios_base::beg,
1098 modeBitMask);
1099}
1100
1101template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
1102std::streamsize
1104 char_type *result,
1105 std::streamsize numCharacters)
1106{
1107 if ((d_mode & ios_base::in) == 0) {
1108 return 0; // RETURN
1109 }
1110
1111 // Additional characters may become available for reading when the input
1112 // area is extended to account for any characters newly written to the
1113 // output sequence.
1114 extendInputArea();
1115
1116 if (this->gptr() != this->egptr()) {
1117 // There are characters available in this buffer.
1118
1119 std::streamsize available = this->egptr() - this->gptr();
1120 std::streamsize readChars = std::min(available,
1121 numCharacters);
1122
1123 traits_type::copy(result, this->gptr(), std::size_t(readChars));
1124 this->gbump(int(readChars));
1125
1126 return readChars; // RETURN
1127 }
1128
1129 return 0;
1130}
1131
1132template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
1135{
1136 if ((d_mode & ios_base::in) == 0) {
1137 return traits_type::eof(); // RETURN
1138 }
1139
1140 if (this->gptr() != this->egptr()) {
1141 // There are characters available in this buffer.
1142
1143 return traits_type::to_int_type(*this->gptr()); // RETURN
1144 }
1145
1146 if (extendInputArea()) {
1147 // Additional characters may become available after the input area is
1148 // extended.
1149
1150 return this->basic_stringbuf::underflow(); // RETURN
1151 }
1152
1153 return traits_type::eof();
1154}
1155
1156template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
1159{
1160 if ((d_mode & ios_base::in) == 0) {
1161 return traits_type::eof(); // RETURN
1162 }
1163
1164 if (this->gptr() != this->egptr()) {
1165 // There are characters available in this buffer.
1166
1167 int_type c = traits_type::to_int_type(*this->gptr());
1168 this->gbump(1);
1169 return c; // RETURN
1170 }
1171
1172 if (extendInputArea()) {
1173 // Additional characters may become available after the input area is
1174 // extended.
1175
1176 return this->basic_stringbuf::uflow(); // RETURN
1177 }
1178
1179 return traits_type::eof();
1180}
1181
1182template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
1185 int_type character)
1186{
1187 if (this->gptr() == this->eback()) {
1188 // The current position is at the start of the buffer, so we cannot
1189 // push back a character.
1190
1191 return traits_type::eof(); // RETURN
1192 }
1193
1194 if (traits_type::eq_int_type(character, traits_type::eof())
1195 || traits_type::eq_int_type(
1196 character,
1197 traits_type::to_int_type(*(this->gptr() - 1)))) {
1198 // If 'character' is 'eof' or the previous input character,
1199 // simply move the current position back 1.
1200
1201 this->gbump(-1);
1202 return traits_type::to_int_type(*this->gptr()); // RETURN
1203 }
1204
1205 if (d_mode & ios_base::out) {
1206 // In output mode, if 'character' is not the previous input character,
1207 // overwrite the previous input character.
1208
1209 this->gbump(-1);
1210 *this->gptr() = traits_type::to_char_type(character);
1211 return character; // RETURN
1212 }
1213
1214 return traits_type::eof();
1215}
1216
1217template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
1218std::streamsize
1220 const char_type *inputString,
1221 std::streamsize numCharacters)
1222{
1223 if ((d_mode & ios_base::out) == 0) {
1224 return 0; // RETURN
1225 }
1226 BSLS_ASSERT(this->pptr());
1227 BSLS_ASSERT(this->pbase());
1228
1229 // Compute the space required.
1230
1231 std::streamsize spaceLeft = d_str.data() + d_str.size() - this->pptr();
1232 std::ptrdiff_t toOverwrite =
1233 std::ptrdiff_t(std::min(spaceLeft, numCharacters));
1234
1235 // Append the portion of 'inputString' that can be written without
1236 // resizing 'd_ptr'.
1237
1238 traits_type::copy(this->pptr(), inputString, toOverwrite);
1239
1240 off_type inputOffset = this->gptr() - this->eback();
1241
1242 if (numCharacters == toOverwrite) {
1243 // If all of 'inputString' has been written, just update the stream
1244 // positions.
1245
1246 off_type newHigh = numCharacters + this->pptr() - this->pbase();
1247 d_endHint = std::max(d_endHint, newHigh);
1248
1249 updateStreamPositions(inputOffset, newHigh);
1250 }
1251 else {
1252 // If some characters remain to be written, append them to 'd_str'
1253 // (resizing 'd_str' in the process).
1254
1255 d_str.append(inputString + toOverwrite, inputString + numCharacters);
1256
1257 // Update the last written character cache, and the input stream
1258 // positions.
1259
1260 d_endHint = d_str.size();
1261 updateStreamPositions(inputOffset, d_endHint);
1262 }
1263
1264 return numCharacters;
1265}
1266
1267template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
1270 int_type character)
1271{
1272 if ((d_mode & ios_base::out) == 0) {
1273 return traits_type::eof(); // RETURN
1274 }
1275
1276 if (traits_type::eq_int_type(character, traits_type::eof())) {
1277 // Nothing to write, so just return success.
1278
1279 return traits_type::not_eof(character); // RETURN
1280 }
1281
1282 char_type c = traits_type::to_char_type(character);
1283 if (this->pptr() != this->epptr()) {
1284 // Additional space is available in 'd_str', so no need to resize the
1285 // buffer.
1286
1287 *this->pptr() = c;
1288 this->pbump(1);
1289
1290 d_endHint = streamSize();
1291 }
1292 else {
1293 // Store the input offset so it can be used to restore the input and
1294 // output positions after the next resize.
1295
1296 off_type inputOffset = this->gptr() - this->eback();
1297
1298 // Append the character, and expand the buffer.
1299
1300 d_str.push_back(c);
1301
1302 // Update the input sequence, restoring the current input position
1303 // from 'inputOffset', and updating the output sequence to reflect the
1304 // newly resized buffer.
1305
1306 d_endHint = d_str.size();
1307 updateStreamPositions(inputOffset, d_endHint);
1308 }
1309
1310 return character;
1311}
1312
1313// CREATORS
1314template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
1317: BaseType()
1318, d_str(allocator)
1319, d_endHint(0)
1320, d_mode(ios_base::in | ios_base::out)
1321{
1322 updateStreamPositions();
1323}
1324
1325template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
1327 basic_stringbuf(ios_base::openmode modeBitMask,
1329: BaseType()
1330, d_str(allocator)
1331, d_endHint(0)
1332, d_mode(modeBitMask)
1333{
1334 updateStreamPositions();
1335}
1336
1337template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
1339 basic_stringbuf(const StringType& initialString,
1341: BaseType()
1342, d_str(initialString, allocator)
1343, d_endHint(initialString.size())
1344, d_mode(ios_base::in | ios_base::out)
1345{
1346 updateStreamPositions();
1347}
1348
1349template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
1350inline
1352 basic_stringbuf(const StringType& initialString,
1353 ios_base::openmode modeBitMask,
1355: BaseType()
1356, d_str(initialString, allocator)
1357, d_endHint(initialString.size())
1358, d_mode(modeBitMask)
1359{
1360 updateStreamPositions(0, d_mode & ios_base::ate ? d_endHint : 0);
1361}
1362
1363template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
1364inline
1366 basic_stringbuf(BloombergLP::bslmf::MovableRef<StringType> initialString)
1367: BaseType()
1368, d_str(MoveUtil::move(initialString))
1369, d_endHint(d_str.size())
1370, d_mode(ios_base::in | ios_base::out)
1371{
1372 updateStreamPositions();
1373}
1374
1375template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
1376inline
1378 basic_stringbuf(BloombergLP::bslmf::MovableRef<StringType> initialString,
1380: BaseType()
1381, d_str(MoveUtil::move(initialString), allocator)
1382, d_endHint(d_str.size())
1383, d_mode(ios_base::in | ios_base::out)
1384{
1385 updateStreamPositions();
1386}
1387
1388template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
1389inline
1391 basic_stringbuf(BloombergLP::bslmf::MovableRef<StringType> initialString,
1392 ios_base::openmode modeBitMask)
1393: BaseType()
1394, d_str(MoveUtil::move(initialString))
1395, d_endHint(d_str.size())
1396, d_mode(modeBitMask)
1397{
1398 updateStreamPositions(0, d_mode & ios_base::ate ? d_endHint : 0);
1399}
1400
1401template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
1402inline
1404 basic_stringbuf(BloombergLP::bslmf::MovableRef<StringType> initialString,
1405 ios_base::openmode modeBitMask,
1407: BaseType()
1408, d_str(MoveUtil::move(initialString), allocator)
1409, d_endHint(d_str.size())
1410, d_mode(modeBitMask)
1411{
1412 updateStreamPositions(0, d_mode & ios_base::ate ? d_endHint : 0);
1413}
1414
1415#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_STREAM_MOVE
1416template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
1417inline
1420: BaseType()
1421, d_str(std::move(original.d_str))
1422, d_endHint(std::move(original.d_endHint))
1423, d_mode(std::move(original.d_mode))
1424{
1425 // Capture the positions for later restoration
1426
1427 const off_type inputOffset = original.gptr() - original.eback();
1428 const off_type outputOffset = original.pptr() - original.pbase();
1429 updateStreamPositions(inputOffset, outputOffset);
1430
1431 this->pubimbue(original.getloc());
1432
1433 if (original.d_endHint > 0 &&
1434 static_cast<size_t>(original.d_endHint) > original.d_str.size()) {
1435
1436 // The move has moved away the string
1437
1438 original.d_endHint = 0;
1439 original.updateStreamPositions();
1440 }
1441}
1442
1443template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
1444inline
1445basic_stringbuf<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>::
1446 basic_stringbuf(basic_stringbuf&& original,
1447 const allocator_type& allocator)
1448: BaseType()
1449, d_str(std::move(original.d_str), allocator)
1450, d_endHint(std::move(original.d_endHint))
1451, d_mode(std::move(original.d_mode))
1452{
1453 // Capture the positions for later restoration
1454
1455 const off_type inputOffset = original.gptr() - original.eback();
1456 const off_type outputOffset = original.pptr() - original.pbase();
1457 updateStreamPositions(inputOffset, outputOffset);
1458
1459 this->pubimbue(original.getloc());
1460
1461 if (original.d_endHint > 0 &&
1462 static_cast<size_t>(original.d_endHint) > original.d_str.size()) {
1463
1464 // The move has moved away the string
1465
1466 original.d_endHint = 0;
1467 original.updateStreamPositions();
1468 }
1469}
1470#endif
1471
1472template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
1475{
1476 if (d_mode & ios_base::in) {
1477 BSLS_ASSERT(arePointersValid(this->eback(),
1478 this->gptr(),
1479 this->egptr()));
1480 }
1481
1482 if (d_mode & ios_base::out) {
1483 BSLS_ASSERT(arePointersValid(this->pbase(),
1484 this->pptr(),
1485 this->epptr()));
1486 }
1487}
1488
1489// MANIPULATORS
1490#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_STREAM_MOVE
1491template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
1492inline
1496{
1497 // Capture the positions for later restoration
1498
1499 const off_type inputOffset = rhs.gptr() - rhs.eback();
1500 const off_type inputSize = rhs.egptr() - rhs.eback();
1501 const off_type outputOffset = rhs.pptr() - rhs.pbase();
1502 const off_type outputSize = rhs.epptr() - rhs.pbase();
1503
1504 this->pubimbue(rhs.getloc());
1505
1506 d_str = std::move(rhs.d_str);
1507 d_endHint = std::move(rhs.d_endHint);
1508 d_mode = std::move(rhs.d_mode);
1509
1510 // Fix the stream-position pointers
1511
1512 char_type *dataPtr = &d_str[0];
1513
1514 // Update positions/pointers in the moved-to object
1515
1516 this->setp(dataPtr, dataPtr + outputSize);
1517 this->pbump(static_cast<int>(outputOffset));
1518 this->setg(dataPtr,
1519 dataPtr + inputOffset,
1520 dataPtr + inputSize);
1521
1522 // Reset positions/pointers in the moved-from object
1523
1524 if (rhs.d_endHint > 0 &&
1525 static_cast<size_t>(rhs.d_endHint) > rhs.d_str.size()) {
1526
1527 // The move has moved away the string
1528
1529 rhs.d_endHint = 0;
1530 rhs.updateStreamPositions();
1531 }
1532
1533 return *this;
1534}
1535#endif
1536
1537template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
1539 const StringType& value)
1540{
1541 d_str = value;
1542 d_endHint = d_str.size();
1543 updateStreamPositions(0, d_mode & ios_base::ate ? d_endHint : 0);
1544}
1545
1546template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
1548 BloombergLP::bslmf::MovableRef<StringType> value)
1549{
1550 StringType& lvalue = value;
1551
1552 d_str = MoveUtil::move(lvalue);
1553 d_endHint = d_str.size();
1554 updateStreamPositions(0, d_mode & ios_base::ate ? d_endHint : 0);
1555}
1556
1557#ifdef BSLS_COMPILERFEATURES_SUPPORT_REF_QUALIFIERS
1558template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
1561{
1562 if (d_mode & ios_base::out) {
1563 d_str.resize(static_cast<typename StringType::size_type>(streamSize()));
1564 this->setp(d_str.data(), d_str.data());
1565 }
1566 else if (d_mode & ios_base::in) {
1567 if (streamSize() > 0) {
1568 if (this->eback() != d_str.data()) {
1569 d_str.erase(0, this->eback() - d_str.data());
1570 }
1571 d_str.resize(static_cast<typename StringType::size_type>(
1572 streamSize()));
1573 this->setg(d_str.data(), d_str.data(), d_str.data());
1574 }
1575 }
1576
1577 StringType ret = std::move(d_str);
1578 d_endHint = 0;
1579 updateStreamPositions();
1580 return ret;
1581}
1582#endif
1583
1584#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY
1585template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
1587 basic_stringbuf& other)
1588{
1591 || d_str.get_allocator() == other.d_str.get_allocator());
1592 // Capture the positions for the later restoration. Formally,
1593 // 'std::basic_streambuf::swap' exchanges the internal pointers and the
1594 // locale object. But 'bsl::string' swapping can invalidate pointers, so
1595 // we need to control this process manually.
1596
1597 const off_type inputOffset = this->gptr() - this->eback();
1598 const off_type outputOffset = this->pptr() - this->pbase();
1599 const std::locale loc = this->getloc();
1600
1601 const off_type otherInputOffset = other.gptr() - other.eback();
1602 const off_type otherOutputOffset = other.pptr() - other.pbase();
1603 const std::locale otherLoc = other.getloc();
1604
1605 // Parent method invocation.
1606
1607 this->BaseType::swap(other);
1608
1609 // Swapping data members.
1610
1611 this->pubimbue(otherLoc);
1612 other.pubimbue(loc);
1613
1614 d_str.swap(other.d_str);
1615 BloombergLP::bslalg::SwapUtil::swap(&this->d_endHint, &other.d_endHint);
1616 BloombergLP::bslalg::SwapUtil::swap(&this->d_mode, &other.d_mode);
1617
1618 // Fix the stream-position pointers.
1619
1620 this->updateStreamPositions(otherInputOffset, otherOutputOffset);
1621 other.updateStreamPositions( inputOffset, outputOffset);
1622}
1623#endif // BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY
1624
1625// ACCESSORS
1626template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
1627inline
1634
1635template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
1636inline
1638#ifdef BSLS_COMPILERFEATURES_SUPPORT_REF_QUALIFIERS
1640#else
1642#endif
1643{
1644 return StringType(view());
1645}
1646
1647template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
1648inline
1652{
1653 if (d_mode & ios_base::out) {
1654 return ViewType(d_str.begin(),
1655 static_cast<std::ptrdiff_t>(streamSize())); // RETURN
1656 }
1657
1658 if (d_mode & ios_base::in) {
1659 return ViewType(this->eback(), this->egptr() - this->eback());// RETURN
1660 }
1661
1662 return ViewType();
1663}
1664
1665} // close namespace bsl
1666
1667// FREE FUNCTIONS
1668#if defined(BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY) \
1669 && defined(BSLS_LIBRARYFEATURES_HAS_CPP11_STREAM_MOVE)
1670template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
1671void bsl::swap(basic_stringbuf<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>& a,
1672 basic_stringbuf<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>& b)
1673{
1674 typedef BloombergLP::bslmf::MovableRefUtil MoveUtil;
1675
1676 if (a.get_allocator() == b.get_allocator()
1678 a.swap(b);
1679 }
1680 else {
1681 basic_stringbuf<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR> aCopy(
1682 MoveUtil::move(a),
1683 b.get_allocator());
1684 basic_stringbuf<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR> bCopy(
1685 MoveUtil::move(b),
1686 a.get_allocator());
1687 swap(a, bCopy);
1688 swap(b, aCopy);
1689 }
1690}
1691#endif
1692
1693// ============================================================================
1694// TYPE TRAITS
1695// ============================================================================
1696
1697
1698namespace bslma {
1699
1700template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
1702 bsl::basic_stringbuf<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR> >
1704{};
1705
1706} // close namespace bslma
1707
1708
1709// Undo 'BSLS_ASSERT' filename fix -- See @ref bsls_assertimputil
1710#ifdef BSLS_ASSERTIMPUTIL_AVOID_STRING_CONSTANTS
1711#undef BSLS_ASSERTIMPUTIL_FILE
1712#define BSLS_ASSERTIMPUTIL_FILE BSLS_ASSERTIMPUTIL_DEFAULTFILE
1713#endif
1714
1715#endif
1716
1717// ----------------------------------------------------------------------------
1718// Copyright 2013 Bloomberg Finance L.P.
1719//
1720// Licensed under the Apache License, Version 2.0 (the "License");
1721// you may not use this file except in compliance with the License.
1722// You may obtain a copy of the License at
1723//
1724// http://www.apache.org/licenses/LICENSE-2.0
1725//
1726// Unless required by applicable law or agreed to in writing, software
1727// distributed under the License is distributed on an "AS IS" BASIS,
1728// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1729// See the License for the specific language governing permissions and
1730// limitations under the License.
1731// ----------------------------- END-OF-FILE ----------------------------------
1732
1733/** @} */
1734/** @} */
1735/** @} */
Definition bslstl_stringbuf.h:746
StreamBufType * rdbuf() const
Definition bslstl_stringbuf.h:864
StringBufContainer(const StringType &initialString, ios_base::openmode modeBitMask, const ALLOCATOR &allocator)
Definition bslstl_stringbuf.h:783
StringBufContainer(ios_base::openmode modeBitMask, const ALLOCATOR &allocator)
Definition bslstl_stringbuf.h:771
StringBufContainer(BloombergLP::bslmf::MovableRef< StringType > initialString, ios_base::openmode modeBitMask)
Definition bslstl_stringbuf.h:798
void swap(StringBufContainer &other)
Definition bslstl_stringbuf.h:857
StringBufContainer(const ALLOCATOR &allocator)
Definition bslstl_stringbuf.h:766
StringBufContainer(STRING_ITER first, STRING_ITER last, ios_base::openmode modeBitMask, const ALLOCATOR &allocator)
Definition bslstl_stringbuf.h:806
StringBufContainer(const StringType &initialString, const ALLOCATOR &allocator)
Definition bslstl_stringbuf.h:777
StringBufContainer(BloombergLP::bslmf::MovableRef< StringType > initialString, ios_base::openmode modeBitMask, const ALLOCATOR &allocator)
Definition bslstl_stringbuf.h:790
Definition bslma_bslallocator.h:580
Definition bslstl_stringview.h:441
Definition bslstl_string.h:1281
basic_string & assign(const basic_string &replacement)
Definition bslstl_string.h:5716
size_type size() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:6592
allocator_type get_allocator() const BSLS_KEYWORD_NOEXCEPT
Return the allocator used by this string to supply memory.
Definition bslstl_string.h:6723
void push_back(CHAR_TYPE character)
Append the specified character to this string.
Definition bslstl_string.h:5699
CHAR_TYPE * data() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:6477
void resize(size_type newLength, CHAR_TYPE character)
Definition bslstl_string.h:5364
void swap(basic_string &other) BSLS_KEYWORD_NOEXCEPT_SPECIFICATION(AllocatorTraits const_iterator begin() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:2533
basic_string & erase(size_type position=0, size_type numChars=npos)
Definition bslstl_string.h:6069
size_type capacity() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:6623
basic_string & append(const basic_string &suffix)
Definition bslstl_string.h:5574
Definition bslstl_stringbuf.h:245
void swap(basic_stringbuf &other)
Definition bslstl_stringbuf.h:1586
ViewType view() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_stringbuf.h:1650
virtual pos_type seekoff(off_type offset, ios_base::seekdir whence, ios_base::openmode modeBitMask=ios_base::in|ios_base::out)
Definition bslstl_stringbuf.h:1005
virtual int_type pbackfail(int_type character=traits_type::eof())
Definition bslstl_stringbuf.h:1184
StringType str() const
Definition bslstl_stringbuf.h:1641
virtual pos_type seekpos(pos_type absoluteOffset, ios_base::openmode modeBitMask=ios_base::in|ios_base::out)
Definition bslstl_stringbuf.h:1092
traits_type::off_type off_type
Definition bslstl_stringbuf.h:261
basic_stringbuf(const bsl::basic_string< CHAR_TYPE, CHAR_TRAITS, SALLOC > &initialString, const allocator_type &allocator=allocator_type(), typename bsl::enable_if< !bsl::is_same< ALLOCATOR, SALLOC >::value, void * >::type=0)
Definition bslstl_stringbuf.h:532
void str(const StringType &value)
Definition bslstl_stringbuf.h:1538
virtual std::streamsize xsgetn(char_type *result, std::streamsize numCharacters)
Definition bslstl_stringbuf.h:1103
allocator_type get_allocator() const BSLS_KEYWORD_NOEXCEPT
Return the allocator used by the underlying string to supply memory.
Definition bslstl_stringbuf.h:1629
CHAR_TYPE char_type
Definition bslstl_stringbuf.h:257
bsl::enable_if< bsl::IsStdAllocator< SALLOC >::value, basic_string< CHAR_TYPE, CHAR_TRAITS, SALLOC > >::type str(const SALLOC &allocator) const
Definition bslstl_stringbuf.h:688
CHAR_TRAITS traits_type
Definition bslstl_stringbuf.h:258
~basic_stringbuf()
Destroy this object.
Definition bslstl_stringbuf.h:1474
virtual int_type uflow()
Definition bslstl_stringbuf.h:1158
basic_stringbuf(const bsl::basic_string< CHAR_TYPE, CHAR_TRAITS, SALLOC > &initialString, ios_base::openmode modeBitMask, const allocator_type &allocator=allocator_type(), typename bsl::enable_if< !bsl::is_same< ALLOCATOR, SALLOC >::value, void * >::type=0)
Definition bslstl_stringbuf.h:563
virtual std::streamsize xsputn(const char_type *inputString, std::streamsize numCharacters)
Definition bslstl_stringbuf.h:1219
virtual int_type underflow()
Definition bslstl_stringbuf.h:1134
traits_type::int_type int_type
Definition bslstl_stringbuf.h:260
traits_type::pos_type pos_type
Definition bslstl_stringbuf.h:262
virtual int_type overflow(int_type character=traits_type::eof())
Definition bslstl_stringbuf.h:1269
bsl::enable_if<!bsl::is_same< ALLOCATOR, SALLOC >::value, void >::type str(const basic_string< CHAR_TYPE, CHAR_TRAITS, SALLOC > &value)
Definition bslstl_stringbuf.h:616
ALLOCATOR allocator_type
Definition bslstl_stringbuf.h:259
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1804
#define BSLS_ASSERT_OPT(X)
Definition bsls_assert.h:1856
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
#define BSLS_KEYWORD_NOEXCEPT
Definition bsls_keyword.h:632
void swap(OptionValue &a, OptionValue &b)
bool isNull(const TYPE &object)
Definition bdlb_printmethods.h:283
basic_stringbuf< wchar_t, char_traits< wchar_t >, allocator< wchar_t > > wstringbuf
Definition bslstl_iosfwd.h:100
basic_stringbuf< char, char_traits< char >, allocator< char > > stringbuf
Definition bslstl_iosfwd.h:91
BSLS_KEYWORD_CONSTEXPR size_t size(const TYPE(&)[DIMENSION]) BSLS_KEYWORD_NOEXCEPT
Return the dimension of the specified array argument.
Definition bslstl_iterator.h:1331
BSLS_KEYWORD_CONSTEXPR CONTAINER::value_type * data(CONTAINER &container)
Definition bslstl_iterator.h:1231
Definition balxml_encoderoptions.h:68
Definition bdldfp_decimal.h:5188
Definition bslma_allocatortraits.h:1061
Definition bslmf_enableif.h:525
Definition bslmf_issame.h:146
Definition bslma_usesbslmaallocator.h:343