BDE 4.39.x 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#include <bsl_string_view.h>
187
188
189namespace ball {
190
191 // ===============
192 // class Attribute
193 // ===============
194
195/// An `Attribute` object contains an attribute name which is not managed
196/// and an attribute value which is managed.
197///
198/// See @ref ball_attribute
200
201 public:
202 // TYPES
203
204 /// `Value` is an alias for the attribute type variant.
205 typedef bdlb::Variant<int,
206 long,
207 long long,
208 unsigned int,
209 unsigned long,
210 unsigned long long,
212 const void *,
214
215 private:
216 // DATA
217 bsl::string_view d_name; // attribute name
218
219 Value d_value; // attribute value
220
221 mutable int d_hashValue; // hash value (-1 indicates it is unset)
222
223 mutable int d_hashSize; // hash size from which the hash value was
224 // calculated (0 indicates hash value is
225 // unset)
226
227 // FRIENDS
228 friend bool operator==(const Attribute&, const Attribute&);
229 friend bool operator!=(const Attribute&, const Attribute&);
230 friend bsl::ostream& operator<<(bsl::ostream&, const Attribute&);
231
232 public:
233 // TYPES
235
236 // TRAITS
238
239 // CLASS METHODS
240
241 /// Return a hash value calculated from the specified `attribute` using
242 /// the specified `size` as the number of slots. The hash value is
243 /// guaranteed to be in the range `[0 .. size - 1]`.
244 ///
245 /// \pre The behavior is undefined unless `0 < size`.
246 static int hash(const Attribute& attribute, int size);
247
248 // CREATORS
249
250 /// Create an `Attribute` object having the specified (literal) `name`
251 /// and (character string) `value`. Optionally specify an `allocator`
252 /// (e.g., the address of a `bslma::Allocator` object) to supply memory; otherwise, the default allocator is used.
253 ///
254 /// \note Note that `name` is not
255 /// managed by this object and therefore must remain valid while in use
256 /// by any `Attribute` object.
257 Attribute(const char *name,
258 const bsl::string_view& value,
259 const allocator_type& allocator = allocator_type());
260
261 /// Create an `Attribute` object having the specified (literal) `name`
262 /// and (character string) `value`. Optionally specify an `allocator`
263 /// (e.g., the address of a `bslma::Allocator` object) to supply memory; otherwise, the default allocator is used.
264 ///
265 /// \note Note that `name` is not
266 /// managed by this object and therefore must remain valid while in use
267 /// by any `Attribute` object.
268 Attribute(const char *name,
269 const char *value,
270 const allocator_type& allocator = allocator_type());
271
272 /// Create an `Attribute` object having the specified (literal) `name`
273 /// and `value`. Optionally specify an `allocator` (e.g., the address
274 /// of a `bslma::Allocator` object) to supply memory; otherwise, the default allocator is used.
275 ///
276 /// \note Note that `name` is not managed by this
277 /// object and therefore must remain valid while in use by any
278 /// `Attribute` object.
279 Attribute(const char *name,
280 int value,
281 const allocator_type& allocator = allocator_type());
282 Attribute(const char *name,
283 long value,
284 const allocator_type& allocator = allocator_type());
285 Attribute(const char *name,
286 long long value,
287 const allocator_type& allocator = allocator_type());
288 Attribute(const char *name,
289 unsigned int value,
290 const allocator_type& allocator = allocator_type());
291 Attribute(const char *name,
292 unsigned long value,
293 const allocator_type& allocator = allocator_type());
294 Attribute(const char *name,
295 unsigned long long value,
296 const allocator_type& allocator = allocator_type());
297 Attribute(const char *name,
299 const allocator_type& allocator = allocator_type());
300
301 /// Create an `Attribute` object having the specified (literal) `name`
302 /// and (const-qualified void pointer) `value`. Optionally specify an
303 /// `allocator` (e.g., the address of a `bslma::Allocator` object) to
304 /// supply memory; otherwise, the default allocator is used.
305 Attribute(const char *name,
306 const void *value,
307 const allocator_type& allocator = allocator_type());
308
309 /// Create an `Attribute` object having the specified (literal) `name`
310 /// and `value`. Optionally specify an `allocator` (e.g., the address
311 /// of a `bslma::Allocator` object) to supply memory; otherwise, the default allocator is used.
312 ///
313 /// \note Note that `name` is not managed by this
314 /// object and therefore must remain valid while in use by any
315 /// `Attribute` object.
316 Attribute(const char *name,
317 const Value& value,
318 const allocator_type& allocator = allocator_type());
319
320 /// Create an `Attribute` object having the same (literal) name and
321 /// attribute value as the specified `original` object. Optionally
322 /// specify an `allocator` (e.g., the address of a `bslma::Allocator`
323 /// object) to supply memory; otherwise, the default allocator is used.
324 Attribute(const Attribute& original,
325 const allocator_type& allocator = allocator_type());
326
327 /// Destroy this object.
328 ~Attribute() = default;
329
330 // MANIPULATORS
331
332 /// Assign the value of the specified `rhs` object to this object.
333 Attribute& operator=(const Attribute& rhs);
334
335 /// Set the attribute name of this object to the specified (literal) `name`.
336 ///
337 /// \note Note that `name` is not managed by this object and
338 /// therefore must remain valid while in use by any `Attribute` object.
339 void setName(const char *name);
340
341 /// Set the attribute value of this object to the specified `value`.
342 void setValue(const Value& value);
343 void setValue(int value);
344 void setValue(long value);
345 void setValue(long long value);
346 void setValue(unsigned int value);
347 void setValue(unsigned long value);
348 void setValue(unsigned long long value);
350 void setValue(const bsl::string_view& value);
351 void setValue(const char *value);
352 void setValue(const void *value);
353
354 // ACCESSORS
355
356 /// Return the name of this object.
357 const char *name() const;
358
359 /// Return a reference to the non-modifiable attribute value of this
360 /// object.
361 const Value& value() const;
362
363 /// Format this object to the specified output `stream` at the (absolute
364 /// value of) the optionally specified indentation `level` and return a
365 /// reference to `stream`. If `level` is specified, optionally specify
366 /// `spacesPerLevel`, the number of spaces per indentation level for
367 /// this and all of its nested objects. If `level` is negative,
368 /// suppress indentation of the first line. If `spacesPerLevel` is
369 /// negative, format the entire output on one line, suppressing all but
370 /// the initial indentation (as governed by `level`). If `stream` is
371 /// not valid on entry, this operation has no effect.
372 bsl::ostream& print(bsl::ostream& stream,
373 int level = 0,
374 int spacesPerLevel = 4) const;
375
376 // Aspects
377
378 /// Return the allocator used by this object to supply memory.
379 ///
380 /// \note Note that if no allocator was supplied at construction the default
381 /// allocator in effect at construction is used.
383};
384
385// FREE OPERATORS
386
387/// Return `true` if the specified `lhs` and `rhs` objects have the same
388/// value, and `false` otherwise. Two `Attribute` objects have the same
389/// value if they have the same name (but not necessarily the identical
390/// representation in memory), the same attribute value type, and the same
391/// attribute value.
392bool operator==(const Attribute& lhs, const Attribute& rhs);
393
394/// Return `true` if the specified `lhs` and `rhs` objects do not have the
395/// same value, and `false` otherwise. Two `Attribute` objects do not have
396/// the same value if any of their respective names (value, not address),
397/// attribute value types, or attribute values differ.
398bool operator!=(const Attribute& lhs, const Attribute& rhs);
399
400/// Write the value of the specified `attribute` to the specified `output`
401/// stream. Return the specified `output` stream.
402bsl::ostream& operator<<(bsl::ostream& output, const Attribute& attribute);
403
404// ============================================================================
405// INLINE DEFINITIONS
406// ============================================================================
407
408 // ---------------
409 // class Attribute
410 // ---------------
411
412// CREATORS
413inline
414Attribute::Attribute(const char *name,
415 const bsl::string_view& value,
416 const allocator_type& allocator)
417: d_name(name)
418, d_value(allocator.mechanism())
419, d_hashValue(-1)
420, d_hashSize(0)
421{
423}
424
425inline
426Attribute::Attribute(const char *name,
427 const char *value,
428 const allocator_type& allocator)
429: d_name(name)
430, d_value(allocator.mechanism())
431, d_hashValue(-1)
432, d_hashSize(0)
433{
435}
436
437inline
438Attribute::Attribute(const char *name,
439 int value,
440 const allocator_type& allocator)
441: d_name(name)
442, d_value(value, allocator.mechanism())
443, d_hashValue(-1)
444, d_hashSize(0)
445{
446}
447
448inline
449Attribute::Attribute(const char *name,
450 long value,
451 const allocator_type& allocator)
452: d_name(name)
453, d_value(value, allocator.mechanism())
454, d_hashValue(-1)
455, d_hashSize(0)
456{
457}
458
459inline
460Attribute::Attribute(const char *name,
461 long long value,
462 const allocator_type& allocator)
463: d_name(name)
464, d_value(value, allocator.mechanism())
465, d_hashValue(-1)
466, d_hashSize(0)
467{
468}
469
470inline
471Attribute::Attribute(const char *name,
472 unsigned int value,
473 const allocator_type& allocator)
474: d_name(name)
475, d_value(value, allocator.mechanism())
476, d_hashValue(-1)
477, d_hashSize(0)
478{
479}
480
481inline
482Attribute::Attribute(const char *name,
483 unsigned long value,
484 const allocator_type& allocator)
485: d_name(name)
486, d_value(value, allocator.mechanism())
487, d_hashValue(-1)
488, d_hashSize(0)
489{
490}
491
492inline
493Attribute::Attribute(const char *name,
494 unsigned long long value,
495 const allocator_type& allocator)
496: d_name(name)
497, d_value(value, allocator.mechanism())
498, d_hashValue(-1)
499, d_hashSize(0)
500{
501}
502
503inline
504Attribute::Attribute(const char *name,
505 bdlb::Guid value,
506 const allocator_type& allocator)
507: d_name(name)
508, d_value(value, allocator.mechanism())
509, d_hashValue(-1)
510, d_hashSize(0)
511{
512}
513
514inline
515Attribute::Attribute(const char *name,
516 const void *value,
517 const allocator_type& allocator)
518: d_name(name)
519, d_value(value, allocator.mechanism())
520, d_hashValue(-1)
521, d_hashSize(0)
522{
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 = value;
575 d_hashValue = -1;
576}
577
578inline
579void Attribute::setValue(long value)
580{
581 d_value = value;
582 d_hashValue = -1;
583}
584
585inline
586void Attribute::setValue(long long value)
587{
588 d_value = value;
589 d_hashValue = -1;
590}
591
592inline
593void Attribute::setValue(unsigned int value)
594{
595 d_value = value;
596 d_hashValue = -1;
597}
598
599inline
600void Attribute::setValue(unsigned long value)
601{
602 d_value = value;
603 d_hashValue = -1;
604}
605
606inline
607void Attribute::setValue(unsigned long long value)
608{
609 d_value = value;
610 d_hashValue = -1;
611}
612
613inline
615{
616 d_value = value;
617 d_hashValue = -1;
618}
619
620inline
622{
624 d_hashValue = -1;
625}
626
627inline
628void Attribute::setValue(const char *value)
629{
631 d_hashValue = -1;
632}
633
634inline
635void Attribute::setValue(const void *value)
636{
637 d_value = value;
638 d_hashValue = -1;
639}
640
641// ACCESSORS
642inline
643const char *Attribute::name() const
644{
645 // guaranteed to be zero-terminated due to the constructors and `setValue`
646 // taking name by `const char*`
647 return d_name.data();
648}
649
650inline
652{
653 return d_value;
654}
655
656 // Aspects
657
658inline
660{
661 // Until bdlb::variant is converted to new allocator model.
662 return d_value.getAllocator();
663}
664
665} // close package namespace
666
667// FREE OPERATORS
668inline
669bool ball::operator==(const Attribute& lhs, const Attribute& rhs)
670{
671 return lhs.d_name == rhs.d_name && lhs.d_value == rhs.d_value;
672}
673
674inline
675bool ball::operator!=(const Attribute& lhs, const Attribute& rhs)
676{
677 return !(lhs == rhs);
678}
679
680
681
682#endif
683
684// ----------------------------------------------------------------------------
685// Copyright 2015 Bloomberg Finance L.P.
686//
687// Licensed under the Apache License, Version 2.0 (the "License");
688// you may not use this file except in compliance with the License.
689// You may obtain a copy of the License at
690//
691// http://www.apache.org/licenses/LICENSE-2.0
692//
693// Unless required by applicable law or agreed to in writing, software
694// distributed under the License is distributed on an "AS IS" BASIS,
695// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
696// See the License for the specific language governing permissions and
697// limitations under the License.
698// ----------------------------- END-OF-FILE ----------------------------------
699
700/** @} */
701/** @} */
702/** @} */
Definition ball_attribute.h:199
Attribute(const char *name, const bsl::string_view &value, const allocator_type &allocator=allocator_type())
Definition ball_attribute.h:414
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:659
friend bool operator==(const Attribute &, const Attribute &)
void setValue(const Value &value)
Set the attribute value of this object to the specified value.
Definition ball_attribute.h:565
bsl::allocator< char > allocator_type
Definition ball_attribute.h:234
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:213
const Value & value() const
Definition ball_attribute.h:651
~Attribute()=default
Destroy this object.
Definition bdlb_guid.h:201
TYPE & createInPlace(ARGS &&... arguments)
Definition bdlb_variant.h:7574
Definition bdlb_variant.h:2389
Definition bslma_bslallocator.h:588
Definition bslstl_stringview.h:471
BSLS_KEYWORD_CONSTEXPR const_pointer data() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_stringview.h:1988
Definition bslstl_string.h:1252
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
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)
ALLOCATOR const STRING_VIEW_LIKE_TYPE & rhs
Definition bslstl_string.h:3918
ALLOCATOR & lhs
Definition bslstl_string.h:3917
basic_string< char > string
Definition bslstl_string.h:844
Definition bslma_usesbslmaallocator.h:344