BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bdld_datum.h
Go to the documentation of this file.
1/// @file bdld_datum.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdld_datum.h -*-C++-*-
8#ifndef INCLUDED_BDLD_DATUM
9#define INCLUDED_BDLD_DATUM
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id$ $CSID$")
13
14/// @defgroup bdld_datum bdld_datum
15/// @brief Provide a discriminated variant type with a small footprint.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdld
19/// @{
20/// @addtogroup bdld_datum
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdld_datum-purpose"> Purpose</a>
25/// * <a href="#bdld_datum-classes"> Classes </a>
26/// * <a href="#bdld_datum-description"> Description </a>
27/// * <a href="#bdld_datum-notion-of-value"> Notion of Value </a>
28/// * <a href="#bdld_datum-special-floating-point-values"> Special Floating Point Values </a>
29/// * <a href="#bdld_datum-treatment-of-nan"> Treatment of NaN (Not-A-Number) </a>
30/// * <a href="#bdld_datum-treatment-of-infinity"> Treatment of Infinity </a>
31/// * <a href="#bdld_datum-immutability"> Immutability </a>
32/// * <a href="#bdld_datum-memory-management"> Memory Management </a>
33/// * <a href="#bdld_datum-analogy-to-raw-pointers"> Analogy to Raw Pointers </a>
34/// * <a href="#bdld_datum-deep-copying"> Deep Copying </a>
35/// * <a href="#bdld_datum-creating-a-datum-that-requires-no-allocation"> Creating a Datum that Requires No Allocation </a>
36/// * <a href="#bdld_datum-creating-a-datum-that-may-require-allocation"> Creating a Datum that May Require Allocation </a>
37/// * <a href="#bdld_datum-destroying-a-datum-object"> Destroying a Datum Object </a>
38/// * <a href="#bdld_datum-references-to-external-strings-and-arrays"> References to External Strings and Arrays </a>
39/// * <a href="#bdld_datum-supported-types"> Supported Types </a>
40/// * <a href="#bdld_datum-user-defined-types"> User Defined Types </a>
41/// * <a href="#bdld_datum-map-and-intmap-types"> Map and IntMap Types </a>
42/// * <a href="#bdld_datum-usage"> Usage </a>
43/// * <a href="#bdld_datum-example-1-basic-use-of-bdld-datum"> Example 1: Basic Use of bdld::Datum </a>
44/// * <a href="#bdld_datum-example-2-creating-a-datum-referring-to-an-array-of-datum-objects"> Example 2: Creating a Datum Referring to an Array of Datum Objects </a>
45/// * <a href="#bdld_datum-example-3-creating-a-datum-with-an-array-value"> Example 3: Creating a Datum with an Array Value </a>
46/// * <a href="#bdld_datum-example-4-creating-a-datum-with-a-map-value"> Example 4: Creating a Datum with a Map Value </a>
47/// * <a href="#bdld_datum-example-5-mass-destruction"> Example 5: Mass Destruction </a>
48/// * <a href="#bdld_datum-example-6-user-defined-error-and-binary-types"> Example 6: User-defined, error and binary types </a>
49///
50/// # Purpose {#bdld_datum-purpose}
51/// Provide a discriminated variant type with a small footprint.
52///
53/// # Classes {#bdld_datum-classes}
54///
55/// - bdld::Datum: POD type representing general-purpose values
56/// - bdld::DatumArrayRef: type for const ref to array of datums
57/// - bdld::DatumIntMapEntry: type for entry inside int-map of datums
58/// - bdld::DatumIntMapRef: type for const ref to int-map of datums
59/// - bdld::DatumMapEntry: type for entry inside map of datums
60/// - bdld::DatumMapRef: type for const ref to map of datums
61/// - bdld::DatumMutableArrayRef: type for mutable ref to array of datums
62/// - bdld::DatumMutableMapRef: type for mutable ref to a map of datums
63/// - bdld::DatumMutableMapOwningKeysRef: mutable ref to a map owning keys
64///
65/// @see bdld_datumerror, bdld_datumudt, bdld_datumbinaryref,
66/// bdld_manageddatum
67///
68/// # Description {#bdld_datum-description}
69/// This component defines a mechanism, `bdld::Datum`, that
70/// provides a space-efficient discriminated union (i.e., a variant) that holds
71/// the value of either a scalar type (e.g., `int`, `double`, `Date`) or an
72/// aggregate (i.e., array or map) of `Datum` objects. The set of possible
73/// types that a datum may hold is described in the {Supported Types} section.
74///
75/// The `Datum` class is implemented as a POD-type, such that instances of the
76/// class are bitwise copyable and have trivial initialization, assignment and
77/// destruction. The `Datum` class is also (primarily) designed to be compact,
78/// especially on a 32-bit platform. Being a compact POD type, `Datum` is
79/// ideal for applications creating and copying very large numbers of variant
80/// values (the canonical use-case is for the values in a spreadsheet).
81///
82/// However, not all representable values can be stored in-line in footprint of
83/// a `Datum` object itself. Those types may require memory be allocated for
84/// storage. In order to keep the footprint of a `Datum` object as small as
85/// possible, a `Datum` object does not hold a reference to an allocator, and so
86/// memory must be explicitly managed by the user of `Datum`. See
87/// {Memory Management} for more details.
88///
89/// ## Notion of Value {#bdld_datum-notion-of-value}
90///
91///
92/// `Datum` has a notion of value, but is neither a value-semantic type, nor is
93/// it an in-core value-semantic type (see @ref bsldoc_glossary ). A consequence
94/// of the `Datum` class's space-efficient design is that it does not fall
95/// neatly into any of the standard BDE type-classifications. The `Datum`
96/// type's notion of value is expressed by its equality-operator -- notice, in
97/// particular, that two `Datum` objects compare equal if the values they refer
98/// to are the same. However, `Datum`, as a POD, has compiler supplied copy and
99/// assignment operators that do not copy any of the storage a `Datum` may be
100/// pointing to, and only copy the address to which the `Datum` is pointing.
101///
102/// Notice that the differing treatment of references to external data between
103/// the equality comparison and the copy and assignment operations violates a
104/// couple properties required of a value-semantic type, most obviously: "The
105/// value of an object of the type is independent of any modifiable state that
106/// is not owned exclusively by that object." (see @ref bsldoc_glossary ).
107///
108/// ### Special Floating Point Values {#bdld_datum-special-floating-point-values}
109///
110///
111/// Floating point data can represent special values, and of particular interest
112/// for `Datum` are values of NaN and infinity. `Datum` may internally store
113/// NaN and infinity values in a different way than the IEEE-754 representation,
114/// and this section describes the resulting behavior for NaN and infinity
115/// values.
116///
117/// ### Treatment of NaN (Not-A-Number) {#bdld_datum-treatment-of-nan}
118///
119///
120/// When storing a NaN value in a `Datum`, `Datum` guarantees only that *a* NaN
121/// value will be represented, but does not guarantee that the particular bit
122/// pattern supplied for a NaN value will be preserved. Note that an IEEE-754
123/// representation for `double` allows for signaling and quiet NaN values, as
124/// well as a sign bit, and other bits of NaN payload data. These non-salient
125/// elements of the "value" of the `double` may not be preserved (and in the
126/// case of signaling NaNs, cannot be preserved on some platforms).
127///
128/// ### Treatment of Infinity {#bdld_datum-treatment-of-infinity}
129///
130///
131/// `Datum` is provides unique representations for positive and negative
132/// infinity. IEEE-754 double precisions format requires also only those two
133/// infinity values. (Unlike NaN values, these two infinity values have no
134/// non-normative bits in their representations, or signaling/quiet forms.)
135///
136/// ## Immutability {#bdld_datum-immutability}
137///
138///
139/// `Datum` objects are generally immutable, meaning the value stored inside a
140/// `Datum` object cannot be changed *except* through the assignment operation.
141/// A `Datum` is copy-assignable, so a `Datum` object can assigned another
142/// `Datum` object. On assignment, a `Datum` object is "shallow-copied".
143/// Meaning that the footprint of original `Datum` object is copied into the
144/// footprint of the destination `Datum` object, but if the `Datum` refers to
145/// dynamically allocated memory, only the value of the address is copied (not
146/// the contents of the dynamic allocation). `Datum` also exposes a `clone`
147/// method to "deep-copy" `Datum` objects, so that any externally allocated
148/// memory (except user defined types) is cloned and not shared like
149/// copy-assignment. See also {Deep Copying}.
150///
151/// ## Memory Management {#bdld_datum-memory-management}
152///
153///
154/// A primary design goal for `Datum` is space-efficiency, particularly on
155/// 32-bit platforms. In order to minimize the foot-print (i.e., the `sizeof`)
156/// of a `Datum` object, `Datum` does not hold a reference to the allocator that
157/// was used to allocate its contents. This component provides static functions
158/// that allocate dynamic data structures referred to by a `Datum` object (i.e.
159/// the `Datum::create*` static functions). This memory is said to be
160/// "externally managed" because it not released when a `Datum` object is
161/// destroyed, instead clients must explicitly call `Datum::destroy` on a
162/// `Datum` to release its memory (see {Analogy to Raw Pointers}). The
163/// `bdld` package provides tools and components that can simplify the process
164/// of managing the memory (see @ref bdld_manageddatum , and the various builder
165/// components like @ref bdld_datumarraybuilder ).
166///
167/// ### Analogy to Raw Pointers {#bdld_datum-analogy-to-raw-pointers}
168///
169///
170/// A good way to understand the model for a `Datum` object's relationship to
171/// its data is by analogy: The relationship between a `Datum` object and the
172/// memory to which it refers is analogous to that of a raw-pointer and the data
173/// to which it points. Where `new` and `delete` are used allocate and free
174/// memory a that a pointer points to, the static class methods `Datum::create*`
175/// and `Datum::destroy` are used to allocate and release the memory a `Datum`
176/// refers to.
177///
178/// In order to create a `Datum` object a client calls one of the `create*`
179/// static methods on the `Datum` class. In order to release the data a
180/// `Datum` holds, a client calls `destroy`.
181///
182/// Copying, or copy assigning a `Datum` object to another behaves just like
183/// copying a raw pointer. This copy does not allocate or deallocate data.
184/// That also means assigning to a datum object is not safe if the `Datum` being
185/// assigned to refers to dynamically allocated memory, and there isn't a (user
186/// controlled) strategy in place to release that memory.
187///
188/// ### Deep Copying {#bdld_datum-deep-copying}
189///
190///
191/// `Datum` exposes a `clone` method that "deep-copies" `Datum` objects, so that
192/// any dynamically or externally referenced memory is cloned and not shared
193/// like it would be when using a copy or copy-assignment operation. The
194/// exception is {User Defined Types} as they are opaque, so `Datum` has no way
195/// to deep-copy them.
196///
197/// The purpose of `clone` is to create an independent copy of the content of
198/// any `Datum`, which also includes `Datum` values where `isExternalreference`
199/// returns `true` (except of course UDTs, as mentioned above). Cloning a
200/// reference to a string results in an owned string, not a reference to a
201/// string, with the cloned `Datum` object's `isExternalReference` returning
202/// `false`. When cloning a map with keys that are references to external
203/// strings the clone will have deep copies of those string keys, it will become
204/// a map with owned keys. This behavior is intentional. The deep-copy
205/// operation (`clone`) is designed to ensure that the lifetime of the new clone
206/// does not, in any way, depend on the lifetime of the original `Datum`, or any
207/// data that `Datum` may have referenced. So (except for UDTs), if a `Datum`
208/// is cloned, the original `Datum` can be destroyed without any effect on the
209/// cloned `Datum`.
210///
211/// ### Creating a Datum that Requires No Allocation {#bdld_datum-creating-a-datum-that-requires-no-allocation}
212///
213///
214/// Datum's containing certain types of scalar values do not require any memory
215/// allocation, so their factory functions do *not* take an allocator. These
216/// values are small enough that they can always fit inside of the footprint of
217/// the `Datum` object itself.
218/// @code
219/// Datum boolean = Datum::createBoolean(true); // Create a boolean datum
220/// Datum integer = Datum::createInteger(7); // Create a integer
221/// Datum real = Datum::createDouble(2.0); // Create a double
222/// @endcode
223///
224/// ### Creating a Datum that May Require Allocation {#bdld_datum-creating-a-datum-that-may-require-allocation}
225///
226///
227/// Datum objects containing certain types *may* (or *may*-*not*!) require
228/// memory allocation, so their creation functions *require* an allocator:
229/// @code
230/// bslma::Allocator *allocator = bslma::Default::defaultAllocator();
231/// Datum datetime = Datum::createDatetime(bdlt::Datetime(), allocator);
232/// Datum int64 = Datum::createInteger64(1LL, allocator);
233/// @endcode
234/// In the example above, `createDatetime` takes an allocator, but may not
235/// allocate memory. Depending on the value of the `Datetime`, a `Datum` might
236/// either store the value within the footprint of the `Datum` (requiring no
237/// allocation) or allocate external storage. The situations in which creation
238/// functions taking an allocator do, and do not, actually allocate memory is
239/// *implementation*-*defined*.
240///
241/// Clients of `Datum` should treat any creation function taking an allocator
242/// *as-if* it allocated memory, and eventually call `Datum::destroy` on the
243/// resulting `Datum`, even though in some instances memory allocation may not
244/// be required.
245///
246/// ### Destroying a Datum Object {#bdld_datum-destroying-a-datum-object}
247///
248///
249/// The contents of a `Datum` object are destroyed using the static method
250/// `destroy`. For example:
251/// @code
252/// bslma::Allocator *allocator = bslma::Default::defaultAllocator();
253/// Datum datetime = Datum::createDatetime(bdlt::Datetime(), allocator);
254///
255/// Datum::destroy(datetime, allocator);
256/// // 'datetime' now refers to deallocated memory. It cannot be used
257/// // unless it is assigned a new value.
258/// @endcode
259/// Notice that the destroyed `Datum` again behaves similar to a raw-pointer
260/// that has been deallocated: the destroyed `Datum` refers to garbage and must
261/// be assigned a new value before it can be used.
262///
263/// For aggregate types -- i.e., maps and arrays -- `destroy` will recursively
264/// call `destroy` on the `Datum` objects that compose the aggregate. The
265/// exception to this is references to external arrays (discussed below).
266///
267/// The `destroy` method does not nothing for {User Defined Types} as they are
268/// opaque, unknown, for `Datum`.
269///
270/// ### References to External Strings and Arrays {#bdld_datum-references-to-external-strings-and-arrays}
271///
272///
273/// Although a `Datum` does not own memory in the traditional sense, a call to
274/// `Datum::destroy` will release the memory to which that `Datum` refers.
275/// However, a `Datum` object also allows a user to create a `Datum` referring
276/// to an externally managed array or string. For a `Datum` having a reference
277/// to an external string or array, the `isExternalReference` method will return
278/// `true` and `Datum::destroy` will not deallocate memory for the data;
279/// otherwise, `isExternalReference` will return `false` and `Datum::destroy`
280/// will deallocate memory for the data.
281///
282/// For example, to create a `Datum` for an externally managed string:
283/// @code
284/// Datum externalStringRef = Datum::createStringRef("text", allocator);
285/// @endcode
286/// Notice that the supplied `allocator` is *not* used to allocate memory in
287/// order copy the contents of the string, but *may* (or *may*-*not*) be used to
288/// allocate meta-data that the `Datum` stores about the string (e.g., the
289/// string's length).
290///
291/// To create a `Datum` that is responsible for the memory of a string:
292/// @code
293/// Datum managedString = Datum::copyString("text", allocator);
294/// @endcode
295/// Here the contents of the string are copied and managed by the created
296/// datum, and later released by `Datum::destroy`.
297///
298/// External references to arrays and strings are important for efficiently
299/// handling memory allocations in situations where a string or array is
300/// externally supplied (e.g., as input to a function) and will clearly outlive
301/// the `Datum` object being created (e.g., a `Datum` variable within the scope
302/// of that function).
303///
304/// In general factory methods of the form `create*Ref` create a reference to
305/// external data that the `Datum` is not responsible for, while `copy*`
306/// methods copy the data and the resulting `Datum` is responsible for the
307/// allocated memory.
308///
309/// ## Supported Types {#bdld_datum-supported-types}
310///
311///
312/// The table below describes the set of types that a `Datum` may be.
313///
314/// @code
315/// external requires
316/// dataType reference allocation Description
317/// -------- --------- ---------- -----------
318/// e_NIL no no null value
319/// e_INTEGER no no integer value
320/// e_DOUBLE no no double value
321/// e_STRING maybe maybe string value
322/// e_BOOLEAN no no boolean value
323/// e_ERROR no maybe error value
324/// e_DATE no no date value
325/// e_TIME no no time value
326/// e_DATETIME no maybe date+time value
327/// e_DATETIME_INTERVAL no maybe date+time interval value
328/// e_INTEGER64 no maybe 64-bit integer value
329/// e_USERDEFINED always maybe pointer to a user-defined obj
330/// e_BINARY no maybe binary data
331/// e_DECIMAL64 no maybe Decimal64
332///
333/// external requires
334/// dataType reference allocation Description
335/// -------- --------- ---------- -----------
336/// e_ARRAY maybe maybe array
337/// e_MAP no maybe map keyed by string values
338/// e_INT_MAP no maybe map keyed by 32-bit int values
339/// @endcode
340/// * *dataType* - the value returned by the `type()`
341/// * *external-reference* - whether `isExternalReference` will return `true`,
342/// in which case `Datum::destroy` will not release the externally
343/// referenced data (see
344/// @ref bdld_datum-references-to-external-strings-and-arrays )
345/// * *requires-allocation* - whether a `Datum` referring to this type requires
346/// memory allocation. Note that for externally represented string or
347/// arrays, meta-data may still need to be allocated.
348///
349/// ### User Defined Types {#bdld_datum-user-defined-types}
350///
351///
352/// `Datum` exposes a type `DatumUdt` with which a user can arbitrarily expand
353/// the set of types a `Datum` can support. A `DatumUdt` object hold a void
354/// pointer, and an integer value identifying the type. A `DatumUdt` object is
355/// always treated as an external reference, and the memory it refers to is not
356/// released by `Datum::destroy`, or deep-copied by `clone`. The meaning of the
357/// integer type identifier is determined by the application, which is
358/// responsible for ensuring the set of "user-defined" type identifiers remains
359/// unique. From the viewpoint of `Datum` a UDT is an opaque pointer with an
360/// integer value that holds no defined meaning. In that sense it is more akin
361/// akin to a `void` pointer than to any of the other kind of values a `Datum`
362/// may hold. All knowledge of what the pointer and integer value means is
363/// elsewhere, in the application that created the UDT.
364///
365/// ### Map and IntMap Types {#bdld_datum-map-and-intmap-types}
366///
367///
368/// Datum provides two `map` types, map (datatype `e_MAP`) and int-map (
369/// datatype `e_INT_MAP`). These types provide a mapping of key to value, as
370/// represented by a sequence of key-value pairs (and are not directly related
371/// to `std::map`). The key types for map and int-map are `bslstl::StringRef`
372/// and `int` respectively, and the value is always a `Datum`. Both map types
373/// keep track of whether they are sorted by key. Key-based lookup is done via
374/// the `find` function. If the map is in a sorted state, `find` has O(logN)
375/// complexity and `find` is O(N) otherwise (where N is the number of elements
376/// in the map). If entries with duplicate keys are present, which matching
377/// entry will be found is unspecified.
378///
379/// ## Usage {#bdld_datum-usage}
380///
381///
382/// This section illustrates intended use of this component.
383///
384/// ### Example 1: Basic Use of bdld::Datum {#bdld_datum-example-1-basic-use-of-bdld-datum}
385///
386///
387/// This example illustrates the construction, manipulation and lifecycle of
388/// datums. Datums are created via a set of static methods called `createTYPE`,
389/// `copyTYPE` or `adoptTYPE` where TYPE is one of the supported types. The
390/// creation methods take a value and sometimes an allocator.
391///
392/// First, we create an allocator that will supply dynamic memory needed for the
393/// `Datum` objects being created:
394/// @code
395/// bslma::TestAllocator oa("object");
396/// @endcode
397/// Then, we create a `Datum`, `number`, having an integer value of `3`:
398/// @code
399/// Datum number = Datum::createInteger(3);
400/// @endcode
401/// Next, we verify that the created object actually represents an integer value
402/// and verify that the value was set correctly:
403/// @code
404/// assert(true == number.isInteger());
405/// assert(3 == number.theInteger());
406/// @endcode
407/// Note that this object does not allocate any dynamic memory on any supported
408/// platforms and thus we do not need to explicitly destroy this object to
409/// release any dynamic memory.
410///
411/// Then, we create a `Datum`, `cityName`, having the string value "Boston":
412/// @code
413/// Datum cityName = Datum::copyString("Boston", strlen("Boston"), &oa);
414/// @endcode
415/// Note, that the `copyString` makes a copy of the specified string and will
416/// allocate memory to hold the copy. Whether the copy is stored in the object
417/// internal storage buffer or in memory obtained from the allocator depends on
418/// the length of the string and the platform.
419///
420/// Next, we verify that the created object actually represents a string value
421/// and verify that the value was set correctly:
422/// @code
423/// assert(true == cityName.isString());
424/// assert("Boston" == cityName.theString());
425/// @endcode
426/// Finally, we destroy the `cityName` object to deallocate memory used to hold
427/// string value:
428/// @code
429/// Datum::destroy(cityName, &oa);
430/// @endcode
431///
432/// ### Example 2: Creating a Datum Referring to an Array of Datum Objects {#bdld_datum-example-2-creating-a-datum-referring-to-an-array-of-datum-objects}
433///
434///
435/// This example demonstrates the construction of the `Datum` object referring
436/// to an existing array of `Datum` object.
437///
438/// First, we create array of the `Datum` object:
439/// @code
440/// const char theDay[] = "Birthday";
441/// const Datum array[2] = { Datum::createDate(bdlt::Date(2015, 10, 15)),
442/// Datum::createStringRef(StringRef(theDay), &oa) };
443/// @endcode
444/// Note, that in this case, the second element of the array does not make a
445/// copy of the string, but represents a string reference.
446///
447/// Then, we create a `Datum` that refers to the array of Datums:
448/// @code
449/// const Datum arrayRef = Datum::createArrayReference(array, 2, &oa);
450/// @endcode
451/// Next, we verify that the created `Datum` represents the array value and that
452/// elements of this array can be accessed. We also verify that the object
453/// refers to external data:
454/// @code
455/// assert(true == arrayRef.isArray());
456/// assert(true == arrayRef.isExternalReference());
457/// assert(2 == arrayRef.theArray().length());
458/// assert(array[0] == arrayRef.theArray().data()[0]);
459/// assert(array[1] == arrayRef.theArray().data()[1]);
460/// @endcode
461/// Then, we call `destroy` on `arrayRef`, releasing any memory it may have
462/// allocated, and verify that the external array is intact:
463/// @code
464/// Datum::destroy(arrayRef, &oa);
465///
466/// assert(bdlt::Date(2015, 10, 15) == array[0].theDate());
467/// assert("Birthday" == array[1].theString());
468/// @endcode
469/// Finally, we need to deallocate memory that was potentially allocated for the
470/// (external) `Datum` string in the external `array`:
471/// @code
472/// Datum::destroy(array[1], &oa);
473/// @endcode
474///
475/// ### Example 3: Creating a Datum with an Array Value {#bdld_datum-example-3-creating-a-datum-with-an-array-value}
476///
477///
478/// The following example illustrates the construction of an owned array of
479/// datums.
480///
481/// > **WARNING**
482/// >> Using corresponding builder components is a preferred way of
483/// >> constructing `Datum` array objects. This example shows how a
484/// >> user-facing builder component might use the primitives provided in
485/// >> @ref bdld_datum .
486///
487/// First we create an array of datums:
488/// @code
489/// DatumMutableArrayRef bartArray;
490/// Datum::createUninitializedArray(&bartArray, 3, &oa);
491/// bartArray.data()[0] = Datum::createStringRef("Bart", &oa);
492/// bartArray.data()[1] = Datum::createStringRef("Simpson", &oa);
493/// bartArray.data()[2] = Datum::createInteger(10);
494/// *bartArray.length() = 3;
495/// @endcode
496/// Then, we construct the Datum that holds the array itself:
497/// @code
498/// Datum bart = Datum::adoptArray(bartArray);
499/// @endcode
500/// Note that after the `bartArray` has been adopted, the `bartArray` object can
501/// be destroyed without invalidating the array contained in the datum.
502///
503/// A DatumArray may be adopted by only one datum. If the DatumArray is not
504/// adopted, it must be destroyed via `disposeUninitializedArray`.
505///
506/// Now, we can access the contents of the array through the datum:
507/// @code
508/// assert(3 == bart.theArray().length());
509/// assert("Bart" == bart.theArray()[0].theString());
510/// @endcode
511/// Finally, we destroy the datum, which releases all memory associated with the
512/// array:
513/// @code
514/// Datum::destroy(bart, &oa);
515/// @endcode
516/// Note that the same allocator must be used to create the array, the
517/// elements, and to destroy the datum.
518///
519/// ### Example 4: Creating a Datum with a Map Value {#bdld_datum-example-4-creating-a-datum-with-a-map-value}
520///
521///
522/// The following example illustrates the construction of a map of datums
523/// indexed by string keys.
524///
525/// > **WARNING**
526/// >> Using corresponding builder components is a preferred way of
527/// >> constructing `Datum` map objects. This example shows how a user-facing
528/// >> builder component might use the primitives provided in @ref bdld_datum .
529///
530/// First we create a map of datums:
531/// @code
532/// DatumMutableMapRef lisaMap;
533/// Datum::createUninitializedMap(&lisaMap, 3, &oa);
534/// lisaMap.data()[0] = DatumMapEntry(StringRef("firstName"),
535/// Datum::createStringRef("Lisa", &oa));
536/// lisaMap.data()[1] = DatumMapEntry(StringRef("lastName"),
537/// Datum::createStringRef("Simpson", &oa));
538/// lisaMap.data()[2] = DatumMapEntry(StringRef("age"),
539/// Datum::createInteger(8));
540/// *lisaMap.size() = 3;
541/// @endcode
542/// Then, we construct the Datum that holds the map itself:
543/// @code
544/// Datum lisa = Datum::adoptMap(lisaMap);
545/// @endcode
546/// Note that after the `lisaMap` has been adopted, the `lisaMap` object can be
547/// destroyed without invalidating the map contained in the datum.
548///
549/// A `DatumMutableMapRef` may be adopted by only one datum. If the
550/// `DatumMutableMapRef` is not adopted, it must be destroyed via
551/// `disposeUninitializedMap`.
552///
553/// Now, we can access the contents of the map through the datum:
554/// @code
555/// assert(3 == lisa.theMap().size());
556/// assert("Lisa" == lisa.theMap().find("firstName")->theString());
557/// @endcode
558/// Finally, we destroy the datum, which releases all memory associated with the
559/// array:
560/// @code
561/// Datum::destroy(lisa, &oa);
562/// @endcode
563/// Note that the same allocator must be used to create the map, the elements,
564/// and to destroy the datum.
565///
566/// ### Example 5: Mass Destruction {#bdld_datum-example-5-mass-destruction}
567///
568///
569/// The following example illustrates an important idiom: the en masse
570/// destruction of a series of datums allocated in an arena.
571/// @code
572/// {
573/// // scope
574/// bsls::AlignedBuffer<200> bufferStorage;
575/// bdlma::BufferedSequentialAllocator arena(bufferStorage.buffer(), 200);
576///
577/// Datum patty = Datum::copyString("Patty Bouvier",
578/// strlen("Patty Bouvier"),
579/// &arena);
580///
581/// Datum selma = Datum::copyString("Selma Bouvier",
582/// strlen("Selma Bouvier"),
583/// &arena);
584/// DatumMutableArrayRef maggieArray;
585/// Datum::createUninitializedArray(&maggieArray, 2, &arena);
586/// maggieArray.data()[0] = Datum::createStringRef("Maggie", &arena);
587/// maggieArray.data()[1] = Datum::createStringRef("Simpson", &arena);
588/// *maggieArray.length() = 2;
589/// Datum maggie = Datum::adoptArray(maggieArray);
590/// // end of scope
591/// }
592/// @endcode
593/// Here all the allocated memory is lodged in the `arena` allocator. At the end
594/// of the scope the memory is freed in a single step. Calling `destroy` for
595/// each datum individually is neither necessary nor permitted.
596///
597/// ### Example 6: User-defined, error and binary types {#bdld_datum-example-6-user-defined-error-and-binary-types}
598///
599///
600/// Imagine we are using `Datum` within an expression evaluation subsystem.
601/// Within that subsystem, along with the set of types defined by
602/// `Datum::DataType` we also need to hold `Sequence` and `Choice` types within
603/// `Datum` values (which are not natively represented by `Datum`). First, we
604/// define the set of types used by our subsystem that are an extension to the
605/// types in `DatumType`:
606/// @code
607/// struct Sequence {
608/// struct Sequence *d_next_p;
609/// int d_value;
610/// };
611///
612/// enum ExtraExpressionTypes {
613/// e_SEQUENCE = 5,
614/// e_CHOICE = 6
615/// };
616/// @endcode
617/// Notice that the numeric values will be provided as the `type` attribute when
618/// constructing `Datum` object.
619///
620/// Then we create a `Sequence` object, and create a `Datum` to hold it (note
621/// that we've created the object on the stack for clarity):
622/// @code
623/// Sequence sequence;
624/// const Datum datumS0 = Datum::createUdt(&sequence, e_SEQUENCE);
625/// assert(true == datumS0.isUdt());
626/// @endcode
627/// Next, we verify that the `datumS0` refers to the external `Sequence` object:
628/// @code
629/// bdld::DatumUdt udt = datumS0.theUdt();
630/// assert(e_SEQUENCE == udt.type());
631/// assert(&sequence == udt.data());
632/// @endcode
633/// Then, we create a `Datum` to hold a `DatumError`, consisting of an error
634/// code and an error description message:
635/// @code
636/// enum { e_FATAL_ERROR = 100 };
637/// Datum datumError = Datum::createError(e_FATAL_ERROR, "Fatal error.", &oa);
638/// assert(true == datumError.isError());
639/// DatumError error = datumError.theError();
640/// assert(e_FATAL_ERROR == error.code());
641/// assert("Fatal error." == error.message());
642/// Datum::destroy(datumError, &oa);
643/// @endcode
644/// Finally, we create a `Datum` that holds arbitrary binary data. Notice that
645/// due to alignment requirements for `int` we need to use `memcpy` to access
646/// the data as it is not guarantee to be well-aligned for a @ref reinterpret_cast .
647/// @code
648/// int buffer[] = { 1, 2, 3 };
649/// Datum datumBlob = Datum::copyBinary(buffer, sizeof(buffer), &oa);
650/// buffer[2] = 666;
651/// assert(true == datumBlob.isBinary());
652/// DatumBinaryRef blob = datumBlob.theBinary();
653/// assert(blob.size() == 3 * sizeof(int));
654///
655/// const char *dataPtr = static_cast<const char *>(blob.data());
656/// const char *thirdElemPtr = dataPtr + sizeof(int) * 2;
657/// int thirdElem;
658/// memcpy(&thirdElem, thirdElemPtr, sizeof(int));
659///
660/// assert(thirdElem == 3);
661/// Datum::destroy(datumBlob, &oa);
662/// @endcode
663/// Note that the bytes have been copied.
664/// @}
665/** @} */
666/** @} */
667
668/** @addtogroup bdl
669 * @{
670 */
671/** @addtogroup bdld
672 * @{
673 */
674/** @addtogroup bdld_datum
675 * @{
676 */
677
678#include <bdlscm_version.h>
679
680#include <bdld_datumbinaryref.h>
681#include <bdld_datumerror.h>
682#include <bdld_datumudt.h>
683
684#include <bdlb_float.h> // 'isSignalingNan'
685#include <bdlb_printmethods.h>
686
687#include <bdldfp_decimal.fwd.h>
688#ifndef BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
689 #include <bdldfp_decimal.h>
690#endif
691
692#include <bdlt_date.h>
693#include <bdlt_datetime.h>
695#include <bdlt_epochutil.h>
696#include <bdlt_time.h>
697#include <bdlt_timeunitratio.h>
698
699#include <bslma_allocator.h>
700#include <bslma_allocatorutil.h>
701#include <bslma_bslallocator.h>
702
703#include <bslmf_assert.h>
708#include <bslmf_nil.h>
709
710#include <bsls_alignedbuffer.h>
711#include <bsls_annotation.h>
712#include <bsls_assert.h>
713#include <bsls_performancehint.h>
714#include <bsls_platform.h>
715#include <bsls_review.h>
716#include <bsls_types.h>
717
718#include <bsl_algorithm.h>
719#include <bsl_climits.h>
720#include <bsl_cstddef.h>
721#include <bsl_cstring.h>
722#include <bsl_iosfwd.h>
723#include <bsl_limits.h>
724#include <bsl_string.h>
725#include <bsl_utility.h>
726
727#if !defined(BSLS_PLATFORM_CPU_32_BIT) && !defined(BSLS_PLATFORM_CPU_64_BIT)
728 #error 'bdld::Datum' supports 32- or 64-bit platforms only.
730#endif
731
732#ifdef BSLS_PLATFORM_CMP_MSVC
733 #define BDLD_DATUM_FORCE_INLINE __forceinline
734#else
735 #define BDLD_DATUM_FORCE_INLINE inline
736#endif
737
738
739
740namespace bdld {
741
742class DatumArrayRef;
743class DatumIntMapEntry;
744class DatumIntMapRef;
745class DatumMapEntry;
746class DatumMapRef;
751
752/// Metafunction for use in templates to create a dependent `type` that is
753/// identical to the `t_WANT_TO_BE_DEPENDENT` type specified as first
754/// template argument using the `t_ALREADY_DEPENDENT` type of the user
755/// template (of this metafunction).
756///
757/// See @ref bdld_datum
758template <class t_WANT_TO_BE_DEPENDENT, class t_ALREADY_DEPENDENT>
760 typedef t_WANT_TO_BE_DEPENDENT type;
761};
762
763 // ===========
764 // class Datum
765 // ===========
766
767/// This class implements a mechanism that provides a space-efficient
768/// discriminated union that holds the value of ether scalar type or an
769/// aggregate of `Datum` objects. The size of `Datum` is 8 bytes (same as a
770/// `double`) on 32-bit platforms and 16 bytes on 64-bit platforms.
771/// Separate representation are needed on 32 and 64 bit platforms because of
772/// the differing size of a pointer (a 64-bit pointer cannot reasonably be
773/// held in a 32-bit footprint).
774///
775/// Representation on a 32-bit Platforms: Values are stored inside an 8-byte
776/// unsigned char array (`d_data`). Any `double` value (including NaN and
777/// infinity values) can be stored inside `Datum`. When storing a value of
778/// a type other than `double`, the bits in `d_data` that correspond to the
779/// exponent part of a `double` value are set to 1, with the 4 bits in the
780/// fraction part used to indicate the type of value stored.
781///
782/// Representation on 64-bit platforms: Values are stored inside a 16 byte
783/// unsigned char array (`d_data`) to store values. The type information is
784/// stored in the upper 2 bytes of the character array. Remaining 14 bytes
785/// are used to store the actual value or the pointer to the external memory
786/// that holds the value.
787///
788/// For details on the internal representations that are used for various
789/// types on 32 and 64 bit platforms, please see the implementation notes in
790/// `bdld_datum.cpp`.
791///
792/// Datum objects are bitwise copyable and have trivial initialization,
793/// assignment and destruction. Only one of the copies of the same `Datum`
794/// object can be passed to `destroy`. The rest of those copies then become
795/// invalid and it is undefined behavior to deep-copy or destroy them.
796/// Although, these copies can be used on the left hand side of assignment.
797///
798/// See @ref bdld_datum
799class Datum {
800
801 private:
802 // TYPES
804
805 public:
806 // TYPES
808
809 /// Enumeration used to discriminate among the different externally-
810 /// exposed types of values that can be stored inside `bdld::Datum`.
811 enum DataType {
812 e_NIL = 0 // null value
813 , e_INTEGER = 1 // integer value
814 , e_DOUBLE = 2 // double value
815 , e_STRING = 3 // string value
816 , e_BOOLEAN = 4 // boolean value
817 , e_ERROR = 5 // error value
818 , e_DATE = 6 // date value
819 , e_TIME = 7 // time value
820 , e_DATETIME = 8 // datetime value
821 , e_DATETIME_INTERVAL = 9 // datetime interval value
822 , e_INTEGER64 = 10 // 64-bit integer value
823 , e_USERDEFINED = 11 // pointer to a user-defined object
824 , e_ARRAY = 12 // array reference
825 , e_MAP = 13 // map reference
826 , e_BINARY = 14 // pointer to the binary data
827 , e_DECIMAL64 = 15 // Decimal64
828 , e_INT_MAP = 16 // integer map reference
829#ifndef BDE_OMIT_INTERNAL_DEPRECATED
830 , e_REAL = e_DOUBLE // old spelling
832#endif // BDE_OMIT_INTERNAL_DEPRECATED
833 };
834
835 // Define `k_NUM_TYPES` to be the number of consecutively valued
836 // enumerators in the range `[ e_NIL .. e_DECIMAL64 ]`.
837 enum {
838 k_NUM_TYPES = 17 // number of distinct enumerated types
839 };
840
841#ifdef BSLS_PLATFORM_CPU_32_BIT
842 private:
843 // PRIVATE TYPES
844 // 32-bit variation
845
846 /// Enumeration used to discriminate among the different types of values
847 /// that can be stored inside `bdld::Datum`.
848 enum InternalDataType {
849
850 e_INTERNAL_INF = 0 // +/- infinity value
851 , e_INTERNAL_LONGEST_SHORTSTRING = 1 // 6 character string
852 , e_INTERNAL_BOOLEAN = 2 // boolean value
853 , e_INTERNAL_SHORTSTRING = 3 // short string value
854 , e_INTERNAL_STRING = 4 // string value
855 , e_INTERNAL_DATE = 5 // date value
856 , e_INTERNAL_TIME = 6 // time value
857 , e_INTERNAL_DATETIME = 7 // date+time value
858 , e_INTERNAL_DATETIME_INTERVAL = 8 // date+time interval value
859 , e_INTERNAL_INTEGER = 9 // integer value
860 , e_INTERNAL_INTEGER64 = 10 // 64-bit integer value
861 , e_INTERNAL_USERDEFINED = 11 // pointer to a user-defined obj
862 , e_INTERNAL_ARRAY = 12 // array of datums
863 , e_INTERNAL_STRING_REFERENCE = 13 // unowned string
864 , e_INTERNAL_ARRAY_REFERENCE = 14 // unowned array of
865 , e_INTERNAL_EXTENDED = 15 // extended data types
866 , e_INTERNAL_DOUBLE = 16 // double value
867 };
868
869 /// Define `k_NUM_INTERNAL_TYPES` to be the number of consecutively
870 /// valued enumerators in the range
871 /// `[ e_INTERNAL_INF .. e_INTERNAL_DOUBLE ]`.
872 enum {
873
874 k_NUM_INTERNAL_TYPES = 17 // number of internal types
875 };
876
877 /// Enumeration used to discriminate among different types of values
878 /// that map on to the `e_INTERNAL_EXTENDED` discriminator value inside
879 /// `bdld::Datum`. It is used to add any new required types.
880 enum ExtendedInternalDataType {
881 e_EXTENDED_INTERNAL_MAP = 0 // map of datums keyed by string
882 // values that are not owned
883
884 , e_EXTENDED_INTERNAL_OWNED_MAP = 1 // map of datums keyed by string
885 // values that are owned
886
887 , e_EXTENDED_INTERNAL_NAN2 = 2 // NaN double value
888
889 , e_EXTENDED_INTERNAL_ERROR = 3 // error with code only
890
891 , e_EXTENDED_INTERNAL_ERROR_ALLOC = 4 // error with code and
892 // description string
893
894 // We never need to externally allocate the reference types with the
895 // 64-bit implementation because we can fit 32 bits of length inline.
896
897 , e_EXTENDED_INTERNAL_SREF_ALLOC = 5 // allocated string ref
898
899 , e_EXTENDED_INTERNAL_AREF_ALLOC = 6 // allocated array ref
900
901 , e_EXTENDED_INTERNAL_DATETIME_ALLOC = 7 // allocated datetime
902
903 , e_EXTENDED_INTERNAL_DATETIME_INTERVAL_ALLOC = 8 // allocated datetime
904 // interval
905
906 , e_EXTENDED_INTERNAL_INTEGER64_ALLOC = 9 // 64-bit integer value
907
908 , e_EXTENDED_INTERNAL_BINARY_ALLOC = 10 // binary data
909
910 , e_EXTENDED_INTERNAL_DECIMAL64 = 11 // Decimal64
911
912 , e_EXTENDED_INTERNAL_DECIMAL64_SPECIAL = 12 // Decimal64 NaN of Inf
913
914 , e_EXTENDED_INTERNAL_DECIMAL64_ALLOC = 13 // allocated Decimal64
915
916 , e_EXTENDED_INTERNAL_NIL = 14 // null value
917
918 , e_EXTENDED_INTERNAL_INT_MAP = 15 // map of datums keyed by
919 // 32-bit integer values
920 };
921
922 // Define `k_NUM_EXTENDED_INTERNAL_TYPES` to be the number of
923 // consecutively valued enumerators in the range
924 // `[ e_EXTENDED_INTERNAL_MAP .. e_EXTENDED_INTERNAL_INT_MAP ]`.
925 enum {
926 k_NUM_EXTENDED_INTERNAL_TYPES = 16 // number of distinct enumerated
927 // extended types
928 };
929
930 // PRIVATE CLASS DATA
931 // 32-bit variation
932 static const unsigned short k_DOUBLE_MASK = 0x7ff0U; // mask value to be
933 // stored in the
934 // exponent part of
935 // `d_data` to
936 // indicate a special
937 // `double` value
938
939 static const int k_SHORTSTRING_SIZE = 6; // maximum size of short strings
940 // stored in the internal storage
941 // buffer
942
943 static const int k_TYPE_MASK_BITS = 16; // number of bits the internal
944 // data type needs to be shifted
945 // into place
946
947 static const short k_DATETIME_OFFSET_FROM_EPOCH = 18262;
948 // Number of days offset from 1970 Jan 1 used to create the epoch used
949 // to determine if `Datum` stores a date-time value using dynamic
950 // memory allocation or withing the `Datum` itself. This offset, added
951 // to the 1970 Jan 1 date, creates an (mid) epoch of 2020 Jan 1.
952 // Given that `Datum` uses a signed 16 bits day-offset when storing
953 // date-time internally, the 2020 Jan 1 epoch enables of storing
954 // date-times internally the range of 1930 Apr 15 to 2109 Sept 18.
955 // Note that the time part of date-time can be stored internally
956 // without data loss, so that makes the no-allocation range to be
957 // 1930 Apr 15 00:00:00.000000 to 2109 Sept 18 24:00:00.000000. See
958 // `createDatetime` and `theDatetime` methods for the implementation.
959
960#ifdef BSLS_PLATFORM_IS_LITTLE_ENDIAN
961 // Check if platform is little endian.
962 static const int k_EXPONENT_OFFSET = 6; // offset of the exponent part in
963 // the internal storage buffer
964
965 static const int k_EXPONENT_LSB = k_EXPONENT_OFFSET; // Low Byte
966
967 static const int k_EXPONENT_MSB = k_EXPONENT_OFFSET + 1; // High Byte
968
969 static const int k_DATA_OFFSET = 0; // offset of the data part in the
970 // internal storage buffer
971
972 static const int k_SHORTSTRING_OFFSET = 0;// offset of short-strings stored
973 // in the internal storage buffer
974
975 static const int k_SHORT_OFFSET = 4; // offset of (2 byte values like)
976 // discriminator values for
977 // extended types and information
978 // for user-defined objects in
979 // the internal storage buffer
980
981 static const int k_MASK_OFFSET = 4; // offset of the special mask
982 // value in the internal storage
983 // buffer
984
985 static const int k_NEARDATE_OFFSET = 4; // offset of the short date
986 // offset from now value in the
987 // internal storage buffer
988
989 static const int k_TIME_OFFSET = 0; // offset of the time value in
990 // the internal storage buffer
991#else // end - little endian / begin - big endian
992 // Check if platform is big endian.
993 static const int k_EXPONENT_OFFSET = 0; // offset of the exponent part in
994 // the internal storage buffer
995
996 static const int k_EXPONENT_LSB = k_EXPONENT_OFFSET + 1; // Low Byte
997
998 static const int k_EXPONENT_MSB = k_EXPONENT_OFFSET; // High Byte
999
1000 static const int k_DATA_OFFSET = 4; // offset of the data part in the
1001 // internal storage buffer
1002
1003 static const int k_SHORTSTRING_OFFSET = 2;// offset of short-strings stored
1004 // in the internal storage buffer
1005
1006 static const int k_SHORT_OFFSET = 2; // offset of (2 byte values like)
1007 // discriminator values for
1008 // extended types and information
1009 // for user-defined objects in
1010 // the internal storage buffer
1011
1012 static const int k_MASK_OFFSET = 0; // offset of the special mask
1013 // value in the internal storage
1014 // buffer
1015
1016 static const int k_NEARDATE_OFFSET = 2; // offset of the short date
1017 // offset from now value in the
1018 // internal storage buffer
1019
1020 static const int k_TIME_OFFSET = 4; // offset of the time value in
1021 // the internal storage buffer
1022#endif // end - big endian
1023
1024 /// Enumeration used to discriminate between the special incompressible
1025 /// Decimal64 values.
1026 enum {
1027 e_DECIMAL64_SPECIAL_NAN,
1028 e_DECIMAL64_SPECIAL_INFINITY,
1029 e_DECIMAL64_SPECIAL_NEGATIVE_INFINITY
1030 };
1031
1032 // DATA
1033 // 32-bit variation
1034
1035 struct ShortString5 {
1036 // Storage for a string shorter than 6 chars and its length.
1037#ifdef BSLS_PLATFORM_IS_LITTLE_ENDIAN
1038 char d_chars[5]; // the string's characters
1039 char d_length; // the string's length
1040 unsigned short d_exponent; // the exponent inside the double
1041#else // end - little endian / begin - big endian
1042 unsigned short d_exponent; // the exponent inside the double
1043 char d_chars[5]; // the string's characters
1044 char d_length; // the string's length
1045#endif // end - big endian
1046 };
1047
1048 struct ShortString6 {
1049 // Storage for a string of exactly 6 chars. Length is implicit.
1050#ifdef BSLS_PLATFORM_IS_LITTLE_ENDIAN
1051 char d_chars[6]; // the string's characters
1052 unsigned short d_exponent; // the exponent inside the double
1053#else // end - little endian / begin - big endian
1054 unsigned short d_exponent; // the exponent inside the double
1055 char d_chars[6]; // the string's characters
1056#endif // end - big endian
1057 };
1058
1059 struct TypedAccess {
1060 // Storage for various combinations of short, int and pointer.
1061 // TYPE FIELDS
1062 // --------------- -------------------------------
1063 // Null d_short = extended type
1064 //
1065 // Boolean d_int = value
1066 //
1067 // Integer d_int = value
1068 //
1069 // String d_cvp = allocated memory containing copy
1070 // (length > 6) of string preceded by length
1071 //
1072 // StringRef d_ushort = length
1073 // (length < USHORT_MAX) d_cvp = pointer to the c-string
1074 //
1075 // StringRef d_short = extended type
1076 // (length >= USHORT_MAX) d_cvp = pointer to allocated memory
1077 // containing pointer to the c-string
1078 // preceded by c-string length
1079 //
1080 // Date d_int = value
1081 //
1082 // Time d_int = value
1083 //
1084 // Datetime d_short = days from now
1085 // (near offset) d_int = time part
1086 //
1087 // Datetime d_short = extended type
1088 // (far offset) d_cvp = pointer to allocated value
1089 //
1090 //
1091 // DatetimeInterval d_short = upper 16 bits
1092 // (short) d_int = lower 32
1093 //
1094 // DatetimeInterval d_short = extended type
1095 // (long) d_cvp = pointer to allocated value
1096 //
1097 // Error d_short = extended type
1098 // (code only) d_int = value
1099 //
1100 // Error d_short = extended type
1101 // (code + error string) d_cvp = pointer to allocated memory
1102 // containing: code, length, c-string
1103 //
1104 // Udt d_ushort = udt type
1105 // d_cvp = pointer to udt object
1106 //
1107 // ArrayReference d_ushort = length
1108 // (length < USHORT_MAX) d_cvp = pointer to array
1109 //
1110 // ArrayReference
1111 // (length >= USHORT_MAX) d_short = extended type
1112 // d_cvp = pointer to allocated memory
1113 // containing: pointer to array,
1114 // length
1115 //
1116 // Map d_short = extended type
1117 // d_cvp = pointer to allocated memory
1118 // containing: length, sorted flag,
1119 // array of map entries
1120 //
1121 // Int-map d_short = extended type
1122 // d_cvp = pointer to allocated memory
1123 // containing: length, sorted flag,
1124 // array of int-map entries
1125 //
1126 // Binary: d_short = extended type
1127 // d_cvp = pointer to allocated memory
1128 // containing: length, binary copy
1129
1130#ifdef BSLS_PLATFORM_IS_LITTLE_ENDIAN
1131 union {
1132 int d_int; // as integer value
1133 const void *d_cvp; // as const void* value
1134 };
1135 union {
1136 short d_short; // as signed short value
1137 unsigned short d_ushort; // as unsigned short value
1138 };
1139 unsigned short d_exponent; // the exponent inside the double
1140#else // end - little endian / begin - big endian
1141 unsigned short d_exponent; // the exponent inside the double
1142 union {
1143 short d_short; // as signed short value
1144 unsigned short d_ushort; // as unsigned short
1145 };
1146 union {
1147 int d_int; // as integer value
1148 const void *d_cvp; // as const void* value
1149 };
1150#endif // end - big endian
1151 };
1152
1153 struct ExponentAccess {
1154 // For accessing exponent as a word, for better performance.
1155#ifdef BSLS_PLATFORM_IS_LITTLE_ENDIAN
1156 unsigned int d_dummy;
1157 unsigned int d_value; // the exponent as a 32 bit word
1158#else // end - little endian / begin - big endian
1159 unsigned int d_value; // the exponent as a 32 bit word
1160 unsigned int d_dummy;
1161#endif // end - big endian
1162 };
1163
1164 // Internal Datum representation
1165 union {
1166 // Do not change the order of these member, otherwise the code will not
1167 // work properly with the clang compiler.
1168
1169 char d_data[8]; // as a byte array of internal storage
1170
1171 ShortString5 d_string5; // as a string shorter than 5 chars
1172
1173 ShortString6 d_string6; // as a string of exactly 6 chars
1174
1175 TypedAccess d_as; // as a combination of pointer, int and
1176 // short
1177
1178 ExponentAccess d_exp; // as the exponent as a 32 bit word
1179
1180 double d_double; // as a double value
1181 };
1182
1183 // PRIVATE CLASS METHODS
1184 // 32-bit variation
1185
1186 // Return a datum by copying the specified `data` of the specified
1187 // `type`. Note that the pointer value in `data` is copied and the
1188 // pointed object is not cloned.
1189 static Datum createExtendedDataObject(ExtendedInternalDataType type,
1190 void *data);
1191 static Datum createExtendedDataObject(ExtendedInternalDataType type,
1192 int data);
1193
1194 // PRIVATE ACCESSORS
1195 // 32-bit variation
1196
1197 /// Return the extended type of the value stored in this object (which
1198 /// cannot be represented by the 4-bit discriminator `InternalDataType`)
1199 /// as one of the enumeration values defined in
1200 /// `ExtendedInternalDataType`.
1201 ExtendedInternalDataType extendedInternalType() const;
1202
1203 /// Return the type of the value stored in this object as one of the
1204 /// enumeration values defined in `DataType` (mapped from the
1205 /// `ExtendedInternalDataType` value).
1206 DataType typeFromExtendedInternalType() const;
1207
1208 /// Return the 64-bit integer value stored in the allocated storage.
1209 bsls::Types::Int64 theLargeInteger64() const;
1210
1211 // Return the array referenced by this object. The behavior is
1212 // undefined unless this object references an array with `length >=
1213 // USHORT_MAX`.
1214 DatumArrayRef theLongArrayReference() const;
1215
1216 /// Return the string referenced by this object.
1217 ///
1218 /// \pre The behavior is undefined unless this object holds a reference to a string with
1219 /// `length >= USHORT_MAX`.
1220 bslstl::StringRef theLongStringReference() const;
1221
1222 /// Return the 64-bit integer value stored inline in this object.
1223 bsls::Types::Int64 theSmallInteger64() const;
1224
1225#else // end - 32 bit / begin - 64 bit
1226 private:
1227 // PRIVATE TYPES
1228
1229
1230 // Enumeration used to discriminate among the different types of values
1231 // that can be stored inside `bdld::Datum`.
1232 enum InternalDataType {
1233 e_INTERNAL_UNINITIALIZED = 0, // zero-filled Datums are invalid
1234
1235 e_INTERNAL_INF = 1, // +/- infinity value
1236
1237 e_INTERNAL_NIL = 2, // null value
1238
1239 e_INTERNAL_BOOLEAN = 3, // boolean value
1240
1241 e_INTERNAL_SHORTSTRING = 4, // short string value
1242
1243 e_INTERNAL_STRING = 5, // string value
1244
1245 e_INTERNAL_DATE = 6, // date value
1246
1247 e_INTERNAL_TIME = 7, // time value
1248
1249 e_INTERNAL_DATETIME = 8, // date+time value
1250
1251 e_INTERNAL_DATETIME_INTERVAL = 9, // date+time interval value
1252
1253 e_INTERNAL_INTEGER = 10, // integer value
1254
1255 e_INTERNAL_INTEGER64 = 11, // 64-bit integer value
1256
1257 e_INTERNAL_USERDEFINED = 12, // pointer to a user-defined object
1258
1259 e_INTERNAL_ARRAY = 13, // array of datums
1260
1261 e_INTERNAL_STRING_REFERENCE = 14, // not owned string
1262
1263 e_INTERNAL_ARRAY_REFERENCE = 15, // not owned array
1264
1265 e_INTERNAL_DOUBLE = 16, // double value
1266
1267 e_INTERNAL_MAP = 17, // map of datums keyed by string
1268 // values that are not owned
1269
1270 e_INTERNAL_OWNED_MAP = 18, // map of datums keyed by string
1271 // values that are owned
1272
1273 e_INTERNAL_ERROR = 19, // error code, internal storage
1274
1275 e_INTERNAL_ERROR_ALLOC = 20, // error code, allocated storage
1276
1277 e_INTERNAL_BINARY = 21, // binary data, internal storage
1278
1279 e_INTERNAL_BINARY_ALLOC = 22, // binary data, allocated storage
1280
1281 e_INTERNAL_DECIMAL64 = 23, // Decimal64
1282
1283 e_INTERNAL_INT_MAP = 24, // map of datums keyed by 32-bit
1284 // integer values
1285
1286 e_INTERNAL_LONGEST_SHORTSTRING = 25 // Short string of length 15 characters
1287 };
1288
1289 /// Define `k_NUM_INTERNAL_TYPES` to be the number of consecutively
1290 /// valued enumerators in the range
1291 /// `[ e_INTERNAL_UNINITIALIZED .. e_INTERNAL_DECIMAL64 ]`.
1292 enum {
1293 k_NUM_INTERNAL_TYPES = 25 // number of internal types
1294 };
1295
1296 // CLASS DATA
1297
1298 // 64-bit variation
1299 static const int k_SHORTSTRING_SIZE = 15; // maximum size of short
1300 // strings that stored in
1301 // the internal storage
1302 // buffer
1303
1304 static const int k_SMALLBINARY_SIZE_OFFSET = 15; // offset of the size of
1305 // small-size binaries
1306 // stored in the internal
1307 // storage buffer
1308
1309 static const int k_SMALLBINARY_SIZE = 14; // maximum size of
1310 // small-size binaries
1311 // stored in the internal
1312 // storage buffer
1313
1314 // DATA
1315
1316 // 64-bit variation
1317
1318 /// Typed access to the bits of the `Datum` internal representation
1319 ///
1320 /// See @ref bdld_datum
1321 struct TypedAccess {
1322 char d_type; // Offset: 0
1323 // 2 separate filler members are required for GCC-13 to generate
1324 // optimal code.
1325 char d_filler; // Offset: 1
1326 short d_filler2; // Offset: 2
1327 int d_int32; // Offset: 4
1328 union { // Offset: 8
1329 bsls::Types::Int64 d_int64;
1330 void *d_ptr;
1331 double d_double;
1332 };
1333 };
1334
1335 /// Ensures proper alignment (16 byte) and provides 2 types of access to
1336 /// the 64-bit `Datum` internal representation. The `d_data` array
1337 /// allows us raw access to the bytes; while `d_as` provides typed
1338 /// access to the individual "data compartments".
1339 union {
1341 TypedAccess d_as;
1342 };
1343
1344 // PRIVATE CLASS METHODS
1345
1346 // 64-bit variation
1347
1348 /// Create a `Datum` object of the specified `type` with the specified
1349 /// `data` value.
1350 static Datum createDatum(InternalDataType type, void *data);
1351
1352 /// Create a `Datum` object of the specified `type` with the specified
1353 /// `data` value.
1354 static Datum createDatum(InternalDataType type, int data);
1355
1356 // PRIVATE ACCESSORS
1357
1358 // 64-bit variation
1359
1360 /// Return a pointer to the internal storage buffer
1361 void* theInlineStorage();
1362
1363 /// Return a pointer to the part of the internal storage buffer that is
1364 /// 64-bit aligned.
1365 void* theAlignedInlineStorage();
1366
1367 /// Return a non-modifiable pointer to the internal storage buffer.
1368 const void* theInlineStorage() const;
1369
1370 /// Return a non-modifiable pointer to the part of the internal storage
1371 /// buffer that is 64-bit aligned.
1372 const void* theAlignedInlineStorage() const;
1373
1374#endif // end - 64 bit
1375
1376 private:
1377 // FRIENDS
1378 friend bool operator==(const Datum& lhs, const Datum& rhs);
1379 friend bool operator!=(const Datum& lhs, const Datum& rhs);
1380 friend bsl::ostream& operator<<(bsl::ostream& stream, const Datum& rhs);
1381
1382 // PRIVATE ACCESSORS
1383
1384 /// Using the specified `allocator` deallocate the specified `nBytes`
1385 /// allocated for the value of this object.
1386 ///
1387 /// \pre The behavior is undefined unless `0 == nBytes` when `0 == this->allocatedPtr<void>()`. The
1388 /// behavior is also undefined unless the non-null value of
1389 /// `this->allocatedPtr<void>()` has been obtained by
1390 /// `AllocUtil::allocateBytes` from `allocator`.
1391 void safeDeallocateBytes(const AllocatorType& allocator,
1392 bsl::size_t nBytes) const;
1393
1394 /// Using the specified `allocator` deallocate the specified `nBytes`
1395 /// allocated for the value of this object with the specified `alignment`.
1396 ///
1397 /// \pre The behavior is undefined unless `0 == nBytes` when
1398 /// `0 == this->allocatedPtr<void>()`. The behavior is also undefined
1399 /// unless the non-null value of `this->allocatedPtr<void>()` has been
1400 /// obtained by `AllocUtil::allocateBytes` from `allocator`.
1401 void safeDeallocateBytes(const AllocatorType& allocator,
1402 bsl::size_t nBytes,
1403 bsl::size_t alignment) const;
1404
1405 /// Return the pointer to the first byte of the memory allocated by this `Datum` object.
1406 ///
1407 /// \pre The behavior is undefined unless the internal type
1408 /// indicates the object *has* allocated.
1409 template <class t_TYPE>
1410 t_TYPE *allocatedPtr() const;
1411
1412 /// Return the internal type of value stored in this object as one of
1413 /// the enumeration values defined in `InternalDataType`.
1414 InternalDataType internalType() const;
1415
1416 /// Return the array reference represented by this object as `DatumArrayRef` object.
1417 ///
1418 /// \pre The behavior is undefined unless the object
1419 /// represents an array reference whose size is stored in the object internal storage buffer.
1420 ///
1421 /// \note Note that all array references store their
1422 /// size in the object internal storage buffer on 64-bit platforms.
1423 DatumArrayRef theArrayReference() const;
1424
1425 /// Return the array represented by this object as `DatumArrayRef` object.
1426 ///
1427 /// \pre The behavior is undefined unless the object represents an
1428 /// array of `Datum`s.
1429 DatumArrayRef theInternalArray() const;
1430
1431 /// Return the string value represented by this object as a `bslstl::StringRef` object.
1432 ///
1433 /// \pre The behavior is undefined unless the
1434 /// object represents an internal (non-reference, non-short) string.
1435 bslstl::StringRef theInternalString() const;
1436
1437 /// Return the short string value represented by this object as a `bslstl::StringRef` object.
1438 ///
1439 /// \pre The behavior is undefined unless the
1440 /// object actually represents a short string value.
1441 bslstl::StringRef theShortString() const;
1442
1443 /// Return the short string value stored in this object as a `bslstl::StringRef` object.
1444 ///
1445 /// \pre The behavior is undefined unless this
1446 /// object actually stores a short string value.
1447 bslstl::StringRef theLongestShortString() const;
1448
1449 /// Return the string reference represented by this object as a `bslstl::StringRef` object.
1450 ///
1451 /// \pre The behavior is undefined unless the
1452 /// object represents a string reference whose size is stored in the object internal storage buffer.
1453 ///
1454 /// \note Note that the size always stored in
1455 /// the object internal storage buffer on 64-bit platforms.
1456 bslstl::StringRef theStringReference() const;
1457
1458
1459 /// Return the number of bytes that have been directly allocated for
1460 /// this object (not for elements or entries). Used in deallocation.
1461 ///
1462 /// \pre The behavior is undefined unless the type of the object matches the
1463 /// allocated internal variant of the type in the function name.
1464 bsl::size_t theMapAllocNumBytes() const;
1465 bsl::size_t theIntMapAllocNumBytes() const;
1466 bsl::size_t theErrorAllocNumBytes() const;
1467 bsl::size_t theBinaryAllocNumBytes() const;
1468 bsl::size_t theInternalStringAllocNumBytes() const;
1469 bsl::size_t theInternalArrayAllocNumBytes() const;
1470
1471 public:
1472 // TYPES
1473
1474 /// `SizeType` is an alias for an unsigned integral value, representing
1475 /// the capacity of a datum array, the capacity of a datum map, the
1476 /// capacity of the *keys-capacity* of a datum-key-owning map or the
1477 /// length of a string.
1479
1480 // CLASS METHODS
1481
1482 /// Return, by value, a datum referring to the specified `array`,
1483 /// having the specified `length`, using the specified `allocator` to
1484 /// supply memory (if needed). `array` is not copied, and is not freed
1485 /// when the returned object is destroyed with `Datum::destroy`.
1486 ///
1487 /// \pre The behavior is undefined unless `array` contains at least `length`
1488 /// elements. The behavior is also undefined unless `length <=
1489 /// UINT_MAX`.
1490 static Datum createArrayReference(const Datum *array,
1491 SizeType length,
1492 const AllocatorType& allocator);
1493
1494 /// Return, by value, a datum having the specified `value`, using the
1495 /// specified `allocator` to supply memory (if needed). The array
1496 /// referenced by `value` is not copied, and is not freed if
1497 /// `Datum::destroy` is called on the returned object.
1498 ///
1499 /// \pre The behavior is undefined unless `value.length() <= UINT_MAX`.
1500 static Datum createArrayReference(const DatumArrayRef& value,
1501 const AllocatorType& allocator);
1502
1503 /// Return, by value, a datum having the specified `bool` `value`.
1504 static Datum createBoolean(bool value);
1505
1506 /// Return, by value, a datum having the specified `Date` `value`.
1507 static Datum createDate(const bdlt::Date& value);
1508
1509 /// Return, by value, a datum having the specified `Datetime` `value`,
1510 /// using the specified `allocator` to supply memory (if needed).
1511 static Datum createDatetime(const bdlt::Datetime& value,
1512 const AllocatorType& allocator);
1513
1514 /// Return, by value, a datum holding the specified `DatetimeInterval`
1515 /// `value`, using the specified `allocator` to supply memory (if
1516 /// needed).
1518 const bdlt::DatetimeInterval& value,
1519 const AllocatorType& allocator);
1520
1521 /// Return, by value, a datum having the specified `Decimal64` `value`,
1522 /// using the specified `allocator` to supply memory (if needed).
1523 ///
1524 /// \note Note that the argument is passed by value because it is assumed to be a
1525 /// fundamental type.
1527 const AllocatorType& allocator);
1528
1529 /// Return, by value, a datum having the specified `double` `value`.
1530 /// When `value` is NaN this method guarantees only that a NaN value is
1531 /// stored. The sign and NaN payload bits of a NaN `value` later
1532 /// retrieved by the `theDouble` method are unspecified (see also
1533 /// {Special Floating Point Values}.
1534 static Datum createDouble(double value);
1535
1536 /// Return, by value, a datum having a `DatumError` value with the
1537 /// specified `code`.
1538 static Datum createError(int code);
1539
1540 /// Return, by value, a datum having a `DatumError` value with the
1541 /// specified `code` and the specified `message`, using the specified
1542 /// `allocator` to supply memory (if needed).
1543 static Datum createError(int code,
1544 const bslstl::StringRef& message,
1545 const AllocatorType& allocator);
1546
1547 /// Return, by value, a datum having the specified `int` `value`.
1548 static Datum createInteger(int value);
1549
1550 /// Return, by value, a datum having the specified `Integer64` `value`,
1551 /// using the specified `allocator` to supply memory (if needed).
1553 const AllocatorType& allocator);
1554
1555 /// Return, by value, a datum having no value.
1556 static Datum createNull();
1557
1558 /// Return, by value, a datum that refers to the specified `string`
1559 /// having the specified `length`, using the specified `allocator` to supply memory (if needed).
1560 ///
1561 /// \pre The behavior is undefined unless
1562 /// `0 != string || 0 == length`. The behavior is also undefined unless `length <= UINT_MAX`.
1563 ///
1564 /// \note Note that `string` is not copied, and
1565 /// is not freed if `Datum::destroy` is called on the returned object.
1566 static Datum createStringRef(const char *string,
1567 SizeType length,
1568 const AllocatorType& allocator);
1569
1570 /// Return, by value, a datum that refers to the specified `string`,
1571 /// using the specified `allocator` to supply memory (if needed).
1572 ///
1573 /// \pre The behavior is undefined unless `string` points to a UTF-8 encoded
1574 /// c-string. The behavior is also undefined unless 'strlen(string) <= UINT_MAX'.
1575 ///
1576 /// \note Note that `string` is not copied, and is not freed if
1577 /// `Datum::destroy` is called on the returned object.
1578 static Datum createStringRef(const char *string,
1579 const AllocatorType& allocator);
1580
1581 /// Return, by value, a datum having the specified `StringRef` `value`,
1582 /// using the specified `allocator` to supply memory (if needed).
1583 ///
1584 /// \pre The behavior is undefined unless `value.length() <= UINT_MAX`.
1585 ///
1586 /// \note Note that `string` is not copied, and is not freed if `Datum::destroy` is
1587 /// called on the returned object.
1588 static Datum createStringRef(const bslstl::StringRef& value,
1589 const AllocatorType& allocator);
1590
1591 /// Return, by value, a datum having the specified `Time` `value`.
1592 static Datum createTime(const bdlt::Time& value);
1593
1594 /// Return, by value, a datum having the `DatumUdt` value with the
1595 /// specified `data` and the specified `type` values.
1596 ///
1597 /// \pre The behavior is undefined unless `0 <= type <= 65535`.
1598 /// \note Note that `data` is held,
1599 /// not owned. Also note that the content pointed to by `data` object
1600 /// is not copied.
1601 static Datum createUdt(void *data, int type);
1602
1603 /// Return, by value, a datum referring to the copy of the specified
1604 /// `value` of the specified `size`, using the specified
1605 /// `allocator` to supply memory (if needed).
1606 ///
1607 /// \pre The behavior is undefined unless `size <= UINT_MAX`.
1608 /// \note Note that the copy of the binary data is
1609 /// owned and will be freed if `Datum::destroy` is called on the
1610 /// returned object.
1611 static Datum copyBinary(const void *value,
1612 SizeType size,
1613 const AllocatorType& allocator);
1614
1615 /// Return, by value, a datum that refers to the copy of the specified
1616 /// `string` having the specified `length`, using the specified
1617 /// `allocator` to supply memory (if needed).
1618 ///
1619 /// \pre The behavior is undefined unless `0 != string || 0 == length`. The behavior is also undefined unless `length <= UINT_MAX`.
1620 ///
1621 /// \note Note that the copied string is owned
1622 /// and will be freed if `Datum::destroy` is called on the returned
1623 /// object.
1624 static Datum copyString(const char *string,
1625 SizeType length,
1626 const AllocatorType& allocator);
1627
1628 /// Return, by value, a datum having the copy of the specified
1629 /// `StringRef` `value`, using the specified `allocator` to supply memory (if needed).
1630 ///
1631 /// \pre The behavior is undefined unless `value.length() <= UINT_MAX`.
1632 ///
1633 /// \note Note that the copied string is owned,
1634 /// and will be freed if `Datum::destroy` is called on the returned
1635 /// object.
1636 static Datum copyString(const bslstl::StringRef& value,
1637 const AllocatorType& allocator);
1638
1639 /// Return, by value, a datum that refers to the specified `array`.
1640 ///
1641 /// \pre The behavior is undefined unless `array` was created using
1642 /// `createUninitializedArray` method. The behavior is also undefined
1643 /// unless each element in the held datum array has been assigned a
1644 /// value and the array's length has been set accordingly.
1645 ///
1646 /// \note Note that the adopted array is owned and will be freed if `Datum::destroy` is
1647 /// called on the returned object.
1648 static Datum adoptArray(const DatumMutableArrayRef& array);
1649
1650 /// Return, by value, a datum that refers to the specified `intMap`.
1651 ///
1652 /// \pre The behavior is undefined unless `map` was created using
1653 /// `createUninitializedIntMap` method. The behavior is also undefined
1654 /// unless each element in the held map has been assigned a value and the size of the map has been set accordingly.
1655 ///
1656 /// \note Note that the adopted
1657 /// map is owned and will be freed if `Datum::destroy` is called on the
1658 /// returned object.
1659 static Datum adoptIntMap(const DatumMutableIntMapRef& intMap);
1660
1661 /// Return, by value, a datum that refers to the specified `map`.
1662 ///
1663 /// \pre The behavior is undefined unless `map` was created using
1664 /// `createUninitializedMap` method. The behavior is also undefined
1665 /// unless each element in the held map has been assigned a value and the size of the map has been set accordingly.
1666 ///
1667 /// \note Note that the adopted
1668 /// map is owned and will be freed if `Datum::destroy` is called on the
1669 /// returned object.
1670 static Datum adoptMap(const DatumMutableMapRef& map);
1671
1672 /// Return, by value, a datum that refers to the specified `map`.
1673 ///
1674 /// \pre The behavior is undefined unless `map` was created using
1675 /// `createUninitializedMapOwningKeys` method. The behavior is also
1676 /// undefined unless each element in the held map has been assigned a
1677 /// value and the size of the map has been set accordingly. The
1678 /// behavior is also undefined unless keys have been copied into the map.
1679 ///
1680 /// \note Note that the adopted map is owned and will be freed if
1681 /// `Datum::destroy` is called on the returned object.
1682 static Datum adoptMap(const DatumMutableMapOwningKeysRef& map);
1683
1684 /// Load the specified `result` with a reference to a newly created
1685 /// datum array having the specified `capacity`, using the specified `allocator` to supply memory.
1686 ///
1687 /// \pre The behavior is undefined if
1688 /// `capacity` `Datum` objects would exceed the addressable memory for the platform.
1689 ///
1690 /// \note Note that the caller is responsible for filling in
1691 /// elements into the datum array and setting its length accordingly.
1692 /// The number of elements in the datum array cannot exceed `capacity`.
1693 /// Also note that any elements in the datum array that need dynamic
1694 /// memory must be allocated with `allocator`.
1696 SizeType capacity,
1697 const AllocatorType& allocator);
1698
1699 /// Load the specified `result` with a reference to a newly created
1700 /// datum int-map having the specified `capacity`, using the specified `allocator` to supply memory.
1701 ///
1702 /// \pre The behavior is undefined if
1703 /// `capacity` `DatumIntMapEntry` objects would exceed the addressable memory for the platform.
1704 ///
1705 /// \note Note that the caller is responsible for
1706 /// filling in elements into the datum int-map and setting its size
1707 /// accordingly. The number of elements in the datum int-map cannot
1708 /// exceed `capacity`. Also note that any elements in the datum int-map
1709 /// that need dynamic memory, should also be allocated with `allocator`.
1711 DatumMutableIntMapRef *result,
1712 SizeType capacity,
1713 const AllocatorType& allocator);
1714
1715 /// Load the specified `result` with a reference to a newly created
1716 /// datum map having the specified `capacity`, using the specified `allocator` to supply memory.
1717 ///
1718 /// \pre The behavior is undefined if
1719 /// `capacity` `DatumMapEntry` objects would exceed the addressable memory for the platform.
1720 ///
1721 /// \note Note that the caller is responsible for
1722 /// filling in elements into the datum map and setting its size
1723 /// accordingly. The number of elements in the datum map cannot exceed
1724 /// `capacity`. Also note that any elements in the datum map that need
1725 /// dynamic memory, should also be allocated with `allocator`.
1727 SizeType capacity,
1728 const AllocatorType& allocator);
1729
1730 /// Load the specified `result` with a reference to a newly created
1731 /// datum-key-owning map having the specified `capacity` and
1732 /// `keysCapacity`, using the specified `allocator` to supply memory.
1733 ///
1734 /// \pre The behavior is undefined if `capacity` `DatumMapEntry` object plus
1735 /// `keysCapacity` would exceed the addressable memory for the platform.
1736 ///
1737 /// \note Note that the caller is responsible for filling in elements into the
1738 /// datum-key-owning map, copying the keys into it, and setting its size
1739 /// accordingly. The number of elements in the datum-key-owning map
1740 /// cannot exceed `capacity` and total size of all the keys cannot
1741 /// exceed `keysCapacity`. Also note that any elements in the
1742 /// datum-key-owning map that need dynamic memory, should also be
1743 /// allocated with `allocator`.
1746 SizeType capacity,
1747 SizeType keysCapacity,
1748 const AllocatorType& allocator);
1749
1750 /// Load the specified `result` with a reference to a newly created
1751 /// character buffer of the specified `length`, using the specified
1752 /// `allocator` to supply memory, and return the address of this buffer.
1753 ///
1754 /// \pre The behavior is undefined unless `length <= UINT_MAX`.
1755 /// \note Note that the
1756 /// caller is responsible for initializing the returned buffer with a
1757 /// UTF-8 encoded string.
1758 static char *createUninitializedString(Datum *result,
1759 SizeType length,
1760 const AllocatorType& allocator);
1761
1762 /// Load the specified `result` with a reference to a newly created binary
1763 /// buffer of the specified `size`, using the specified `allocator` to
1764 /// supply memory, and return the address of this buffer.
1765 ///
1766 /// \pre The behavior is undefined unless `size <= UINT_MAX`.
1767 /// \note Note that the caller is
1768 /// responsible for initializing the returned buffer with binary data.
1769 static void *createUninitializedBinary(Datum *result,
1770 SizeType size,
1771 const AllocatorType& allocator);
1772
1773 /// Return the non-modifiable string representation corresponding to the
1774 /// specified `type`, if it exists, and a unique (error) string
1775 /// otherwise. The string representation of `type` matches its
1776 /// corresponding enumerator name with the `e_` prefix elided.
1777 ///
1778 /// For example:
1779 /// @code
1780 /// bsl::cout << bdld::Datum::dataTypeToAscii(bdld::Datum::e_NIL);
1781 /// @endcode
1782 /// will print the following on standard output:
1783 /// @code
1784 /// NIL
1785 /// @endcode
1786 ///
1787 /// \note Note that specifying a `type` that does not match any of the
1788 /// enumerators will result in a string representation that is distinct
1789 /// from any of those corresponding to the enumerators, but is otherwise
1790 /// unspecified.
1791 static const char *dataTypeToAscii(DataType type);
1792
1793 /// Deallocate any memory that was previously allocated within the
1794 /// specified `value` using the specified `allocator`. If the `value`
1795 /// contains an adopted array of datums, `destroy` is called on each
1796 /// array element. If the `value` contains an adopted map of datums,
1797 /// `destroy` is called on each map element.
1798 ///
1799 /// \pre The behavior is undefined unless all dynamically allocated memory owned by `value` was
1800 /// allocated using `allocator`, and has not previously been released by
1801 /// a call to `destroy`, either on this object, or on another object
1802 /// referring to same contents as this object (i.e., only one copy of a
1803 /// `Datum` object can be destroyed). The behavior is also undefined if
1804 /// `value` has an uninitialized or partially initialized array or map
1805 /// (created using `createUninitializedArray`, `createUninitializedMap` or `createUninitializeMapOwningKeys`).
1806 ///
1807 /// \note Note that after this
1808 /// operation completes, `value` is left in an uninitialized state, and
1809 /// must be assigned a new value before being accessed again.
1810 static void destroy(const Datum& value, const AllocatorType& allocator);
1811
1812 /// Deallocate the memory used by the specified `array` (but *not*
1813 /// memory allocated for its contained elements) using the specified
1814 /// `allocator`. This method does not destroy individual array elements
1815 /// and the memory allocated for those elements must be explicitly
1816 /// deallocated before calling this method.
1817 ///
1818 /// \pre The behavior is undefined unless `array` was created with `createUninitializedArray` using
1819 /// `allocator`.
1820 static void disposeUninitializedArray(
1821 const DatumMutableArrayRef& array,
1822 const AllocatorType& allocator);
1823
1824 /// Deallocate the memory used by the specified `intMap` (but *not*
1825 /// memory allocated for its contained elements) using the specified
1826 /// `allocator`. This method does not destroy individual map elements
1827 /// and the memory allocated for those elements must be explicitly
1828 /// deallocated before calling this method.
1829 ///
1830 /// \pre The behavior is undefined unless `map` was created with `createUninitializedIntMap` using
1831 /// `allocator`.
1832 static void disposeUninitializedIntMap(
1833 const DatumMutableIntMapRef& intMap,
1834 const AllocatorType& allocator);
1835
1836 /// Deallocate the memory used by the specified `map` (but *not* memory
1837 /// allocated for its contained elements) using the specified
1838 /// `allocator`. This method does not destroy individual map elements
1839 /// and the memory allocated for those elements must be explicitly
1840 /// deallocated before calling this method.
1841 ///
1842 /// \pre The behavior is undefined unless `map` was created with `createUninitializedMap` using
1843 /// `allocator`.
1844 static void disposeUninitializedMap(const DatumMutableMapRef& map,
1845 const AllocatorType& allocator);
1846 static void disposeUninitializedMap(
1848 const AllocatorType& allocator);
1849
1850 // TRAITS
1856
1857 // CREATORS
1858
1859 /// Create a datum having an uninitialized value. The behavior for
1860 /// every accessor method is undefined until this object is assigned a
1861 /// value.
1862 Datum() = default;
1863
1864 /// Create a datum having the value of the specified `original`.
1865 Datum(const Datum& original) = default;
1866
1867 /// Destroy this object.
1868 /// \note Note that this method does not deallocate any
1869 /// dynamically allocated memory used by this object (see `destroy`).
1870 ~Datum() = default;
1871
1872 // MANIPULATORS
1873
1874 // Assign to this object the value of the specified `rhs` object. Note
1875 // that this method's definition is compiler generated.
1876 Datum& operator=(const Datum& rhs) = default;
1877
1878 // ACCESSORS
1879
1880 /// Apply the specified `visitor` to the current value represented by
1881 /// this object by passing held value to the `visitor` object's
1882 /// `operator()` overload.
1883 template <class t_VISITOR>
1884 void apply(t_VISITOR& visitor) const;
1885
1886 /// Return a datum holding a "deep-copy" of this object, using the
1887 /// specified `allocator` to supply memory. This method creates an
1888 /// independent deep-copy of the data of this object, including any
1889 /// referenced data, with the exception of {User Defined Types}. For
1890 /// further information see {Deep Copying}.
1891 Datum clone(const AllocatorType& allocator) const;
1892
1893 // Type-Identifiers
1894
1895 /// Return `true` if this object represents an array of `Datum`s and
1896 /// `false` otherwise.
1897 bool isArray() const;
1898
1899 /// Return `true` if this object represents a binary value and `false`
1900 /// otherwise.
1901 bool isBinary() const;
1902
1903 /// Return `true` if this object represents a boolean value and `false`
1904 /// otherwise.
1905 bool isBoolean() const;
1906
1907 /// Return `true` if this object represents a `bdlt::Date` value and
1908 /// `false` otherwise.
1909 bool isDate() const;
1910
1911 /// Return `true` if this object represents a `bdlt::Datetime` value and
1912 /// `false` otherwise.
1913 bool isDatetime() const;
1914
1915 /// Return `true` if this object represents a `bdlt::DatetimeInterval`
1916 /// value and `false` otherwise.
1917 bool isDatetimeInterval() const;
1918
1919 /// Return `true` if this object represents a `bdlfpd::Decimal64` value
1920 /// and `false` otherwise.
1921 bool isDecimal64() const;
1922
1923 /// Return `true` if this object represents a `double` value and `false`
1924 /// otherwise.
1925 bool isDouble() const;
1926
1927 /// Return `true` if this object represents a `DatumError` value and
1928 /// `false` otherwise.
1929 bool isError() const;
1930
1931 /// Return `true` if this object represents a reference to an externally
1932 /// managed array, string or user-defined object and `false` otherwise.
1933 /// If this method returns `false`, calling `destroy` on this object
1934 /// will release the memory used by the array, string, or used-defined
1935 /// object as well as any meta-data directly used by this datum (e.g.,
1936 /// length information); otherwise (if this method returns `true`)
1937 /// calling `destroy` on this object will release any allocated
1938 /// meta-data, but will not impact the externally managed array, string,
1939 /// or user-defined object.
1940 bool isExternalReference() const;
1941
1942 /// Return `true` if this object represents an integer value and `false`
1943 /// otherwise.
1944 bool isInteger() const;
1945
1946 /// Return `true` if this object represents a `Int64` value and `false`
1947 /// otherwise.
1948 bool isInteger64() const;
1949
1950 /// Return `true` if this object represents a map of datums that are
1951 /// keyed by 32-bit int values and `false` otherwise.
1952 bool isIntMap() const;
1953
1954 /// Return `true` if this object represents a map of datums that are
1955 /// keyed by string values and `false` otherwise.
1956 bool isMap() const;
1957
1958 /// Return `true` if this object represents no value and `false`
1959 /// otherwise.
1960 bool isNull() const;
1961
1962 /// Return `true` if this object represents a string value and `false`
1963 /// otherwise.
1964 bool isString() const;
1965
1966 /// Return `true` if this object represents a `bdlt::Time` value and
1967 /// `false` otherwise.
1968 bool isTime() const;
1969
1970 /// Return `true` if this object represents a `DatumUdt` value and
1971 /// `false` otherwise.
1972 bool isUdt() const;
1973
1974 // Type-Accessors
1975
1976 /// Return the array value represented by this object as a `DatumArrayRef` object.
1977 ///
1978 /// \pre The behavior is undefined unless this
1979 /// object actually represents an array of datums.
1980 DatumArrayRef theArray() const;
1981
1982 /// Return the binary reference represented by this object as a `DatumBinaryRef` object.
1983 ///
1984 /// \pre The behavior is undefined unless this
1985 /// object actually represents a binary reference.
1986 DatumBinaryRef theBinary() const;
1987
1988 /// Return the boolean value represented by this object.
1989 ///
1990 /// \pre The behavior is undefined unless this object actually represents a `bool` value.
1991 bool theBoolean() const;
1992
1993 /// Return the date value represented by this object as a `bdlt::Date` object.
1994 ///
1995 /// \pre The behavior is undefined unless this object actually
1996 /// represents a date value.
1997 bdlt::Date theDate() const;
1998
1999 /// Return the date+time value represented by this object as a `bdlt::Datetime` object.
2000 ///
2001 /// \pre The behavior is undefined unless this
2002 /// object actually represents date+time value.
2004
2005 /// Return the date+time interval value represented by this object as a `bdlt::DatetimeInterval`.
2006 ///
2007 /// \pre The behavior is undefined unless this
2008 /// object actually represents a date+time interval value.
2010
2011 /// Return the decimal floating point value represented by this object as a `bdlfpd::Decimal64` value.
2012 ///
2013 /// \pre The behavior is undefined unless
2014 /// this object actually represents a decimal floating point value.
2016
2017 /// Return the double value represented by this object.
2018 ///
2019 /// \pre The behavior is undefined unless this object actually represents a double value.
2020 /// If the returned value is NaN this method guarantees only that a NaN
2021 /// value will be returned. The sign and NaN payload bits of NaN values
2022 /// returned are unspecified (see also {Special Floating Point Values}.
2023 double theDouble() const;
2024
2025 /// Return the error value represented by this object as a `DatumError` value.
2026 ///
2027 /// \pre The behavior is undefined unless this object actually
2028 /// represents an error value.
2029 DatumError theError() const;
2030
2031 /// Return the integer value represented by this object.
2032 ///
2033 /// \pre The behavior is undefined unless this object actually represents an integer
2034 /// value.
2035 int theInteger() const;
2036
2037 /// Return the 64-bit integer value represented by this object as a `Int64` value.
2038 ///
2039 /// \pre The behavior is undefined unless this object
2040 /// actually represents a 64-bit integer value.
2042
2043 /// Return the int-map value represented by this object as a `DatumIntMapRef` object.
2044 ///
2045 /// \pre The behavior is undefined unless this
2046 /// object actually represents an int-map of datums.
2047 DatumIntMapRef theIntMap() const;
2048
2049 /// Return the map value represented by this object as a `DatumMapRef` object.
2050 ///
2051 /// \pre The behavior is undefined unless this object actually
2052 /// represents a map of datums.
2053 DatumMapRef theMap() const;
2054
2055 /// Return the string value represented by this object as a `bslstl::StringRef` object.
2056 ///
2057 /// \pre The behavior is undefined unless this
2058 /// object actually represents a string value.
2060
2061 /// Return the time value represented by this object as a `bdlt::Time` object.
2062 ///
2063 /// \pre The behavior is undefined unless this object actually
2064 /// represents a time value.
2065 bdlt::Time theTime() const;
2066
2067 /// Return the user-defined object represented by this object as a `DatumUdt` object.
2068 ///
2069 /// \pre The behavior is undefined unless this object
2070 /// actually represents a user-defined object.
2071 DatumUdt theUdt() const;
2072
2073 /// Return the type of value represented by this object as one of the
2074 /// enumeration values defined in `DataType`.
2075 DataType type() const;
2076
2077 /// Write the value of this object to the specified output `stream` in a
2078 /// human-readable format, and return a reference to the modifiable
2079 /// `stream`. Optionally specify an initial indentation `level`, whose
2080 /// absolute value is incremented recursively for nested objects. If
2081 /// `level` is specified, optionally specify `spacesPerLevel`, whose
2082 /// absolute value indicates the number of spaces per indentation level
2083 /// for this and all of its nested objects. If `level` is negative,
2084 /// suppress indentation of the first line. If `spacesPerLevel` is
2085 /// negative, format the entire output on one line, suppressing all but
2086 /// the initial indentation (as governed by `level`). If `stream` is not valid on entry, this operation has no effect.
2087 ///
2088 /// \note Note that this
2089 /// human-readable format is not fully specified, and can change without
2090 /// notice.
2091 bsl::ostream& print(bsl::ostream& stream,
2092 int level = 0,
2093 int spacesPerLevel = 4) const;
2094
2095#ifndef BDE_OMIT_INTERNAL_DEPRECATED
2096 // DEPRECATED
2097
2098 /// @deprecated Use @ref createUninitializedMap instead.
2101 SizeType capacity,
2102 SizeType keysCapacity,
2103 const AllocatorType& allocator);
2104
2105 /// @deprecated Use @ref adoptMap instead.
2107 const DatumMutableMapOwningKeysRef& mapping);
2108
2109 /// @deprecated Use @ref disposeUninitializedMap instead.
2111 const DatumMutableMapOwningKeysRef& mapping,
2112 const AllocatorType& allocator);
2113#endif // end - do not omit deprecated symbols
2114};
2115
2116// FREE OPERATORS
2117
2118/// Return `true` if the specified `lhs` and `rhs` represent the same value,
2119/// and `false` otherwise. Two datums (not holding strings and user-
2120/// defined objects) represent the same value if they have the same type of
2121/// value stored inside them and invoking `==` operator on the stored values
2122/// returns `true`. Two datums holding strings are equal if the strings
2123/// have the same length and and values at each respective character
2124/// position are also same. Two datums holding user-defined objects are
2125/// equal if the user-defined objects have the same pointer and type values.
2126/// Two `nil` datums are always equal. Two `Datum` objects holding `NaN`
2127/// values are never equal. Two datums that hold arrays of datums have the
2128/// same value if the underlying arrays have the same length and invoking
2129/// `==` operator on each corresponding element returns `true`. Two datums
2130/// that hold maps of datums have the same value if the underlying maps have
2131/// the same size and each corresponding pair of elements in the maps have
2132/// the same keys and invoking `==` operator on the values returns `true`.
2133bool operator==(const Datum& lhs, const Datum& rhs);
2134
2135/// Return `true` if the specified `lhs` and `rhs` datums do not represent
2136/// the same value, and `false` otherwise. Two datums do not represent the
2137/// same value if they do not hold values of the same type, or they hold
2138/// values of the same type but invoking `==` operator on the stored values
2139/// returns `false`. Two strings do not have the same value if they have
2140/// different lengths or values at one of the respective character position
2141/// are not the same. Two `DatumUdt` objects are not equal if they have
2142/// different pointer or type values. Two `bslmf::Nil` values are always
2143/// equal. Two datums with `NaN` values are never equal. Two datums that
2144/// hold arrays of datums have different values if the underlying arrays
2145/// have different lengths or invoking `==` operator on at least one of the
2146/// corresponding pair of contained elements returns `false`. Two datums
2147/// that hold maps of datums have different values if the underlying maps
2148/// have different sizes or at least one of the corresponding pair of
2149/// elements in the maps have different keys or invoking `==` operator on
2150/// the values returns `false`.
2151bool operator!=(const Datum& lhs, const Datum& rhs);
2152
2153/// Write the specified `rhs` value to the specified output `stream` in the
2154/// format shown in the second column in the table below (based on the type
2155/// of value stored, indicated by the first column):
2156/// @code
2157/// null - nil
2158///
2159/// bool - true/false
2160///
2161/// DatumError - error(code)/error(code, `msg`)
2162/// where `code` is the integer error code and
2163/// `msg` is the error description message
2164///
2165/// int - plain integer value
2166///
2167/// Int64 - plain Int64 value
2168///
2169/// double - plain double value
2170///
2171/// string - plain double-quoted string value
2172///
2173/// array - [ elem0, ..., elemN]
2174/// where elem1..elemN are output for individual
2175/// array elements
2176///
2177/// int-map - [key0 = val0, ..., keyN = valN]
2178/// where keyX and valX are respectively key and
2179/// value of the map entry elements of the map
2180///
2181/// map - [key0 = val0, ..., keyN = valN]
2182/// where keyX and valX are respectively key and
2183/// value of the map entry elements of the map
2184///
2185/// bdlt::Date - ddMONyyyy
2186///
2187/// bdlt::Time - hh:mm:ss.sss
2188///
2189/// bdlt::Datetime - ddMONyyyy_hh:mm:ss.sss
2190///
2191/// bdlt::DatetimeInterval - sDD_HH:MM:SS.SSS (where s is the sign(+/-))
2192///
2193/// DatumUdt - user-defined(address,type)
2194/// where `address` is a hex encoded pointer to
2195/// the user-defined object and `type` is its type
2196/// @endcode
2197/// and return a reference to the modifiable `stream`. The function will
2198/// have no effect if the specified `stream` is not valid.
2199bsl::ostream& operator<<(bsl::ostream& stream, const Datum& rhs);
2200
2201/// Invoke the specified `hashAlgorithm` on the value of the specified `datum` object.
2202///
2203/// \note Note that the value of a User Defined Type in Datum is
2204/// a combination of its type integer and the address (pointer value), not
2205/// the actual value of the object that the pointer points to.
2206template <class t_HASH_ALGORITHM>
2207void hashAppend(t_HASH_ALGORITHM& hashAlgorithm, const Datum& datum);
2208
2209/// Write the string representation of the specified enumeration `rhs` to
2210/// the specified `stream` in a single-line format, and return a reference
2211/// to the modifiable `stream`. See `dataTypeToAscii` for what constitutes
2212/// the string representation of a `Datum::DataType` value.
2213bsl::ostream& operator<<(bsl::ostream& stream, Datum::DataType rhs);
2214
2215 // ==========================
2216 // class DatumMutableArrayRef
2217 // ==========================
2218
2219/// This `class` provides mutable access to a datum array. The users of
2220/// this class can read from and assign to the individual elements as well
2221/// as change the length of the array.
2222///
2223/// See @ref bdld_datum
2225
2226 public:
2227 // TYPES
2228
2229 /// `SizeType` is an alias for an unsigned integral value, representing
2230 /// the capacity of a datum array.
2232
2233 private:
2234 // DATA
2235 Datum *d_data_p; // pointer to an array (not owned)
2236 SizeType *d_length_p; // pointer to the length of the array
2237 SizeType d_capacity; // array capacity (to dispose of uninitialized
2238 // arrays)
2239 public:
2240 // CREATORS
2241
2242 /// Create a `DatumMutableArrayRef` object that refers to no array.
2244
2245 /// Create a `DatumMutableArrayRef` object having the specified `data`,
2246 /// `length`, and `capacity`.
2248
2249 /// Create a `DatumMutableArrayRef` having the value of the specified `original` object.
2250 ///
2251 /// \note Note that this method's definition is compiler
2252 /// generated.
2253 DatumMutableArrayRef(const DatumMutableArrayRef& original) = default;
2254
2255 /// Destroy this object.
2256 /// \note Note that this method's definition is compiler
2257 /// generated.
2259
2260 // MANIPULATORS
2261
2262 /// Assign to this object the value of the specified `rhs` object.
2263 ///
2264 /// \note Note that this method's definition is compiler generated.
2266 const DatumMutableArrayRef& rhs) = default;
2267
2268 // ACCESSORS
2269
2270 /// Return pointer to the memory allocated for the array.
2271 void *allocatedPtr() const;
2272
2273 /// Return pointer to the first element of the held array.
2274 Datum *data() const;
2275
2276 /// Return pointer to the length of the array.
2277 SizeType *length() const;
2278
2279 /// Return the allocated capacity of the array.
2280 SizeType capacity() const;
2281};
2282
2283 // =========================
2284 // struct Datum_IntMapHeader
2285 // =========================
2286
2287/// This component-local class provides a layout of the meta-information
2288/// stored in front of the Datum int-maps.
2289///
2290/// See @ref bdld_datum
2292
2293 // DATA
2294 Datum::SizeType d_size; // size of the map
2295 Datum::SizeType d_capacity; // number of allocated map entries
2296 bool d_sorted; // sorted flag
2297};
2298
2299 // ======================
2300 // struct Datum_MapHeader
2301 // ======================
2302
2303/// This component-local class provides a layout of the meta-information
2304/// stored in front of the Datum maps.
2305///
2306/// See @ref bdld_datum
2308
2309 // DATA
2310 Datum::SizeType d_size; // size of the map
2311 Datum::SizeType d_capacity; // number of allocated map entries
2312 Datum::SizeType d_allocatedSize; // full allocated memory size in bytes
2313 bool d_sorted; // sorted flag
2314 bool d_ownsKeys; // owns keys flag
2315};
2316
2317 // ========================
2318 // class DatumMutableMapRef
2319 // ========================
2320
2321/// This `class` provides a mutable access to a datum map. The users of
2322/// this class can assign to the individual elements and also change the
2323/// size of the map.
2324///
2325/// See @ref bdld_datum
2327
2328 public:
2329
2330 /// `SizeType` is an alias for an unsigned integral value, representing
2331 /// the capacity of a datum array, the capacity of a datum map, the
2332 /// capacity of the *keys-capacity* of a datum-key-owning map or the
2333 /// length of a string.
2335
2336 private:
2337 // DATA
2338 DatumMapEntry *d_data_p; // pointer to a map of datums (not owned)
2339
2340 SizeType *d_size_p; // pointer to the size of the map
2341
2342 bool *d_sorted_p; // pointer to flag indicating whether the map
2343 // is sorted or not
2344
2345 public:
2346 // CREATORS
2347
2348 /// Create a `DatumMutableMapRef` object.
2350
2351 /// Create a `DatumMutableMapRef` object having the specified `data`,
2352 /// `size`, and `sorted`.
2354
2355 /// Create a `DatumMutableMapRef` having the value of the specified `original` object.
2356 ///
2357 /// \note Note that this method's definition is compiler
2358 /// generated.
2359 DatumMutableMapRef(const DatumMutableMapRef& original) = default;
2360
2361 /// Destroy this object.
2362 /// \note Note that this method's definition is compiler
2363 /// generated.
2365
2366 // MANIPULATORS
2367
2368 // Assign to this object the value of the specified `rhs` object. Note
2369 // that this method's definition is compiler generated.
2371
2372 // ACCESSORS
2373
2374 /// Return pointer to the memory allocated for the map.
2375 void *allocatedPtr() const;
2376
2377 /// Return pointer to the first element in the (held) map.
2378 DatumMapEntry *data() const;
2379
2380 /// Return pointer to the location where the (held) map's size is
2381 /// stored.
2382 SizeType *size() const;
2383
2384 /// Return pointer to the location where the (held) map's *sorted* flag
2385 /// is stored.
2386 bool *sorted() const;
2387};
2388
2389 // ===========================
2390 // class DatumMutableIntMapRef
2391 // ===========================
2392
2393/// This `class` provides a mutable access to a datum int-map. The users of
2394/// this class can assign to the individual elements and also change the
2395/// size of the map.
2396///
2397/// See @ref bdld_datum
2399
2400 public:
2401
2402 /// `SizeType` is an alias for an unsigned integral value, representing
2403 /// the capacity of a datum array, the capacity of a datum map, the
2404 /// capacity of the *keys-capacity* of a datum-key-owning map or the
2405 /// length of a string.
2407
2408 private:
2409 // DATA
2410 DatumIntMapEntry *d_data_p; // pointer to an int-map of datums (not
2411 // owned)
2412
2413 SizeType *d_size_p; // pointer to the size of the map
2414
2415 bool *d_sorted_p; // pointer to flag indicating whether the
2416 // int-map is sorted or not
2417
2418 public:
2419 // CREATORS
2420
2421 /// Create a `DatumMutableIntMapRef` object.
2423
2424 /// Create a `DatumMutableIntMapRef` object having the specified `data`,
2425 /// `size`, and `sorted`.
2427 SizeType *size,
2428 bool *sorted);
2429
2430 /// Create a `DatumMutableIntMapRef` having the value of the specified `original` object.
2431 ///
2432 /// \note Note that this method's definition is compiler
2433 /// generated.
2435
2436 /// Destroy this object.
2437 /// \note Note that this method's definition is compiler
2438 /// generated.
2440
2441 // MANIPULATORS
2442
2443 // Assign to this object the value of the specified `rhs` object. Note
2444 // that this method's definition is compiler generated.
2446 = default;
2447
2448 // ACCESSORS
2449
2450 /// Return pointer to the memory allocated for the map.
2451 void *allocatedPtr() const;
2452
2453 /// Return pointer to the first element in the (held) map.
2454 DatumIntMapEntry *data() const;
2455
2456 /// Return pointer to the location where the (held) map's size is
2457 /// stored.
2458 SizeType *size() const;
2459
2460 /// Return pointer to the location where the (held) map's *sorted* flag
2461 /// is stored.
2462 bool *sorted() const;
2463};
2464
2465 // ==================================
2466 // class DatumMutableMapOwningKeysRef
2467 // ==================================
2468
2469/// This `class` provides mutable access to a datum key-owning map. The
2470/// users of this class can assign to the individual elements, copy keys and
2471/// change the size of the map.
2472///
2473/// See @ref bdld_datum
2475
2476 public:
2477
2478 /// `SizeType` is an alias for an unsigned integral value, representing
2479 /// the capacity of a datum array, the capacity of a datum map, the
2480 /// capacity of the *keys-capacity* of a datum-key-owning map or the
2481 /// length of a string.
2483
2484 private:
2485 // DATA
2486 DatumMapEntry *d_data_p; // pointer to a map of datums (not owned)
2487
2488 SizeType *d_size_p; // pointer to the size of the map
2489
2490 SizeType d_allocatedSize; // number of bytes allocated for the map
2491
2492 char *d_keys_p; // pointer to the key storage
2493
2494 bool *d_sorted_p; // pointer to flag indicating whether the
2495 // map is sorted or not
2496
2497 public:
2498 // CREATORS
2499
2500 /// Create a `DatumMutableMapOwningKeysRef` object.
2502
2503 /// Create a `DatumMutableMapOwningKeysRef` object having the specified
2504 /// `data`, `size`, `allocatedSize`, `keys`, and `sorted`.
2506 SizeType *size,
2508 char *keys,
2509 bool *sorted);
2510
2511 /// Create a `DatumMutableMapOwningKeysRef` having the value of the
2512 /// specified `original` object.
2514 const DatumMutableMapOwningKeysRef& original) = default;
2515
2516 /// Destroy this object.
2518
2519 // MANIPULATORS
2520
2521 /// Assign to this object the value of the specified `rhs` object.
2522 ///
2523 /// \note Note that this method's definition is compiler generated.
2525 const DatumMutableMapOwningKeysRef& rhs) = default;
2526
2527 // ACCESSORS
2528
2529 /// Return the number of bytes allocated for the map.
2530 SizeType allocatedSize() const;
2531
2532 /// Return pointer to the memory allocated for the map.
2533 void *allocatedPtr() const;
2534
2535 /// Return pointer to the first element in the held map.
2536 DatumMapEntry *data() const;
2537
2538 /// Return pointer to the start of the buffer where keys are stored.
2539 char *keys() const;
2540
2541 /// Return pointer to the location where the (held) map's size is
2542 /// stored.
2543 SizeType *size() const;
2544
2545 /// Return pointer to the location where the (held) map's *sorted* flag
2546 /// is stored.
2547 bool *sorted() const;
2548};
2549
2550 // ===================
2551 // class DatumArrayRef
2552 // ===================
2553
2554/// This `class` provides a read-only view to an array of datums. It holds
2555/// the array by a `const` pointer and an integral length value. It acts as
2556/// return value for accessors inside the `Datum` class that return an array of datums.
2557///
2558/// \note Note that zero-length arrays are valid.
2559///
2560/// See @ref bdld_datum
2562
2563 public:
2564 // PUBLIC TYPES
2567
2568 typedef bsl::size_t size_type;
2569 typedef bsl::ptrdiff_t difference_type;
2570
2573
2576
2579
2580 typedef bsl::reverse_iterator<iterator> reverse_iterator;
2581 typedef bsl::reverse_iterator<const_iterator> const_reverse_iterator;
2582
2583 /// `SizeType` is an alias for an unsigned integral value, representing
2584 /// the length of a datum array.
2586
2587 private:
2588 // DATA
2589 const Datum *d_data_p; // pointer to the first array element (not owned)
2590 SizeType d_length; // length of the array of
2591
2592 public:
2593 // TRAITS
2596
2597
2598 // CREATORS
2599
2600 /// Create a `DatumArrayRef` object representing an empty array.
2601 DatumArrayRef();
2602
2603 /// Create a `DatumArrayRef` object having the specified `data` and `length`.
2604 ///
2605 /// \pre The behavior is undefined unless `0 != data` or `0 == length`.
2606 ///
2607 /// \note Note that the pointer to the array is just copied.
2609
2610 /// Create a `DatumArrayRef` object having the value of the specified
2611 /// `original` object.
2612 DatumArrayRef(const DatumArrayRef& other) = default;
2613
2614 // Destroy this object.
2615 ~DatumArrayRef() = default;
2616
2617 // MANIPULATORS
2618
2619 /// Assign to this object the value of the specified `rhs` object.
2620 DatumArrayRef& operator=(const DatumArrayRef& rhs) = default;
2621
2622 // ACCESSORS
2623
2624 /// Return a reference providing non-modifiable access to the element at
2625 /// the specified `position` in the array this reference object represents.
2626 ///
2627 /// \pre The behavior is undefined unless `position < size()`.
2628 const_reference operator[](size_type position) const;
2629
2631
2632 /// Return an iterator providing non-modifiable access to the first
2633 /// element of the array this reference object represents; return a
2634 /// past-the-end iterator if `size() == 0`.
2636
2638
2639 /// Return an iterator providing non-modifiable access pointing
2640 /// past-the-end of the array this reference object represents.
2642
2644
2645 /// Return a reverse iterator providing non-modifiable access to the
2646 /// last element of the array this reference object represents, and the
2647 /// past-the-end reverse iterator if `size() == 0`.
2649
2651
2652 /// Return a reverse iterator providing non-modifiable access pointing
2653 /// past-the-end of the array this reference object represents.
2655
2656 /// Return `size() == 0`.
2657 bool empty() const BSLS_KEYWORD_NOEXCEPT;
2658
2659 /// Return a const-pointer to the number of elements of the array this
2660 /// reference object represents.
2661 size_type size() const BSLS_KEYWORD_NOEXCEPT;
2662
2663 /// Return a reference providing non-modifiable access to the first
2664 /// element of the array this reference object represents.
2665 ///
2666 /// \pre The behavior is undefined unless `size() > 0`.
2667 const_reference front() const;
2668
2669 /// Return a reference providing non-modifiable access to the last
2670 /// element of the array this reference object represents.
2671 ///
2672 /// \pre The behavior is undefined unless `size() > 0`.
2673 const_reference back() const;
2674
2675 /// Return the address providing non-modifiable access to the first
2676 /// element of the array this reference object represents. Return a
2677 /// valid pointer which cannot be dereferenced if the `size() == 0`.
2679
2680 /// Return a const pointer to the length of the array.
2681 size_type length() const;
2682
2683 /// Write the value of this object to the specified output `stream` in a
2684 /// human-readable format, and return a reference to the modifiable
2685 /// `stream`. Optionally specify an initial indentation `level`, whose
2686 /// absolute value is incremented recursively for nested objects. If
2687 /// `level` is specified, optionally specify `spacesPerLevel`, whose
2688 /// absolute value indicates the number of spaces per indentation level
2689 /// for this and all of its nested objects. If `level` is negative,
2690 /// suppress indentation of the first line. If `spacesPerLevel` is
2691 /// negative, format the entire output on one line, suppressing all but
2692 /// the initial indentation (as governed by `level`). If `stream` is not valid on entry, this operation has no effect.
2693 ///
2694 /// \note Note that this
2695 /// human-readable format is not fully specified, and can change without
2696 /// notice.
2697 bsl::ostream& print(bsl::ostream& stream,
2698 int level = 0,
2699 int spacesPerLevel = 4) const;
2700};
2701
2702// FREE OPERATORS
2703
2704/// Return `true` if the specified `lhs` and `rhs` have the same value, and
2705/// `false` otherwise. Two `DatumArrayRef` objects have the same value if
2706/// they hold arrays of the same length and all the corresponding `Datum`
2707/// objects in the two arrays also compare equal.
2708bool operator==(const DatumArrayRef& lhs, const DatumArrayRef& rhs);
2709
2710/// Return `true` if the specified `lhs` and `rhs` have different values,
2711/// and `false` otherwise. Two `DatumArrayRef` objects have different
2712/// values if they hold arrays of different lengths or invoking operator
2713/// `==` returns false for at least one of the corresponding elements in the
2714/// arrays.
2715bool operator!=(const DatumArrayRef& lhs, const DatumArrayRef& rhs);
2716
2717/// Write the specified `rhs` value to the specified output `stream` in the
2718/// format shown below:
2719/// @code
2720/// [aa,bb,cc] - aa, bb and cc are the result of invoking operator `<<`
2721/// on the individual elements in the array
2722/// @endcode
2723/// and return a reference to the modifiable `stream`. The function will
2724/// have no effect if the `stream` is not valid.
2725bsl::ostream& operator<<(bsl::ostream& stream, const DatumArrayRef& rhs);
2726
2727 // ======================
2728 // class DatumIntMapEntry
2729 // ======================
2730
2731/// This class represents an entry in a datum map keyed by string values.
2732///
2733/// See @ref bdld_datum
2735
2736 BSLMF_ASSERT(sizeof(int) == 4 && CHAR_BIT == 8);
2737
2738 private:
2739 // DATA
2740 int d_key; // key for this entry
2741 Datum d_value; // value for this entry
2742
2743 public:
2744 // TRAITS
2748
2749 // CREATORS
2750
2751 /// Create a `DatumIntMapEntry` object.
2753
2754 /// Create a `DatumIntMapEntry` object using the specified `key` and
2755 /// `value`.
2756 DatumIntMapEntry(int key, const Datum& value);
2757
2758 /// Destroy this object.
2760
2761 // MANIPULATORS
2762
2763 /// Set the key for this entry to the specified `key`.
2764 void setKey(int key);
2765
2766 /// Set the value for this entry to the specified `value`.
2767 void setValue(const Datum& value);
2768
2769 // ACCESSORS
2770
2771 /// Return the key for this entry.
2772 int key() const;
2773
2774 /// Return the value for this entry.
2775 const Datum& value() const;
2776
2777 /// Write the value of this object to the specified output `stream` in a
2778 /// human-readable format, and return a reference to the modifiable
2779 /// `stream`. Optionally specify an initial indentation `level`, whose
2780 /// absolute value is incremented recursively for nested objects. If
2781 /// `level` is specified, optionally specify `spacesPerLevel`, whose
2782 /// absolute value indicates the number of spaces per indentation level
2783 /// for this and all of its nested objects. If `level` is negative,
2784 /// suppress indentation of the first line. If `spacesPerLevel` is
2785 /// negative, format the entire output on one line, suppressing all but
2786 /// the initial indentation (as governed by `level`). If `stream` is not valid on entry, this operation has no effect.
2787 ///
2788 /// \note Note that this
2789 /// human-readable format is not fully specified, and can change without
2790 /// notice.
2791 bsl::ostream& print(bsl::ostream& stream,
2792 int level = 0,
2793 int spacesPerLevel = 4) const;
2794
2795};
2796
2797// FREE OPERATORS
2798
2799/// Return `true` if the specified `lhs` and `rhs` have the same value, and
2800/// `false` otherwise. Two `DatumIntMapEntry` objects have the same value
2801/// if their keys and values compare equal.
2802bool operator==(const DatumIntMapEntry& lhs, const DatumIntMapEntry& rhs);
2803
2804/// Return `true` if the specified `lhs` and `rhs` have different values,
2805/// and `false` otherwise. Two `DatumIntMapEntry` objects have different
2806/// values if either the keys or values are not equal.
2807bool operator!=(const DatumIntMapEntry& lhs, const DatumIntMapEntry& rhs);
2808
2809/// Write the specified `rhs` value to the specified output `stream` in the
2810/// format shown below:
2811/// @code
2812/// (nnn,aa) - nnn is key integer, while aa is the result of invoking
2813/// operator `<<` on the value
2814/// @endcode
2815/// and return a reference to the modifiable `stream`. The function will
2816/// have no effect if the `stream` is not valid.
2817bsl::ostream& operator<<(bsl::ostream& stream, const DatumIntMapEntry& rhs);
2818
2819 // ====================
2820 // class DatumIntMapRef
2821 // ====================
2822
2823/// This class provides a read-only view to a map of datums (an array of
2824/// `DatumIntMapEntry` objects). It holds the array by a `const` pointer
2825/// and an integral size value. It acts as return value for accessors
2826/// inside the `Datum` class that return a map of `Datum` objects.
2827///
2828/// \note Note that zero-size maps are valid.
2829///
2830/// See @ref bdld_datum
2832
2833 public:
2834 // PUBLIC TYPES
2837
2838 typedef bsl::size_t size_type;
2839 typedef bsl::ptrdiff_t difference_type;
2840
2843
2846
2849
2850 typedef bsl::reverse_iterator<iterator> reverse_iterator;
2851 typedef bsl::reverse_iterator<const_iterator> const_reverse_iterator;
2852
2853 /// `SizeType` is an alias for an unsigned integral value, representing
2854 /// the capacity of a datum array, the capacity of a datum map, the
2855 /// capacity of the *keys-capacity* of a datum-key-owning map or the
2856 /// length of a string.
2858
2859 private:
2860 // DATA
2861 const DatumIntMapEntry *d_data_p; // entry-array pointer (not owned)
2862 SizeType d_size; // length of the map
2863 bool d_sorted; // flag indicating whether the array is
2864 // sorted or not
2865 public:
2866 // TRAITS
2869
2870 // CREATORS
2871
2872 /// Create a `DatumIntMapRef` object having the specified `data` of the
2873 /// specified `size` and the specified `sorted` flag.
2874 ///
2875 /// \pre The behavior is undefined unless `0 != data` or `0 == size`.
2876 /// \note Note that the pointer
2877 /// to the array is just copied.
2878 DatumIntMapRef(const DatumIntMapEntry *data,
2879 SizeType size,
2880 bool sorted);
2881
2882 /// Destroy this object.
2883 ~DatumIntMapRef() = default;
2884
2885 // ACCESSORS
2886
2887 /// Return a reference providing non-modifiable access to the element at
2888 /// the specified `position` in the array of map entries this reference object represents.
2889 ///
2890 /// \pre The behavior is undefined unless
2891 /// `position < size()`.
2892 const_reference operator[](size_type position) const;
2893
2895
2896 /// Return an iterator providing non-modifiable access to the first
2897 /// element of the array of map entries this reference object
2898 /// represents; return a past-the-end iterator if `size() == 0`.
2900
2902
2903 /// Return an iterator providing non-modifiable access pointing
2904 /// past-the-end of the array this reference object represents.
2906
2908
2909 /// Return a reverse iterator providing non-modifiable access to the
2910 /// last element of the array this reference object represents, and the
2911 /// past-the-end reverse iterator if `size() == 0`.
2913
2915
2916 /// Return a reverse iterator providing non-modifiable access pointing
2917 /// past-the-end of the array this reference object represents.
2919
2920 /// Return `size() == 0`.
2921 bool empty() const BSLS_KEYWORD_NOEXCEPT;
2922
2923 /// Return a const-pointer to the number of elements of the array this
2924 /// reference object represents.
2925 size_type size() const BSLS_KEYWORD_NOEXCEPT;
2926
2927 /// Return a reference providing non-modifiable access to the first
2928 /// element of the array this reference object represents.
2929 ///
2930 /// \pre The behavior is undefined unless `size() > 0`.
2931 const_reference front() const;
2932
2933 /// Return a reference providing non-modifiable access to the last
2934 /// element of the array this reference object represents.
2935 ///
2936 /// \pre The behavior is undefined unless `size() > 0`.
2937 const_reference back() const;
2938
2939 /// Return the address providing non-modifiable access to the first
2940 /// element of the array this reference object represents. Return a
2941 /// valid pointer which cannot be dereferenced if the `size() == 0`.
2942 pointer data() const BSLS_KEYWORD_NOEXCEPT;
2943
2944 /// Return `true` if underlying map is sorted and `false` otherwise.
2945 bool isSorted() const;
2946
2947 /// Return a const pointer to the datum having the specified `key`, if it exists and 0 otherwise.
2948 ///
2949 /// \note Note that the `find` has order of `O(n)`
2950 /// if the data is not sorted based on the keys; if the data is sorted,
2951 /// it has order of `O(log(n))`. Also note that if multiple entries
2952 /// with matching keys are present, which matching record is found is
2953 /// unspecified.
2954 const Datum *find(int key) const;
2955
2956 /// Write the value of this object to the specified output `stream` in a
2957 /// human-readable format, and return a reference to the modifiable
2958 /// `stream`. Optionally specify an initial indentation `level`, whose
2959 /// absolute value is incremented recursively for nested objects. If
2960 /// `level` is specified, optionally specify `spacesPerLevel`, whose
2961 /// absolute value indicates the number of spaces per indentation level
2962 /// for this and all of its nested objects. If `level` is negative,
2963 /// suppress indentation of the first line. If `spacesPerLevel` is
2964 /// negative, format the entire output on one line, suppressing all but
2965 /// the initial indentation (as governed by `level`). If `stream` is not valid on entry, this operation has no effect.
2966 ///
2967 /// \note Note that this
2968 /// human-readable format is not fully specified, and can change without
2969 /// notice.
2970 bsl::ostream& print(bsl::ostream& stream,
2971 int level = 0,
2972 int spacesPerLevel = 4) const;
2973};
2974
2975// FREE OPERATORS
2976
2977/// Return `true` if the specified `lhs` and `rhs` have the same value, and
2978/// `false` otherwise. Two `DatumIntMapRef` objects have the same value if
2979/// they hold maps of the same size and all the corresponding
2980/// `DatumIntMapEntry` elements in the two maps also compare equal.
2981bool operator==(const DatumIntMapRef& lhs, const DatumIntMapRef& rhs);
2982
2983/// Return `true` if the specified `lhs` and `rhs` have different values,
2984/// and `false` otherwise. Two `DatumIntMapRef` objects have different
2985/// values if they hold maps of different sizes or operator `==` returns
2986/// `false` for at least one of the corresponding elements in the maps.
2987bool operator!=(const DatumIntMapRef& lhs, const DatumIntMapRef& rhs);
2988
2989/// Write the specified `rhs` value to the specified output `stream` in the
2990/// format shown below:
2991/// @code
2992/// [ nnn = aa, mmm = bb] - nnn and mmm are key ints, while aa and bb
2993/// are the result of invoking operator `<<` on the
2994/// individual value elements in the map
2995/// @endcode
2996/// and return a reference to the modifiable `stream`. The function will
2997/// have no effect if the `stream` is not valid.
2998bsl::ostream& operator<<(bsl::ostream& stream, const DatumIntMapRef& rhs);
2999
3000 // ===================
3001 // class DatumMapEntry
3002 // ===================
3003
3004/// This class represents an entry in a datum map keyed by string values.
3005///
3006/// See @ref bdld_datum
3008
3009 private:
3010 // DATA
3011 bslstl::StringRef d_key_p; // key for this entry (not owned)
3012 Datum d_value; // value for this entry
3013
3014 public:
3015 // TRAITS
3018
3019 // CREATORS
3020
3021 /// Create a `DatumMapEntry` object.
3022 DatumMapEntry();
3023
3024 /// Create a `DatumMapEntry` object using the specified `key` and
3025 /// `value`.
3026 DatumMapEntry(const bslstl::StringRef& key, const Datum& value);
3027
3028 /// Destroy this object.
3029 ~DatumMapEntry() = default;
3030
3031 // MANIPULATORS
3032
3033 /// Set the key for this entry to the specified `key`.
3034 void setKey(const bslstl::StringRef& key);
3035
3036 /// Set the value for this entry to the specified `value`.
3037 void setValue(const Datum& value);
3038
3039 // ACCESSORS
3040
3041 /// Return the key for this entry.
3042 const bslstl::StringRef& key() const;
3043
3044 /// Return the value for this entry.
3045 const Datum& value() const;
3046
3047 /// Write the value of this object to the specified output `stream` in a
3048 /// human-readable format, and return a reference to the modifiable
3049 /// `stream`. Optionally specify an initial indentation `level`, whose
3050 /// absolute value is incremented recursively for nested objects. If
3051 /// `level` is specified, optionally specify `spacesPerLevel`, whose
3052 /// absolute value indicates the number of spaces per indentation level
3053 /// for this and all of its nested objects. If `level` is negative,
3054 /// suppress indentation of the first line. If `spacesPerLevel` is
3055 /// negative, format the entire output on one line, suppressing all but
3056 /// the initial indentation (as governed by `level`). If `stream` is not valid on entry, this operation has no effect.
3057 ///
3058 /// \note Note that this
3059 /// human-readable format is not fully specified, and can change without
3060 /// notice.
3061 bsl::ostream& print(bsl::ostream& stream,
3062 int level = 0,
3063 int spacesPerLevel = 4) const;
3064};
3065
3066// FREE OPERATORS
3067
3068/// Return `true` if the specified `lhs` and `rhs` have the same value, and
3069/// `false` otherwise. Two `DatumMapEntry` objects have the same value if
3070/// their keys and values compare equal.
3071bool operator==(const DatumMapEntry& lhs, const DatumMapEntry& rhs);
3072
3073/// Return `true` if the specified `lhs` and `rhs` have different values,
3074/// and `false` otherwise. Two `DatumMapEntry` objects have different
3075/// values if either the keys or values are not equal.
3076bool operator!=(const DatumMapEntry& lhs, const DatumMapEntry& rhs);
3077
3078/// Write the specified `rhs` value to the specified output `stream` in the
3079/// format shown below:
3080/// @code
3081/// (abc,aa) - abc is key string, while aa is the result of invoking
3082/// operator `<<` on the value
3083/// @endcode
3084/// and return a reference to the modifiable `stream`. The function will
3085/// have no effect if the `stream` is not valid.
3086bsl::ostream& operator<<(bsl::ostream& stream, const DatumMapEntry& rhs);
3087
3088 // =================
3089 // class DatumMapRef
3090 // =================
3091
3092/// This class provides a read-only view to a map of datums (an array of
3093/// `DatumMapEntry` objects). It holds the array by a `const` pointer and
3094/// an integral size value. It acts as return value for accessors inside
3095/// the `Datum` class that return a map of `Datum` objects.
3096///
3097/// \note Note that zero-size maps are valid.
3098///
3099/// See @ref bdld_datum
3101
3102 public:
3103 // PUBLIC TYPES
3106
3107 typedef bsl::size_t size_type;
3108 typedef bsl::ptrdiff_t difference_type;
3109
3112
3115
3118
3119 typedef bsl::reverse_iterator<iterator> reverse_iterator;
3120 typedef bsl::reverse_iterator<const_iterator> const_reverse_iterator;
3121
3122 /// `SizeType` is an alias for an unsigned integral value, representing
3123 /// the capacity of a datum array, the capacity of a datum map, the
3124 /// capacity of the *keys-capacity* of a datum-key-owning map or the
3125 /// length of a string.
3127
3128 private:
3129 // DATA
3130 const DatumMapEntry *d_data_p; // pointer to the entry-array (not owned)
3131 SizeType d_size; // length of the map
3132 bool d_sorted; // flag indicating whether the array is
3133 // sorted or not
3134 bool d_ownsKeys; // flag indicating whether the map owns
3135 // the keys or not
3136 public:
3137 // TRAITS
3140
3141 // CREATORS
3142
3143 /// Create a `DatumMapRef` object having the specified `data` of the
3144 /// specified `size` and the specified `sorted` and `ownsKeys` flags.
3145 ///
3146 /// \pre The behavior is undefined unless `0 != data` or `0 == size`.
3147 ///
3148 /// \note Note that the pointer to the array is just copied.
3149 DatumMapRef(const DatumMapEntry *data,
3150 SizeType size,
3151 bool sorted,
3152 bool ownsKeys);
3153
3154 /// Destroy this object.
3155 ~DatumMapRef() = default;
3156
3157 // ACCESSORS
3158
3159 /// Return a reference providing non-modifiable access to the element at
3160 /// the specified `position` in the array of map entries this reference object represents.
3161 ///
3162 /// \pre The behavior is undefined unless
3163 /// `position < size()`.
3164 const_reference operator[](size_type position) const;
3165
3167
3168 /// Return an iterator providing non-modifiable access to the first
3169 /// element of the array of map entries this reference object
3170 /// represents; return a past-the-end iterator if `size() == 0`.
3172
3174
3175 /// Return an iterator providing non-modifiable access pointing
3176 /// past-the-end of the array this reference object represents.
3178
3180
3181 /// Return a reverse iterator providing non-modifiable access to the
3182 /// last element of the array this reference object represents, and the
3183 /// past-the-end reverse iterator if `size() == 0`.
3185
3187
3188 /// Return a reverse iterator providing non-modifiable access pointing
3189 /// past-the-end of the array this reference object represents.
3191
3192 /// Return `size() == 0`.
3193 bool empty() const BSLS_KEYWORD_NOEXCEPT;
3194
3195 /// Return a const-pointer to the number of elements of the map this
3196 /// reference object represents.
3197 size_type size() const BSLS_KEYWORD_NOEXCEPT;
3198
3199 /// Return a reference providing non-modifiable access to the first
3200 /// element of the map this reference object represents.
3201 ///
3202 /// \pre The behavior is undefined unless `size() > 0`.
3203 const_reference front() const;
3204
3205 /// Return a reference providing non-modifiable access to the last
3206 /// element of the map this reference object represents.
3207 ///
3208 /// \pre The behavior is undefined unless `size() > 0`.
3209 const_reference back() const;
3210
3211 /// Return the address providing non-modifiable access to the first
3212 /// element of the map this reference object represents. Return a
3213 /// valid pointer which cannot be dereferenced if the `size() == 0`.
3214 pointer data() const BSLS_KEYWORD_NOEXCEPT;
3215
3216 /// Return `true` if underlying map is sorted and `false` otherwise.
3217 bool isSorted() const;
3218
3219 /// Return `true` if underlying map owns the keys and `false` otherwise.
3220 ///
3221 /// \note Note that `false` is always returned for zero-sized `DatumMapRef`.
3222 bool ownsKeys() const;
3223
3224 /// Return a const pointer to the datum having the specified `key`, if it exists and 0 otherwise.
3225 ///
3226 /// \note Note that the `find` has order of `O(n)`
3227 /// if the data is not sorted based on the keys. If the data is sorted,
3228 /// it has order of `O(log(n))`. Also note that if multiple entries
3229 /// with matching keys are present, which matching record is found is
3230 /// unspecified.
3231 const Datum *find(const bslstl::StringRef& key) const;
3232
3233 /// Write the value of this object to the specified output `stream` in a
3234 /// human-readable format, and return a reference to the modifiable
3235 /// `stream`. Optionally specify an initial indentation `level`, whose
3236 /// absolute value is incremented recursively for nested objects. If
3237 /// `level` is specified, optionally specify `spacesPerLevel`, whose
3238 /// absolute value indicates the number of spaces per indentation level
3239 /// for this and all of its nested objects. If `level` is negative,
3240 /// suppress indentation of the first line. If `spacesPerLevel` is
3241 /// negative, format the entire output on one line, suppressing all but
3242 /// the initial indentation (as governed by `level`). If `stream` is not valid on entry, this operation has no effect.
3243 ///
3244 /// \note Note that this
3245 /// human-readable format is not fully specified, and can change without
3246 /// notice.
3247 bsl::ostream& print(bsl::ostream& stream,
3248 int level = 0,
3249 int spacesPerLevel = 4) const;
3250};
3251
3252// FREE OPERATORS
3253
3254/// Return `true` if the specified `lhs` and `rhs` have the same value, and
3255/// `false` otherwise. Two `DatumMapRef` objects have the same value if
3256/// they hold maps of the same size and all the corresponding
3257/// `DatumMapEntry` elements in the two maps also compare equal.
3258bool operator==(const DatumMapRef& lhs, const DatumMapRef& rhs);
3259
3260/// Return `true` if the specified `lhs` and `rhs` have different values,
3261/// and `false` otherwise. Two `DatumMapRef` objects have different values
3262/// if they hold maps of different sizes or operator `==` returns false for
3263/// at least one of the corresponding elements in the maps.
3264bool operator!=(const DatumMapRef& lhs, const DatumMapRef& rhs);
3265
3266/// Write the specified `rhs` value to the specified output `stream` in the
3267/// format shown below:
3268/// @code
3269/// [ abc = aa, pqr = bb] - abc and pqr are key strings, while aa and bb
3270/// are the result of invoking operator '<<' on the
3271/// individual value elements in the map
3272/// @endcode
3273/// and return a reference to the modifiable `stream`. The function will
3274/// have no effect if the `stream` is not valid.
3275bsl::ostream& operator<<(bsl::ostream& stream, const DatumMapRef& rhs);
3276
3277
3278 // ====================
3279 // struct Datum_Helpers
3280 // ====================
3281
3282/// This struct contains helper functions used to access typed objects
3283/// within a buffer. The functions assume that objects within the buffers
3284/// have proper alignment and use casts to suppress compiler warnings about
3285/// possible alignment problems.
3286///
3287/// See @ref bdld_datum
3289
3290 /// Return the typed value found at the specified `offset` within the
3291 /// specified `source`.
3292 template <class t_TYPE>
3293 static t_TYPE load(const void *source, int offset);
3294
3295 /// Store the specified typed `value` at the specified `offset` within
3296 /// the specified `destination` and return `value`.
3297 template <class t_TYPE>
3298 static t_TYPE store(void *destination, int offset, t_TYPE value);
3299};
3300
3301#ifdef BSLS_PLATFORM_CPU_32_BIT
3302
3303 // ======================
3304 // struct Datum_Helpers32
3305 // ======================
3306
3307/// This struct contains helper functions used in the 32-bit variation. The
3308/// functions are for internal use only and may change or disappear without
3309/// notice.
3310struct Datum_Helpers32 : Datum_Helpers {
3311
3312 // CLASS DATA
3313#ifdef BSLS_PLATFORM_IS_LITTLE_ENDIAN
3314 static const int b00 = 0; // Bits 0 to 32.
3315 static const int b32 = 4; // Bits 32 to 48.
3316 static const int b48 = 6; // Bits 48 to 64.
3317#else // end - little endian / begin - big endian
3318 static const int b00 = 4;
3319 static const int b32 = 2;
3320 static const int b48 = 0;
3321#endif // end - big endian
3322
3323 // CLASS METHODS
3324
3325 /// Load an Int64 from the specified `high16` and `low32` values created
3326 /// by storeSmallInt48. This method is public for testing purpose only.
3327 /// It may change or be removed without notice.
3328 static bsls::Types::Int64 loadInt48(short high16, int low32);
3329
3330 /// Store an Int64 in short at `phigh16` and int at `plow32` if its
3331 /// highest order 16 bits are zero. Return true if it fits. This
3332 /// method is public for testing purpose only. It may change or be
3333 /// removed without notice.
3334 static bool storeInt48(bsls::Types::Int64 value,
3335 short *phigh16,
3336 int *plow32);
3337
3338 /// Load an Int64 from the specified `high16` and `low32` values created
3339 /// by storeSmallInt64. This method is public for testing purpose only.
3340 /// It may change or be removed without notice.
3341 static bsls::Types::Int64 loadSmallInt64(short high16, int low32);
3342
3343 /// Store an Int64 in short at `phigh16` and int at `plow32`. Return
3344 /// true if it fits. This method is public for testing purpose only.
3345 /// It may change or be removed without notice.
3346 static bool storeSmallInt64(bsls::Types::Int64 value,
3347 short *phigh16,
3348 int *plow32);
3349};
3350
3351#endif // end - 32 bit
3352
3353// ============================================================================
3354// INLINE DEFINITIONS
3355// ============================================================================
3356
3357 // --------------------
3358 // struct Datum_Helpers
3359 // --------------------
3360
3361// CLASS METHODS
3362template <class t_TYPE>
3363inline
3364t_TYPE Datum_Helpers::load(const void *source, int offset)
3365{
3366 // The intermediate cast to `void *` avoids warnings about the cast to a
3367 // pointer of stricter alignment.
3368 return *static_cast<const t_TYPE *>(
3369 static_cast<const void *>(
3370 static_cast<const char *>(source) + offset));
3371}
3372
3373template <class t_TYPE>
3374inline
3375t_TYPE Datum_Helpers::store(void *destination, int offset, t_TYPE value)
3376{
3377 // The intermediate cast to `void *` avoids warnings about the cast to a
3378 // pointer of stricter alignment.
3379 return *static_cast<t_TYPE *>(
3380 static_cast<void *>(
3381 static_cast<char *>(destination) + offset)) = value;
3382}
3383
3384#ifdef BSLS_PLATFORM_CPU_32_BIT
3385
3386 // ----------------------
3387 // struct Datum32_Helpers
3388 // ----------------------
3389
3390// CLASS METHODS
3391inline
3392bsls::Types::Int64 Datum_Helpers32::loadSmallInt64(short high16, int low32)
3393{
3394 bsls::Types::Int64 value;
3395
3396 store<short>(&value, b48, store<short>(&value, b32, high16) < 0 ? -1 : 0);
3397 store<long> (&value, b00, low32);
3398
3399 return value;
3400}
3401
3402inline
3403bool Datum_Helpers32::storeSmallInt64(bsls::Types::Int64 value,
3404 short *phigh16,
3405 int *plow32)
3406{
3407 // Check that the sign can be inferred from the compressed 6-byte integer.
3408 // It is the case if the upper 16 bits are the same as the 17th bit.
3409
3410 if ((load<short>(&value, b48) == 0 && load<short>(&value, b32) >= 0) ||
3411 (load<short>(&value, b48) == -1 && load<short>(&value, b32) < 0)) {
3412 *phigh16 = load<short>(&value, b32);
3413 *plow32 = load<long> (&value, b00);
3414 return true; // RETURN
3415 }
3416 return false;
3417}
3418
3419inline
3420bsls::Types::Int64 Datum_Helpers32::loadInt48(short high16, int low32)
3421{
3422 bsls::Types::Int64 value;
3423
3424 store<short>(&value, b48, 0);
3425 store<short>(&value, b32, high16);
3426 store<long>(&value, b00, low32);
3427
3428 return value;
3429}
3430
3431inline
3432bool Datum_Helpers32::storeInt48(bsls::Types::Int64 value,
3433 short *phigh16,
3434 int *plow32)
3435{
3436 // Check 'value' is a 6-byte integer. It is the case if the upper 16 bits
3437 // are zero.
3438
3439 if (load<short>(&value, b48) == 0) {
3440 *phigh16 = load<short>(&value, b32);
3441 *plow32 = load<long>(&value, b00);
3442 return true; // RETURN
3443 }
3444 return false;
3445}
3446#endif // end - 32 bit
3447
3448 // -----------
3449 // class Datum
3450 // -----------
3451
3452// This section contains all class methods and private accessors that are used
3453// only in implementation for specific platform.
3454
3455#ifdef BSLS_PLATFORM_CPU_32_BIT
3456// PRIVATE CLASS METHODS
3457// 32-bit only
3458inline
3459Datum Datum::createExtendedDataObject(ExtendedInternalDataType type,
3460 void *data)
3461{
3462 Datum result;
3463 result.d_exp.d_value = (k_DOUBLE_MASK | e_INTERNAL_EXTENDED)
3464 << k_TYPE_MASK_BITS | type;
3465 result.d_as.d_cvp = data;
3466 return result;
3467}
3468
3469inline
3470Datum Datum::createExtendedDataObject(ExtendedInternalDataType type,
3471 int data)
3472{
3473 Datum result;
3474 result.d_exp.d_value = (k_DOUBLE_MASK | e_INTERNAL_EXTENDED)
3475 << k_TYPE_MASK_BITS | type;
3476 result.d_as.d_int = data;
3477 return result;
3478}
3479
3480// PRIVATE ACCESSORS
3481// 32-bit only
3482inline
3483Datum::ExtendedInternalDataType Datum::extendedInternalType() const
3484{
3485 BSLS_ASSERT_SAFE(e_INTERNAL_EXTENDED == internalType());
3486 return static_cast<ExtendedInternalDataType>(d_as.d_short);
3487}
3488
3489inline
3490Datum::DataType Datum::typeFromExtendedInternalType() const
3491{
3492 BSLS_ASSERT_SAFE(e_INTERNAL_EXTENDED == internalType());
3493
3494 static const DataType convert[] = {
3495 Datum::e_MAP // e_EXTENDED_INTERNAL_MAP = 0
3496 , Datum::e_MAP // e_EXTENDED_INTERNAL_OWNED_MAP = 1
3497 , Datum::e_DOUBLE // e_EXTENDED_INTERNAL_NAN2 = 2
3498 , Datum::e_ERROR // e_EXTENDED_INTERNAL_ERROR = 3
3499 , Datum::e_ERROR // e_EXTENDED_INTERNAL_ERROR_ALLOC = 4
3500 , Datum::e_STRING // e_EXTENDED_INTERNAL_SREF_ALLOC = 5
3501 , Datum::e_ARRAY // e_EXTENDED_INTERNAL_AREF_ALLOC = 6
3502 , Datum::e_DATETIME // e_EXTENDED_INTERNAL_DATETIME_ALLOC = 7
3503 , Datum::e_DATETIME_INTERVAL
3504 // e_EXTENDED_INTERNAL_DATETIME_INTERVAL_ALLOC = 8
3505 , Datum::e_INTEGER64 // e_EXTENDED_INTERNAL_INTEGER64_ALLOC = 9
3506 , Datum::e_BINARY // e_EXTENDED_INTERNAL_BINARY_ALLOC = 10
3507 , Datum::e_DECIMAL64 // e_EXTENDED_INTERNAL_DECIMAL64 = 11
3508 , Datum::e_DECIMAL64 // e_EXTENDED_INTERNAL_DECIMAL64_SPECIAL = 12
3509 , Datum::e_DECIMAL64 // e_EXTENDED_INTERNAL_DECIMAL64_ALLOC = 13
3510 , Datum::e_NIL // e_EXTENDED_INTERNAL_NIL = 14
3511 , Datum::e_INT_MAP // e_EXTENDED_INTERNAL_INT_MAP = 15
3512 };
3513
3514 BSLMF_ASSERT(sizeof(convert)/sizeof(convert[0]) ==
3515 k_NUM_EXTENDED_INTERNAL_TYPES);
3516
3517 const ExtendedInternalDataType type = extendedInternalType();
3518
3519 BSLS_ASSERT_OPT(static_cast<int>(type) <
3520 static_cast<int>(k_NUM_EXTENDED_INTERNAL_TYPES));
3521
3522 // GCC bug 108770: the `BSLS_ASSERT_OPT` above makes GCC warn about the
3523 // path where the assertion fails but execution continues.
3524#ifdef BSLS_PLATFORM_CMP_GNU
3525# pragma GCC diagnostic push
3526# pragma GCC diagnostic ignored "-Warray-bounds"
3527#endif
3528 return convert[type];
3529#ifdef BSLS_PLATFORM_CMP_GNU
3530# pragma GCC diagnostic pop
3531#endif
3532}
3533
3534inline
3535bsls::Types::Int64 Datum::theLargeInteger64() const
3536{
3537 BSLS_ASSERT_SAFE(internalType() == e_INTERNAL_EXTENDED);
3539 extendedInternalType() == e_EXTENDED_INTERNAL_INTEGER64_ALLOC);
3540 return Datum_Helpers::load<bsls::Types::Int64>(d_as.d_cvp, 0);
3541}
3542
3543inline
3544DatumArrayRef Datum::theLongArrayReference() const
3545{
3546 return DatumArrayRef(
3547 Datum_Helpers::load<Datum *> (d_as.d_cvp, 0),
3548 Datum_Helpers::load<SizeType>(d_as.d_cvp, sizeof(Datum *)));
3549}
3550
3551inline
3552bslstl::StringRef Datum::theLongStringReference() const
3553{
3554 return bslstl::StringRef(
3555 Datum_Helpers::load<char *> (d_as.d_cvp, 0),
3556 Datum_Helpers::load<SizeType>(d_as.d_cvp, sizeof(char *)));
3557}
3558
3559inline
3560bsls::Types::Int64 Datum::theSmallInteger64() const
3561{
3562 BSLS_ASSERT_SAFE(internalType() == e_INTERNAL_INTEGER64);
3563 return Datum_Helpers32::loadSmallInt64(d_as.d_short, d_as.d_int);
3564}
3565#else // end - 32 bit / begin - 64 bit
3566// PRIVATE CLASS METHODS
3567
3568// 64-bit only
3569inline
3570Datum Datum::createDatum(InternalDataType type, void *data)
3571{
3572 Datum result;
3573 result.d_as.d_type = type;
3574 result.d_as.d_ptr = data;
3575 return result;
3576}
3577
3578inline
3579Datum Datum::createDatum(InternalDataType type, int data)
3580{
3581 Datum result;
3582 result.d_as.d_type = type;
3583 result.d_as.d_int64 = data;
3584 return result;
3585}
3586
3587// PRIVATE ACCESSORS
3588
3589// 64-bit only
3590inline
3591void* Datum::theInlineStorage()
3592{
3593 return d_data.buffer() + 1;
3594}
3595
3596inline
3597void* Datum::theAlignedInlineStorage()
3598{
3599 return d_data.buffer() + 8;
3600}
3601
3602inline
3603const void* Datum::theInlineStorage() const
3604{
3605 return d_data.buffer() + 1;
3606}
3607
3608inline
3609const void* Datum::theAlignedInlineStorage() const
3610{
3611 return d_data.buffer() + 8;
3612}
3613#endif // end - 64 bit
3614
3615// This section contains all methods that are common for all platforms, but may
3616// have platform-specific implementation.
3617
3618// PRIVATE ACCESSORS
3619inline
3620void Datum::safeDeallocateBytes(const AllocatorType& allocator,
3621 bsl::size_t nBytes) const
3622{
3623 void *ptr = allocatedPtr<void>();
3624
3625 if (ptr) {
3626 AllocUtil::deallocateBytes(allocator, ptr, nBytes);
3627 }
3628}
3629
3630inline
3631void Datum::safeDeallocateBytes(const AllocatorType& allocator,
3632 bsl::size_t nBytes,
3633 bsl::size_t alignment) const
3634{
3635 void *ptr = allocatedPtr<void>();
3636
3637 if (ptr) {
3638 AllocUtil::deallocateBytes(allocator, ptr, nBytes, alignment);
3639 }
3640}
3641
3642template <class t_TYPE>
3643inline
3644t_TYPE *Datum::allocatedPtr() const
3645{
3646#ifdef BSLS_PLATFORM_CPU_32_BIT
3647 return static_cast<t_TYPE *>(const_cast<void*>(d_as.d_cvp));
3648#else // end - 32 bit / begin - 64 bit
3649 return static_cast<t_TYPE *>(d_as.d_ptr);
3650#endif // end - 64 bit
3651}
3652inline
3653Datum::InternalDataType Datum::internalType() const
3654{
3655#ifdef BSLS_PLATFORM_CPU_32_BIT
3656 if (0x7f == d_data[k_EXPONENT_MSB] &&
3657 0xf0 == (d_data[k_EXPONENT_LSB] & 0xf0)) {
3658 return static_cast<InternalDataType>(d_data[k_EXPONENT_LSB] & 0x0f);
3659 }
3660 return e_INTERNAL_DOUBLE;
3661#else // end - 32 bit / begin - 64 bit
3662 return static_cast<InternalDataType>(d_as.d_type);
3663#endif // end - 64 bit
3664}
3665
3666inline
3667DatumArrayRef Datum::theArrayReference() const
3668{
3669#ifdef BSLS_PLATFORM_CPU_32_BIT
3670 return DatumArrayRef(allocatedPtr<const Datum>(), d_as.d_ushort);
3671#else // end - 32 bit / begin - 64 bit
3672 return DatumArrayRef(allocatedPtr<const Datum>(), d_as.d_int32);
3673#endif // end - 64 bit
3674}
3675
3676inline
3677DatumArrayRef Datum::theInternalArray() const
3678{
3679 const Datum *data = allocatedPtr<const Datum>();
3680 if (data) {
3681 const SizeType size = *reinterpret_cast<const SizeType *>(data);
3682 return DatumArrayRef(data + 1, size); // RETURN
3683 }
3684 return DatumArrayRef(0, 0);
3685}
3686
3687inline
3688bslstl::StringRef Datum::theInternalString() const
3689{
3690#ifdef BSLS_PLATFORM_CPU_32_BIT
3691 const char *data = allocatedPtr<const char>();
3692 return bslstl::StringRef(data + sizeof(SizeType),
3693 Datum_Helpers::load<SizeType>(data, 0));
3694#else // end - 32 bit / begin - 64 bit
3695 return bslstl::StringRef(allocatedPtr<const char>(),
3696 d_as.d_int32);
3697#endif // end - 64 bit
3698}
3699
3701bslstl::StringRef Datum::theShortString() const
3702{
3703#ifdef BSLS_PLATFORM_CPU_32_BIT
3704 return bslstl::StringRef(d_string5.d_chars, d_string5.d_length);
3705#else // end - 32 bit / begin - 64 bit
3706 const char *str = reinterpret_cast<const char *>(theInlineStorage());
3707 const SizeType len = *str++;
3708 return bslstl::StringRef(str, static_cast<int>(len));
3709#endif // end - 64 bit
3710}
3711
3713bslstl::StringRef Datum::theLongestShortString() const
3714{
3715#ifdef BSLS_PLATFORM_CPU_32_BIT
3716 return bslstl::StringRef(d_string6.d_chars, sizeof d_string6.d_chars);
3717#else // end - 32 bit / begin - 64 bit
3718 const char* str = reinterpret_cast<const char*>(theInlineStorage());
3719 return bslstl::StringRef(str, k_SHORTSTRING_SIZE);
3720#endif // end - 64 bit
3721}
3722
3723
3724inline
3725bslstl::StringRef Datum::theStringReference() const
3726{
3727#ifdef BSLS_PLATFORM_CPU_32_BIT
3728 return bslstl::StringRef(allocatedPtr<const char>(), d_as.d_ushort);
3729#else // end - 32 bit / begin - 64 bit
3730 return bslstl::StringRef(allocatedPtr<const char>(), d_as.d_int32);
3731#endif // BSLS_PLATFORM_CPU_32_BIT
3732}
3733
3734inline
3735bsl::size_t Datum::theMapAllocNumBytes() const
3736{
3737 BSLS_ASSERT_SAFE(isMap());
3738
3739 // Map header is stored in the place of the first DatumMapEntry
3740 const Datum_MapHeader *header = allocatedPtr<const Datum_MapHeader>();
3741
3742 return header ? header->d_allocatedSize : 0;
3743}
3744
3745inline
3746bsl::size_t Datum::theIntMapAllocNumBytes() const
3747{
3748 BSLS_ASSERT_SAFE(isIntMap());
3749
3750 // Map header is stored in the place of the first DatumIntMapEntry
3751 const Datum_IntMapHeader *hdr = allocatedPtr<const Datum_IntMapHeader>();
3752
3753 return hdr ? (hdr->d_capacity + 1) * sizeof(DatumIntMapEntry) : 0;
3754}
3755
3756inline
3757bsl::size_t Datum::theErrorAllocNumBytes() const
3758{
3759 BSLS_ASSERT(isError());
3760
3761#ifdef BSLS_PLATFORM_CPU_32_BIT
3762 // If the extended type is 'e_EXTENDED_INTERNAL_ERROR', we are storing
3763 // just a code, at the data offset. Otherwise, we're storing an allocated
3764 // object.
3765
3767 e_EXTENDED_INTERNAL_ERROR_ALLOC == extendedInternalType());
3768#else // end - 32 bit / begin - 64 bit
3769 BSLS_ASSERT_SAFE(e_INTERNAL_ERROR_ALLOC == internalType());
3770#endif // end - 64 bit
3771
3772 const char* data = allocatedPtr<const char>();
3773
3774 const bsl::size_t msgLen = Datum_Helpers::load<int>(data, sizeof(int));
3775 const bsl::size_t align = sizeof(int);
3776 const bsl::size_t headLen = 2 * sizeof(int);
3777
3778 return headLen + ((msgLen + align - 1) & ~(align - 1));
3779}
3780
3781inline
3782bsl::size_t Datum::theBinaryAllocNumBytes() const
3783{
3784 BSLS_ASSERT_SAFE(isBinary());
3785
3786#ifdef BSLS_PLATFORM_CPU_32_BIT
3788 e_EXTENDED_INTERNAL_BINARY_ALLOC == extendedInternalType());
3789 return *allocatedPtr<const SizeType>() + sizeof(double);
3790#else // end - 32 bit / begin - 64 bit
3791 BSLS_ASSERT_SAFE(e_INTERNAL_BINARY_ALLOC == internalType());
3792 return d_as.d_int32;
3793#endif // end - 64 bit
3794}
3795
3796inline
3797bsl::size_t Datum::theInternalStringAllocNumBytes() const
3798{
3799 BSLS_ASSERT_SAFE(isString());
3800 BSLS_ASSERT_SAFE(e_INTERNAL_STRING == internalType());
3801
3802#ifdef BSLS_PLATFORM_CPU_32_BIT
3803 const char *data = allocatedPtr<const char>();
3804 const bsl::size_t msgLen = Datum_Helpers::load<SizeType>(data, 0);
3805 const bsl::size_t align = sizeof(SizeType);
3806 const bsl::size_t headLen = sizeof(SizeType);
3807
3808 return headLen + ((msgLen + align - 1) & ~(align - 1));
3809#else // end - 32 bit / begin - 64 bit
3810
3811 return d_as.d_int32;
3812#endif // end - 64 bit
3813 }
3814
3815inline
3816bsl::size_t Datum::theInternalArrayAllocNumBytes() const
3817{
3818 BSLS_ASSERT_SAFE(isArray());
3819 BSLS_ASSERT_SAFE(e_INTERNAL_ARRAY == internalType());
3820
3821 const Datum *data = allocatedPtr<const Datum>();
3822 if (data) {
3823 const bsl::size_t length = *reinterpret_cast<const SizeType*>(data);
3824 return (length + 1) * sizeof(Datum); // RETURN
3825 }
3826 return 0;
3827
3828}
3829
3830// CLASS METHODS
3831inline
3832Datum Datum::createArrayReference(const Datum *array,
3833 SizeType length,
3834 const AllocatorType& allocator)
3835{
3836 BSLS_ASSERT(array || 0 == length);
3837
3838#ifdef BSLS_PLATFORM_CPU_32_BIT
3839 // If the length will fit in the 'd_ushort' area, store everything inline;
3840 // otherwise, must allocate space.
3841
3842 if (bsl::numeric_limits<unsigned short>::max() >= length) {
3843 Datum result;
3844 result.d_as.d_exponent = k_DOUBLE_MASK | e_INTERNAL_ARRAY_REFERENCE;
3845 result.d_as.d_ushort = static_cast<unsigned short>(length);
3846 result.d_as.d_cvp = array;
3847 return result; // RETURN
3848 }
3849
3850 void *mem = AllocUtil::allocateBytes(allocator,
3851 sizeof(array) + sizeof(length));
3852 Datum_Helpers::store<const Datum *>(mem, 0, array);
3853 Datum_Helpers::store<SizeType> (mem, sizeof(array), length);
3854
3855 return createExtendedDataObject(e_EXTENDED_INTERNAL_AREF_ALLOC, mem);
3856#else // end - 32 bit / begin - 64 bit
3857 (void)allocator;
3858
3859 BSLS_ASSERT(length <= bsl::numeric_limits<unsigned int>::max());
3860
3861 Datum result;
3862 result.d_as.d_type = e_INTERNAL_ARRAY_REFERENCE;
3863 result.d_as.d_int32 = static_cast<int>(length);
3864 result.d_as.d_ptr = reinterpret_cast<void*>(const_cast<Datum*>(array));
3865 return result;
3866#endif // end - 64 bit
3867}
3868
3869inline
3870Datum Datum::createArrayReference(const DatumArrayRef& value,
3871 const AllocatorType& allocator)
3872{
3873 return createArrayReference(value.data(), value.length(), allocator);
3874}
3875
3876inline
3877Datum Datum::createBoolean(bool value)
3878{
3879 Datum result;
3880#ifdef BSLS_PLATFORM_CPU_32_BIT
3881 result.d_exp.d_value = (k_DOUBLE_MASK | e_INTERNAL_BOOLEAN)
3882 << k_TYPE_MASK_BITS;
3883 result.d_as.d_int = value;
3884#else // end - 32 bit / begin - 64 bit
3885 result.d_as.d_type = e_INTERNAL_BOOLEAN;
3886 result.d_as.d_int32 = value;
3887#endif // end - 64 bit
3888 return result;
3889}
3890
3891inline
3892Datum Datum::createDate(const bdlt::Date& value)
3893{
3894 Datum result;
3895#ifdef BSLS_PLATFORM_CPU_32_BIT
3896 BSLMF_ASSERT(sizeof(value) == sizeof(result.d_as.d_int));
3898
3899 result.d_exp.d_value = (k_DOUBLE_MASK | e_INTERNAL_DATE)
3900 << k_TYPE_MASK_BITS;
3901 *reinterpret_cast<bdlt::Date*>(&result.d_as.d_int) = value;
3902#else // end - 32 bit / begin - 64 bit
3903 result.d_as.d_type = e_INTERNAL_DATE;
3904 new (result.theAlignedInlineStorage()) bdlt::Date(value);
3905#endif // end - 64 bit
3906 return result;
3907}
3908
3909inline
3910Datum Datum::createDatetime(const bdlt::Datetime& value,
3911 const AllocatorType& allocator)
3912{
3913 Datum result;
3914#ifdef BSLS_PLATFORM_CPU_32_BIT
3915 // Check if number of days from now fits in two bytes.
3916
3917 const int dateOffsetFromEpoch =
3918 (value.date() - bdlt::EpochUtil::epoch().date())
3919 - k_DATETIME_OFFSET_FROM_EPOCH;
3920 const short shortDateOffsetFromEpoch =
3921 static_cast<short>(dateOffsetFromEpoch);
3922
3923 if (static_cast<int>(shortDateOffsetFromEpoch) == dateOffsetFromEpoch &&
3924 value.microsecond() == 0) {
3925 result.d_exp.d_value =
3926 (k_DOUBLE_MASK | e_INTERNAL_DATETIME) << k_TYPE_MASK_BITS
3927 | (0xffff & dateOffsetFromEpoch);
3928 if (value.time() != bdlt::Time()) {
3929 bdlt::DatetimeInterval interval = value.time() - bdlt::Time();
3930 result.d_as.d_int = static_cast<int>(interval.totalMilliseconds());
3931 }
3932 else {
3934 }
3935 }
3936 else {
3937 void *mem = AllocUtil::newObject<bdlt::Datetime>(allocator, value);
3938 result = createExtendedDataObject(e_EXTENDED_INTERNAL_DATETIME_ALLOC,
3939 mem);
3940 }
3941#else // end - 32 bit / begin - 64 bit
3942 (void)allocator;
3943
3944 result.d_as.d_type = e_INTERNAL_DATETIME;
3945 new (result.theAlignedInlineStorage()) bdlt::Datetime(value);
3946#endif // end - 64 bit
3947 return result;
3948}
3949
3950inline
3951Datum Datum::createDatetimeInterval(const bdlt::DatetimeInterval& value,
3952 const AllocatorType& allocator)
3953{
3954 Datum result;
3955#ifdef BSLS_PLATFORM_CPU_32_BIT
3956 const int usValue = value.microseconds();
3957 const bsls::Types::Int64 msValue = value.totalMilliseconds();
3958
3959 if (usValue == 0 && // Low-resolution (old) interval
3960 Datum_Helpers32::storeSmallInt64(msValue,
3961 &result.d_as.d_short,
3962 &result.d_as.d_int)) {
3963 result.d_as.d_exponent = k_DOUBLE_MASK | e_INTERNAL_DATETIME_INTERVAL;
3964 } else {
3965 void *mem = AllocUtil::newObject<bdlt::DatetimeInterval>(allocator,
3966 value);
3967 result = createExtendedDataObject(
3968 e_EXTENDED_INTERNAL_DATETIME_INTERVAL_ALLOC,
3969 mem);
3970 }
3971#else // end - 32 bit / begin - 64 bit
3972 (void)allocator;
3973
3974 result.d_as.d_type = e_INTERNAL_DATETIME_INTERVAL;
3975 result.d_as.d_int32 = value.days();
3976 result.d_as.d_int64 = value.fractionalDayInMicroseconds();
3977#endif // end - 64 bit
3978 return result;
3979}
3980
3981inline
3982Datum Datum::createDouble(double value)
3983{
3984 Datum result;
3985#ifdef BSLS_PLATFORM_CPU_32_BIT
3986 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!(value == value))) {
3988 return createExtendedDataObject(e_EXTENDED_INTERNAL_NAN2, 0); // RETURN
3989 } else {
3990 result.d_double = value;
3991 }
3992#else // end - 32 bit / begin - 64 bit
3993 result.d_as.d_type = e_INTERNAL_DOUBLE;
3994 result.d_as.d_double = value;
3995#endif // end - 64 bit
3996 return result;
3997}
3998
3999inline
4000Datum Datum::createError(int code)
4001{
4002#ifdef BSLS_PLATFORM_CPU_32_BIT
4003 return createExtendedDataObject(e_EXTENDED_INTERNAL_ERROR, code);
4004#else // end - 32 bit / begin - 64 bit
4005 return createDatum(e_INTERNAL_ERROR, code);
4006#endif // end - 64 bit
4007}
4008
4009inline
4010Datum Datum::createInteger(int value)
4011{
4012 Datum result;
4013#ifdef BSLS_PLATFORM_CPU_32_BIT
4014 result.d_exp.d_value = (k_DOUBLE_MASK | e_INTERNAL_INTEGER)
4015 << k_TYPE_MASK_BITS;
4016 result.d_as.d_int = value;
4017#else // end - 32 bit / begin - 64 bit
4018 result.d_as.d_type = e_INTERNAL_INTEGER;
4019 result.d_as.d_int32 = value;
4020#endif // end - 64 bit
4021 return result;
4022}
4023
4024inline
4025Datum Datum::createInteger64(bsls::Types::Int64 value,
4026 const AllocatorType& allocator)
4027{
4028 Datum result;
4029#ifdef BSLS_PLATFORM_CPU_32_BIT
4030 if (Datum_Helpers32::storeSmallInt64(value,
4031 &result.d_as.d_short,
4032 &result.d_as.d_int)) {
4033 result.d_as.d_exponent = k_DOUBLE_MASK | e_INTERNAL_INTEGER64;
4034 } else {
4035 void *mem = AllocUtil::newObject<bsls::Types::Int64>(allocator, value);
4036 result = createExtendedDataObject(e_EXTENDED_INTERNAL_INTEGER64_ALLOC,
4037 mem);
4038 }
4039#else // end - 32 bit / begin - 64 bit
4040 (void)allocator;
4041
4042 result.d_as.d_type = e_INTERNAL_INTEGER64;
4043 result.d_as.d_int64 = value;
4044#endif // end - 64 bit
4045 return result;
4046}
4047
4048inline
4049Datum Datum::createNull()
4050{
4051 Datum result;
4052#ifdef BSLS_PLATFORM_CPU_32_BIT
4053 // Setting exponent using half-word is faster, maybe the compiler folds the
4054 // two statements into one?
4055
4056 result.d_as.d_exponent = k_DOUBLE_MASK | Datum::e_INTERNAL_EXTENDED;
4057 result.d_as.d_ushort = e_EXTENDED_INTERNAL_NIL;
4058#else // end - 32 bit / begin - 64 bit
4059 result.d_as.d_type = e_INTERNAL_NIL;
4060#endif // end - 64 bit
4061 return result;
4062}
4063
4064inline
4065Datum Datum::createStringRef(const char *string,
4066 SizeType length,
4067 const AllocatorType& allocator)
4068{
4069 BSLS_ASSERT(string || 0 == length);
4070
4071#ifdef BSLS_PLATFORM_CPU_32_BIT
4072 // If the length will fit in the 'k_SHORT_OFFSET' area, store everything
4073 // inline; otherwise allocate space.
4074
4075 if (bsl::numeric_limits<unsigned short>::max() >= length) {
4076 Datum result;
4077 result.d_exp.d_value = (k_DOUBLE_MASK | e_INTERNAL_STRING_REFERENCE)
4078 << k_TYPE_MASK_BITS | length;
4079 result.d_as.d_cvp = string;
4080 return result; // RETURN
4081 }
4082
4083 void *mem = AllocUtil::allocateBytes(allocator,
4084 sizeof(length) + sizeof(string));
4085 Datum_Helpers::store<const char *>(mem, 0, string);
4086 Datum_Helpers::store<SizeType> (mem, sizeof(string), length);
4087
4088 return createExtendedDataObject(e_EXTENDED_INTERNAL_SREF_ALLOC, mem);
4089#else // end - 32 bit / begin - 64 bit
4090 (void)allocator;
4091
4092 BSLS_ASSERT(length <= bsl::numeric_limits<unsigned int>::max());
4093
4094 Datum result;
4095 result.d_as.d_type = e_INTERNAL_STRING_REFERENCE;
4096 result.d_as.d_int32 = static_cast<int>(length);
4097 result.d_as.d_ptr = const_cast<char*>(string);
4098 return result;
4099#endif // end - 64 bit
4100}
4101
4102inline
4103Datum Datum::createStringRef(const char *string,
4104 const AllocatorType& allocator)
4105{
4106 BSLS_ASSERT(string);
4107
4108 return createStringRef(string, bsl::strlen(string), allocator);
4109}
4110
4111inline
4112Datum Datum::createStringRef(const bslstl::StringRef& value,
4113 const AllocatorType& allocator)
4114{
4115 return createStringRef(value.data(), value.length(), allocator);
4116}
4117
4118inline
4119Datum Datum::createTime(const bdlt::Time& value)
4120{
4121 Datum result;
4122#ifdef BSLS_PLATFORM_CPU_32_BIT
4123 result.d_exp.d_value = (k_DOUBLE_MASK | e_INTERNAL_TIME)
4124 << k_TYPE_MASK_BITS;
4125 bsls::Types::Int64 rawTime;
4127 *reinterpret_cast<bdlt::Time*>(&rawTime) = value;
4128 const bool rc = Datum_Helpers32::storeInt48(rawTime,
4129 &result.d_as.d_short,
4130 &result.d_as.d_int);
4131 BSLS_ASSERT(rc); (void)rc;
4132#else // end - 32 bit / begin - 64 bit
4133 result.d_as.d_type = e_INTERNAL_TIME;
4134 new (result.theAlignedInlineStorage()) bdlt::Time(value);
4135#endif // end - 64 bit
4136 return result;
4137}
4138
4139inline
4140Datum Datum::createUdt(void *data, int type)
4141{
4142 BSLS_ASSERT(0 <= type && type <= 65535);
4143
4144 Datum result;
4145#ifdef BSLS_PLATFORM_CPU_32_BIT
4146 result.d_as.d_exponent = k_DOUBLE_MASK | e_INTERNAL_USERDEFINED;
4147 result.d_as.d_ushort = static_cast<unsigned short>(type);
4148 result.d_as.d_cvp = data;
4149#else // end - 32 bit / begin - 64 bit
4150 result.d_as.d_type = e_INTERNAL_USERDEFINED;
4151 result.d_as.d_int32 = type;
4152 result.d_as.d_ptr = data;
4153#endif // end - 64 bit
4154 return result;
4155}
4156
4157inline
4158Datum Datum::adoptArray(const DatumMutableArrayRef& array)
4159{
4160 // Note that 'array.length' contains the *address* of the 'length'
4161 // information for the array, which precedes the 'array' data in a
4162 // contiguously allocated block (see 'DatumMutableArrayRef').
4163
4164 Datum result;
4165#ifdef BSLS_PLATFORM_CPU_32_BIT
4166 result.d_as.d_exponent = k_DOUBLE_MASK | e_INTERNAL_ARRAY;
4167 result.d_as.d_cvp = array.length();
4168#else // end - 32 bit / begin - 64 bit
4169 result.d_as.d_type = e_INTERNAL_ARRAY;
4170 result.d_as.d_ptr = array.length();
4171#endif // end - 64 bit
4172 return result;
4173}
4174
4175inline
4176Datum Datum::adoptMap(const DatumMutableMapRef& map)
4177{
4178 // Note that 'map.size' contains the *address* of the 'size' information
4179 // for the map, which precedes the 'map' data in a contiguously allocated
4180 // block (see 'DatumMutableMapRef').
4181
4182#ifdef BSLS_PLATFORM_CPU_32_BIT
4183 return createExtendedDataObject(e_EXTENDED_INTERNAL_MAP, map.size());
4184#else // end - 32 bit / begin - 64 bit
4185 return createDatum(e_INTERNAL_MAP, map.size());
4186#endif // end - 64 bit
4187}
4188
4189inline
4190Datum Datum::adoptIntMap(const DatumMutableIntMapRef& map)
4191{
4192 // Note that 'map.size' contains the *address* of the 'size' information
4193 // for the map, which precedes the 'map' data in a contiguously allocated
4194 // block (see 'DatumMutableIntMapRef').
4195
4196#ifdef BSLS_PLATFORM_CPU_32_BIT
4197 return createExtendedDataObject(e_EXTENDED_INTERNAL_INT_MAP, map.size());
4198#else // end - 32 bit / begin - 64 bit
4199 return createDatum(e_INTERNAL_INT_MAP, map.size());
4200#endif // end - 64 bit
4201}
4202
4203inline
4204Datum Datum::adoptMap(const DatumMutableMapOwningKeysRef& map)
4205{
4206 // Note that 'map.size' contains the *address* of the 'size' information
4207 // for the map, which precedes the 'map' data in a contiguously allocated
4208 // block (see 'DatumMutableMapOwningKeysRefRef').
4209
4210#ifdef BSLS_PLATFORM_CPU_32_BIT
4211 return createExtendedDataObject(e_EXTENDED_INTERNAL_OWNED_MAP,
4212 map.size());
4213#else // end - 32 bit / begin - 64 bit
4214 return createDatum(e_INTERNAL_OWNED_MAP, map.size());
4215#endif // end - 64 bit
4216}
4217
4218inline
4219Datum Datum::copyString(const bslstl::StringRef& value,
4220 const AllocatorType& allocator)
4221{
4222 return copyString(value.data(), value.length(), allocator);
4223}
4224
4225inline
4226void Datum::disposeUninitializedArray(const DatumMutableArrayRef& array,
4227 const AllocatorType& allocator)
4228{
4229 void *ptr = array.allocatedPtr();
4230
4231 if (ptr) {
4232 AllocUtil::deallocateBytes(allocator, ptr,
4233 sizeof(Datum) * (array.capacity() + 1));
4234 }
4235}
4236
4237inline
4238void Datum::disposeUninitializedIntMap(const DatumMutableIntMapRef& map,
4239 const AllocatorType& allocator)
4240{
4241 void *ptr = map.allocatedPtr();
4242
4243 if (ptr) {
4244 Datum_IntMapHeader *hdr = static_cast<Datum_IntMapHeader*>(ptr);
4245
4246 AllocUtil::deallocateBytes(
4247 allocator,
4248 ptr,
4249 (hdr->d_capacity + 1) * sizeof(DatumIntMapEntry));
4250 }
4251}
4252
4253inline
4254void Datum::disposeUninitializedMap(const DatumMutableMapRef& map,
4255 const AllocatorType& allocator)
4256{
4257 void *ptr = map.allocatedPtr();
4258
4259 if (ptr) {
4260 Datum_MapHeader *hdr = static_cast<Datum_MapHeader*>(ptr);
4261
4262 AllocUtil::deallocateBytes(allocator, ptr, hdr->d_allocatedSize);
4263 }
4264}
4265
4266inline
4267void Datum::disposeUninitializedMap(
4269 const AllocatorType& allocator)
4270{
4271 void *ptr = map.allocatedPtr();
4272
4273 if (ptr) {
4274 Datum_MapHeader *hdr = static_cast<Datum_MapHeader*>(ptr);
4275
4276 AllocUtil::deallocateBytes(allocator, ptr, hdr->d_allocatedSize);
4277 }
4278}
4279
4280// ACCESSORS
4281inline
4282bool Datum::isArray() const
4283{
4284 return (e_ARRAY == type());
4285}
4286
4287inline
4288bool Datum::isBinary() const
4289{
4290 return (e_BINARY == type());
4291}
4292
4293inline
4294bool Datum::isBoolean() const
4295{
4296#ifdef BSLS_PLATFORM_CPU_32_BIT
4297 return d_exp.d_value == (k_DOUBLE_MASK | e_INTERNAL_BOOLEAN)
4298 << k_TYPE_MASK_BITS;
4299#else // end - 32 bit / begin - 64 bit
4300 return (e_BOOLEAN == type());
4301#endif // end - 64 bit
4302}
4303
4304inline
4305bool Datum::isDate() const
4306{
4307#ifdef BSLS_PLATFORM_CPU_32_BIT
4308 return d_exp.d_value == (k_DOUBLE_MASK | e_INTERNAL_DATE)
4309 << k_TYPE_MASK_BITS;
4310#else // end - 32 bit / begin - 64 bit
4311 return (e_DATE == type());
4312#endif // end - 64 bit
4313}
4314
4315inline
4316bool Datum::isDatetime() const
4317{
4318 return (e_DATETIME == type());
4319}
4320
4321inline
4322bool Datum::isDatetimeInterval() const
4323{
4324 return (e_DATETIME_INTERVAL == type());
4325}
4326
4327inline
4328bool Datum::isDecimal64() const
4329{
4330 return (e_DECIMAL64 == type());
4331}
4332
4333inline
4334bool Datum::isDouble() const
4335{
4336 return (e_DOUBLE == type());
4337}
4338
4339inline
4340bool Datum::isError() const
4341{
4342 return (e_ERROR == type());
4343}
4344
4345inline
4346bool Datum::isExternalReference() const
4347{
4348#ifdef BSLS_PLATFORM_CPU_32_BIT
4349 switch (internalType()) {
4350 case e_INTERNAL_STRING_REFERENCE:
4351 case e_INTERNAL_ARRAY_REFERENCE:
4352 case e_INTERNAL_USERDEFINED:
4353 return true; // RETURN
4354 case e_INTERNAL_EXTENDED:
4355 switch (extendedInternalType()) {
4356 case e_EXTENDED_INTERNAL_SREF_ALLOC:
4357 case e_EXTENDED_INTERNAL_AREF_ALLOC:
4358 return true; // RETURN
4359 default:
4360 break;
4361 }
4362 default:
4363 break;
4364 }
4365#else // end - 32 bit / begin - 64 bit
4366 switch (internalType()) {
4367 case e_INTERNAL_STRING_REFERENCE:
4368 case e_INTERNAL_ARRAY_REFERENCE:
4369 case e_INTERNAL_USERDEFINED:
4370 return true; // RETURN
4371 case e_INTERNAL_UNINITIALIZED:
4372 BSLS_ASSERT(0 == "Uninitialized Datum");
4373 break;
4374 default:
4375 break;
4376 }
4377#endif // end - 64 bit
4378 return false;
4379}
4380
4381inline
4382bool Datum::isInteger() const
4383{
4384#ifdef BSLS_PLATFORM_CPU_32_BIT
4385 return d_exp.d_value == (k_DOUBLE_MASK | e_INTERNAL_INTEGER)
4386 << k_TYPE_MASK_BITS;
4387#else // end - 32 bit / begin - 64 bit
4388 return (e_INTEGER == type());
4389#endif // end - 64 bit
4390}
4391
4392inline
4393bool Datum::isInteger64() const
4394{
4395 return (e_INTEGER64 == type());
4396}
4397
4398inline
4399bool Datum::isIntMap() const
4400{
4401 return (e_INT_MAP == type());
4402}
4403
4404inline
4405bool Datum::isMap() const
4406{
4407 return (e_MAP == type());
4408}
4409
4410inline
4411bool Datum::isNull() const
4412{
4413#ifdef BSLS_PLATFORM_CPU_32_BIT
4414 return d_exp.d_value == (((k_DOUBLE_MASK | Datum::e_INTERNAL_EXTENDED) << k_TYPE_MASK_BITS)
4415 | e_EXTENDED_INTERNAL_NIL);
4416#else // end - 32 bit / begin - 64 bit
4417 return (e_NIL == type());
4418#endif // end - 64 bit
4419}
4420
4421inline
4422bool Datum::isString() const
4423{
4424 return (e_STRING == type());
4425}
4426
4427inline
4428bool Datum::isTime() const
4429{
4430 return (e_TIME == type());
4431}
4432
4433inline
4434bool Datum::isUdt() const
4435{
4436 return (e_USERDEFINED == type());
4437}
4438
4439inline
4440DatumArrayRef Datum::theArray() const
4441{
4442 BSLS_ASSERT_SAFE(isArray());
4443
4444 const InternalDataType type = internalType();
4445 if (e_INTERNAL_ARRAY == type) {
4446 return theInternalArray(); // RETURN
4447 }
4448
4449#ifdef BSLS_PLATFORM_CPU_32_BIT
4450 if (e_INTERNAL_EXTENDED == type) {
4451 return theLongArrayReference(); // RETURN
4452 }
4453#endif // end - 32 bit
4454
4455 return theArrayReference();
4456}
4457
4458inline
4459DatumBinaryRef Datum::theBinary() const
4460{
4461 BSLS_ASSERT_SAFE(isBinary());
4462
4463#ifdef BSLS_PLATFORM_CPU_32_BIT
4464 return DatumBinaryRef(allocatedPtr<const double>() + 1,
4465 *allocatedPtr<const SizeType>()); // RETURN
4466#else // end - 32 bit / begin - 64 bit
4467 const InternalDataType type = internalType();
4468 switch(type) {
4469 case e_INTERNAL_BINARY:
4470 return DatumBinaryRef(theInlineStorage(), // RETURN
4471 d_data.buffer()[k_SMALLBINARY_SIZE_OFFSET]);
4472 case e_INTERNAL_BINARY_ALLOC:
4473 return DatumBinaryRef(d_as.d_ptr, d_as.d_int32); // RETURN
4474 default:
4475 BSLS_ASSERT(0 == "Bad binary internal-type (memory corruption?)");
4476 }
4477 return DatumBinaryRef();
4478#endif // end - 64 bit
4479}
4480
4481inline
4482bool Datum::theBoolean() const
4483{
4484 BSLS_ASSERT_SAFE(isBoolean());
4485
4486#ifdef BSLS_PLATFORM_CPU_32_BIT
4487 return static_cast<bool>(d_as.d_int);
4488#else // end - 32 bit / begin - 64 bit
4489 return d_as.d_int32;
4490#endif // end - 64 bit
4491}
4492
4493inline
4494bdlt::Date Datum::theDate() const
4495{
4496 BSLS_ASSERT_SAFE(isDate());
4497
4498#ifdef BSLS_PLATFORM_CPU_32_BIT
4499 return *reinterpret_cast<const bdlt::Date *>(&d_as.d_int);
4500#else // end - 32 bit / begin - 64 bit
4501 return *reinterpret_cast<const bdlt::Date *>(theAlignedInlineStorage());
4502#endif // end - 64 bit
4503}
4504
4505inline
4506bdlt::Datetime Datum::theDatetime() const
4507{
4508 BSLS_ASSERT_SAFE(isDatetime());
4509
4510#ifdef BSLS_PLATFORM_CPU_32_BIT
4511 const InternalDataType type = internalType();
4512
4513 if (type == e_INTERNAL_DATETIME) {
4514 const bdlt::Date date = bdlt::EpochUtil::epoch().date() +
4515 k_DATETIME_OFFSET_FROM_EPOCH + d_as.d_short;
4516 if (d_as.d_int != bdlt::TimeUnitRatio::k_MS_PER_D_32) {
4517 bdlt::Time time;
4518 time.addMilliseconds(d_as.d_int);
4519 return bdlt::Datetime(date, time); // RETURN
4520 }
4521 else {
4522 // The special 24:00:00.00000 time point
4523 return bdlt::Datetime(date, bdlt::Time()); // RETURN
4524 }
4525 }
4526
4527 BSLS_ASSERT_SAFE(type == e_INTERNAL_EXTENDED);
4529 extendedInternalType() == e_EXTENDED_INTERNAL_DATETIME_ALLOC);
4530 return *allocatedPtr<const bdlt::Datetime>();
4531#else // end - 32 bit / begin - 64 bit
4532 return *reinterpret_cast<const bdlt::Datetime *>(
4533 theAlignedInlineStorage());
4534#endif // end - 64 bit
4535}
4536
4537inline // BDLD_DATUM_FORCE_INLINE
4538bdlt::DatetimeInterval Datum::theDatetimeInterval() const
4539{
4540 BSLS_ASSERT_SAFE(isDatetimeInterval());
4541
4542#ifdef BSLS_PLATFORM_CPU_32_BIT
4543 const InternalDataType type = internalType();
4544
4545 if (type == e_INTERNAL_DATETIME_INTERVAL) {
4547 result.setTotalMilliseconds(
4548 Datum_Helpers32::loadSmallInt64(d_as.d_short, d_as.d_int));
4549 return result; // RETURN
4550 }
4551
4552 BSLS_ASSERT_SAFE(type == e_INTERNAL_EXTENDED);
4554 extendedInternalType() == e_EXTENDED_INTERNAL_DATETIME_INTERVAL_ALLOC);
4555 return *allocatedPtr<const bdlt::DatetimeInterval>();
4556#else // end - 32 bit / begin - 64 bit
4557 return bdlt::DatetimeInterval(d_as.d_int32, // days
4558 0, // hours
4559 0, // minutes
4560 0, // seconds
4561 0, // milliseconds
4562 d_as.d_int64); // microseconds
4563#endif // end - 64 bit
4564}
4565
4566inline
4567double Datum::theDouble() const
4568{
4569 BSLS_ASSERT_SAFE(isDouble());
4570
4571#ifdef BSLS_PLATFORM_CPU_32_BIT
4573 0x7f != d_data[k_EXPONENT_MSB] || // exponent is not the
4574 0xf0 != (d_data[k_EXPONENT_LSB] & 0xf0) || // special '7ff' value
4575 e_INTERNAL_INF == (d_data[k_EXPONENT_LSB] & 0x0f))) { // or infinity
4576 return d_double; // RETURN
4577 }
4579 return bsl::numeric_limits<double>::quiet_NaN(); // RETURN
4580#else // end - 32 bit / begin - 64 bit
4581 return d_as.d_double;
4582#endif // end - 64 bit
4583}
4584
4585inline
4586DatumError Datum::theError() const
4587{
4588 BSLS_ASSERT(isError());
4589
4590#ifdef BSLS_PLATFORM_CPU_32_BIT
4591 // If the extended type is 'e_EXTENDED_INTERNAL_ERROR', we are storing
4592 // just a code, at the data offset. Otherwise, we're storing an allocated
4593 // object.
4594
4595 if (e_EXTENDED_INTERNAL_ERROR == extendedInternalType()) {
4596 return DatumError(d_as.d_int); // RETURN
4597 }
4598
4599 const char *data = allocatedPtr<const char>();
4600#else // end - 32 bit / begin - 64 bit
4601 if (e_INTERNAL_ERROR == internalType()) {
4602 return DatumError(static_cast<int>(d_as.d_int64)); // RETURN
4603 }
4604
4605 const char *data = allocatedPtr<const char>();
4606#endif // end - 64 bit
4607
4608 return DatumError(
4609 Datum_Helpers::load<int>(data, 0),
4610 bslstl::StringRef(data + 2 * sizeof(int),
4611 Datum_Helpers::load<int>(data, sizeof(int))));
4612}
4613
4614inline
4615int Datum::theInteger() const
4616{
4617 BSLS_ASSERT_SAFE(isInteger());
4618
4619#ifdef BSLS_PLATFORM_CPU_32_BIT
4620 return d_as.d_int;
4621#else // end - 32 bit / begin - 64 bit
4622 return d_as.d_int32;
4623#endif // end - 64 bit
4624}
4625
4626inline
4627bsls::Types::Int64 Datum::theInteger64() const
4628{
4629 BSLS_ASSERT_SAFE(isInteger64());
4630
4631#ifdef BSLS_PLATFORM_CPU_32_BIT
4632 const InternalDataType type = internalType();
4633
4634 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(e_INTERNAL_INTEGER64 == type)) {
4635 return theSmallInteger64(); // RETURN
4636 }
4637 BSLS_ASSERT_SAFE(e_INTERNAL_EXTENDED == type);
4639 e_EXTENDED_INTERNAL_INTEGER64_ALLOC == extendedInternalType());
4640 return theLargeInteger64(); // RETURN
4641#else // end - 32 bit / begin - 64 bit
4642 return d_as.d_int64;
4643#endif // end - 64 bit
4644}
4645
4646inline
4647DatumMapRef Datum::theMap() const
4648{
4649 BSLS_ASSERT_SAFE(isMap());
4650
4651 const DatumMapEntry *map = allocatedPtr<const DatumMapEntry>();
4652
4653 if (map) {
4654 // Map header takes first DatumMapEntry
4655 const Datum_MapHeader *header =
4656 reinterpret_cast<const Datum_MapHeader *>(map);
4657
4658 return DatumMapRef(map + 1,
4659 header->d_size,
4660 header->d_sorted,
4661 header->d_ownsKeys); // RETURN
4662 }
4663 return DatumMapRef(0, 0, false, false);
4664}
4665
4666inline
4667DatumIntMapRef Datum::theIntMap() const
4668{
4669 BSLS_ASSERT_SAFE(isIntMap());
4670
4671 const DatumIntMapEntry *map = allocatedPtr<const DatumIntMapEntry>();
4672
4673 if (map) {
4674 // Map header takes first DatumMapEntry
4675 const Datum_IntMapHeader *header =
4676 reinterpret_cast<const Datum_IntMapHeader *>(map);
4677
4678 return DatumIntMapRef(map + 1,
4679 header->d_size,
4680 header->d_sorted); // RETURN
4681 }
4682 return DatumIntMapRef(0, 0, false);
4683}
4684
4685inline
4686bslstl::StringRef Datum::theString() const
4687{
4688 BSLS_ASSERT_SAFE(isString());
4689
4690 const InternalDataType type = internalType();
4691 switch(type) {
4692 case e_INTERNAL_SHORTSTRING:
4693 return theShortString(); // RETURN
4694 case e_INTERNAL_STRING:
4695 return theInternalString(); // RETURN
4696 case e_INTERNAL_STRING_REFERENCE:
4697 return theStringReference(); // RETURN
4698 case e_INTERNAL_LONGEST_SHORTSTRING: {
4700 return theLongestShortString(); // RETURN
4701 }
4702#ifdef BSLS_PLATFORM_CPU_32_BIT
4703 default:
4704 return theLongStringReference(); // RETURN
4705#else // end - 32 bit / begin - 64 bit
4706 default: {
4707 BSLS_ASSERT(0 == "Bad string internal-type (memory corruption?)");
4708 return bslstl::StringRef(); // RETURN
4709 }
4710#endif // end - 64 bit
4711 }
4712}
4713
4714inline
4715bdlt::Time Datum::theTime() const
4716{
4717 BSLS_ASSERT_SAFE(isTime());
4718
4719#ifdef BSLS_PLATFORM_CPU_32_BIT
4721 bsls::Types::Int64 rawTime;
4722 rawTime = Datum_Helpers32::loadInt48(d_as.d_short, d_as.d_int);
4723 return *reinterpret_cast<bdlt::Time*>(&rawTime);
4724#else // end - 32 bit / begin - 64 bit
4725 return *reinterpret_cast<const bdlt::Time *>(theAlignedInlineStorage());
4726#endif // end - 64 bit
4727}
4728
4729inline
4730DatumUdt Datum::theUdt() const
4731{
4732 BSLS_ASSERT_SAFE(isUdt());
4733#ifdef BSLS_PLATFORM_CPU_32_BIT
4734 return DatumUdt(allocatedPtr<void>(), d_as.d_ushort);
4735#else // end - 32 bit / begin - 64 bit
4736 return DatumUdt(allocatedPtr<void>(), d_as.d_int32);
4737#endif // end - 64 bit
4738}
4739
4740inline
4741Datum::DataType Datum::type() const
4742{
4743#ifdef BSLS_PLATFORM_CPU_32_BIT
4744 static const DataType convert[] = {
4745 e_DOUBLE // e_INTERNAL_INF = 0x00
4746 , e_STRING // e_INTERNAL_LONGEST_SHORTSTR = 0x01
4747 , e_BOOLEAN // e_INTERNAL_BOOLEAN = 0x02
4748 , e_STRING // e_INTERNAL_SHORTSTRING = 0x03
4749 , e_STRING // e_INTERNAL_STRING = 0x04
4750 , e_DATE // e_INTERNAL_DATE = 0x05
4751 , e_TIME // e_INTERNAL_TIME = 0x06
4752 , e_DATETIME // e_INTERNAL_DATETIME = 0x07
4753 , e_DATETIME_INTERVAL // e_INTERNAL_DATETIME_INTERVAL = 0x08
4754 , e_INTEGER // e_INTERNAL_INTEGER = 0x09
4755 , e_INTEGER64 // e_INTERNAL_INTEGER64 = 0x0a
4756 , e_USERDEFINED // e_INTERNAL_USERDEFINED = 0x0b
4757 , e_ARRAY // e_INTERNAL_ARRAY = 0x0c
4758 , e_STRING // e_INTERNAL_STRING_REFERENCE = 0x0d
4759 , e_ARRAY // e_INTERNAL_ARRAY_REFERENCE = 0x0e
4760 , e_NIL // e_INTERNAL_EXTENDED = 0x0f
4761 , e_DOUBLE // e_INTERNAL_DOUBLE = 0x10
4762 };
4763
4764 const InternalDataType type = internalType();
4765 if (e_INTERNAL_EXTENDED == type) {
4766 return typeFromExtendedInternalType(); // RETURN
4767 }
4768 return convert[type];
4769#else // end - 32 bit / begin - 64 bit
4770 static const DataType convert[] = {
4771 e_ERROR // e_INTERNAL_UNINITIALIZED; invalid
4772 , e_DOUBLE // e_INTERNAL_INF = 1
4773 , e_NIL // e_INTERNAL_NIL = 2
4774 , e_BOOLEAN // e_INTERNAL_BOOLEAN = 3
4775 , e_STRING // e_INTERNAL_SHORTSTRING = 4
4776 , e_STRING // e_INTERNAL_STRING = 5
4777 , e_DATE // e_INTERNAL_DATE = 6
4778 , e_TIME // e_INTERNAL_TIME = 7
4779 , e_DATETIME // e_INTERNAL_DATETIME = 8
4780 , e_DATETIME_INTERVAL // e_INTERNAL_DATETIME_INTERVAL = 9
4781 , e_INTEGER // e_INTERNAL_INTEGER = 10
4782 , e_INTEGER64 // e_INTERNAL_INTEGER64 = 11
4783 , e_USERDEFINED // e_INTERNAL_USERDEFINED = 12
4784 , e_ARRAY // e_INTERNAL_ARRAY = 13
4785 , e_STRING // e_INTERNAL_STRING_REFERENCE = 14
4786 , e_ARRAY // e_INTERNAL_ARRAY_REFERENCE = 15
4787 , e_DOUBLE // e_INTERNAL_DOUBLE = 16
4788 , e_MAP // e_INTERNAL_MAP = 17
4789 , e_MAP // e_INTERNAL_OWNED_MAP = 18
4790 , e_ERROR // e_INTERNAL_ERROR = 19
4791 , e_ERROR // e_INTERNAL_ERROR_ALLOC = 20
4792 , e_BINARY // e_INTERNAL_BINARY = 21
4793 , e_BINARY // e_INTERNAL_BINARY_ALLOC = 22
4794 , e_DECIMAL64 // e_INTERNAL_DECIMAL64 = 23
4795 , e_INT_MAP // e_INTERNAL_INT_MAP = 24
4796 , e_STRING // e_INTERNAL_LONGEST_SHORTSTRING = 25
4797 };
4798
4799 const InternalDataType type = internalType();
4800
4801 BSLS_ASSERT_SAFE(e_INTERNAL_UNINITIALIZED != type);
4802
4803 return convert[type];
4804#endif // end - 64 bit
4805}
4806
4807template <class t_VISITOR>
4808void Datum::apply(t_VISITOR& visitor) const
4809{
4810#ifdef BSLS_PLATFORM_CPU_32_BIT
4811 switch (internalType()) {
4812 case e_INTERNAL_INF:
4813 visitor(bsl::numeric_limits<double>::infinity());
4814 break;
4815 case e_INTERNAL_BOOLEAN:
4816 visitor(theBoolean());
4817 break;
4818 case e_INTERNAL_SHORTSTRING:
4819 visitor(theShortString());
4820 break;
4821 case e_INTERNAL_LONGEST_SHORTSTRING:
4822 visitor(theLongestShortString());
4823 break;
4824 case e_INTERNAL_STRING:
4825 visitor(theInternalString());
4826 break;
4827 case e_INTERNAL_DATE:
4828 visitor(theDate());
4829 break;
4830 case e_INTERNAL_TIME:
4831 visitor(theTime());
4832 break;
4833 case e_INTERNAL_DATETIME:
4834 visitor(theDatetime());
4835 break;
4836 case e_INTERNAL_DATETIME_INTERVAL:
4837 visitor(theDatetimeInterval());
4838 break;
4839 case e_INTERNAL_INTEGER:
4840 visitor(theInteger());
4841 break;
4842 case e_INTERNAL_INTEGER64:
4843 visitor(theInteger64());
4844 break;
4845 case e_INTERNAL_USERDEFINED:
4846 visitor(theUdt());
4847 break;
4848 case e_INTERNAL_ARRAY:
4849 visitor(theInternalArray());
4850 break;
4851 case e_INTERNAL_STRING_REFERENCE:
4852 visitor(theStringReference());
4853 break;
4854 case e_INTERNAL_ARRAY_REFERENCE:
4855 visitor(theArrayReference());
4856 break;
4857 case e_INTERNAL_EXTENDED:
4858 switch (extendedInternalType()) {
4859 case e_EXTENDED_INTERNAL_INT_MAP:
4860 visitor(theIntMap());
4861 break;
4862 case e_EXTENDED_INTERNAL_MAP:
4864 case e_EXTENDED_INTERNAL_OWNED_MAP:
4865 visitor(theMap());
4866 break;
4867 case e_EXTENDED_INTERNAL_NAN2:
4868 visitor(theDouble());
4869 break;
4870 case e_EXTENDED_INTERNAL_ERROR:
4872 case e_EXTENDED_INTERNAL_ERROR_ALLOC:
4873 visitor(theError());
4874 break;
4875 case e_EXTENDED_INTERNAL_SREF_ALLOC:
4876 visitor(theLongStringReference());
4877 break;
4878 case e_EXTENDED_INTERNAL_AREF_ALLOC:
4879 visitor(theLongArrayReference());
4880 break;
4881 case e_EXTENDED_INTERNAL_DATETIME_ALLOC:
4882 visitor(theDatetime());
4883 break;
4884 case e_EXTENDED_INTERNAL_DATETIME_INTERVAL_ALLOC:
4885 visitor(theDatetimeInterval());
4886 break;
4887 case e_EXTENDED_INTERNAL_INTEGER64_ALLOC:
4888 visitor(theInteger64());
4889 break;
4890 case e_EXTENDED_INTERNAL_BINARY_ALLOC:
4891 visitor(theBinary());
4892 break;
4893 case e_EXTENDED_INTERNAL_DECIMAL64:
4894 case e_EXTENDED_INTERNAL_DECIMAL64_SPECIAL:
4895 case e_EXTENDED_INTERNAL_DECIMAL64_ALLOC: {
4896 // Code below is identical to 'visitor(theDecimal64())' but
4897 // postpones the name lookup for 'theDecimal64()' to the second
4898 // (instantiation) phase, so that we can use only a forward
4899 // declaration of 'bdldfp::Decimal64' in this header. Without this
4900 // workaround clang won't compile calls to 'apply' or 'hashAppend'
4901 // even if '<bdldfp_decimal.h>' is included after this header. See
4902 // the test driver for more information.
4903 typedef bdldfp::Decimal64 (Datum::*Dec64MemFunPtr)() const;
4904 const typename Datum_MakeDependent<
4905 Dec64MemFunPtr,
4906 t_VISITOR>::type dec64MemFunPtr = &Datum::theDecimal64;
4907 visitor((this->*dec64MemFunPtr)());
4908 } break;
4909 case e_EXTENDED_INTERNAL_NIL:
4910 visitor(bslmf::Nil());
4911 break;
4912 default:
4914 0 == "Unknown extended-type (memory corruption?)");
4915 }
4916 break;
4917 case e_INTERNAL_DOUBLE:
4918 visitor(d_double);
4919 break;
4920 default:
4921 BSLS_ASSERT_SAFE(0 == "Unknown type (memory corruption?)");
4922 }
4923#else // end - 32 bit / begin - 64 bit
4924 switch (internalType()) {
4925 case e_INTERNAL_INF:
4926 visitor(bsl::numeric_limits<double>::infinity());
4927 break;
4928 case e_INTERNAL_NIL:
4929 visitor(bslmf::Nil());
4930 break;
4931 case e_INTERNAL_BOOLEAN:
4932 visitor(theBoolean());
4933 break;
4934 case e_INTERNAL_SHORTSTRING:
4935 visitor(theShortString());
4936 break;
4937 case e_INTERNAL_STRING:
4938 visitor(theInternalString());
4939 break;
4940 case e_INTERNAL_DATE:
4941 visitor(theDate());
4942 break;
4943 case e_INTERNAL_TIME:
4944 visitor(theTime());
4945 break;
4946 case e_INTERNAL_DATETIME:
4947 visitor(theDatetime());
4948 break;
4949 case e_INTERNAL_DATETIME_INTERVAL:
4950 visitor(theDatetimeInterval());
4951 break;
4952 case e_INTERNAL_INTEGER:
4953 visitor(theInteger());
4954 break;
4955 case e_INTERNAL_INTEGER64:
4956 visitor(theInteger64());
4957 break;
4958 case e_INTERNAL_USERDEFINED:
4959 visitor(theUdt());
4960 break;
4961 case e_INTERNAL_ARRAY:
4962 visitor(theInternalArray());
4963 break;
4964 case e_INTERNAL_STRING_REFERENCE:
4965 visitor(theStringReference());
4966 break;
4967 case e_INTERNAL_ARRAY_REFERENCE:
4968 visitor(theArrayReference());
4969 break;
4970 case e_INTERNAL_MAP:
4972 case e_INTERNAL_OWNED_MAP:
4973 visitor(theMap());
4974 break;
4975 case e_INTERNAL_ERROR:
4977 case e_INTERNAL_ERROR_ALLOC:
4978 visitor(theError());
4979 break;
4980 case e_INTERNAL_DOUBLE:
4981 visitor(d_as.d_double);
4982 break;
4983 case e_INTERNAL_BINARY:
4985 case e_INTERNAL_BINARY_ALLOC:
4986 visitor(theBinary());
4987 break;
4988 case e_INTERNAL_DECIMAL64: {
4989 // Code below is identical to 'visitor(theDecimal64())' but postpones
4990 // the name lookup for 'theDecimal64()' to the second (instantiation)
4991 // phase, so that we can use only forward declaration of
4992 // 'bdldfp::Decimal64' in this header. Without this workaround clang
4993 // won't compile calls to 'apply' or 'hashAppend' even if
4994 // '<bdldfp_decimal.h>' is included after this header. See the test
4995 // driver for more information.
4996 typedef bdldfp::Decimal64 (Datum::*Dec64MemFunPtr)() const;
4997 const typename Datum_MakeDependent<
4998 Dec64MemFunPtr,
4999 t_VISITOR>::type dec64MemFunPtr = &Datum::theDecimal64;
5000 visitor((this->*dec64MemFunPtr)());
5001 } break;
5002 case e_INTERNAL_INT_MAP:
5003 visitor(theIntMap());
5004 break;
5005 case e_INTERNAL_LONGEST_SHORTSTRING:
5006 visitor(theLongestShortString());
5007 break;
5008 case e_INTERNAL_UNINITIALIZED:
5009 BSLS_ASSERT(0 == "Uninitialized Datum");
5010 break;
5011 default:
5012 BSLS_ASSERT_SAFE(0 == "Unknown type (memory corruption?)");
5013 }
5014#endif // end - 64 bit
5015}
5016
5017#ifndef BDE_OMIT_INTERNAL_DEPRECATED
5018inline
5019void Datum::createUninitializedMapOwningKeys(
5021 SizeType capacity,
5022 SizeType keysCapacity,
5023 const AllocatorType& allocator)
5024{
5025 createUninitializedMap(result, capacity, keysCapacity, allocator);
5026}
5027
5028inline
5029Datum Datum::adoptMapOwningKeys(const DatumMutableMapOwningKeysRef& mapping)
5030{
5031 return adoptMap(mapping);
5032}
5033
5034inline
5035void Datum::disposeUninitializedMapOwningKeys(
5036 const DatumMutableMapOwningKeysRef& mapping,
5037 const AllocatorType& allocator)
5038{
5039 return disposeUninitializedMap(mapping, allocator);
5040}
5041#endif // end - do not omit internal deprecated
5042
5043 // -------------------
5044 // class DatumArrayRef
5045 // -------------------
5046
5047// CREATORS
5048inline
5049DatumArrayRef::DatumArrayRef()
5050: d_data_p(0)
5051, d_length(0)
5052{
5053}
5054
5055inline
5057 SizeType length)
5058: d_data_p(data)
5059, d_length(length)
5060{
5061 BSLS_ASSERT(data || 0 == length);
5062}
5063
5064// ACCESSORS
5065inline
5067{
5068 BSLS_ASSERT_SAFE(index < d_length);
5069 return d_data_p[index];
5070}
5071
5072inline
5075{
5076 return d_data_p;
5077}
5078
5079inline
5082{
5083 return d_length;
5084}
5085
5086inline
5089{
5090 return d_length;
5091}
5092
5093inline
5096{
5097 return d_data_p;
5098}
5099
5100inline
5103{
5104 return d_data_p;
5105}
5106
5107inline
5113
5114inline
5120
5121inline
5124{
5125 return d_data_p + d_length;
5126}
5127
5128inline
5131{
5132 return end();
5133}
5134
5135inline
5141
5142inline
5148
5149
5150inline
5153{
5154 BSLS_ASSERT(!empty());
5155 return *begin();
5156}
5157
5158inline
5161{
5162 BSLS_ASSERT(!empty());
5163 return *(end() - 1);
5164}
5165
5166inline
5168{
5169 return 0 == d_length;
5170}
5171
5172 // ----------------------
5173 // class DatumIntMapEntry
5174 // ----------------------
5175// CREATORS
5176inline
5180
5181inline
5183 const Datum& value)
5184: d_key(key)
5185, d_value(value)
5186{
5187}
5188
5189// MANIPULATORS
5190inline
5192{
5193 d_key = key;
5194}
5195
5196inline
5198{
5199 d_value = value;
5200}
5201
5202// ACCESSORS
5203inline
5205{
5206 return d_key;
5207}
5208
5209inline
5211{
5212 return d_value;
5213}
5214
5215 // --------------------
5216 // class DatumIntMapRef
5217 // --------------------
5218// CREATORS
5219inline
5221 SizeType size,
5222 bool sorted)
5223: d_data_p(data)
5224, d_size(size)
5225, d_sorted(sorted)
5226{
5227 BSLS_ASSERT((size && data) || !size);
5228}
5229
5230// ACCESSORS
5231inline
5233{
5234 BSLS_ASSERT_SAFE(index < d_size);
5235 return d_data_p[index];
5236}
5237
5238inline
5241{
5242 return d_data_p;
5243}
5244
5245inline
5251
5252inline
5255{
5256 return d_data_p;
5257}
5258
5259inline
5262{
5263 return d_data_p;
5264}
5265
5266inline
5272
5273inline
5279
5280inline
5283{
5284 return d_data_p + d_size;
5285}
5286
5287inline
5290{
5291 return end();
5292}
5293
5294inline
5300
5301inline
5307
5308
5309inline
5312{
5313 BSLS_ASSERT(!empty());
5314 return *begin();
5315}
5316
5317inline
5320{
5321 BSLS_ASSERT(!empty());
5322 return *(end() - 1);
5323}
5324
5325inline
5327{
5328 return 0 == d_size;
5329}
5330
5331inline
5333{
5334 return d_sorted;
5335}
5336
5337 // -------------------
5338 // class DatumMapEntry
5339 // -------------------
5340// CREATORS
5341inline
5345
5346inline
5348 const Datum& value)
5349: d_key_p(key)
5350, d_value(value)
5351{
5352}
5353
5354// MANIPULATORS
5355inline
5357{
5358 d_key_p = key;
5359}
5360
5361inline
5363{
5364 d_value = value;
5365}
5366
5367// ACCESSORS
5368inline
5370{
5371 return d_key_p;
5372}
5373
5374inline
5376{
5377 return d_value;
5378}
5379
5380 // -----------------
5381 // class DatumMapRef
5382 // -----------------
5383// CREATORS
5384inline
5386 SizeType size,
5387 bool sorted,
5388 bool ownsKeys)
5389: d_data_p(data)
5390, d_size(size)
5391, d_sorted(sorted)
5392, d_ownsKeys(ownsKeys)
5393{
5394 BSLS_ASSERT((size && data) || !size);
5395 if (0 == size) {
5396 d_ownsKeys = false;
5397 }
5398}
5399
5400// ACCESSORS
5401inline
5403{
5404 BSLS_ASSERT_SAFE(index < d_size);
5405 return d_data_p[index];
5406}
5407
5408inline
5411{
5412 return d_data_p;
5413}
5414
5415inline
5418{
5419 return d_size;
5420}
5421
5422inline
5425{
5426 return d_data_p;
5427}
5428
5429inline
5432{
5433 return d_data_p;
5434}
5435
5436inline
5442
5443inline
5449
5450inline
5453{
5454 return d_data_p + d_size;
5455}
5456
5457inline
5460{
5461 return end();
5462}
5463
5464inline
5470
5471inline
5477
5478
5479inline
5482{
5483 BSLS_ASSERT(!empty());
5484 return *begin();
5485}
5486
5487inline
5490{
5491 BSLS_ASSERT(!empty());
5492 return *(end() - 1);
5493}
5494
5495inline
5497{
5498 return 0 == d_size;
5499}
5500
5501inline
5503{
5504 return d_sorted;
5505}
5506
5507inline
5509{
5510 return d_ownsKeys;
5511}
5512
5513 // --------------------------
5514 // class DatumMutableArrayRef
5515 // --------------------------
5516
5517// CREATORS
5518inline
5520: d_data_p(0)
5521, d_length_p(0)
5522, d_capacity(0)
5523{
5524}
5525
5526inline
5528 SizeType *length,
5529 SizeType capacity)
5530: d_data_p(data)
5531, d_length_p(length)
5532, d_capacity(capacity)
5533{
5534}
5535
5536// ACCESSORS
5537inline
5539{
5540 return d_length_p;
5541}
5542
5543inline
5545{
5546 return d_data_p;
5547}
5548
5549inline
5551{
5552 return d_length_p;
5553}
5554
5555inline
5557{
5558 return d_capacity;
5559}
5560
5561 // ---------------------------
5562 // class DatumMutableIntMapRef
5563 // ---------------------------
5564
5565// CREATORS
5566inline
5568: d_data_p(0)
5569, d_size_p(0)
5570, d_sorted_p(0)
5571{
5572}
5573
5574inline
5576 SizeType *size,
5577 bool *sorted)
5578: d_data_p(data)
5579, d_size_p(size)
5580, d_sorted_p(sorted)
5581{
5582}
5583
5584// ACCESSORS
5585inline
5587{
5588 return d_size_p;
5589}
5590
5591inline
5593{
5594 return d_data_p;
5595}
5596
5597inline
5599{
5600 return d_size_p;
5601}
5602
5603inline
5605{
5606 return d_sorted_p;
5607}
5608
5609 // ------------------------
5610 // class DatumMutableMapRef
5611 // ------------------------
5612
5613// CREATORS
5614inline
5616: d_data_p(0)
5617, d_size_p(0)
5618, d_sorted_p(0)
5619{
5620}
5621
5622inline
5624 SizeType *size,
5625 bool *sorted)
5626: d_data_p(data)
5627, d_size_p(size)
5628, d_sorted_p(sorted)
5629{
5630}
5631
5632// ACCESSORS
5633inline
5635{
5636 return d_size_p;
5637}
5638
5639inline
5641{
5642 return d_data_p;
5643}
5644
5645inline
5647{
5648 return d_size_p;
5649}
5650
5651inline
5653{
5654 return d_sorted_p;
5655}
5656
5657 // ----------------------------------
5658 // class DatumMutableMapOwningKeysRef
5659 // ----------------------------------
5660
5661// CREATORS
5662inline
5664: d_data_p(0)
5665, d_size_p(0)
5666, d_allocatedSize(0)
5667, d_keys_p(0)
5668, d_sorted_p(0)
5669{
5670}
5671
5672inline
5674 DatumMapEntry *data,
5675 SizeType *size,
5676 SizeType allocatedSize,
5677 char *keys,
5678 bool *sorted)
5679: d_data_p(data)
5680, d_size_p(size)
5681, d_allocatedSize(allocatedSize)
5682, d_keys_p(keys)
5683, d_sorted_p(sorted)
5684{
5685}
5686
5687// ACCESSORS
5688inline
5690{
5691 return d_size_p;
5692}
5693
5694inline
5697{
5698 return d_allocatedSize;
5699}
5700
5701inline
5703{
5704 return d_data_p;
5705}
5706
5707inline
5709{
5710 return d_keys_p;
5711}
5712
5713inline
5716{
5717 return d_size_p;
5718}
5719
5720inline
5722{
5723 return d_sorted_p;
5724}
5725
5726} // close package namespace
5727
5728// FREE OPERATORS
5729inline
5730bool bdld::operator!=(const Datum& lhs, const Datum& rhs)
5731{
5732 return !(lhs == rhs);
5733}
5734
5735inline
5736bool bdld::operator!=(const DatumArrayRef& lhs, const DatumArrayRef& rhs)
5737{
5738 return !(lhs == rhs);
5739}
5740
5741inline
5742bool bdld::operator==(const DatumIntMapEntry& lhs, const DatumIntMapEntry& rhs)
5743{
5744 return (lhs.key() == rhs.key()) && (lhs.value() == rhs.value());
5745}
5746
5747inline
5748bool bdld::operator!=(const DatumIntMapEntry& lhs, const DatumIntMapEntry& rhs)
5749{
5750 return !(lhs == rhs);
5751}
5752
5753inline
5754bool bdld::operator!=(const DatumIntMapRef& lhs, const DatumIntMapRef& rhs)
5755{
5756 return !(lhs == rhs);
5757}
5758
5759inline
5760bool bdld::operator==(const DatumMapEntry& lhs, const DatumMapEntry& rhs)
5761{
5762 return (lhs.key() == rhs.key()) && (lhs.value() == rhs.value());
5763}
5764
5765inline
5766bool bdld::operator!=(const DatumMapEntry& lhs, const DatumMapEntry& rhs)
5767{
5768 return !(lhs == rhs);
5769}
5770
5771inline
5772bool bdld::operator!=(const DatumMapRef& lhs, const DatumMapRef& rhs)
5773{
5774 return !(lhs == rhs);
5775}
5776
5777inline
5778bsl::ostream& bdld::operator<<(bsl::ostream& stream, const Datum& rhs)
5779{
5780 return rhs.print(stream, 0, -1);
5781}
5782
5783template <class t_HASH_ALGORITHM>
5784void bdld::hashAppend(t_HASH_ALGORITHM& hashAlg, const bdld::Datum& input)
5785{
5786 using bslh::hashAppend;
5787 hashAppend(hashAlg, input.type());
5788
5789 switch (input.type()) {
5790 case bdld::Datum::e_NIL: {
5791 // Do nothing. This is sufficient because 'type' has already been
5792 // hashed (differentiating the nil value).
5793 } break;
5795 hashAppend(hashAlg, input.theInteger());
5796 } break;
5797 case bdld::Datum::e_DOUBLE: {
5798 hashAppend(hashAlg, input.theDouble());
5799 } break;
5800 case bdld::Datum::e_STRING: {
5801 hashAppend(hashAlg, input.theString());
5802 } break;
5804 hashAppend(hashAlg, input.theBoolean());
5805 } break;
5806 case bdld::Datum::e_ERROR: {
5807 hashAppend(hashAlg, input.theError().code());
5808 hashAppend(hashAlg, input.theError().message());
5809 } break;
5810 case bdld::Datum::e_DATE: {
5811 hashAppend(hashAlg, input.theDate());
5812 } break;
5813 case bdld::Datum::e_TIME: {
5814 hashAppend(hashAlg, input.theTime());
5815 } break;
5817 hashAppend(hashAlg, input.theDatetime());
5818 } break;
5820 hashAppend(hashAlg, input.theDatetimeInterval());
5821 } break;
5823 hashAppend(hashAlg, input.theInteger64());
5824 } break;
5826 hashAppend(hashAlg, input.theUdt().type());
5827 hashAppend(hashAlg, input.theUdt().data());
5828 } break;
5829 case bdld::Datum::e_ARRAY: {
5830 hashAppend(hashAlg, input.theArray().length());
5831 for (bsl::size_t i = 0; i < input.theArray().length(); ++i) {
5832 bdld::hashAppend(hashAlg, input.theArray()[i]);
5833 }
5834 } break;
5835 case bdld::Datum::e_MAP: {
5836 hashAppend(hashAlg, input.theMap().size());
5837 for (bsl::size_t i = 0; i < input.theMap().size(); ++i) {
5838 hashAppend(hashAlg, input.theMap()[i].key());
5839 bdld::hashAppend(hashAlg, input.theMap()[i].value());
5840 }
5841 } break;
5842 case bdld::Datum::e_BINARY: {
5843 hashAppend(hashAlg, input.theBinary().size());
5844 if (input.theBinary().size() > 0) {
5845 hashAlg(input.theBinary().data(), input.theBinary().size());
5846 }
5847 } break;
5849 // Code below is identical to
5850 // 'hashAppend(hashAlg, input.theDecimal64())', but postpones the
5851 // name lookup for 'theDecimal64()' to the second (instantiation)
5852 // phase so that we can use only forward declaration of
5853 // 'bdldfp::Decimal64' in this header. Without this workaround clang
5854 // won't compile calls to 'apply' or 'hashAppend' even if
5855 // '<bdldfp_decimal.h>' is included after this header. See the test
5856 // driver for more information.
5857 typedef bdldfp::Decimal64 (Datum::*Dec64MemFunPtr)() const;
5858 const typename Datum_MakeDependent<Dec64MemFunPtr,
5859 t_HASH_ALGORITHM>::type
5860 dec64MemFunPtr = &Datum::theDecimal64;
5861 hashAppend(hashAlg, (input.*dec64MemFunPtr)());
5862 } break;
5864 hashAppend(hashAlg, input.theIntMap().size());
5865 for (bsl::size_t i = 0; i < input.theIntMap().size(); ++i) {
5866 hashAppend(hashAlg, input.theIntMap()[i].key());
5867 bdld::hashAppend(hashAlg, input.theIntMap()[i].value());
5868 }
5869 } break;
5870 default: {
5871 BSLS_ASSERT(0 == "Unknown type (memory corruption?)");
5872 }
5873 }
5874}
5875
5876inline
5877bsl::ostream& bdld::operator<<(bsl::ostream& stream, const DatumArrayRef& rhs)
5878{
5879 return rhs.print(stream, 0 , -1);
5880}
5881
5882inline
5883bsl::ostream& bdld::operator<<(bsl::ostream& stream, const DatumMapEntry& rhs)
5884{
5885 return rhs.print(stream, 0 , -1);
5886}
5887
5888inline
5889bsl::ostream& bdld::operator<<(bsl::ostream& stream,
5890 const DatumIntMapEntry& rhs)
5891{
5892 return rhs.print(stream, 0 , -1);
5893}
5894
5895inline
5896bsl::ostream& bdld::operator<<(bsl::ostream& stream, const DatumIntMapRef& rhs)
5897{
5898 return rhs.print(stream, 0 , -1);
5899}
5900
5901inline
5902bsl::ostream& bdld::operator<<(bsl::ostream& stream, const DatumMapRef& rhs)
5903{
5904 return rhs.print(stream, 0 , -1);
5905}
5906
5907
5908
5909#endif
5910
5911// ----------------------------------------------------------------------------
5912// Copyright 2020 Bloomberg Finance L.P.
5913//
5914// Licensed under the Apache License, Version 2.0 (the "License");
5915// you may not use this file except in compliance with the License.
5916// You may obtain a copy of the License at
5917//
5918// http://www.apache.org/licenses/LICENSE-2.0
5919//
5920// Unless required by applicable law or agreed to in writing, software
5921// distributed under the License is distributed on an "AS IS" BASIS,
5922// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
5923// See the License for the specific language governing permissions and
5924// limitations under the License.
5925// ----------------------------- END-OF-FILE ----------------------------------
5926
5927/** @} */
5928/** @} */
5929/** @} */
Definition bdld_datum.h:2561
size_type length() const
Return a const pointer to the length of the array.
Definition bdld_datum.h:5081
~DatumArrayRef()=default
const_iterator begin() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5095
BSLMF_NESTED_TRAIT_DECLARATION(DatumArrayRef, bdlb::HasPrintMethod)
bsl::reverse_iterator< const_iterator > const_reverse_iterator
Definition bdld_datum.h:2581
size_type size() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5088
DatumArrayRef()
Create a DatumArrayRef object representing an empty array.
Definition bdld_datum.h:5049
bsl::size_t size_type
Definition bdld_datum.h:2568
const_iterator end() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5123
DatumArrayRef(const DatumArrayRef &other)=default
DatumArrayRef & operator=(const DatumArrayRef &rhs)=default
Assign to this object the value of the specified rhs object.
const_reverse_iterator rbegin() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5109
bsl::ptrdiff_t difference_type
Definition bdld_datum.h:2569
const_reverse_iterator crbegin() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5116
element_type & reference
Definition bdld_datum.h:2574
pointer data() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5074
bsl::reverse_iterator< iterator > reverse_iterator
Definition bdld_datum.h:2580
const_reference operator[](size_type position) const
Definition bdld_datum.h:5066
Datum::SizeType SizeType
Definition bdld_datum.h:2585
const bdld::Datum element_type
Definition bdld_datum.h:2565
const_reverse_iterator rend() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5137
element_type * pointer
Definition bdld_datum.h:2571
bool empty() const BSLS_KEYWORD_NOEXCEPT
Return size() == 0.
Definition bdld_datum.h:5167
pointer iterator
Definition bdld_datum.h:2577
const_iterator cbegin() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5102
const_reference back() const
Definition bdld_datum.h:5160
BSLMF_NESTED_TRAIT_DECLARATION(DatumArrayRef, bsl::is_trivially_copyable)
const_iterator cend() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5130
const_reverse_iterator crend() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5144
const element_type & const_reference
Definition bdld_datum.h:2575
bdld::Datum value_type
Definition bdld_datum.h:2566
const_reference front() const
Definition bdld_datum.h:5152
const element_type * const_pointer
Definition bdld_datum.h:2572
const_pointer const_iterator
Definition bdld_datum.h:2578
Definition bdld_datumbinaryref.h:157
const void * data() const
Return the pointer to the non-modifiable binary data.
Definition bdld_datumbinaryref.h:294
SizeType size() const
Return the size of the binary data.
Definition bdld_datumbinaryref.h:300
Definition bdld_datumerror.h:161
bslstl::StringRef message() const
Definition bdld_datumerror.h:327
int code() const
Return the error code.
Definition bdld_datumerror.h:321
Definition bdld_datum.h:2734
const Datum & value() const
Return the value for this entry.
Definition bdld_datum.h:5210
bsl::ostream & print(bsl::ostream &stream, int level=0, int spacesPerLevel=4) const
BSLMF_NESTED_TRAIT_DECLARATION(DatumIntMapEntry, bdlb::HasPrintMethod)
BSLMF_NESTED_TRAIT_DECLARATION(DatumIntMapEntry, bsl::is_trivially_copyable)
void setValue(const Datum &value)
Set the value for this entry to the specified value.
Definition bdld_datum.h:5197
DatumIntMapEntry()
Create a DatumIntMapEntry object.
Definition bdld_datum.h:5177
void setKey(int key)
Set the key for this entry to the specified key.
Definition bdld_datum.h:5191
~DatumIntMapEntry()=default
Destroy this object.
int key() const
Return the key for this entry.
Definition bdld_datum.h:5204
Definition bdld_datum.h:2831
const_iterator begin() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5254
const_reverse_iterator crbegin() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5275
const element_type * const_pointer
Definition bdld_datum.h:2842
~DatumIntMapRef()=default
Destroy this object.
Datum::SizeType SizeType
Definition bdld_datum.h:2857
element_type * pointer
Definition bdld_datum.h:2841
const_iterator cbegin() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5261
element_type & reference
Definition bdld_datum.h:2844
const_pointer const_iterator
Definition bdld_datum.h:2848
bsl::reverse_iterator< iterator > reverse_iterator
Definition bdld_datum.h:2850
pointer data() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5240
bsl::ptrdiff_t difference_type
Definition bdld_datum.h:2839
const element_type & const_reference
Definition bdld_datum.h:2845
const_reference back() const
Definition bdld_datum.h:5319
const_iterator cend() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5289
bdld::DatumIntMapEntry value_type
Definition bdld_datum.h:2836
bool empty() const BSLS_KEYWORD_NOEXCEPT
Return size() == 0.
Definition bdld_datum.h:5326
const_reverse_iterator crend() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5303
const_iterator end() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5282
const_reverse_iterator rbegin() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5268
BSLMF_NESTED_TRAIT_DECLARATION(DatumIntMapRef, bsl::is_trivially_copyable)
bool isSorted() const
Return true if underlying map is sorted and false otherwise.
Definition bdld_datum.h:5332
const_reference operator[](size_type position) const
Definition bdld_datum.h:5232
size_type size() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5246
bsl::size_t size_type
Definition bdld_datum.h:2838
DatumIntMapRef(const DatumIntMapEntry *data, SizeType size, bool sorted)
Definition bdld_datum.h:5220
const bdld::DatumIntMapEntry element_type
Definition bdld_datum.h:2835
bsl::reverse_iterator< const_iterator > const_reverse_iterator
Definition bdld_datum.h:2851
pointer iterator
Definition bdld_datum.h:2847
BSLMF_NESTED_TRAIT_DECLARATION(DatumIntMapRef, bdlb::HasPrintMethod)
const_reference front() const
Definition bdld_datum.h:5311
const_reverse_iterator rend() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5296
Definition bdld_datum.h:3007
DatumMapEntry()
Create a DatumMapEntry object.
Definition bdld_datum.h:5342
BSLMF_NESTED_TRAIT_DECLARATION(DatumMapEntry, bsl::is_trivially_copyable)
const Datum & value() const
Return the value for this entry.
Definition bdld_datum.h:5375
BSLMF_NESTED_TRAIT_DECLARATION(DatumMapEntry, bdlb::HasPrintMethod)
bsl::ostream & print(bsl::ostream &stream, int level=0, int spacesPerLevel=4) const
void setKey(const bslstl::StringRef &key)
Set the key for this entry to the specified key.
Definition bdld_datum.h:5356
const bslstl::StringRef & key() const
Return the key for this entry.
Definition bdld_datum.h:5369
void setValue(const Datum &value)
Set the value for this entry to the specified value.
Definition bdld_datum.h:5362
~DatumMapEntry()=default
Destroy this object.
Definition bdld_datum.h:3100
bsl::size_t size_type
Definition bdld_datum.h:3107
const_pointer const_iterator
Definition bdld_datum.h:3117
bsl::reverse_iterator< const_iterator > const_reverse_iterator
Definition bdld_datum.h:3120
element_type * pointer
Definition bdld_datum.h:3110
bool empty() const BSLS_KEYWORD_NOEXCEPT
Return size() == 0.
Definition bdld_datum.h:5496
const_iterator cbegin() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5431
size_type size() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5416
DatumMapRef(const DatumMapEntry *data, SizeType size, bool sorted, bool ownsKeys)
Definition bdld_datum.h:5385
const_reverse_iterator crbegin() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5445
const element_type & const_reference
Definition bdld_datum.h:3114
pointer data() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5410
BSLMF_NESTED_TRAIT_DECLARATION(DatumMapRef, bdlb::HasPrintMethod)
const_reverse_iterator crend() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5473
const_reference front() const
Definition bdld_datum.h:5481
bdld::DatumMapEntry value_type
Definition bdld_datum.h:3105
bool ownsKeys() const
Definition bdld_datum.h:5508
bsl::ptrdiff_t difference_type
Definition bdld_datum.h:3108
bsl::reverse_iterator< iterator > reverse_iterator
Definition bdld_datum.h:3119
const_reverse_iterator rend() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5466
pointer iterator
Definition bdld_datum.h:3116
const bdld::DatumMapEntry element_type
Definition bdld_datum.h:3104
element_type & reference
Definition bdld_datum.h:3113
Datum::SizeType SizeType
Definition bdld_datum.h:3126
const_iterator end() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5452
const_reverse_iterator rbegin() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5438
bool isSorted() const
Return true if underlying map is sorted and false otherwise.
Definition bdld_datum.h:5502
const_iterator cend() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5459
const_iterator begin() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5424
const element_type * const_pointer
Definition bdld_datum.h:3111
~DatumMapRef()=default
Destroy this object.
BSLMF_NESTED_TRAIT_DECLARATION(DatumMapRef, bsl::is_trivially_copyable)
const_reference back() const
Definition bdld_datum.h:5489
const_reference operator[](size_type position) const
Definition bdld_datum.h:5402
Definition bdld_datum.h:2224
DatumMutableArrayRef & operator=(const DatumMutableArrayRef &rhs)=default
SizeType capacity() const
Return the allocated capacity of the array.
Definition bdld_datum.h:5556
Datum::SizeType SizeType
Definition bdld_datum.h:2231
void * allocatedPtr() const
Return pointer to the memory allocated for the array.
Definition bdld_datum.h:5538
DatumMutableArrayRef()
Create a DatumMutableArrayRef object that refers to no array.
Definition bdld_datum.h:5519
SizeType * length() const
Return pointer to the length of the array.
Definition bdld_datum.h:5550
Datum * data() const
Return pointer to the first element of the held array.
Definition bdld_datum.h:5544
DatumMutableArrayRef(const DatumMutableArrayRef &original)=default
Definition bdld_datum.h:2398
void * allocatedPtr() const
Return pointer to the memory allocated for the map.
Definition bdld_datum.h:5586
bool * sorted() const
Definition bdld_datum.h:5604
Datum::SizeType SizeType
Definition bdld_datum.h:2406
DatumMutableIntMapRef(const DatumMutableIntMapRef &original)=default
SizeType * size() const
Definition bdld_datum.h:5598
DatumMutableIntMapRef()
Create a DatumMutableIntMapRef object.
Definition bdld_datum.h:5567
DatumMutableIntMapRef & operator=(const DatumMutableIntMapRef &rhs)=default
DatumIntMapEntry * data() const
Return pointer to the first element in the (held) map.
Definition bdld_datum.h:5592
Definition bdld_datum.h:2474
DatumMutableMapOwningKeysRef()
Create a DatumMutableMapOwningKeysRef object.
Definition bdld_datum.h:5663
Datum::SizeType SizeType
Definition bdld_datum.h:2482
SizeType * size() const
Definition bdld_datum.h:5715
~DatumMutableMapOwningKeysRef()=default
Destroy this object.
DatumMapEntry * data() const
Return pointer to the first element in the held map.
Definition bdld_datum.h:5702
DatumMutableMapOwningKeysRef(const DatumMutableMapOwningKeysRef &original)=default
DatumMutableMapOwningKeysRef & operator=(const DatumMutableMapOwningKeysRef &rhs)=default
void * allocatedPtr() const
Return pointer to the memory allocated for the map.
Definition bdld_datum.h:5689
char * keys() const
Return pointer to the start of the buffer where keys are stored.
Definition bdld_datum.h:5708
bool * sorted() const
Definition bdld_datum.h:5721
SizeType allocatedSize() const
Return the number of bytes allocated for the map.
Definition bdld_datum.h:5696
Definition bdld_datum.h:2326
DatumMapEntry * data() const
Return pointer to the first element in the (held) map.
Definition bdld_datum.h:5640
Datum::SizeType SizeType
Definition bdld_datum.h:2334
SizeType * size() const
Definition bdld_datum.h:5646
DatumMutableMapRef & operator=(const DatumMutableMapRef &rhs)=default
DatumMutableMapRef()
Create a DatumMutableMapRef object.
Definition bdld_datum.h:5615
DatumMutableMapRef(const DatumMutableMapRef &original)=default
void * allocatedPtr() const
Return pointer to the memory allocated for the map.
Definition bdld_datum.h:5634
bool * sorted() const
Definition bdld_datum.h:5652
Definition bdld_datumudt.h:144
void * data() const
Return the pointer to the user-defined object.
Definition bdld_datumudt.h:275
int type() const
Return the type of the user-defined object.
Definition bdld_datumudt.h:281
Definition bdld_datum.h:799
DatumArrayRef theArray() const
Definition bdld_datum.h:4440
bsls::AlignedBuffer< 16 > d_data
Definition bdld_datum.h:1340
bool isArray() const
Definition bdld_datum.h:4282
friend bool operator==(const Datum &lhs, const Datum &rhs)
static Datum adoptMapOwningKeys(const DatumMutableMapOwningKeysRef &mapping)
Definition bdld_datum.h:5029
static Datum createTime(const bdlt::Time &value)
Return, by value, a datum having the specified Time value.
Definition bdld_datum.h:4119
static void createUninitializedMap(DatumMutableMapOwningKeysRef *result, SizeType capacity, SizeType keysCapacity, const AllocatorType &allocator)
bdlt::Datetime theDatetime() const
Definition bdld_datum.h:4506
static Datum adoptIntMap(const DatumMutableIntMapRef &intMap)
Definition bdld_datum.h:4190
static Datum createStringRef(const char *string, SizeType length, const AllocatorType &allocator)
Definition bdld_datum.h:4065
@ k_NUM_TYPES
Definition bdld_datum.h:838
bool isError() const
Definition bdld_datum.h:4340
static Datum createNull()
Return, by value, a datum having no value.
Definition bdld_datum.h:4049
DatumMapRef theMap() const
Definition bdld_datum.h:4647
bsls::Types::size_type SizeType
Definition bdld_datum.h:1478
static void createUninitializedMap(DatumMutableMapRef *result, SizeType capacity, const AllocatorType &allocator)
bool isString() const
Definition bdld_datum.h:4422
static Datum createError(int code)
Definition bdld_datum.h:4000
bool isBoolean() const
Definition bdld_datum.h:4294
DatumBinaryRef theBinary() const
Definition bdld_datum.h:4459
static const char * dataTypeToAscii(DataType type)
static Datum copyString(const char *string, SizeType length, const AllocatorType &allocator)
friend bool operator!=(const Datum &lhs, const Datum &rhs)
DataType type() const
Definition bdld_datum.h:4741
static Datum createInteger64(bsls::Types::Int64 value, const AllocatorType &allocator)
Definition bdld_datum.h:4025
bdlt::DatetimeInterval theDatetimeInterval() const
Definition bdld_datum.h:4538
bslstl::StringRef theString() const
Definition bdld_datum.h:4686
bsl::allocator AllocatorType
Definition bdld_datum.h:807
Datum()=default
static Datum createUdt(void *data, int type)
Definition bdld_datum.h:4140
TypedAccess d_as
Definition bdld_datum.h:1341
static void createUninitializedArray(DatumMutableArrayRef *result, SizeType capacity, const AllocatorType &allocator)
bool isInteger() const
Definition bdld_datum.h:4382
bool isMap() const
Definition bdld_datum.h:4405
bdlt::Time theTime() const
Definition bdld_datum.h:4715
BSLMF_NESTED_TRAIT_DECLARATION(Datum, bdlb::HasPrintMethod)
~Datum()=default
bsl::ostream & print(bsl::ostream &stream, int level=0, int spacesPerLevel=4) const
Datum & operator=(const Datum &rhs)=default
static Datum createArrayReference(const Datum *array, SizeType length, const AllocatorType &allocator)
Definition bdld_datum.h:3832
DatumError theError() const
Definition bdld_datum.h:4586
static void destroy(const Datum &value, const AllocatorType &allocator)
bdldfp::Decimal64 theDecimal64() const
bool theBoolean() const
Definition bdld_datum.h:4482
static Datum createDecimal64(bdldfp::Decimal64 value, const AllocatorType &allocator)
BSLMF_NESTED_TRAIT_DECLARATION(Datum, bslmf::IsBitwiseMoveable)
static Datum createDouble(double value)
Definition bdld_datum.h:3982
static Datum createInteger(int value)
Return, by value, a datum having the specified int value.
Definition bdld_datum.h:4010
static Datum adoptArray(const DatumMutableArrayRef &array)
Definition bdld_datum.h:4158
static void * createUninitializedBinary(Datum *result, SizeType size, const AllocatorType &allocator)
bool isExternalReference() const
Definition bdld_datum.h:4346
Datum clone(const AllocatorType &allocator) const
BSLMF_NESTED_TRAIT_DECLARATION(Datum, bsl::is_trivially_copyable)
static Datum createDatetime(const bdlt::Datetime &value, const AllocatorType &allocator)
Definition bdld_datum.h:3910
bool isDouble() const
Definition bdld_datum.h:4334
BSLMF_NESTED_TRAIT_DECLARATION(Datum, bsl::is_trivially_default_constructible)
bdlt::Date theDate() const
Definition bdld_datum.h:4494
static void disposeUninitializedIntMap(const DatumMutableIntMapRef &intMap, const AllocatorType &allocator)
Definition bdld_datum.h:4238
static Datum copyBinary(const void *value, SizeType size, const AllocatorType &allocator)
static void disposeUninitializedMapOwningKeys(const DatumMutableMapOwningKeysRef &mapping, const AllocatorType &allocator)
Definition bdld_datum.h:5035
DatumIntMapRef theIntMap() const
Definition bdld_datum.h:4667
static void createUninitializedIntMap(DatumMutableIntMapRef *result, SizeType capacity, const AllocatorType &allocator)
double theDouble() const
Definition bdld_datum.h:4567
static void createUninitializedMapOwningKeys(DatumMutableMapOwningKeysRef *result, SizeType capacity, SizeType keysCapacity, const AllocatorType &allocator)
Definition bdld_datum.h:5019
bsls::Types::Int64 theInteger64() const
Definition bdld_datum.h:4627
static Datum createError(int code, const bslstl::StringRef &message, const AllocatorType &allocator)
bool isNull() const
Definition bdld_datum.h:4411
static Datum createDatetimeInterval(const bdlt::DatetimeInterval &value, const AllocatorType &allocator)
Definition bdld_datum.h:3951
bool isDecimal64() const
Definition bdld_datum.h:4328
bool isInteger64() const
Definition bdld_datum.h:4393
static void disposeUninitializedMap(const DatumMutableMapRef &map, const AllocatorType &allocator)
Definition bdld_datum.h:4254
bool isBinary() const
Definition bdld_datum.h:4288
friend bsl::ostream & operator<<(bsl::ostream &stream, const Datum &rhs)
void apply(t_VISITOR &visitor) const
Definition bdld_datum.h:4808
static Datum createDate(const bdlt::Date &value)
Return, by value, a datum having the specified Date value.
Definition bdld_datum.h:3892
DataType
Definition bdld_datum.h:811
@ e_MAP
Definition bdld_datum.h:825
@ e_BINARY
Definition bdld_datum.h:826
@ e_DATETIME_INTERVAL
Definition bdld_datum.h:821
@ e_ARRAY
Definition bdld_datum.h:824
@ e_TIME
Definition bdld_datum.h:819
@ e_INTEGER
Definition bdld_datum.h:813
@ e_USERDEFINED
Definition bdld_datum.h:823
@ e_DATE
Definition bdld_datum.h:818
@ e_ERROR_VALUE
Definition bdld_datum.h:831
@ e_INT_MAP
Definition bdld_datum.h:828
@ e_DECIMAL64
Definition bdld_datum.h:827
@ e_BOOLEAN
Definition bdld_datum.h:816
@ e_DATETIME
Definition bdld_datum.h:820
@ e_REAL
Definition bdld_datum.h:830
@ e_INTEGER64
Definition bdld_datum.h:822
@ e_STRING
Definition bdld_datum.h:815
@ e_DOUBLE
Definition bdld_datum.h:814
@ e_NIL
Definition bdld_datum.h:812
@ e_ERROR
Definition bdld_datum.h:817
bool isDate() const
Definition bdld_datum.h:4305
bool isUdt() const
Definition bdld_datum.h:4434
DatumUdt theUdt() const
Definition bdld_datum.h:4730
static char * createUninitializedString(Datum *result, SizeType length, const AllocatorType &allocator)
static void disposeUninitializedArray(const DatumMutableArrayRef &array, const AllocatorType &allocator)
Definition bdld_datum.h:4226
bool isDatetimeInterval() const
Definition bdld_datum.h:4322
static Datum adoptMap(const DatumMutableMapRef &map)
Definition bdld_datum.h:4176
static Datum createBoolean(bool value)
Return, by value, a datum having the specified bool value.
Definition bdld_datum.h:3877
Datum(const Datum &original)=default
Create a datum having the value of the specified original.
bool isDatetime() const
Definition bdld_datum.h:4316
bool isIntMap() const
Definition bdld_datum.h:4399
bool isTime() const
Definition bdld_datum.h:4428
int theInteger() const
Definition bdld_datum.h:4615
Definition bdldfp_decimal.h:1890
Definition bdlt_date.h:294
Definition bdlt_datetimeinterval.h:201
int days() const
Definition bdlt_datetimeinterval.h:1156
void setTotalMilliseconds(bsls::Types::Int64 milliseconds)
Definition bdlt_datetimeinterval.h:970
bsls::Types::Int64 fractionalDayInMicroseconds() const
Definition bdlt_datetimeinterval.h:1162
int microseconds() const
Definition bdlt_datetimeinterval.h:1195
bsls::Types::Int64 totalMilliseconds() const
Definition bdlt_datetimeinterval.h:1236
Definition bdlt_datetime.h:330
Date date() const
Return the value of the "date" part of this object.
Definition bdlt_datetime.h:2234
int microsecond() const
Return the value of the microsecond attribute of this object.
Definition bdlt_datetime.h:2301
Time time() const
Return the value of the "time" part of this object.
Definition bdlt_datetime.h:2345
Definition bdlt_time.h:195
int addMilliseconds(int milliseconds)
Definition bslma_bslallocator.h:588
Definition bsls_alignedbuffer.h:262
Definition bslstl_stringref.h:374
const CHAR_TYPE * data() const
Definition bslstl_stringref.h:962
size_type length() const
Definition bslstl_stringref.h:984
bsl::ostream & operator<<(bsl::ostream &stream, const bdlat_AttributeInfo &attributeInfo)
BSLS_PLATFORM_COMPILER_ERROR
Definition bdld_datum.h:729
#define BDLD_DATUM_FORCE_INLINE
Definition bdld_datum.h:735
#define BSLMF_ASSERT(expr)
Definition bslmf_assert.h:231
#define BSLS_ANNOTATION_FALLTHROUGH
Definition bsls_annotation.h:410
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1976
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1917
#define BSLS_ASSERT_OPT(X)
Definition bsls_assert.h:2045
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
#define BSLS_KEYWORD_NOEXCEPT
Definition bsls_keyword.h:674
#define BSLS_PERFORMANCEHINT_PREDICT_LIKELY(expr)
Definition bsls_performancehint.h:451
#define BSLS_PERFORMANCEHINT_UNLIKELY_HINT
Definition bsls_performancehint.h:484
#define BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(expr)
Definition bsls_performancehint.h:452
bsl::size_t size(const TYPE &array)
Return the number of elements in the specified array.
void hashAppend(HASH_ALGORITHM &hashAlgorithm, const BigEndianInt16 &object)
Definition bdld_datum.h:740
bsl::ostream & operator<<(bsl::ostream &stream, const Datum &rhs)
void hashAppend(t_HASH_ALGORITHM &hashAlgorithm, const Datum &datum)
bool operator==(const Datum &lhs, const Datum &rhs)
bool operator!=(const Datum &lhs, const Datum &rhs)
Decimal_Type64 Decimal64
Definition bdldfp_decimal.h:750
Definition bdlat_valuetypefunctions.h:939
ALLOCATOR const STRING_VIEW_LIKE_TYPE & rhs
Definition bslstl_string.h:3918
ALLOCATOR & lhs
Definition bslstl_string.h:3917
BSLS_KEYWORD_CONSTEXPR CONTAINER::value_type * data(CONTAINER &container)
Definition bslstl_iterator.h:1325
bsl::enable_if<(bsl::is_integral< TYPE >::value||bsl::is_pointer< TYPE >::value||bsl::is_enum< TYPE >::value)&&!bsl::is_same< TYPE, bool >::value >::type hashAppend(HASH_ALGORITHM &hashAlg, TYPE input)
Definition bslh_hash.h:643
Definition bslstl_algorithm.h:84
StringRefImp< char > StringRef
Definition bslstl_stringref.h:725
Definition bdlb_printmethods.h:306
Definition bdld_datum.h:3288
Definition bdld_datum.h:2291
Datum::SizeType d_size
Definition bdld_datum.h:2294
bool d_sorted
Definition bdld_datum.h:2296
Datum::SizeType d_capacity
Definition bdld_datum.h:2295
Definition bdld_datum.h:759
t_WANT_TO_BE_DEPENDENT type
Definition bdld_datum.h:760
Definition bdld_datum.h:2307
Datum::SizeType d_allocatedSize
Definition bdld_datum.h:2312
Datum::SizeType d_capacity
Definition bdld_datum.h:2311
bool d_ownsKeys
Definition bdld_datum.h:2314
bool d_sorted
Definition bdld_datum.h:2313
Datum::SizeType d_size
Definition bdld_datum.h:2310
static const Datetime & epoch()
Definition bdlt_epochutil.h:397
static const int k_MS_PER_D_32
Definition bdlt_timeunitratio.h:339
Definition bslmf_istriviallycopyable.h:324
Definition bslmf_istriviallydefaultconstructible.h:296
Definition bslma_allocatorutil.h:413
Definition bslmf_isbitwisecopyable.h:298
Definition bslmf_isbitwisemoveable.h:718
Definition bslmf_nil.h:133
std::size_t size_type
Definition bsls_types.h:126
long long Int64
Definition bsls_types.h:134