BDE 4.14.0 Production release
Loading...
Searching...
No Matches
ball_recordattributes.h
Go to the documentation of this file.
1/// @file ball_recordattributes.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// ball_recordattributes.h -*-C++-*-
8#ifndef INCLUDED_BALL_RECORDATTRIBUTES
9#define INCLUDED_BALL_RECORDATTRIBUTES
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup ball_recordattributes ball_recordattributes
15/// @brief Provide a container for a fixed set of fields suitable for logging.
16/// @addtogroup bal
17/// @{
18/// @addtogroup ball
19/// @{
20/// @addtogroup ball_recordattributes
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#ball_recordattributes-purpose"> Purpose</a>
25/// * <a href="#ball_recordattributes-classes"> Classes </a>
26/// * <a href="#ball_recordattributes-description"> Description </a>
27/// * <a href="#ball_recordattributes-usage"> Usage </a>
28/// * <a href="#ball_recordattributes-example-1-syntax"> Example 1: Syntax </a>
29/// * <a href="#ball_recordattributes-example-2-streaming-data-into-a-message-attribute"> Example 2: Streaming Data Into a Message Attribute </a>
30///
31/// # Purpose {#ball_recordattributes-purpose}
32/// Provide a container for a fixed set of fields suitable for logging.
33///
34/// # Classes {#ball_recordattributes-classes}
35///
36/// - ball::RecordAttributes: container for a fixed set of log fields
37///
38/// @see ball_record
39///
40/// # Description {#ball_recordattributes-description}
41/// This component defines a container for aggregating a fixed set
42/// of fields intrinsically appropriate for logging. Using
43/// `ball::RecordAttributes`, a logger can transmit log message text together
44/// with relevant auxiliary information (e.g., timestamp, filename, line number,
45/// etc.) as a single instance, rather than passing around individual attributes
46/// separately.
47///
48/// The attributes held by `ball::RecordAttributes` are given in the following
49/// table:
50/// @code
51/// Attribute Type Description Default
52/// ---------- ------------- ------------------------------ --------
53/// timestamp bdlt::Datetime creation date and time (*Note*)
54/// processID int process id of creator 0
55/// threadID Uint64 thread id of creator 0
56/// fileName string file where created (__FILE__) ""
57/// lineNumber int line number in file (__LINE__) 0
58/// category string category of logged record ""
59/// severity int severity of logged record 0
60/// message string log message text ""
61/// @endcode
62/// *Note*: The default value given to the timestamp attribute is implementation
63/// defined. (See the @ref bdlt_datetime component-level documentation for more
64/// information.)
65///
66/// *Cached Stream State*: Although a `RecordAttributes` object is nominally a
67/// value-semantic attribute type whose attributes are described in the table
68/// above, for performance and convenience a `RecordAttributes` object provides
69/// access to internal instances of `bdlsb::MemOutStreamBuf` and `bsl::ostream`
70/// objects (via `messageStreamBuf` and `messageStream` accessors, respectively)
71/// that allow users to build the `message` directly without having to construct
72/// any I/O stream objects independently. This is useful because `ball::Record`
73/// objects and their `RecordAttributes` are cached for performance. Note that
74/// it's possible for two equal instances of `RecordAttributes` objects to have
75/// different stream states. Resetting the message will clear most stream
76/// state, except for the locale, installed callbacks, and any pword/iword data.
77///
78/// For each attribute, there is a method to access its value and a method to
79/// change its value. E.g., for the timestamp attribute, there is the
80/// `timestamp` accessor and the `setTimestamp` manipulator. Note that for the
81/// message attribute, there is a `message` accessor which is *deprecated*; use
82/// the `messageRef` accessor instead. The class also provides the ability to
83/// stream an object (whose class must support the `operator<<`) into the
84/// message attribute using `messageStreamBuf` method (see the usage example-2).
85///
86/// Alternately, an object can be streamed directly into the message attribute
87/// via the stream exposed by the `messageStream` method: in that case, the
88/// `messageStreamBuf` should not also be used simultaneously. More precisely,
89/// use of the references returned by the `messageStreamBuf` and `messageStream`
90/// methods to build a message results in undefined behavior if interleaved with
91/// each other, or if interspersed with calls to `setMessage`, `clearMessage`,
92/// `operator=`, or `message` (but not `messageRef`). In other words, streaming
93/// an object into the message attribute must be done in one uninterrupted
94/// sequence of operations.
95///
96/// The default values listed in the table above are the values given to the
97/// respective attributes by the default constructor of
98/// `ball::RecordAttributes`.
99///
100/// ## Usage {#ball_recordattributes-usage}
101///
102///
103/// This section illustrates intended use of this component.
104///
105/// ### Example 1: Syntax {#ball_recordattributes-example-1-syntax}
106///
107///
108/// The `ball::RecordAttributes` class holds sufficient information on which to
109/// base a rudimentary logging, tracing, or reporting facility. The following
110/// code fragments illustrate the essentials of working with these attributes.
111///
112/// Assume that our example is part of a financial application using categories
113/// and message severities as follows:
114/// @code
115/// const char *Category[] = { "Bonds", "Equities", "Futures" };
116/// enum { INFO, WARN, BUY, SELL };
117/// @endcode
118/// First define a `ball::RecordAttributes` object with each attribute
119/// initialized to its default value:
120/// @code
121/// ball::RecordAttributes attributes;
122/// @endcode
123/// Next set each of the attributes to some meaningful value:
124/// @code
125/// bdlt::Datetime now;
126/// bdlt::EpochUtil::convertFromTimeT(&now, time(0));
127/// attributes.setTimestamp(now); // current time
128/// attributes.setProcessID(getpid());
129/// attributes.setThreadID((bsls::Types::Uint64) pthread_self());
130/// attributes.setFileName(__FILE__);
131/// attributes.setLineNumber(__LINE__);
132/// attributes.setCategory(Category[2]); // "Futures"
133/// attributes.setSeverity(WARN);
134/// attributes.setMessage("sugar up (locust infestations on the rise)");
135/// @endcode
136/// The message in this example briefly informs that something interesting may
137/// be happening with respect to sugar futures. In general, the message
138/// attribute can contain an arbitrary amount of information.
139///
140/// Now that the sample `ball::RecordAttributes` object has been populated with
141/// the desired information, it can be passed to a function, stored in a
142/// database, cached in a container of `ball::RecordAttributes` objects, etc.
143/// For the purposes of this illustration, we'll simply format and stream
144/// selected attributes to a specified `ostream` using the following function:
145/// @code
146/// void printMessage(ostream& stream,
147/// const ball::RecordAttributes& attributes)
148/// {
149/// using namespace std;
150/// stream << "\tTimestamp: " << attributes.timestamp() << endl;
151/// stream << "\tCategory: " << attributes.category() << endl;
152/// stream << "\tMessage: " << attributes.messageRef() << endl;
153/// stream << endl;
154/// }
155/// @endcode
156/// The following call:
157/// @code
158/// printMessage(bsl::cout, attributes);
159/// @endcode
160/// prints these attributes to `stdout`:
161/// @code
162/// Timestamp: 19JAN2004_23:07:38.000
163/// Category: Futures
164/// Message: sugar up (locust infestations on the rise)
165/// @endcode
166///
167/// ### Example 2: Streaming Data Into a Message Attribute {#ball_recordattributes-example-2-streaming-data-into-a-message-attribute}
168///
169///
170/// Following example demonstrates how an object of a class supporting `ostream`
171/// operation (`operator<<`) can be streamed into the message attribute.
172/// Suppose we want to stream objects of the following class.
173/// @code
174/// class Information
175/// {
176/// private:
177/// bsl::string d_heading;
178/// bsl::string d_contents;
179///
180/// public:
181/// Information(const char *heading, const char *contents);
182/// const bsl::string& heading() const;
183/// const bsl::string& contents() const;
184/// };
185/// @endcode
186/// The component containing the `Information` must provide `operator<<`. Here
187/// is a possible implementation.
188/// @code
189/// bsl::ostream& operator<<(bsl::ostream& stream,
190/// const Information& information)
191/// {
192/// stream << information.heading() << endl;
193/// stream << '\t';
194/// stream << information.contents() << endl;
195/// return stream;
196/// }
197/// @endcode
198/// The following function streams an `Information` object into the message
199/// attribute of a `ball::RecordAttributes` object.
200/// @code
201/// void streamInformationIntoMessageAttribute(
202/// ball::RecordAttributes& attributes,
203/// const Information& information)
204/// {
205/// // First clear the message attributes.
206/// attributes.clearMessage();
207///
208/// // Create an 'ostream' from message stream buffer.
209/// bsl::ostream os(&attributes.messageStreamBuf());
210///
211/// // Now stream the information object into the created ostream.
212/// // This will set the message attribute of 'attributes' to the
213/// // streamed contents.
214/// os << information;
215/// }
216/// @endcode
217/// @}
218/** @} */
219/** @} */
220
221/** @addtogroup bal
222 * @{
223 */
224/** @addtogroup ball
225 * @{
226 */
227/** @addtogroup ball_recordattributes
228 * @{
229 */
230
231#include <balscm_version.h>
232
234
235#include <bdlt_datetime.h>
236
237#include <bslma_allocator.h>
239
241
242#include <bsls_performancehint.h>
243#include <bsls_platform.h>
244#include <bsls_types.h>
245
246#include <bsl_ostream.h>
247#include <bsl_string.h>
248
249
250namespace ball {
251
252 // ======================
253 // class RecordAttributes
254 // ======================
255
256/// This class provides a container for a fixed set of attributes
257/// appropriate for logging. For each attribute in this class (e.g.,
258/// `category`), there is an accessor for obtaining the attribute's value
259/// (the `category` accessor) and a manipulator for changing the attribute's
260/// value (the `setCategory` manipulator).
261///
262/// Additionally, this class supports a complete set of *value* *semantic*
263/// operations, including copy construction, assignment and equality
264/// comparison, and `ostream` printing. A precise operational definition of
265/// when two instances have the same value can be found in the description
266/// of `operator==` for the class. This class is *exception* *neutral* with
267/// no guarantee of rollback: If an exception is thrown during the
268/// invocation of a method on a pre-existing instance, the object is left in
269/// a valid state, but its value is undefined. In no event is memory
270/// leaked. Finally, *aliasing* (e.g., using all or part of an object as
271/// both source and destination) is supported in all cases.
272///
273/// See @ref ball_recordattributes
275
276 // PRIVATE TYPES
277 typedef bsls::Types::Uint64 Uint64;
278
279 // PRIVATE CONSTANTS
280 enum {
281 k_RESET_MESSAGE_STREAM_CAPACITY = 256 // maximum capacity above which
282 // the message stream is reset
283 // (and not rewound)
284 };
285
286 // DATA
287 bdlt::Datetime d_timestamp; // creation date and time
288 int d_processID; // process id of creator
289 Uint64 d_threadID; // thread id of creator
290 bsl::string d_fileName; // name of file where created (__FILE__)
291 int d_lineNumber; // line number of said file (__LINE__)
292 bsl::string d_category; // category of log record
293 int d_severity; // severity of log record
294
295 bdlsb::MemOutStreamBuf d_messageStreamBuf; // stream buffer associated
296 // with the message attribute
297
298 bsl::ostream d_messageStream; // stream associated with the
299 // message attribute
300
301 // FRIENDS
302 friend bool operator==(const RecordAttributes&, const RecordAttributes&);
303
304 // PRIVATE MANIPULATORS
305
306 /// Reset the message stream state to the default stream state, except
307 /// for the imbued locale, any installed callbacks, and any pword/iword
308 /// data (in practice these are unlikely to deviate from the default in
309 /// the first place).
310 void resetMessageStreamState();
311
312 public:
313 // TRAITS
316
317 // CREATORS
318
319 /// Create a record attributes object with all attributes having default
320 /// values. Optionally specify a `basicAllocator` used to supply
321 /// memory. If `basicAllocator` is 0, the currently installed default
322 /// allocator is used.
323 explicit RecordAttributes(bslma::Allocator *basicAllocator = 0);
324
325 /// Create a record attributes object having the specified `timestamp`,
326 /// `processID`, `threadID`, `fileName`, `lineNumber`, `category`,
327 /// `severity` and `message` values, respectively. Optionally specify a
328 /// `basicAllocator` used to supply memory. If `basicAllocator` is 0,
329 /// the currently installed default allocator is used. The behavior is
330 /// undefined if any `const char *` argument is null.
332 int processID,
334 const char *fileName,
335 int lineNumber,
336 const char *category,
337 int severity,
338 const char *message,
339 bslma::Allocator *basicAllocator = 0);
340
341 /// Create a record attributes object having the value of the specified
342 /// `original` record attributes object. Optionally specify a
343 /// `basicAllocator` used to supply memory. If `basicAllocator` is 0,
344 /// the currently installed default allocator is used.
346 bslma::Allocator *basicAllocator = 0);
347
348 /// Destroy this object.
349 ~RecordAttributes() = default;
350
351 // MANIPULATORS
352
353 /// Assign to this record attributes object the value of the specified
354 /// `rhs` record attributes object. Resets the objects returned by the
355 /// `messageStreamBuf` and `messageStream` methods.
357
358 /// Set the message attribute of this record attributes object to the
359 /// empty string. Resets the objects returned by the `messageStreamBuf`
360 /// and `messageStream` methods.
361 void clearMessage();
362
363 /// Return a reference to the modifiable stream buffer associated with
364 /// the message attribute of this record attributes object.
366
367 /// Return a reference to the modifiable stream associated with the
368 /// message attribute of this record attributes object.
369 bsl::ostream& messageStream();
370
371 /// Set the category attribute of this record attributes object to the
372 /// specified (non-null) `category`.
373 void setCategory(const char *category);
374
375 /// Set the filename attribute of this record attributes object to the
376 /// specified (non-null) `fileName`.
377 void setFileName(const char *fileName);
378
379 /// Set the line number attribute of this record attributes object to
380 /// the specified `lineNumber`.
381 void setLineNumber(int lineNumber);
382
383 /// Set the message attribute of this record attributes object to the
384 /// specified (non-null) `message`. Resets the objects returned by the
385 /// `messageStreamBuf` and `messageStream` methods.
386 void setMessage(const char *message);
387
388 /// Set the processID attribute of this record attributes object to the
389 /// specified `processID`.
390 void setProcessID(int processID);
391
392 /// Set the severity attribute of this record attributes object to the
393 /// specified `severity`.
394 void setSeverity(int severity);
395
396 /// Set the threadID attribute of this record attributes object to the
397 /// specified `threadID`.
399
400 /// Set the timestamp attribute of this record attributes object to the
401 /// specified `timestamp`.
403
404 // ACCESSORS
405
406 /// Return the category attribute of this record attributes object.
407 const char *category() const;
408
409 /// Return the filename attribute of this record attributes object.
410 const char *fileName() const;
411
412 /// Return the line number attribute of this record attributes object.
413 int lineNumber() const;
414
415 /// Return the message attribute of this record attributes object. Note
416 /// that this method will return a truncated message if it contains
417 /// embedded null ('\0') characters; see `messageRef` for an alternative
418 /// to this method. **Warning:** This method is *not* const thread-safe,
419 /// and cannot be safely called concurrently. It may modify the stream
420 /// buffer returned by `messageStreamBuf`.
421 ///
422 /// @deprecated Use @ref messageRef instead.
423 const char *message() const;
424
425 /// Return a string reference providing non-modifiable access to the
426 /// message attribute of this record attributes object. Note that the
427 /// returned string reference is not null-terminated, and may contain
428 /// null ('\0') characters.
430
431 /// Return the processID attribute of this record attributes object.
432 int processID() const;
433
434 /// Return the severity attribute of this record attributes object.
435 int severity() const;
436
437 /// Return the threadID attribute of this record attributes object.
439
440 /// Return the timestamp attribute of this record attributes object.
441 const bdlt::Datetime& timestamp() const;
442
443 /// Return a reference to the non-modifiable stream buffer associated
444 /// with the message attribute of this record attributes object.
446
447 /// Return a reference to the non-modifiable stream associated with the
448 /// message attribute of this record attributes object.
449 const bsl::ostream& messageStream() const;
450
451 /// Format this object to the specified output `stream` at the
452 /// optionally specified indentation `level` and return a reference to
453 /// the modifiable `stream`. If `level` is specified, optionally
454 /// specify `spacesPerLevel`, the number of spaces per indentation level
455 /// for this and all of its nested objects. Each line is indented by
456 /// the absolute value of `level * spacesPerLevel`. If `level` is
457 /// negative, suppress indentation of the first line. If
458 /// `spacesPerLevel` is negative, suppress line breaks and format the
459 /// entire output on one line. If `stream` is initially invalid, this
460 /// operation has no effect.
461 bsl::ostream& print(bsl::ostream& stream,
462 int level = 0,
463 int spacesPerLevel = 4) const;
464
465};
466
467// FREE OPERATORS
468
469/// Return `true` if the specified `lhs` and `rhs` record attributes objects
470/// have the same value, and `false` otherwise. Two record attributes
471/// objects have the same value if each respective pair of attributes have
472/// the same value.
473bool operator==(const RecordAttributes& lhs, const RecordAttributes& rhs);
474
475/// Return `true` if the specified `lhs` and `rhs` record attributes objects
476/// do not have the same value, and `false` otherwise. Two record
477/// attributes objects do not have the same value if one or more respective
478/// attributes differ in value.
479inline
480bool operator!=(const RecordAttributes& lhs, const RecordAttributes& rhs);
481
482/// Format the members of the specified `object` to the specified output
483/// `stream` and return a reference to the modifiable `stream`.
484inline
485bsl::ostream& operator<<(bsl::ostream& stream, const RecordAttributes& object);
486
487// ============================================================================
488// INLINE DEFINITIONS
489// ============================================================================
490
491 // ----------------------
492 // class RecordAttributes
493 // ----------------------
494
495// PRIVATE MANIPULATORS
496inline
497void RecordAttributes::resetMessageStreamState()
498{
499 // See basic_ios::init; note that we intentionally avoid 'copyfmt' here as
500 // re-imbuing the stream with a locale is quite expensive, and would defeat
501 // the purpose of caching the stream object in the attributes in the first
502 // place.
503 d_messageStream.exceptions(bsl::ios_base::goodbit);
504 d_messageStream.clear();
505 d_messageStream.tie(0);
506 d_messageStream.flags(bsl::ios_base::dec | bsl::ios_base::skipws);
507 d_messageStream.fill(' ');
508 d_messageStream.precision(6);
509 d_messageStream.width(0);
510}
511
512// MANIPULATORS
513inline
515{
516 // Note that the stream buffer holding the message attribute has initial
517 // capacity of 256 bytes (by implementation). Reset those stream buffers
518 // that are bigger than the default and "rewind" those that are smaller or
519 // equal.
521 k_RESET_MESSAGE_STREAM_CAPACITY < d_messageStreamBuf.capacity())) {
523 d_messageStreamBuf.reset();
524 }
525 else {
526 d_messageStreamBuf.pubseekpos(0);
527 }
528 resetMessageStreamState();
529}
530
531inline
533{
534 return d_messageStreamBuf;
535}
536
537inline
539{
540 return d_messageStream;
541}
542
543inline
544void RecordAttributes::setCategory(const char *category)
545{
546 d_category = category;
547}
548
549inline
550void RecordAttributes::setFileName(const char *fileName)
551{
552 d_fileName = fileName;
553}
554
555inline
557{
558 d_lineNumber = lineNumber;
559}
560
561inline
563{
564 d_processID = processID;
565}
566
567inline
569{
570 d_severity = severity;
571}
572
573inline
575{
576 d_threadID = threadID;
577}
578
579inline
581{
582 d_timestamp = timestamp;
583}
584
585// ACCESSORS
586inline
587const char *RecordAttributes::category() const
588{
589 return d_category.c_str();
590}
591
592inline
593const char *RecordAttributes::fileName() const
594{
595 return d_fileName.c_str();
596}
597
598inline
600{
601 return d_lineNumber;
602}
603
604inline
606{
607 return d_processID;
608}
609
610inline
612{
613 return d_severity;
614}
615
616inline
618{
619 return d_threadID;
620}
621
622inline
624{
625 return d_messageStreamBuf;
626}
627
628inline
629const bsl::ostream& RecordAttributes::messageStream() const
630{
631 return d_messageStream;
632}
633
634inline
636{
637 return d_timestamp;
638}
639
640} // close package namespace
641
642// FREE OPERATORS
643inline
644bool ball::operator!=(const RecordAttributes& lhs, const RecordAttributes& rhs)
645{
646 return !(lhs == rhs);
647}
648
649inline
650bsl::ostream& ball::operator<<(bsl::ostream& stream,
651 const RecordAttributes& object)
652{
653 return object.print(stream, 0, -1);
654}
655
656
657
658#endif
659
660// ----------------------------------------------------------------------------
661// Copyright 2015 Bloomberg Finance L.P.
662//
663// Licensed under the Apache License, Version 2.0 (the "License");
664// you may not use this file except in compliance with the License.
665// You may obtain a copy of the License at
666//
667// http://www.apache.org/licenses/LICENSE-2.0
668//
669// Unless required by applicable law or agreed to in writing, software
670// distributed under the License is distributed on an "AS IS" BASIS,
671// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
672// See the License for the specific language governing permissions and
673// limitations under the License.
674// ----------------------------- END-OF-FILE ----------------------------------
675
676/** @} */
677/** @} */
678/** @} */
Definition ball_recordattributes.h:274
void clearMessage()
Definition ball_recordattributes.h:514
bslstl::StringRef messageRef() const
RecordAttributes & operator=(const RecordAttributes &rhs)
BSLMF_NESTED_TRAIT_DECLARATION(RecordAttributes, bslma::UsesBslmaAllocator)
RecordAttributes(const RecordAttributes &original, bslma::Allocator *basicAllocator=0)
bsl::ostream & messageStream()
Definition ball_recordattributes.h:538
int lineNumber() const
Return the line number attribute of this record attributes object.
Definition ball_recordattributes.h:599
~RecordAttributes()=default
Destroy this object.
void setCategory(const char *category)
Definition ball_recordattributes.h:544
void setProcessID(int processID)
Definition ball_recordattributes.h:562
bdlsb::MemOutStreamBuf & messageStreamBuf()
Definition ball_recordattributes.h:532
void setTimestamp(const bdlt::Datetime &timestamp)
Definition ball_recordattributes.h:580
void setThreadID(bsls::Types::Uint64 threadID)
Definition ball_recordattributes.h:574
const bdlt::Datetime & timestamp() const
Return the timestamp attribute of this record attributes object.
Definition ball_recordattributes.h:635
bsls::Types::Uint64 threadID() const
Return the threadID attribute of this record attributes object.
Definition ball_recordattributes.h:617
void setLineNumber(int lineNumber)
Definition ball_recordattributes.h:556
bsl::ostream & print(bsl::ostream &stream, int level=0, int spacesPerLevel=4) const
const char * category() const
Return the category attribute of this record attributes object.
Definition ball_recordattributes.h:587
int processID() const
Return the processID attribute of this record attributes object.
Definition ball_recordattributes.h:605
friend bool operator==(const RecordAttributes &, const RecordAttributes &)
void setSeverity(int severity)
Definition ball_recordattributes.h:568
const char * message() const
const char * fileName() const
Return the filename attribute of this record attributes object.
Definition ball_recordattributes.h:593
int severity() const
Return the severity attribute of this record attributes object.
Definition ball_recordattributes.h:611
RecordAttributes(const bdlt::Datetime &timestamp, int processID, bsls::Types::Uint64 threadID, const char *fileName, int lineNumber, const char *category, int severity, const char *message, bslma::Allocator *basicAllocator=0)
void setFileName(const char *fileName)
Definition ball_recordattributes.h:550
RecordAttributes(bslma::Allocator *basicAllocator=0)
void setMessage(const char *message)
Definition bdlsb_memoutstreambuf.h:212
bsl::size_t capacity() const
Definition bdlsb_memoutstreambuf.h:388
void reset()
Definition bdlsb_memoutstreambuf.h:380
Definition bdlt_datetime.h:331
bsl::ostream & print(bsl::ostream &stream, int level=0, int spacesPerLevel=4) const
Definition bslstl_string.h:1281
const CHAR_TYPE * c_str() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:6705
Definition bslma_allocator.h:457
Definition bslstl_stringref.h:372
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
#define BSLS_PERFORMANCEHINT_UNLIKELY_HINT
Definition bsls_performancehint.h:484
#define BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(expr)
Definition bsls_performancehint.h:452
Definition ball_administration.h:214
bsl::ostream & operator<<(bsl::ostream &output, const Attribute &attribute)
bool operator!=(const Attribute &lhs, const Attribute &rhs)
Definition bslma_usesbslmaallocator.h:343
unsigned long long Uint64
Definition bsls_types.h:137