BDE 4.14.0 Production release
Loading...
Searching...
No Matches
ball_attribute.h
Go to the documentation of this file.
1/// @file ball_attribute.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// ball_attribute.h -*-C++-*-
8#ifndef INCLUDED_BALL_ATTRIBUTE
9#define INCLUDED_BALL_ATTRIBUTE
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup ball_attribute ball_attribute
15/// @brief Provide a representation of (literal) name/value pairs.
16/// @addtogroup bal
17/// @{
18/// @addtogroup ball
19/// @{
20/// @addtogroup ball_attribute
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#ball_attribute-purpose"> Purpose</a>
25/// * <a href="#ball_attribute-classes"> Classes </a>
26/// * <a href="#ball_attribute-description"> Description </a>
27/// * <a href="#ball_attribute-attribute-naming-recommendations"> Attribute Naming Recommendations </a>
28/// * <a href="#ball_attribute-usage"> Usage </a>
29/// * <a href="#ball_attribute-example-1-basic-attribute-usage"> Example 1: Basic Attribute usage </a>
30/// * <a href="#ball_attribute-example-2-using-attribute-to-log-pointers-to-opaque-structure"> Example 2: Using Attribute to log pointers to opaque structure </a>
31///
32/// # Purpose {#ball_attribute-purpose}
33/// Provide a representation of (literal) name/value pairs.
34///
35/// # Classes {#ball_attribute-classes}
36///
37/// - ball::Attribute: (literal) name/value pair
38///
39/// @see ball_managedattribute
40///
41/// # Description {#ball_attribute-description}
42/// This component implements an unusual in-core value-semantic
43/// class, `ball::Attribute`. Each instance of this type represents an
44/// attribute that consists of a (literal) name (held but not owned), and an
45/// associated value (owned) that can be an `int`, `long`, `long long`,
46/// `unsigned int`, unsigned long', `unsigned long long`, `bdlb::Guid`, or a
47/// `bsl::string`.
48///
49/// This component participates in the implementation of "Rule-Based Logging".
50/// For more information on how to use that feature, please see the package
51/// level documentation and usage examples for "Rule-Based Logging".
52///
53/// IMPORTANT: The attribute name, whose type is `const char *`, must therefore
54/// remain valid throughout the life time of the `ball::Attribute` object and
55/// that of any other `ball::Attribute` objects that are copied or assigned from
56/// the original object. It is recommended that only null-terminated C-string
57/// literals be used for names.
58///
59/// ## Attribute Naming Recommendations {#ball_attribute-attribute-naming-recommendations}
60///
61///
62/// Attributes can be rendered as part of a log message and used for log
63/// post-processing and analysis. It is recommended to use the following naming
64/// conventions for attribute names:
65///
66/// * An attribute name should start with an alphabetic character, no other
67/// special characters, digits should be allowed as the first character of
68/// the attribute name.
69/// * An attribute name should not contain whitespaces.
70/// * An attribute name should contain only alphanumeric characters,
71/// underscores(`_`), and dots(`.`). Do not use any other special
72/// characters.
73///
74/// Disregarding these conventions may prevent the log output from being
75/// correctly parsed by commonly used log processing software.
76///
77/// ## Usage {#ball_attribute-usage}
78///
79///
80/// This section illustrates intended use of this component.
81///
82/// ### Example 1: Basic Attribute usage {#ball_attribute-example-1-basic-attribute-usage}
83///
84///
85/// The following code creates four attributes having the same name, but
86/// different attribute value types.
87/// @code
88/// ball::Attribute a1("day", "Sunday");
89/// ball::Attribute a2("day", 7);
90/// ball::Attribute a3("day", 7LL);
91/// ball::Attribute a4("day", 7ULL);
92/// @endcode
93/// The names of the attributes can be found by calling the `name` method:
94/// @code
95/// assert(0 == bsl::strcmp("day", a1.name()));
96/// assert(0 == bsl::strcmp("day", a2.name()));
97/// assert(0 == bsl::strcmp("day", a3.name()));
98/// assert(0 == bsl::strcmp("day", a4.name()));
99/// @endcode
100/// The `value` method returns a non-modifiable reference to the
101/// `bdlb::Variant` object that manages the value of the attribute:
102/// @code
103/// assert(true == a1.value().is<bsl::string>());
104/// assert("Sunday" == a1.value().the<bsl::string>());
105///
106/// assert(true == a2.value().is<int>());
107/// assert(7 == a2.value().the<int>());
108///
109/// assert(true == a3.value().is<long long>());
110/// assert(7 == a3.value().the<long long>());
111///
112/// assert(true == a4.value().is<unsigned long long>());
113/// assert(7 == a4.value().the<unsigned long long>());
114/// @endcode
115/// Note that the name string that is passed to the constructor of
116/// `ball::Attribute` *must* remain valid and unchanged after the
117/// `ball::Attribute` object is created. In the next example, we create a
118/// temporary buffer to store the name string, and then use the buffer to
119/// create an attribute. Note that any subsequent changes to this temporary
120/// buffer will also modify the name of the attribute:
121/// @code
122/// char buffer[] = "Hello";
123/// ball::Attribute a4(buffer, 1); // BAD IDEA!!!
124/// bsl::strcpy(buffer, "World");
125/// assert(0 == bsl::strcmp("World", a4.name()));
126/// @endcode
127/// The `ball::Attribute` class also provides a constructor that takes a value
128/// of type `ball::Attribute::Value`:
129/// @code
130/// ball::Attribute::Value value;
131/// value.assign<bsl::string>("Sunday");
132/// ball::Attribute a5("day", value);
133/// assert(a5 == a1);
134/// @endcode
135///
136/// ### Example 2: Using Attribute to log pointers to opaque structure {#ball_attribute-example-2-using-attribute-to-log-pointers-to-opaque-structure}
137///
138///
139/// Consider we have an event scheduler that operates on events referred to by
140/// event handle:
141/// @code
142/// struct Event {
143/// d_int d_id;
144/// };
145///
146/// typedef Event * EventHandle;
147/// @endcode
148/// The event handler value can be logged using `ball::Attribute` as follows:
149/// @code
150/// Event event;
151/// EventHandle handle = &event;
152/// ball::Attribute a7("event", handle);
153///
154/// assert(true == a7.value().is<const void *>());
155/// assert(handle == a7.value().the<const void *>());
156/// @endcode
157/// @}
158/** @} */
159/** @} */
160
161/** @addtogroup bal
162 * @{
163 */
164/** @addtogroup ball
165 * @{
166 */
167/** @addtogroup ball_attribute
168 * @{
169 */
170
171#include <balscm_version.h>
172
173#include <bdlb_guid.h>
174#include <bdlb_variant.h>
175
176#include <bslma_allocator.h>
177#include <bslma_bslallocator.h>
179
181
182#include <bsls_assert.h>
183
184#include <bsl_cstring.h>
185#include <bsl_string.h>
186
187
188namespace ball {
189
190 // ===============
191 // class Attribute
192 // ===============
193
194/// An `Attribute` object contains an attribute name which is not managed
195/// and an attribute value which is managed.
196///
197/// See @ref ball_attribute
199
200 public:
201 // TYPES
202
203 /// `Value` is an alias for the attribute type variant.
204 typedef bdlb::Variant<int,
205 long,
206 long long,
207 unsigned int,
208 unsigned long,
209 unsigned long long,
211 const void *,
213
214 private:
215 // DATA
216 const char *d_name; // attribute name
217
218 Value d_value; // attribute value
219
220 mutable int d_hashValue; // hash value (-1 indicates it is unset)
221
222 mutable int d_hashSize; // hash size from which the hash value was
223 // calculated (0 indicates hash value is unset)
224
225 // FRIENDS
226 friend bool operator==(const Attribute&, const Attribute&);
227 friend bool operator!=(const Attribute&, const Attribute&);
228 friend bsl::ostream& operator<<(bsl::ostream&, const Attribute&);
229
230 public:
231 // TYPES
233
234 // TRAITS
236
237 // CLASS METHODS
238
239 /// Return a hash value calculated from the specified `attribute` using
240 /// the specified `size` as the number of slots. The hash value is
241 /// guaranteed to be in the range `[0 .. size - 1]`. The behavior is
242 /// undefined unless `0 < size`.
243 static int hash(const Attribute& attribute, int size);
244
245 // CREATORS
246
247 /// Create an `Attribute` object having the specified (literal) `name`
248 /// and (character string) `value`. Optionally specify an `allocator`
249 /// (e.g., the address of a `bslma::Allocator` object) to supply memory;
250 /// otherwise, the default allocator is used. Note that `name` is not
251 /// managed by this object and therefore must remain valid while in use
252 /// by any `Attribute` object.
253 Attribute(const char *name,
254 const bsl::string_view& value,
255 const allocator_type& allocator = allocator_type());
256
257 /// Create an `Attribute` object having the specified (literal) `name`
258 /// and (character string) `value`. Optionally specify an `allocator`
259 /// (e.g., the address of a `bslma::Allocator` object) to supply memory;
260 /// otherwise, the default allocator is used. Note that `name` is not
261 /// managed by this object and therefore must remain valid while in use
262 /// by any `Attribute` object.
263 Attribute(const char *name,
264 const char *value,
265 const allocator_type& allocator = allocator_type());
266
267 Attribute(const char *name,
268 int value,
269 const allocator_type& allocator = allocator_type());
270 Attribute(const char *name,
271 long value,
272 const allocator_type& allocator = allocator_type());
273 Attribute(const char *name,
274 long long value,
275 const allocator_type& allocator = allocator_type());
276 Attribute(const char *name,
277 unsigned int value,
278 const allocator_type& allocator = allocator_type());
279 Attribute(const char *name,
280 unsigned long value,
281 const allocator_type& allocator = allocator_type());
282 Attribute(const char *name,
283 unsigned long long value,
284 const allocator_type& allocator = allocator_type());
285 /// Create an `Attribute` object having the specified (literal) `name`
286 /// and `value`. Optionally specify an `allocator` (e.g., the address
287 /// of a `bslma::Allocator` object) to supply memory; otherwise, the
288 /// default allocator is used. Note that `name` is not managed by this
289 /// object and therefore must remain valid while in use by any
290 /// `Attribute` object.
291 Attribute(const char *name,
293 const allocator_type& allocator = allocator_type());
294
295 /// Create an `Attribute` object having the specified (literal) `name`
296 /// and (const-qualified void pointer) `value`. Optionally specify an
297 /// `allocator` (e.g., the address of a `bslma::Allocator` object) to
298 /// supply memory; otherwise, the default allocator is used.
299 Attribute(const char *name,
300 const void *value,
301 const allocator_type& allocator = allocator_type());
302
303 /// Create an `Attribute` object having the specified (literal) `name`
304 /// and `value`. Optionally specify an `allocator` (e.g., the address
305 /// of a `bslma::Allocator` object) to supply memory; otherwise, the
306 /// default allocator is used. Note that `name` is not managed by this
307 /// object and therefore must remain valid while in use by any
308 /// `Attribute` object.
309 Attribute(const char *name,
310 const Value& value,
311 const allocator_type& allocator = allocator_type());
312
313 /// Create an `Attribute` object having the same (literal) name and
314 /// attribute value as the specified `original` object. Optionally
315 /// specify an `allocator` (e.g., the address of a `bslma::Allocator`
316 /// object) to supply memory; otherwise, the default allocator is used.
317 Attribute(const Attribute& original,
318 const allocator_type& allocator = allocator_type());
319
320 /// Destroy this object.
321 ~Attribute() = default;
322
323 // MANIPULATORS
324
325 /// Assign the value of the specified `rhs` object to this object.
326 Attribute& operator=(const Attribute& rhs);
327
328 /// Set the attribute name of this object to the specified (literal)
329 /// `name`. Note that `name` is not managed by this object and
330 /// therefore must remain valid while in use by any `Attribute` object.
331 void setName(const char *name);
332
333 void setValue(const Value& value);
334 void setValue(int value);
335 void setValue(long value);
336 void setValue(long long value);
337 void setValue(unsigned int value);
338 void setValue(unsigned long value);
339 void setValue(unsigned long long value);
341 void setValue(const bsl::string_view& value);
342 void setValue(const char *value);
343 /// Set the attribute value of this object to the specified `value`.
344 void setValue(const void *value);
345
346 // ACCESSORS
347
348 /// Return the name of this object.
349 const char *name() const;
350
351 /// Return a reference to the non-modifiable attribute value of this
352 /// object.
353 const Value& value() const;
354
355 /// Format this object to the specified output `stream` at the (absolute
356 /// value of) the optionally specified indentation `level` and return a
357 /// reference to `stream`. If `level` is specified, optionally specify
358 /// `spacesPerLevel`, the number of spaces per indentation level for
359 /// this and all of its nested objects. If `level` is negative,
360 /// suppress indentation of the first line. If `spacesPerLevel` is
361 /// negative, format the entire output on one line, suppressing all but
362 /// the initial indentation (as governed by `level`). If `stream` is
363 /// not valid on entry, this operation has no effect.
364 bsl::ostream& print(bsl::ostream& stream,
365 int level = 0,
366 int spacesPerLevel = 4) const;
367
368 // Aspects
369
370 /// Return the allocator used by this object to supply memory. Note
371 /// that if no allocator was supplied at construction the default
372 /// allocator in effect at construction is used.
374};
375
376// FREE OPERATORS
377
378/// Return `true` if the specified `lhs` and `rhs` objects have the same
379/// value, and `false` otherwise. Two `Attribute` objects have the same
380/// value if they have the same name (but not necessarily the identical
381/// representation in memory), the same attribute value type, and the same
382/// attribute value.
383bool operator==(const Attribute& lhs, const Attribute& rhs);
384
385/// Return `true` if the specified `lhs` and `rhs` objects do not have the
386/// same value, and `false` otherwise. Two `Attribute` objects do not have
387/// the same value if any of their respective names (value, not address),
388/// attribute value types, or attribute values differ.
389bool operator!=(const Attribute& lhs, const Attribute& rhs);
390
391/// Write the value of the specified `attribute` to the specified `output`
392/// stream. Return the specified `output` stream.
393bsl::ostream& operator<<(bsl::ostream& output, const Attribute& attribute);
394
395// ============================================================================
396// INLINE DEFINITIONS
397// ============================================================================
398
399 // ---------------
400 // class Attribute
401 // ---------------
402
403// CREATORS
404inline
405Attribute::Attribute(const char *name,
406 const bsl::string_view& value,
407 const allocator_type& allocator)
408: d_name(name)
409, d_value(allocator.mechanism())
410, d_hashValue(-1)
411, d_hashSize(0)
412{
414}
415
416inline
417Attribute::Attribute(const char *name,
418 const char *value,
419 const allocator_type& allocator)
420: d_name(name)
421, d_value(allocator.mechanism())
422, d_hashValue(-1)
423, d_hashSize(0)
424{
425 d_value.assign<bsl::string>(value);
426}
427
428inline
429Attribute::Attribute(const char *name,
430 int value,
431 const allocator_type& allocator)
432: d_name(name)
433, d_value(allocator.mechanism())
434, d_hashValue(-1)
435, d_hashSize(0)
436{
437 d_value.assign<int>(value);
438}
439
440inline
441Attribute::Attribute(const char *name,
442 long value,
443 const allocator_type& allocator)
444: d_name(name)
445, d_value(allocator.mechanism())
446, d_hashValue(-1)
447, d_hashSize(0)
448{
449 d_value.assign<long>(value);
450}
451
452inline
453Attribute::Attribute(const char *name,
454 long long value,
455 const allocator_type& allocator)
456: d_name(name)
457, d_value(allocator.mechanism())
458, d_hashValue(-1)
459, d_hashSize(0)
460{
461 d_value.assign<long long>(value);
462}
463
464inline
465Attribute::Attribute(const char *name,
466 unsigned int value,
467 const allocator_type& allocator)
468: d_name(name)
469, d_value(allocator.mechanism())
470, d_hashValue(-1)
471, d_hashSize(0)
472{
473 d_value.assign<unsigned int>(value);
474}
475
476inline
477Attribute::Attribute(const char *name,
478 unsigned long value,
479 const allocator_type& allocator)
480: d_name(name)
481, d_value(allocator.mechanism())
482, d_hashValue(-1)
483, d_hashSize(0)
484{
485 d_value.assign<unsigned long>(value);
486}
487
488inline
489Attribute::Attribute(const char *name,
490 unsigned long long value,
491 const allocator_type& allocator)
492: d_name(name)
493, d_value(allocator.mechanism())
494, d_hashValue(-1)
495, d_hashSize(0)
496{
497 d_value.assign<unsigned long long>(value);
498}
499
500
501inline
502Attribute::Attribute(const char *name,
503 bdlb::Guid value,
504 const allocator_type& allocator)
505: d_name(name)
506, d_value(allocator.mechanism())
507, d_hashValue(-1)
508, d_hashSize(0)
509{
510 d_value.assign<bdlb::Guid>(value);
511}
512
513inline
514Attribute::Attribute(const char *name,
515 const void *value,
516 const allocator_type& allocator)
517: d_name(name)
518, d_value(allocator.mechanism())
519, d_hashValue(-1)
520, d_hashSize(0)
521{
522 d_value.assign<const void *>(value);
523}
524
525inline
526Attribute::Attribute(const char *name,
527 const Value& value,
528 const allocator_type& allocator)
529: d_name(name)
530, d_value(value, allocator.mechanism())
531, d_hashValue(-1)
532, d_hashSize(0)
533{
534}
535
536inline
538 const allocator_type& allocator)
539: d_name(original.d_name)
540, d_value(original.d_value, allocator.mechanism())
541, d_hashValue(original.d_hashValue)
542, d_hashSize(original.d_hashSize)
543{
544}
545
546// MANIPULATORS
547inline
549{
550 d_name = rhs.d_name;
551 d_value = rhs.d_value;
552 d_hashValue = rhs.d_hashValue;
553 d_hashSize = rhs.d_hashSize;
554 return *this;
555}
556
557inline
558void Attribute::setName(const char *name)
559{
560 d_name = name;
561 d_hashValue = -1;
562}
563
564inline
565void Attribute::setValue(const Value& value)
566{
567 d_value = value;
568 d_hashValue = -1;
569}
570
571inline
572void Attribute::setValue(int value)
573{
574 d_value.assign(value);
575 d_hashValue = -1;
576}
577
578inline
579void Attribute::setValue(long value)
580{
581 d_value.assign(value);
582 d_hashValue = -1;
583}
584
585inline
586void Attribute::setValue(long long value)
587{
588 d_value.assign(value);
589 d_hashValue = -1;
590}
591
592inline
593void Attribute::setValue(unsigned int value)
594{
595 d_value.assign(value);
596 d_hashValue = -1;
597}
598
599inline
600void Attribute::setValue(unsigned long value)
601{
602 d_value.assign(value);
603 d_hashValue = -1;
604}
605
606inline
607void Attribute::setValue(unsigned long long value)
608{
609 d_value.assign(value);
610 d_hashValue = -1;
611}
612
613inline
615{
616 d_value.assign(value);
617 d_hashValue = -1;
618}
619
620inline
622{
623 d_value.assign(bsl::string(value));
624 d_hashValue = -1;
625}
626
627inline
628void Attribute::setValue(const char *value)
629{
630 d_value.assign<bsl::string>(value);
631 d_hashValue = -1;
632}
633
634inline
635void Attribute::setValue(const void *value)
636{
637 d_value.assign<const void *>(value);
638 d_hashValue = -1;
639}
640
641// ACCESSORS
642inline
643const char *Attribute::name() const
644{
645 return d_name;
646}
647
648inline
650{
651 return d_value;
652}
653
654 // Aspects
655
656inline
658{
659 // Until bdlb::variant is converted to new allocator model.
660 return allocator_type(d_value.getAllocator());
661}
662
663} // close package namespace
664
665// FREE OPERATORS
666inline
667bool ball::operator==(const Attribute& lhs, const Attribute& rhs)
668{
669 return 0 == bsl::strcmp(lhs.d_name, rhs.d_name)
670 && lhs.d_value == rhs.d_value;
671}
672
673inline
674bool ball::operator!=(const Attribute& lhs, const Attribute& rhs)
675{
676 return !(lhs == rhs);
677}
678
679
680
681#endif
682
683// ----------------------------------------------------------------------------
684// Copyright 2015 Bloomberg Finance L.P.
685//
686// Licensed under the Apache License, Version 2.0 (the "License");
687// you may not use this file except in compliance with the License.
688// You may obtain a copy of the License at
689//
690// http://www.apache.org/licenses/LICENSE-2.0
691//
692// Unless required by applicable law or agreed to in writing, software
693// distributed under the License is distributed on an "AS IS" BASIS,
694// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
695// See the License for the specific language governing permissions and
696// limitations under the License.
697// ----------------------------- END-OF-FILE ----------------------------------
698
699/** @} */
700/** @} */
701/** @} */
Definition ball_attribute.h:198
Attribute(const char *name, const bsl::string_view &value, const allocator_type &allocator=allocator_type())
Definition ball_attribute.h:405
friend bool operator!=(const Attribute &, const Attribute &)
void setName(const char *name)
Definition ball_attribute.h:558
bsl::ostream & print(bsl::ostream &stream, int level=0, int spacesPerLevel=4) const
BSLMF_NESTED_TRAIT_DECLARATION(Attribute, bslma::UsesBslmaAllocator)
allocator_type get_allocator() const
Definition ball_attribute.h:657
friend bool operator==(const Attribute &, const Attribute &)
void setValue(const Value &value)
Definition ball_attribute.h:565
bsl::allocator< char > allocator_type
Definition ball_attribute.h:232
Attribute & operator=(const Attribute &rhs)
Assign the value of the specified rhs object to this object.
Definition ball_attribute.h:548
const char * name() const
Return the name of this object.
Definition ball_attribute.h:643
static int hash(const Attribute &attribute, int size)
friend bsl::ostream & operator<<(bsl::ostream &, const Attribute &)
bdlb::Variant< int, long, long long, unsigned int, unsigned long, unsigned long long, bsl::string, const void *, bdlb::Guid > Value
Value is an alias for the attribute type variant.
Definition ball_attribute.h:212
const Value & value() const
Definition ball_attribute.h:649
~Attribute()=default
Destroy this object.
Definition bdlb_guid.h:201
VariantImp & assign(const TYPE &value)
Definition bdlb_variant.h:2312
Definition bslma_bslallocator.h:580
Definition bslstl_stringview.h:441
Definition bslstl_string.h:1281
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition ball_administration.h:214
bsl::ostream & operator<<(bsl::ostream &output, const Attribute &attribute)
bool operator!=(const Attribute &lhs, const Attribute &rhs)
bool operator==(const Attribute &lhs, const Attribute &rhs)
basic_string< char > string
Definition bslstl_string.h:782
Definition bslma_usesbslmaallocator.h:343