BDE 4.14.0 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/// // used 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 `disposeUnitializedArray`.
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 an arbitrary binary data:
645/// @code
646/// int buffer[] = { 1, 2, 3 };
647/// Datum datumBlob = Datum::copyBinary(buffer, sizeof(buffer), &oa);
648/// buffer[2] = 666;
649/// assert(true == datumBlob.isBinary());
650/// DatumBinaryRef blob = datumBlob.theBinary();
651/// assert(blob.size() == 3 * sizeof(int));
652/// assert(reinterpret_cast<const int*>(blob.data())[2] == 3);
653/// Datum::destroy(datumBlob, &oa);
654/// @endcode
655/// Note that the bytes have been copied.
656/// @}
657/** @} */
658/** @} */
659
660/** @addtogroup bdl
661 * @{
662 */
663/** @addtogroup bdld
664 * @{
665 */
666/** @addtogroup bdld_datum
667 * @{
668 */
669
670#include <bdlscm_version.h>
671
672#include <bdld_datumbinaryref.h>
673#include <bdld_datumerror.h>
674#include <bdld_datumudt.h>
675
676#include <bdlb_float.h> // 'isSignalingNan'
677#include <bdlb_printmethods.h>
678
679#include <bdldfp_decimal.fwd.h>
680#ifndef BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
681 #include <bdldfp_decimal.h>
682#endif
683
684#include <bdlt_date.h>
685#include <bdlt_datetime.h>
687#include <bdlt_epochutil.h>
688#include <bdlt_time.h>
689
690#include <bslma_allocator.h>
691#include <bslma_allocatorutil.h>
692#include <bslma_bslallocator.h>
693
694#include <bslmf_assert.h>
699#include <bslmf_nil.h>
700
701#include <bsls_alignedbuffer.h>
702#include <bsls_annotation.h>
703#include <bsls_assert.h>
704#include <bsls_performancehint.h>
705#include <bsls_platform.h>
706#include <bsls_review.h>
707#include <bsls_types.h>
708
709#include <bsl_algorithm.h>
710#include <bsl_climits.h>
711#include <bsl_cstring.h>
712#include <bsl_iosfwd.h>
713#include <bsl_limits.h>
714#include <bsl_string.h>
715#include <bsl_utility.h>
716
717#if !defined(BSLS_PLATFORM_CPU_32_BIT) && !defined(BSLS_PLATFORM_CPU_64_BIT)
718 #error 'bdld::Datum' supports 32- or 64-bit platforms only.
720#endif
721
722#ifdef BSLS_PLATFORM_CMP_MSVC
723 #define BDLD_DATUM_FORCE_INLINE __forceinline
724#else
725 #define BDLD_DATUM_FORCE_INLINE inline
726#endif
727
728
729
730namespace bdld {
731
732class DatumArrayRef;
733class DatumIntMapEntry;
734class DatumIntMapRef;
735class DatumMapEntry;
736class DatumMapRef;
741
742/// Metafunction for use in templates to create a dependent `type` that is
743/// identical to the `t_WANT_TO_BE_DEPENDENT` type specified as first
744/// template argument using the `t_ALREADY_DEPENDENT` type of the user
745/// template (of this metafunction).
746template <class t_WANT_TO_BE_DEPENDENT, class t_ALREADY_DEPENDENT>
748 typedef t_WANT_TO_BE_DEPENDENT type;
749};
750
751 // ===========
752 // class Datum
753 // ===========
754
755/// This class implements a mechanism that provides a space-efficient
756/// discriminated union that holds the value of ether scalar type or an
757/// aggregate of `Datum` objects. The size of `Datum` is 8 bytes (same as a
758/// `double`) on 32-bit platforms and 16 bytes on 64-bit platforms.
759/// Separate representation are needed on 32 and 64 bit platforms because of
760/// the differing size of a pointer (a 64-bit pointer cannot reasonably be
761/// held in a 32-bit footprint).
762///
763/// Representation on a 32-bit Platforms: Values are stored inside an 8-byte
764/// unsigned char array (`d_data`). Any `double` value (including NaN and
765/// infinity values) can be stored inside `Datum`. When storing a value of
766/// a type other than `double`, the bits in `d_data` that correspond to the
767/// exponent part of a `double` value are set to 1, with the 4 bits in the
768/// fraction part used to indicate the type of value stored.
769///
770/// Representation on 64-bit platforms: Values are stored inside a 16 byte
771/// unsigned char array (`d_data`) to store values. The type information is
772/// stored in the upper 2 bytes of the character array. Remaining 14 bytes
773/// are used to store the actual value or the pointer to the external memory
774/// that holds the value.
775///
776/// For details on the internal representations that are used for various
777/// types on 32 and 64 bit platforms, please see the implementation notes in
778/// `bdld_datum.cpp`.
779///
780/// Datum objects are bitwise copyable and have trivial initialization,
781/// assignment and destruction. Only one of the copies of the same `Datum`
782/// object can be passed to `destroy`. The rest of those copies then become
783/// invalid and it is undefined behavior to deep-copy or destroy them.
784/// Although, these copies can be used on the left hand side of assignment.
785///
786/// See @ref bdld_datum
787class Datum {
788
789 private:
790 // TYPES
792
793 public:
794 // TYPES
796
797 /// Enumeration used to discriminate among the different externally-
798 /// exposed types of values that can be stored inside `bdld::Datum`.
799 enum DataType {
800 e_NIL = 0 // null value
801 , e_INTEGER = 1 // integer value
802 , e_DOUBLE = 2 // double value
803 , e_STRING = 3 // string value
804 , e_BOOLEAN = 4 // boolean value
805 , e_ERROR = 5 // error value
806 , e_DATE = 6 // date value
807 , e_TIME = 7 // time value
808 , e_DATETIME = 8 // datetime value
809 , e_DATETIME_INTERVAL = 9 // datetime interval value
810 , e_INTEGER64 = 10 // 64-bit integer value
811 , e_USERDEFINED = 11 // pointer to a user-defined object
812 , e_ARRAY = 12 // array reference
813 , e_MAP = 13 // map reference
814 , e_BINARY = 14 // pointer to the binary data
815 , e_DECIMAL64 = 15 // Decimal64
816 , e_INT_MAP = 16 // integer map reference
817
818#ifndef BDE_OMIT_INTERNAL_DEPRECATED
819 , e_REAL = e_DOUBLE // old spelling
837#endif // end - do not omit internal deprecated
838 };
839
840 // Define `k_NUM_TYPES` to be the number of consecutively valued
841 // enumerators in the range `[ e_NIL .. e_DECIMAL64 ]`.
842 enum {
843 k_NUM_TYPES = 17 // number of distinct enumerated types
844#ifndef BDE_OMIT_INTERNAL_DEPRECATED
846#endif // end - do not omit internal deprecated
847 };
848
849#ifdef BSLS_PLATFORM_CPU_32_BIT
850 private:
851 // PRIVATE TYPES
852 // 32-bit variation
853
854 /// Enumeration used to discriminate among the different types of values
855 /// that can be stored inside `bdld::Datum`.
856 enum InternalDataType {
857
858 e_INTERNAL_INF = 0 // +/- infinity value
859 , e_INTERNAL_LONGEST_SHORTSTRING = 1 // 6 character string
860 , e_INTERNAL_BOOLEAN = 2 // boolean value
861 , e_INTERNAL_SHORTSTRING = 3 // short string value
862 , e_INTERNAL_STRING = 4 // string value
863 , e_INTERNAL_DATE = 5 // date value
864 , e_INTERNAL_TIME = 6 // time value
865 , e_INTERNAL_DATETIME = 7 // date+time value
866 , e_INTERNAL_DATETIME_INTERVAL = 8 // date+time interval value
867 , e_INTERNAL_INTEGER = 9 // integer value
868 , e_INTERNAL_INTEGER64 = 10 // 64-bit integer value
869 , e_INTERNAL_USERDEFINED = 11 // pointer to a user-defined obj
870 , e_INTERNAL_ARRAY = 12 // array of datums
871 , e_INTERNAL_STRING_REFERENCE = 13 // unowned string
872 , e_INTERNAL_ARRAY_REFERENCE = 14 // unowned array of
873 , e_INTERNAL_EXTENDED = 15 // extended data types
874 , e_INTERNAL_DOUBLE = 16 // double value
875 };
876
877 /// Define `k_NUM_INTERNAL_TYPES` to be the number of consecutively
878 /// valued enumerators in the range
879 /// `[ e_INTERNAL_INF .. e_INTERNAL_DOUBLE ]`.
880 enum {
881
882 k_NUM_INTERNAL_TYPES = 17 // number of internal types
883 };
884
885 /// Enumeration used to discriminate among different types of values
886 /// that map on to the `e_INTERNAL_EXTENDED` discriminator value inside
887 /// `bdld::Datum`. It is used to add any new required types.
888 enum ExtendedInternalDataType {
889 e_EXTENDED_INTERNAL_MAP = 0 // map of datums keyed by string
890 // values that are not owned
891
892 , e_EXTENDED_INTERNAL_OWNED_MAP = 1 // map of datums keyed by string
893 // values that are owned
894
895 , e_EXTENDED_INTERNAL_NAN2 = 2 // NaN double value
896
897 , e_EXTENDED_INTERNAL_ERROR = 3 // error with code only
898
899 , e_EXTENDED_INTERNAL_ERROR_ALLOC = 4 // error with code and
900 // description string
901
902 // We never need to externally allocate the reference types with the
903 // 64-bit implementation because we can fit 32 bits of length inline.
904
905 , e_EXTENDED_INTERNAL_SREF_ALLOC = 5 // allocated string ref
906
907 , e_EXTENDED_INTERNAL_AREF_ALLOC = 6 // allocated array ref
908
909 , e_EXTENDED_INTERNAL_DATETIME_ALLOC = 7 // allocated datetime
910
911 , e_EXTENDED_INTERNAL_DATETIME_INTERVAL_ALLOC = 8 // allocated datetime
912 // interval
913
914 , e_EXTENDED_INTERNAL_INTEGER64_ALLOC = 9 // 64-bit integer value
915
916 , e_EXTENDED_INTERNAL_BINARY_ALLOC = 10 // binary data
917
918 , e_EXTENDED_INTERNAL_DECIMAL64 = 11 // Decimal64
919
920 , e_EXTENDED_INTERNAL_DECIMAL64_SPECIAL = 12 // Decimal64 NaN of Inf
921
922 , e_EXTENDED_INTERNAL_DECIMAL64_ALLOC = 13 // allocated Decimal64
923
924 , e_EXTENDED_INTERNAL_NIL = 14 // null value
925
926 , e_EXTENDED_INTERNAL_INT_MAP = 15 // map of datums keyed by
927 // 32-bit integer values
928 };
929
930 // Define `k_NUM_EXTENDED_INTERNAL_TYPES` to be the number of
931 // consecutively valued enumerators in the range
932 // `[ e_EXTENDED_INTERNAL_MAP .. e_EXTENDED_INTERNAL_INT_MAP ]`.
933 enum {
934 k_NUM_EXTENDED_INTERNAL_TYPES = 16 // number of distinct enumerated
935 // extended types
936 };
937
938 // PRIVATE CLASS DATA
939 // 32-bit variation
940 static const unsigned short k_DOUBLE_MASK = 0x7ff0U; // mask value to be
941 // stored in the
942 // exponent part of
943 // `d_data` to
944 // indicate a special
945 // `double` value
946
947 static const int k_SHORTSTRING_SIZE = 6; // maximum size of short strings
948 // stored in the internal storage
949 // buffer
950
951 static const int k_TYPE_MASK_BITS = 16; // number of bits the internal
952 // data type needs to be shifted
953 // into place
954
955 static const short k_DATETIME_OFFSET_FROM_EPOCH = 18262;
956 // Number of days offset from 1970 Jan 1 used to create the epoch used
957 // to determine if `Datum` stores a date-time value using dynamic
958 // memory allocation or withing the `Datum` itself. This offset, added
959 // to the 1970 Jan 1 date, creates an (mid) epoch of 2020 Jan 1.
960 // Given that `Datum` uses a signed 16 bits day-offset when storing
961 // date-time internally, the 2020 Jan 1 epoch enables of storing
962 // date-times internally the range of 1930 Apr 15 to 2109 Sept 18.
963 // Note that the time part of date-time can be stored internally
964 // without data loss, so that makes the no-allocation range to be
965 // 1930 Apr 15 00:00:00.000000 to 2109 Sept 18 24:00:00.000000. See
966 // `createDatetime` and `theDatetime` methods for the implementation.
967
968#ifdef BSLS_PLATFORM_IS_LITTLE_ENDIAN
969 // Check if platform is little endian.
970 static const int k_EXPONENT_OFFSET = 6; // offset of the exponent part in
971 // the internal storage buffer
972
973 static const int k_EXPONENT_LSB = k_EXPONENT_OFFSET; // Low Byte
974
975 static const int k_EXPONENT_MSB = k_EXPONENT_OFFSET + 1; // High Byte
976
977 static const int k_DATA_OFFSET = 0; // offset of the data part in the
978 // internal storage buffer
979
980 static const int k_SHORTSTRING_OFFSET = 0;// offset of short-strings stored
981 // in the internal storage buffer
982
983 static const int k_SHORT_OFFSET = 4; // offset of (2 byte values like)
984 // discriminator values for
985 // extended types and information
986 // for user-defined objects in
987 // the internal storage buffer
988
989 static const int k_MASK_OFFSET = 4; // offset of the special mask
990 // value in the internal storage
991 // buffer
992
993 static const int k_NEARDATE_OFFSET = 4; // offset of the short date
994 // offset from now value in the
995 // internal storage buffer
996
997 static const int k_TIME_OFFSET = 0; // offset of the time value in
998 // the internal storage buffer
999#else // end - little endian / begin - big endian
1000 // Check if platform is big endian.
1001 static const int k_EXPONENT_OFFSET = 0; // offset of the exponent part in
1002 // the internal storage buffer
1003
1004 static const int k_EXPONENT_LSB = k_EXPONENT_OFFSET + 1; // Low Byte
1005
1006 static const int k_EXPONENT_MSB = k_EXPONENT_OFFSET; // High Byte
1007
1008 static const int k_DATA_OFFSET = 4; // offset of the data part in the
1009 // internal storage buffer
1010
1011 static const int k_SHORTSTRING_OFFSET = 2;// offset of short-strings stored
1012 // in the internal storage buffer
1013
1014 static const int k_SHORT_OFFSET = 2; // offset of (2 byte values like)
1015 // discriminator values for
1016 // extended types and information
1017 // for user-defined objects in
1018 // the internal storage buffer
1019
1020 static const int k_MASK_OFFSET = 0; // offset of the special mask
1021 // value in the internal storage
1022 // buffer
1023
1024 static const int k_NEARDATE_OFFSET = 2; // offset of the short date
1025 // offset from now value in the
1026 // internal storage buffer
1027
1028 static const int k_TIME_OFFSET = 4; // offset of the time value in
1029 // the internal storage buffer
1030#endif // end - big endian
1031
1032 /// Enumeration used to discriminate between the special incompressible
1033 /// Decimal64 values.
1034 enum {
1035 e_DECIMAL64_SPECIAL_NAN,
1036 e_DECIMAL64_SPECIAL_INFINITY,
1037 e_DECIMAL64_SPECIAL_NEGATIVE_INFINITY
1038 };
1039
1040 // DATA
1041 // 32-bit variation
1042
1043 struct ShortString5 {
1044 // Storage for a string shorter than 6 chars and its length.
1045#ifdef BSLS_PLATFORM_IS_LITTLE_ENDIAN
1046 char d_chars[5]; // the string's characters
1047 char d_length; // the string's length
1048 unsigned short d_exponent; // the exponent inside the double
1049#else // end - little endian / begin - big endian
1050 unsigned short d_exponent; // the exponent inside the double
1051 char d_chars[5]; // the string's characters
1052 char d_length; // the string's length
1053#endif // end - big endian
1054 };
1055
1056 struct ShortString6 {
1057 // Storage for a string of exactly 6 chars. Length is implicit.
1058#ifdef BSLS_PLATFORM_IS_LITTLE_ENDIAN
1059 char d_chars[6]; // the string's characters
1060 unsigned short d_exponent; // the exponent inside the double
1061#else // end - little endian / begin - big endian
1062 unsigned short d_exponent; // the exponent inside the double
1063 char d_chars[6]; // the string's characters
1064#endif // end - big endian
1065 };
1066
1067 struct TypedAccess {
1068 // Storage for various combinations of short, int and pointer.
1069 // TYPE FIELDS
1070 // --------------- -------------------------------
1071 // Null d_short = extended type
1072 //
1073 // Boolean d_int = value
1074 //
1075 // Integer d_int = value
1076 //
1077 // String d_cvp = allocated memory containing copy
1078 // (length > 6) of string preceded by length
1079 //
1080 // StringRef d_ushort = length
1081 // (length < USHORT_MAX) d_cvp = pointer to the c-string
1082 //
1083 // StringRef d_short = extended type
1084 // (length >= USHORT_MAX) d_cvp = pointer to allocated memory
1085 // containing pointer to the c-string
1086 // preceded by c-string length
1087 //
1088 // Date d_int = value
1089 //
1090 // Time d_int = value
1091 //
1092 // Datetime d_short = days from now
1093 // (near offset) d_int = time part
1094 //
1095 // Datetime d_short = extended type
1096 // (far offset) d_cvp = pointer to allocated value
1097 //
1098 //
1099 // DatetimeInterval d_short = upper 16 bits
1100 // (short) d_int = lower 32
1101 //
1102 // DatetimeInterval d_short = extended type
1103 // (long) d_cvp = pointer to allocated value
1104 //
1105 // Error d_short = extended type
1106 // (code only) d_int = value
1107 //
1108 // Error d_short = extended type
1109 // (code + error string) d_cvp = pointer to allocated memory
1110 // containing: code, length, c-string
1111 //
1112 // Udt d_ushort = udt type
1113 // d_cvp = pointer to udt object
1114 //
1115 // ArrayReference d_ushort = length
1116 // (length < USHORT_MAX) d_cvp = pointer to array
1117 //
1118 // ArrayReference
1119 // (length >= USHORT_MAX) d_short = extended type
1120 // d_cvp = pointer to allocated memory
1121 // containing: pointer to array,
1122 // length
1123 //
1124 // Map d_short = extended type
1125 // d_cvp = pointer to allocated memory
1126 // containing: length, sorted flag,
1127 // array of map entries
1128 //
1129 // Int-map d_short = extended type
1130 // d_cvp = pointer to allocated memory
1131 // containing: length, sorted flag,
1132 // array of int-map entries
1133 //
1134 // Binary: d_short = extended type
1135 // d_cvp = pointer to allocated memory
1136 // containing: length, binary copy
1137
1138#ifdef BSLS_PLATFORM_IS_LITTLE_ENDIAN
1139 union {
1140 int d_int; // as integer value
1141 const void *d_cvp; // as const void* value
1142 };
1143 union {
1144 short d_short; // as signed short value
1145 unsigned short d_ushort; // as unsigned short value
1146 };
1147 unsigned short d_exponent; // the exponent inside the double
1148#else // end - little endian / begin - big endian
1149 unsigned short d_exponent; // the exponent inside the double
1150 union {
1151 short d_short; // as signed short value
1152 unsigned short d_ushort; // as unsigned short
1153 };
1154 union {
1155 int d_int; // as integer value
1156 const void *d_cvp; // as const void* value
1157 };
1158#endif // end - big endian
1159 };
1160
1161 struct ExponentAccess {
1162 // For accessing exponent as a word, for better performance.
1163#ifdef BSLS_PLATFORM_IS_LITTLE_ENDIAN
1164 unsigned int d_dummy;
1165 unsigned int d_value; // the exponent as a 32 bit word
1166#else // end - little endian / begin - big endian
1167 unsigned int d_value; // the exponent as a 32 bit word
1168 unsigned int d_dummy;
1169#endif // end - big endian
1170 };
1171
1172 // Internal Datum representation
1173 union {
1174 // Do not change the order of these member, otherwise the code will not
1175 // work properly with the clang compiler.
1176
1177 char d_data[8]; // as a byte array of internal storage
1178
1179 ShortString5 d_string5; // as a string shorter than 5 chars
1180
1181 ShortString6 d_string6; // as a string of exactly 6 chars
1182
1183 TypedAccess d_as; // as a combination of pointer, int and
1184 // short
1185
1186 ExponentAccess d_exp; // as the exponent as a 32 bit word
1187
1188 double d_double; // as a double value
1189 };
1190
1191 // PRIVATE CLASS METHODS
1192 // 32-bit variation
1193
1194 // Return a datum by copying the specified `data` of the specified
1195 // `type`. Note that the pointer value in `data` is copied and the
1196 // pointed object is not cloned.
1197 static Datum createExtendedDataObject(ExtendedInternalDataType type,
1198 void *data);
1199 static Datum createExtendedDataObject(ExtendedInternalDataType type,
1200 int data);
1201
1202 // PRIVATE ACCESSORS
1203 // 32-bit variation
1204
1205 /// Return the extended type of the value stored in this object (which
1206 /// cannot be represented by the 4-bit discriminator `InternalDataType`)
1207 /// as one of the enumeration values defined in
1208 /// `ExtendedInternalDataType`.
1209 ExtendedInternalDataType extendedInternalType() const;
1210
1211 /// Return the type of the value stored in this object as one of the
1212 /// enumeration values defined in `DataType` (mapped from the
1213 /// `ExtendedInternalDataType` value).
1214 DataType typeFromExtendedInternalType() const;
1215
1216 /// Return the 64-bit integer value stored in the allocated storage.
1217 bsls::Types::Int64 theLargeInteger64() const;
1218
1219 // Return the array referenced by this object. The behavior is
1220 // undefined unless this object references an array with `length >=
1221 // USHORT_MAX`.
1222 DatumArrayRef theLongArrayReference() const;
1223
1224 /// Return the short string value stored in this object as a
1225 /// `bslstl::StringRef` object. The behavior is undefined unless this
1226 /// object actually stores a short string value.
1227 bslstl::StringRef theLongestShortString() const;
1228
1229 /// Return the string referenced by this object. The behavior is
1230 /// undefined unless this object holds a reference to a string with
1231 /// `length >= USHORT_MAX`.
1232 bslstl::StringRef theLongStringReference() const;
1233
1234 /// Return the 64-bit integer value stored inline in this object.
1235 bsls::Types::Int64 theSmallInteger64() const;
1236
1237#else // end - 32 bit / begin - 64 bit
1238 private:
1239 // PRIVATE TYPES
1240
1241
1242 // Enumeration used to discriminate among the different types of values
1243 // that can be stored inside `bdld::Datum`.
1244 enum InternalDataType {
1245 e_INTERNAL_UNINITIALIZED = 0, // zero-filled Datums are invalid
1246
1247 e_INTERNAL_INF = 1, // +/- infinity value
1248
1249 e_INTERNAL_NIL = 2, // null value
1250
1251 e_INTERNAL_BOOLEAN = 3, // boolean value
1252
1253 e_INTERNAL_SHORTSTRING = 4, // short string value
1254
1255 e_INTERNAL_STRING = 5, // string value
1256
1257 e_INTERNAL_DATE = 6, // date value
1258
1259 e_INTERNAL_TIME = 7, // time value
1260
1261 e_INTERNAL_DATETIME = 8, // date+time value
1262
1263 e_INTERNAL_DATETIME_INTERVAL = 9, // date+time interval value
1264
1265 e_INTERNAL_INTEGER = 10, // integer value
1266
1267 e_INTERNAL_INTEGER64 = 11, // 64-bit integer value
1268
1269 e_INTERNAL_USERDEFINED = 12, // pointer to a user-defined object
1270
1271 e_INTERNAL_ARRAY = 13, // array of datums
1272
1273 e_INTERNAL_STRING_REFERENCE = 14, // not owned string
1274
1275 e_INTERNAL_ARRAY_REFERENCE = 15, // not owned array
1276
1277 e_INTERNAL_DOUBLE = 16, // double value
1278
1279 e_INTERNAL_MAP = 17, // map of datums keyed by string
1280 // values that are not owned
1281
1282 e_INTERNAL_OWNED_MAP = 18, // map of datums keyed by string
1283 // values that are owned
1284
1285 e_INTERNAL_ERROR = 19, // error code, internal storage
1286
1287 e_INTERNAL_ERROR_ALLOC = 20, // error code, allocated storage
1288
1289 e_INTERNAL_BINARY = 21, // binary data, internal storage
1290
1291 e_INTERNAL_BINARY_ALLOC = 22, // binary data, allocated storage
1292
1293 e_INTERNAL_DECIMAL64 = 23, // Decimal64
1294
1295 e_INTERNAL_INT_MAP = 24 // map of datums keyed by 32-bit
1296 // integer values
1297 };
1298
1299 /// Define `k_NUM_INTERNAL_TYPES` to be the number of consecutively
1300 /// valued enumerators in the range
1301 /// `[ e_INTERNAL_UNINITIALIZED .. e_INTERNAL_DECIMAL64 ]`.
1302 enum {
1303 k_NUM_INTERNAL_TYPES = 25 // number of internal types
1304 };
1305
1306 // CLASS DATA
1307
1308 // 64-bit variation
1309 static const int k_TYPE_OFFSET = 14; // offset of type in the
1310 // internal storage
1311 // buffer
1312
1313 static const int k_SHORTSTRING_SIZE = 13; // maximum size of short
1314 // strings that stored in
1315 // the internal storage
1316 // buffer
1317
1318 static const int k_SMALLBINARY_SIZE_OFFSET = 13; // offset of the size of
1319 // small-size binaries
1320 // stored in the internal
1321 // storage buffer
1322
1323 static const int k_SMALLBINARY_SIZE = 13; // maximum size of
1324 // small-size binaries
1325 // stored in the internal
1326 // storage buffer
1327
1328 // DATA
1329
1330 // 64-bit variation
1331
1332 /// Typed access to the bits of the `Datum` internal representation
1333 struct TypedAccess {
1334 union { // Offset: 0
1335 bsls::Types::Int64 d_int64;
1336 void *d_ptr;
1337 double d_double;
1338 };
1339 int d_int32; // Offset: 8
1340 short d_filler; // Offset: 12
1341 short d_type; // Offset: 14
1342 };
1343
1344 /// Ensures proper alignment (16 byte) and provides 2 types of access to
1345 /// the 64-bit `Datum` internal representation. The `d_data` array
1346 /// allows us raw access to the bytes; while `d_as` provides typed
1347 /// access to the individual "data compartments".
1348 union {
1350 TypedAccess d_as;
1351 };
1352
1353 // PRIVATE CLASS METHODS
1354
1355 // 64-bit variation
1356
1357 /// Create a `Datum` object of the specified `type` with the specified
1358 /// `data` value.
1359 static Datum createDatum(InternalDataType type, void *data);
1360
1361 /// Create a `Datum` object of the specified `type` with the specified
1362 /// `data` value.
1363 static Datum createDatum(InternalDataType type, int data);
1364
1365 // PRIVATE ACCESSORS
1366
1367 // 64-bit variation
1368
1369 /// Return a pointer to the internal storage buffer
1370 void* theInlineStorage();
1371
1372 /// Return a non-modifiable pointer to the internal storage buffer.
1373 const void* theInlineStorage() const;
1374
1375#endif // end - 64 bit
1376
1377 private:
1378 // FRIENDS
1379 friend bool operator==(const Datum& lhs, const Datum& rhs);
1380 friend bool operator!=(const Datum& lhs, const Datum& rhs);
1381 friend bsl::ostream& operator<<(bsl::ostream& stream, const Datum& rhs);
1382
1383 // PRIVATE ACCESSORS
1384
1385 /// Using the specified `allocator` deallocate the specified `nBytes`
1386 /// allocated for the value of this object. The behavior is undefined
1387 /// 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
1396 /// `alignment`. The behavior is undefined unless `0 == nBytes` when
1397 /// `0 == this->allocatedPtr<void>()`. The behavior is also undefined
1398 /// unless the non-null value of `this->allocatedPtr<void>()` has been
1399 /// obtained by `AllocUtil::allocateBytes` from `allocator`.
1400 void safeDeallocateBytes(const AllocatorType& allocator,
1401 bsl::size_t nBytes,
1402 bsl::size_t alignment) const;
1403
1404 /// Return the pointer to the first byte of the memory allocated by this
1405 /// `Datum` object. The behavior is undefined unless the internal type
1406 /// indicates the object *has* allocated.
1407 template <class t_TYPE>
1408 t_TYPE *allocatedPtr() const;
1409
1410 /// Return the internal type of value stored in this object as one of
1411 /// the enumeration values defined in `InternalDataType`.
1412 InternalDataType internalType() const;
1413
1414 /// Return the array reference represented by this object as
1415 /// `DatumArrayRef` object. The behavior is undefined unless the object
1416 /// represents an array reference whose size is stored in the object
1417 /// internal storage buffer. Note that all array references store their
1418 /// size in the object internal storage buffer on 64-bit platforms.
1419 DatumArrayRef theArrayReference() const;
1420
1421 /// Return the array represented by this object as `DatumArrayRef`
1422 /// object. The behavior is undefined unless the object represents an
1423 /// array of `Datum`s.
1424 DatumArrayRef theInternalArray() const;
1425
1426 /// Return the string value represented by this object as a
1427 /// `bslstl::StringRef` object. The behavior is undefined unless the
1428 /// object represents an internal (non-reference, non-short) string.
1429 bslstl::StringRef theInternalString() const;
1430
1431 /// Return the short string value represented by this object as a
1432 /// `bslstl::StringRef` object. The behavior is undefined unless the
1433 /// object actually represents a short string value.
1434 bslstl::StringRef theShortString() const;
1435
1436 /// Return the string reference represented by this object as a
1437 /// `bslstl::StringRef` object. The behavior is undefined unless the
1438 /// object represents a string reference whose size is stored in the
1439 /// object internal storage buffer. Note that the size always stored in
1440 /// the object internal storage buffer on 64-bit platforms.
1441 bslstl::StringRef theStringReference() const;
1442
1443
1444 /// Return the number of bytes that have been directly allocated for
1445 /// this object (not for elements or entries). Used in deallocation.
1446 /// The behavior is undefined unless the type of the object matches the
1447 /// allocated internal variant of the type in the function name.
1448 bsl::size_t theMapAllocNumBytes() const;
1449 bsl::size_t theIntMapAllocNumBytes() const;
1450 bsl::size_t theErrorAllocNumBytes() const;
1451 bsl::size_t theBinaryAllocNumBytes() const;
1452 bsl::size_t theInternalStringAllocNumBytes() const;
1453 bsl::size_t theInternalArrayAllocNumBytes() const;
1454
1455 public:
1456 // TYPES
1457
1458 /// `SizeType` is an alias for an unsigned integral value, representing
1459 /// the capacity of a datum array, the capacity of a datum map, the
1460 /// capacity of the *keys-capacity* of a datum-key-owning map or the
1461 /// length of a string.
1463
1464 // CLASS METHODS
1465
1466 /// Return, by value, a datum referring to the specified `array`,
1467 /// having the specified `length`, using the specified `allocator` to
1468 /// supply memory (if needed). `array` is not copied, and is not freed
1469 /// when the returned object is destroyed with `Datum::destroy`. The
1470 /// behavior is undefined unless `array` contains at least `length`
1471 /// elements. The behavior is also undefined unless `length <
1472 /// UINT_MAX`.
1473 static Datum createArrayReference(const Datum *array,
1474 SizeType length,
1475 const AllocatorType& allocator);
1476
1477 /// Return, by value, a datum having the specified `value`, using the
1478 /// specified `allocator` to supply memory (if needed). The array
1479 /// referenced by `value` is not copied, and is not freed if
1480 /// `Datum::destroy` is called on the returned object. The behavior is
1481 /// undefined unless `value.length() < UINT_MAX`.
1482 static Datum createArrayReference(const DatumArrayRef& value,
1483 const AllocatorType& allocator);
1484
1485 /// Return, by value, a datum having the specified `bool` `value`.
1486 static Datum createBoolean(bool value);
1487
1488 /// Return, by value, a datum having the specified `Date` `value`.
1489 static Datum createDate(const bdlt::Date& value);
1490
1491 /// Return, by value, a datum having the specified `Datetime` `value`,
1492 /// using the specified `allocator` to supply memory (if needed).
1493 static Datum createDatetime(const bdlt::Datetime& value,
1494 const AllocatorType& allocator);
1495
1496 /// Return, by value, a datum holding the specified `DatetimeInterval`
1497 /// `value`, using the specified `allocator` to supply memory (if
1498 /// needed).
1500 const bdlt::DatetimeInterval& value,
1501 const AllocatorType& allocator);
1502
1503 /// Return, by value, a datum having the specified `Decimal64` `value`,
1504 /// using the specified `allocator` to supply memory (if needed). Note
1505 /// that the argument is passed by value because it is assumed to be a
1506 /// fundamental type.
1508 const AllocatorType& allocator);
1509
1510 /// Return, by value, a datum having the specified `double` `value`.
1511 /// When `value` is NaN this method guarantees only that a NaN value is
1512 /// stored. The sign and NaN payload bits of a NaN `value` later
1513 /// retrieved by the `theDouble` method are unspecified (see also
1514 /// {Special Floating Point Values}.
1515 static Datum createDouble(double value);
1516
1517 /// Return, by value, a datum having a `DatumError` value with the
1518 /// specified `code`.
1519 static Datum createError(int code);
1520
1521 /// Return, by value, a datum having a `DatumError` value with the
1522 /// specified `code` and the specified `message`, using the specified
1523 /// `allocator` to supply memory (if needed).
1524 static Datum createError(int code,
1525 const bslstl::StringRef& message,
1526 const AllocatorType& allocator);
1527
1528 /// Return, by value, a datum having the specified `int` `value`.
1529 static Datum createInteger(int value);
1530
1531 /// Return, by value, a datum having the specified `Integer64` `value`,
1532 /// using the specified `allocator` to supply memory (if needed).
1534 const AllocatorType& allocator);
1535
1536 /// Return, by value, a datum having no value.
1537 static Datum createNull();
1538
1539 /// Return, by value, a datum that refers to the specified `string`
1540 /// having the specified `length`, using the specified `allocator` to
1541 /// supply memory (if needed). The behavior is undefined unless
1542 /// `0 != string || 0 == length`. The behavior is also undefined
1543 /// unless `length < UINT_MAX`. Note that `string` is not copied, and
1544 /// is not freed if `Datum::destroy` is called on the returned object.
1545 static Datum createStringRef(const char *string,
1546 SizeType length,
1547 const AllocatorType& allocator);
1548
1549 /// Return, by value, a datum that refers to the specified `string`,
1550 /// using the specified `allocator` to supply memory (if needed). The
1551 /// behavior is undefined unless `string` points to a UTF-8 encoded
1552 /// c-string. The behavior is also undefined unless 'strlen(string) <
1553 /// UINT_MAX'. Note that `string` is not copied, and is not freed if
1554 /// `Datum::destroy` is called on the returned object.
1555 static Datum createStringRef(const char *string,
1556 const AllocatorType& allocator);
1557
1558 /// Return, by value, a datum having the specified `StringRef` `value`,
1559 /// using the specified `allocator` to supply memory (if needed). The
1560 /// behavior is undefined unless `value.length() < UINT_MAX`. Note that
1561 /// `string` is not copied, and is not freed if `Datum::destroy` is
1562 /// called on the returned object.
1563 static Datum createStringRef(const bslstl::StringRef& value,
1564 const AllocatorType& allocator);
1565
1566 /// Return, by value, a datum having the specified `Time` `value`.
1567 static Datum createTime(const bdlt::Time& value);
1568
1569 /// Return, by value, a datum having the `DatumUdt` value with the
1570 /// specified `data` and the specified `type` values. The behavior is
1571 /// undefined unless `0 <= type <= 65535`. Note that `data` is held,
1572 /// not owned. Also note that the content pointed to by `data` object
1573 /// is not copied.
1574 static Datum createUdt(void *data, int type);
1575
1576 /// Return, by value, a datum referring to the copy of the specified
1577 /// `value` of the specified `size`, using the specified
1578 /// `allocator` to supply memory (if needed). The behavior is undefined
1579 /// unless `size < UINT_MAX`. Note that the copy of the binary data is
1580 /// owned and will be freed if `Datum::destroy` is called on the
1581 /// returned object.
1582 static Datum copyBinary(const void *value,
1583 SizeType size,
1584 const AllocatorType& allocator);
1585
1586 /// Return, by value, a datum that refers to the copy of the specified
1587 /// `string` having the specified `length`, using the specified
1588 /// `allocator` to supply memory (if needed). The behavior is undefined
1589 /// unless `0 != string || 0 == length`. The behavior is also undefined
1590 /// unless `length < UINT_MAX`. Note that the copied string is owned
1591 /// and will be freed if `Datum::destroy` is called on the returned
1592 /// object.
1593 static Datum copyString(const char *string,
1594 SizeType length,
1595 const AllocatorType& allocator);
1596
1597 /// Return, by value, a datum having the copy of the specified
1598 /// `StringRef` `value`, using the specified `allocator` to supply
1599 /// memory (if needed). The behavior is undefined unless
1600 /// `value.length() < UINT_MAX`. Note that the copied string is owned,
1601 /// and will be freed if `Datum::destroy` is called on the returned
1602 /// object.
1603 static Datum copyString(const bslstl::StringRef& value,
1604 const AllocatorType& allocator);
1605
1606 /// Return, by value, a datum that refers to the specified `array`. The
1607 /// behavior is undefined unless `array` was created using
1608 /// `createUninitializedArray` method. The behavior is also undefined
1609 /// unless each element in the held datum array has been assigned a
1610 /// value and the array's length has been set accordingly. Note that
1611 /// the adopted array is owned and will be freed if `Datum::destroy` is
1612 /// called on the returned object.
1613 static Datum adoptArray(const DatumMutableArrayRef& array);
1614
1615 /// Return, by value, a datum that refers to the specified `intMap`.
1616 /// The behavior is undefined unless `map` was created using
1617 /// `createUninitializedIntMap` method. The behavior is also undefined
1618 /// unless each element in the held map has been assigned a value and
1619 /// the size of the map has been set accordingly. Note that the adopted
1620 /// map is owned and will be freed if `Datum::destroy` is called on the
1621 /// returned object.
1622 static Datum adoptIntMap(const DatumMutableIntMapRef& intMap);
1623
1624 /// Return, by value, a datum that refers to the specified `map`. The
1625 /// behavior is undefined unless `map` was created using
1626 /// `createUninitializedMap` method. The behavior is also undefined
1627 /// unless each element in the held map has been assigned a value and
1628 /// the size of the map has been set accordingly. Note that the adopted
1629 /// map is owned and will be freed if `Datum::destroy` is called on the
1630 /// returned object.
1631 static Datum adoptMap(const DatumMutableMapRef& map);
1632
1633 /// Return, by value, a datum that refers to the specified `map`. The
1634 /// behavior is undefined unless `map` was created using
1635 /// `createUninitializedMapOwningKeys` method. The behavior is also
1636 /// undefined unless each element in the held map has been assigned a
1637 /// value and the size of the map has been set accordingly. The
1638 /// behavior is also undefined unless keys have been copied into the
1639 /// map. Note that the adopted map is owned and will be freed if
1640 /// `Datum::destroy` is called on the returned object.
1641 static Datum adoptMap(const DatumMutableMapOwningKeysRef& map);
1642
1643 /// Load the specified `result` with a reference to a newly created
1644 /// datum array having the specified `capacity`, using the specified
1645 /// `allocator` to supply memory. The behavior is undefined if
1646 /// `capacity` `Datum` objects would exceed the addressable memory for
1647 /// the platform. Note that the caller is responsible for filling in
1648 /// elements into the datum array and setting its length accordingly.
1649 /// The number of elements in the datum array cannot exceed `capacity`.
1650 /// Also note that any elements in the datum array that need dynamic
1651 /// memory must be allocated with `allocator`.
1653 SizeType capacity,
1654 const AllocatorType& allocator);
1655
1656 /// Load the specified `result` with a reference to a newly created
1657 /// datum int-map having the specified `capacity`, using the specified
1658 /// `allocator` to supply memory. The behavior is undefined if
1659 /// `capacity` `DatumIntMapEntry` objects would exceed the addressable
1660 /// memory for the platform. Note that the caller is responsible for
1661 /// filling in elements into the datum int-map and setting its size
1662 /// accordingly. The number of elements in the datum int-map cannot
1663 /// exceed `capacity`. Also note that any elements in the datum int-map
1664 /// that need dynamic memory, should also be allocated with `allocator`.
1666 DatumMutableIntMapRef *result,
1667 SizeType capacity,
1668 const AllocatorType& allocator);
1669
1670 /// Load the specified `result` with a reference to a newly created
1671 /// datum map having the specified `capacity`, using the specified
1672 /// `allocator` to supply memory. The behavior is undefined if
1673 /// `capacity` `DatumMapEntry` objects would exceed the addressable
1674 /// memory for the platform. Note that the caller is responsible for
1675 /// filling in elements into the datum map and setting its size
1676 /// accordingly. The number of elements in the datum map cannot exceed
1677 /// `capacity`. Also note that any elements in the datum map that need
1678 /// dynamic memory, should also be allocated with `allocator`.
1680 SizeType capacity,
1681 const AllocatorType& allocator);
1682
1683 /// Load the specified `result` with a reference to a newly created
1684 /// datum-key-owning map having the specified `capacity` and
1685 /// `keysCapacity`, using the specified `allocator` to supply memory.
1686 /// The behavior is undefined if `capacity` `DatumMapEntry` object plus
1687 /// `keysCapacity` would exceed the addressable memory for the platform.
1688 /// Note that the caller is responsible for filling in elements into the
1689 /// datum-key-owning map, copying the keys into it, and setting its size
1690 /// accordingly. The number of elements in the datum-key-owning map
1691 /// cannot exceed `capacity` and total size of all the keys cannot
1692 /// exceed `keysCapacity`. Also note that any elements in the
1693 /// datum-key-owning map that need dynamic memory, should also be
1694 /// allocated with `allocator`.
1697 SizeType capacity,
1698 SizeType keysCapacity,
1699 const AllocatorType& allocator);
1700
1701 /// Load the specified `result` with a reference to a newly created
1702 /// character buffer of the specified `length`, using the specified
1703 /// `allocator` to supply memory, and return the address of this buffer
1704 /// The behavior is undefined unless `length < UINT_MAX`. Note that the
1705 /// caller is responsible for initializing the returned buffer with a
1706 /// UTF-8 encoded string.
1707 static char *createUninitializedString(Datum *result,
1708 SizeType length,
1709 const AllocatorType& allocator);
1710
1711 /// Return the non-modifiable string representation corresponding to the
1712 /// specified `type`, if it exists, and a unique (error) string
1713 /// otherwise. The string representation of `type` matches its
1714 /// corresponding enumerator name with the `e_` prefix elided.
1715 ///
1716 /// For example:
1717 /// @code
1718 /// bsl::cout << bdld::Datum::dataTypeToAscii(bdld::Datum::e_NIL);
1719 /// @endcode
1720 /// will print the following on standard output:
1721 /// @code
1722 /// NIL
1723 /// @endcode
1724 /// Note that specifying a `type` that does not match any of the
1725 /// enumerators will result in a string representation that is distinct
1726 /// from any of those corresponding to the enumerators, but is otherwise
1727 /// unspecified.
1728 static const char *dataTypeToAscii(DataType type);
1729
1730 /// Deallocate any memory that was previously allocated within the
1731 /// specified `value` using the specified `allocator`. If the `value`
1732 /// contains an adopted array of datums, `destroy` is called on each
1733 /// array element. If the `value` contains an adopted map of datums,
1734 /// `destroy` is called on each map element. The behavior is undefined
1735 /// unless all dynamically allocated memory owned by `value` was
1736 /// allocated using `allocator`, and has not previously been released by
1737 /// a call to `destroy`, either on this object, or on another object
1738 /// referring to same contents as this object (i.e., only one copy of a
1739 /// `Datum` object can be destroyed). The behavior is also undefined if
1740 /// `value` has an uninitialized or partially initialized array or map
1741 /// (created using `createUninitializedArray`, `createUninitializedMap`
1742 /// or `createUninitializeMapOwningKeys`). Note that after this
1743 /// operation completes, `value` is left in an uninitialized state, and
1744 /// must be assigned a new value before being accessed again.
1745 static void destroy(const Datum& value, const AllocatorType& allocator);
1746
1747 /// Deallocate the memory used by the specified `array` (but *not*
1748 /// memory allocated for its contained elements) using the specified
1749 /// `allocator`. This method does not destroy individual array elements
1750 /// and the memory allocated for those elements must be explicitly
1751 /// deallocated before calling this method. The behavior is undefined
1752 /// unless `array` was created with `createUninitializedArray` using
1753 /// `allocator`.
1754 static void disposeUninitializedArray(
1755 const DatumMutableArrayRef& array,
1756 const AllocatorType& allocator);
1757
1758 /// Deallocate the memory used by the specified `intMap` (but *not*
1759 /// memory allocated for its contained elements) using the specified
1760 /// `allocator`. This method does not destroy individual map elements
1761 /// and the memory allocated for those elements must be explicitly
1762 /// deallocated before calling this method. The behavior is undefined
1763 /// unless `map` was created with `createUninitializedIntMap` using
1764 /// `allocator`.
1765 static void disposeUninitializedIntMap(
1766 const DatumMutableIntMapRef& intMap,
1767 const AllocatorType& allocator);
1768
1769 static void disposeUninitializedMap(const DatumMutableMapRef& map,
1770 const AllocatorType& allocator);
1771 /// Deallocate the memory used by the specified `map` (but *not* memory
1772 /// allocated for its contained elements) using the specified
1773 /// `allocator`. This method does not destroy individual map elements
1774 /// and the memory allocated for those elements must be explicitly
1775 /// deallocated before calling this method. The behavior is undefined
1776 /// unless `map` was created with `createUninitializedMap` using
1777 /// `allocator`.
1778 static void disposeUninitializedMap(
1780 const AllocatorType& allocator);
1781
1782 // TRAITS
1788
1789 // CREATORS
1790
1791 /// Create a datum having an uninitialized value. The behavior for
1792 /// every accessor method is undefined until this object is assigned a
1793 /// value.
1794 Datum() = default;
1795
1796 /// Create a datum having the value of the specified `original`.
1797 Datum(const Datum& original) = default;
1798
1799 /// Destroy this object. Note that this method does not deallocate any
1800 /// dynamically allocated memory used by this object (see `destroy`).
1801 ~Datum() = default;
1802
1803 // MANIPULATORS
1804
1805 // Assign to this object the value of the specified `rhs` object. Note
1806 // that this method's definition is compiler generated.
1807 Datum& operator=(const Datum& rhs) = default;
1808
1809 // ACCESSORS
1810
1811 /// Apply the specified `visitor` to the current value represented by
1812 /// this object by passing held value to the `visitor` object's
1813 /// `operator()` overload.
1814 template <class t_VISITOR>
1815 void apply(t_VISITOR& visitor) const;
1816
1817 /// Return a datum holding a "deep-copy" of this object, using the
1818 /// specified `allocator` to supply memory. This method creates an
1819 /// independent deep-copy of the data of this object, including any
1820 /// referenced data, with the exception of {User Defined Types}. For
1821 /// further information see {Deep Copying}.
1822 Datum clone(const AllocatorType& allocator) const;
1823
1824 // Type-Identifiers
1825
1826 /// Return `true` if this object represents an array of `Datum`s and
1827 /// `false` otherwise.
1828 bool isArray() const;
1829
1830 /// Return `true` if this object represents a binary value and `false`
1831 /// otherwise.
1832 bool isBinary() const;
1833
1834 /// Return `true` if this object represents a boolean value and `false`
1835 /// otherwise.
1836 bool isBoolean() const;
1837
1838 /// Return `true` if this object represents a `bdlt::Date` value and
1839 /// `false` otherwise.
1840 bool isDate() const;
1841
1842 /// Return `true` if this object represents a `bdlt::Datetime` value and
1843 /// `false` otherwise.
1844 bool isDatetime() const;
1845
1846 /// Return `true` if this object represents a `bdlt::DatetimeInterval`
1847 /// value and `false` otherwise.
1848 bool isDatetimeInterval() const;
1849
1850 /// Return `true` if this object represents a `bdlfpd::Decimal64` value
1851 /// and `false` otherwise.
1852 bool isDecimal64() const;
1853
1854 /// Return `true` if this object represents a `double` value and `false`
1855 /// otherwise.
1856 bool isDouble() const;
1857
1858 /// Return `true` if this object represents a `DatumError` value and
1859 /// `false` otherwise.
1860 bool isError() const;
1861
1862 /// Return `true` if this object represents a reference to an externally
1863 /// managed array, string or user-defined object and `false` otherwise.
1864 /// If this method returns `false`, calling `destroy` on this object
1865 /// will release the memory used by the array, string, or used-defined
1866 /// object as well as any meta-data directly used by this datum (e.g.,
1867 /// length information); otherwise (if this method returns `true`)
1868 /// calling `destroy` on this object will release any allocated
1869 /// meta-data, but will not impact the externally managed array, string,
1870 /// or user-defined object.
1871 bool isExternalReference() const;
1872
1873 /// Return `true` if this object represents an integer value and `false`
1874 /// otherwise.
1875 bool isInteger() const;
1876
1877 /// Return `true` if this object represents a `Int64` value and `false`
1878 /// otherwise.
1879 bool isInteger64() const;
1880
1881 /// Return `true` if this object represents a map of datums that are
1882 /// keyed by 32-bit int values and `false` otherwise.
1883 bool isIntMap() const;
1884
1885 /// Return `true` if this object represents a map of datums that are
1886 /// keyed by string values and `false` otherwise.
1887 bool isMap() const;
1888
1889 /// Return `true` if this object represents no value and `false`
1890 /// otherwise.
1891 bool isNull() const;
1892
1893 /// Return `true` if this object represents a string value and `false`
1894 /// otherwise.
1895 bool isString() const;
1896
1897 /// Return `true` if this object represents a `bdlt::Time` value and
1898 /// `false` otherwise.
1899 bool isTime() const;
1900
1901 /// Return `true` if this object represents a `DatumUdt` value and
1902 /// `false` otherwise.
1903 bool isUdt() const;
1904
1905 // Type-Accessors
1906
1907 /// Return the array value represented by this object as a
1908 /// `DatumArrayRef` object. The behavior is undefined unless this
1909 /// object actually represents an array of datums.
1910 DatumArrayRef theArray() const;
1911
1912 /// Return the binary reference represented by this object as a
1913 /// `DatumBinaryRef` object. The behavior is undefined unless this
1914 /// object actually represents a binary reference.
1915 DatumBinaryRef theBinary() const;
1916
1917 /// Return the boolean value represented by this object. The behavior
1918 /// is undefined unless this object actually represents a `bool` value.
1919 bool theBoolean() const;
1920
1921 /// Return the date value represented by this object as a `bdlt::Date`
1922 /// object. The behavior is undefined unless this object actually
1923 /// represents a date value.
1924 bdlt::Date theDate() const;
1925
1926 /// Return the date+time value represented by this object as a
1927 /// `bdlt::Datetime` object. The behavior is undefined unless this
1928 /// object actually represents date+time value.
1930
1931 /// Return the date+time interval value represented by this object as a
1932 /// `bdlt::DatetimeInterval`. The behavior is undefined unless this
1933 /// object actually represents a date+time interval value.
1935
1936 /// Return the decimal floating point value represented by this object
1937 /// as a `bdlfpd::Decimal64` value. The behavior is undefined unless
1938 /// this object actually represents a decimal floating point value.
1940
1941 /// Return the double value represented by this object. The behavior is
1942 /// undefined unless this object actually represents a double value.
1943 /// If the returned value is NaN this method guarantees only that a NaN
1944 /// value will be returned. The sign and NaN payload bits of NaN values
1945 /// returned are unspecified (see also {Special Floating Point Values}.
1946 double theDouble() const;
1947
1948 /// Return the error value represented by this object as a `DatumError`
1949 /// value. The behavior is undefined unless this object actually
1950 /// represents an error value.
1951 DatumError theError() const;
1952
1953 /// Return the integer value represented by this object. The behavior
1954 /// is undefined unless this object actually represents an integer
1955 /// value.
1956 int theInteger() const;
1957
1958 /// Return the 64-bit integer value represented by this object as a
1959 /// `Int64` value. The behavior is undefined unless this object
1960 /// actually represents a 64-bit integer value.
1962
1963 /// Return the int-map value represented by this object as a
1964 /// `DatumIntMapRef` object. The behavior is undefined unless this
1965 /// object actually represents an int-map of datums.
1966 DatumIntMapRef theIntMap() const;
1967
1968 /// Return the map value represented by this object as a `DatumMapRef`
1969 /// object. The behavior is undefined unless this object actually
1970 /// represents a map of datums.
1971 DatumMapRef theMap() const;
1972
1973 /// Return the string value represented by this object as a
1974 /// `bslstl::StringRef` object. The behavior is undefined unless this
1975 /// object actually represents a string value.
1977
1978 /// Return the time value represented by this object as a `bdlt::Time`
1979 /// object. The behavior is undefined unless this object actually
1980 /// represents a time value.
1981 bdlt::Time theTime() const;
1982
1983 /// Return the user-defined object represented by this object as a
1984 /// `DatumUdt` object. The behavior is undefined unless this object
1985 /// actually represents a user-defined object.
1986 DatumUdt theUdt() const;
1987
1988 /// Return the type of value represented by this object as one of the
1989 /// enumeration values defined in `DataType`.
1990 DataType type() const;
1991
1992 /// Write the value of this object to the specified output `stream` in a
1993 /// human-readable format, and return a reference to the modifiable
1994 /// `stream`. Optionally specify an initial indentation `level`, whose
1995 /// absolute value is incremented recursively for nested objects. If
1996 /// `level` is specified, optionally specify `spacesPerLevel`, whose
1997 /// absolute value indicates the number of spaces per indentation level
1998 /// for this and all of its nested objects. If `level` is negative,
1999 /// suppress indentation of the first line. If `spacesPerLevel` is
2000 /// negative, format the entire output on one line, suppressing all but
2001 /// the initial indentation (as governed by `level`). If `stream` is
2002 /// not valid on entry, this operation has no effect. Note that this
2003 /// human-readable format is not fully specified, and can change without
2004 /// notice.
2005 bsl::ostream& print(bsl::ostream& stream,
2006 int level = 0,
2007 int spacesPerLevel = 4) const;
2008
2009#ifndef BDE_OMIT_INTERNAL_DEPRECATED
2010 // DEPRECATED
2011
2012 /// [**DEPRECATED**] Use `createUninitializedMap` instead.
2015 SizeType capacity,
2016 SizeType keysCapacity,
2017 const AllocatorType& allocator);
2018
2019 /// [**DEPRECATED**] Use `adoptMap` instead.
2021 const DatumMutableMapOwningKeysRef& mapping);
2022
2023 /// [**DEPRECATED**] Use `disposeUninitializedMap` instead.
2025 const DatumMutableMapOwningKeysRef& mapping,
2026 const AllocatorType& allocator);
2027#endif // end - do not omit deprecated symbols
2028};
2029
2030// FREE OPERATORS
2031
2032/// Return `true` if the specified `lhs` and `rhs` represent the same value,
2033/// and `false` otherwise. Two datums (not holding strings and user-
2034/// defined objects) represent the same value if they have the same type of
2035/// value stored inside them and invoking `==` operator on the stored values
2036/// returns `true`. Two datums holding strings are equal if the strings
2037/// have the same length and and values at each respective character
2038/// position are also same. Two datums holding user-defined objects are
2039/// equal if the user-defined objects have the same pointer and type values.
2040/// Two `nil` datums are always equal. Two `Datum` objects holding `NaN`
2041/// values are never equal. Two datums that hold arrays of datums have the
2042/// same value if the underlying arrays have the same length and invoking
2043/// `==` operator on each corresponding element returns `true`. Two datums
2044/// that hold maps of datums have the same value if the underlying maps have
2045/// the same size and each corresponding pair of elements in the maps have
2046/// the same keys and invoking `==` operator on the values returns `true`.
2047bool operator==(const Datum& lhs, const Datum& rhs);
2048
2049/// Return `true` if the specified `lhs` and `rhs` datums do not represent
2050/// the same value, and `false` otherwise. Two datums do not represent the
2051/// same value if they do not hold values of the same type, or they hold
2052/// values of the same type but invoking `==` operator on the stored values
2053/// returns `false`. Two strings do not have the same value if they have
2054/// different lengths or values at one of the respective character position
2055/// are not the same. Two `DatumUdt` objects are not equal if they have
2056/// different pointer or type values. Two `bslmf::Nil` values are always
2057/// equal. Two datums with `NaN` values are never equal. Two datums that
2058/// hold arrays of datums have different values if the underlying arrays
2059/// have different lengths or invoking `==` operator on at least one of the
2060/// corresponding pair of contained elements returns `false`. Two datums
2061/// that hold maps of datums have different values if the underlying maps
2062/// have different sizes or at least one of the corresponding pair of
2063/// elements in the maps have different keys or invoking `==` operator on
2064/// the values returns `false`.
2065bool operator!=(const Datum& lhs, const Datum& rhs);
2066
2067/// Write the specified `rhs` value to the specified output `stream` in the
2068/// format shown in the second column in the table below (based on the type
2069/// of value stored, indicated by the first column):
2070/// @code
2071/// null - nil
2072///
2073/// bool - true/false
2074///
2075/// DatumError - error(code)/error(code, `msg`)
2076/// where `code` is the integer error code and
2077/// `msg` is the error description message
2078///
2079/// int - plain integer value
2080///
2081/// Int64 - plain Int64 value
2082///
2083/// double - plain double value
2084///
2085/// string - plain double-quoted string value
2086///
2087/// array - [ elem0, ..., elemN]
2088/// where elem1..elemN are output for individual
2089/// array elements
2090///
2091/// int-map - [key0 = val0, ..., keyN = valN]
2092/// where keyX and valX are respectively key and
2093/// value of the map entry elements of the map
2094///
2095/// map - [key0 = val0, ..., keyN = valN]
2096/// where keyX and valX are respectively key and
2097/// value of the map entry elements of the map
2098///
2099/// bdlt::Date - ddMONyyyy
2100///
2101/// bdlt::Time - hh:mm:ss.sss
2102///
2103/// bdlt::Datetime - ddMONyyyy_hh:mm:ss.sss
2104///
2105/// bdlt::DatetimeInterval - sDD_HH:MM:SS.SSS (where s is the sign(+/-))
2106///
2107/// DatumUdt - user-defined(address,type)
2108/// where `address` is a hex encoded pointer to
2109/// the user-defined object and `type` is its type
2110/// @endcode
2111/// and return a reference to the modifiable `stream`. The function will
2112/// have no effect if the specified `stream` is not valid.
2113bsl::ostream& operator<<(bsl::ostream& stream, const Datum& rhs);
2114
2115/// Invoke the specified `hashAlgorithm` on the value of the specified
2116/// `datum` object. Note that the value of a User Defined Type in Datum is
2117/// a combination of its type integer and the address (pointer value), not
2118/// the actual value of the object that the pointer points to.
2119template <class t_HASH_ALGORITHM>
2120void hashAppend(t_HASH_ALGORITHM& hashAlgorithm, const Datum& datum);
2121
2122/// Write the string representation of the specified enumeration `rhs` to
2123/// the specified `stream` in a single-line format, and return a reference
2124/// to the modifiable `stream`. See `dataTypeToAscii` for what constitutes
2125/// the string representation of a `Datum::DataType` value.
2126bsl::ostream& operator<<(bsl::ostream& stream, Datum::DataType rhs);
2127
2128 // ==========================
2129 // class DatumMutableArrayRef
2130 // ==========================
2131
2132/// This `class` provides mutable access to a datum array. The users of
2133/// this class can read from and assign to the individual elements as well
2134/// as change the length of the array.
2135///
2136/// See @ref bdld_datum
2138
2139 public:
2140 // TYPES
2141
2142 /// `SizeType` is an alias for an unsigned integral value, representing
2143 /// the capacity of a datum array.
2145
2146 private:
2147 // DATA
2148 Datum *d_data_p; // pointer to an array (not owned)
2149 SizeType *d_length_p; // pointer to the length of the array
2150 SizeType d_capacity; // array capacity (to dispose of uninitialized
2151 // arrays)
2152 public:
2153 // CREATORS
2154
2155 /// Create a `DatumMutableArrayRef` object that refers to no array.
2157
2158 /// Create a `DatumMutableArrayRef` object having the specified `data`,
2159 /// `length`, and `capacity`.
2161
2162 /// Create a `DatumMutableArrayRef` having the value of the specified
2163 /// `original` object. Note that this method's definition is compiler
2164 /// generated.
2165 DatumMutableArrayRef(const DatumMutableArrayRef& original) = default;
2166
2167 /// Destroy this object. Note that this method's definition is compiler
2168 /// generated.
2170
2171 // MANIPULATORS
2172
2173 /// Assign to this object the value of the specified `rhs` object. Note
2174 /// that this method's definition is compiler generated.
2176 const DatumMutableArrayRef& rhs) = default;
2177
2178 // ACCESSORS
2179
2180 /// Return pointer to the memory allocated for the array.
2181 void *allocatedPtr() const;
2182
2183 /// Return pointer to the first element of the held array.
2184 Datum *data() const;
2185
2186 /// Return pointer to the length of the array.
2187 SizeType *length() const;
2188
2189 /// Return the allocated capacity of the array.
2190 SizeType capacity() const;
2191};
2192
2193 // =========================
2194 // struct Datum_IntMapHeader
2195 // =========================
2196
2197/// This component-local class provides a layout of the meta-information
2198/// stored in front of the Datum int-maps.
2200
2201 // DATA
2202 Datum::SizeType d_size; // size of the map
2203 Datum::SizeType d_capacity; // number of allocated map entries
2204 bool d_sorted; // sorted flag
2205};
2206
2207 // ======================
2208 // struct Datum_MapHeader
2209 // ======================
2210
2211/// This component-local class provides a layout of the meta-information
2212/// stored in front of the Datum maps.
2214
2215 // DATA
2216 Datum::SizeType d_size; // size of the map
2217 Datum::SizeType d_capacity; // number of allocated map entries
2218 Datum::SizeType d_allocatedSize; // full allocated memory size in bytes
2219 bool d_sorted; // sorted flag
2220 bool d_ownsKeys; // owns keys flag
2221};
2222
2223 // ========================
2224 // class DatumMutableMapRef
2225 // ========================
2226
2227/// This `class` provides a mutable access to a datum map. The users of
2228/// this class can assign to the individual elements and also change the
2229/// size of the map.
2230///
2231/// See @ref bdld_datum
2233
2234 public:
2235
2236 /// `SizeType` is an alias for an unsigned integral value, representing
2237 /// the capacity of a datum array, the capacity of a datum map, the
2238 /// capacity of the *keys-capacity* of a datum-key-owning map or the
2239 /// length of a string.
2241
2242 private:
2243 // DATA
2244 DatumMapEntry *d_data_p; // pointer to a map of datums (not owned)
2245
2246 SizeType *d_size_p; // pointer to the size of the map
2247
2248 bool *d_sorted_p; // pointer to flag indicating whether the map
2249 // is sorted or not
2250
2251 public:
2252 // CREATORS
2253
2254 /// Create a `DatumMutableMapRef` object.
2256
2257 /// Create a `DatumMutableMapRef` object having the specified `data`,
2258 /// `size`, and `sorted`.
2260
2261 /// Create a `DatumMutableMapRef` having the value of the specified
2262 /// `original` object. Note that this method's definition is compiler
2263 /// generated.
2264 DatumMutableMapRef(const DatumMutableMapRef& original) = default;
2265
2266 /// Destroy this object. Note that this method's definition is compiler
2267 /// generated.
2269
2270 // MANIPULATORS
2271
2272 // Assign to this object the value of the specified `rhs` object. Note
2273 // that this method's definition is compiler generated.
2275
2276 // ACCESSORS
2277
2278 /// Return pointer to the memory allocated for the map.
2279 void *allocatedPtr() const;
2280
2281 /// Return pointer to the first element in the (held) map.
2282 DatumMapEntry *data() const;
2283
2284 /// Return pointer to the location where the (held) map's size is
2285 /// stored.
2286 SizeType *size() const;
2287
2288 /// Return pointer to the location where the (held) map's *sorted* flag
2289 /// is stored.
2290 bool *sorted() const;
2291};
2292
2293 // ===========================
2294 // class DatumMutableIntMapRef
2295 // ===========================
2296
2297/// This `class` provides a mutable access to a datum int-map. The users of
2298/// this class can assign to the individual elements and also change the
2299/// size of the map.
2300///
2301/// See @ref bdld_datum
2303
2304 public:
2305
2306 /// `SizeType` is an alias for an unsigned integral value, representing
2307 /// the capacity of a datum array, the capacity of a datum map, the
2308 /// capacity of the *keys-capacity* of a datum-key-owning map or the
2309 /// length of a string.
2311
2312 private:
2313 // DATA
2314 DatumIntMapEntry *d_data_p; // pointer to an int-map of datums (not
2315 // owned)
2316
2317 SizeType *d_size_p; // pointer to the size of the map
2318
2319 bool *d_sorted_p; // pointer to flag indicating whether the
2320 // int-map is sorted or not
2321
2322 public:
2323 // CREATORS
2324
2325 /// Create a `DatumMutableIntMapRef` object.
2327
2328 /// Create a `DatumMutableIntMapRef` object having the specified `data`,
2329 /// `size`, and `sorted`.
2331 SizeType *size,
2332 bool *sorted);
2333
2334 /// Create a `DatumMutableIntMapRef` having the value of the specified
2335 /// `original` object. Note that this method's definition is compiler
2336 /// generated.
2338
2339 /// Destroy this object. Note that this method's definition is compiler
2340 /// generated.
2342
2343 // MANIPULATORS
2344
2345 // Assign to this object the value of the specified `rhs` object. Note
2346 // that this method's definition is compiler generated.
2348 = default;
2349
2350 // ACCESSORS
2351
2352 /// Return pointer to the memory allocated for the map.
2353 void *allocatedPtr() const;
2354
2355 /// Return pointer to the first element in the (held) map.
2356 DatumIntMapEntry *data() const;
2357
2358 /// Return pointer to the location where the (held) map's size is
2359 /// stored.
2360 SizeType *size() const;
2361
2362 /// Return pointer to the location where the (held) map's *sorted* flag
2363 /// is stored.
2364 bool *sorted() const;
2365};
2366
2367 // ==================================
2368 // class DatumMutableMapOwningKeysRef
2369 // ==================================
2370
2371/// This `class` provides mutable access to a datum key-owning map. The
2372/// users of this class can assign to the individual elements, copy keys and
2373/// change the size of the map.
2374///
2375/// See @ref bdld_datum
2377
2378 public:
2379
2380 /// `SizeType` is an alias for an unsigned integral value, representing
2381 /// the capacity of a datum array, the capacity of a datum map, the
2382 /// capacity of the *keys-capacity* of a datum-key-owning map or the
2383 /// length of a string.
2385
2386 private:
2387 // DATA
2388 DatumMapEntry *d_data_p; // pointer to a map of datums (not owned)
2389
2390 SizeType *d_size_p; // pointer to the size of the map
2391
2392 SizeType d_allocatedSize; // number of bytes allocated for the map
2393
2394 char *d_keys_p; // pointer to the key storage
2395
2396 bool *d_sorted_p; // pointer to flag indicating whether the
2397 // map is sorted or not
2398
2399 public:
2400 // CREATORS
2401
2402 /// Create a `DatumMutableMapOwningKeysRef` object.
2404
2405 /// Create a `DatumMutableMapOwningKeysRef` object having the specified
2406 /// `data`, `size`, `allocatedSize`, `keys`, and `sorted`.
2408 SizeType *size,
2410 char *keys,
2411 bool *sorted);
2412
2413 /// Create a `DatumMutableMapOwningKeysRef` having the value of the
2414 /// specified `original` object.
2416 const DatumMutableMapOwningKeysRef& original) = default;
2417
2418 /// Destroy this object.
2420
2421 // MANIPULATORS
2422
2423 /// Assign to this object the value of the specified `rhs` object. Note
2424 /// that this method's definition is compiler generated.
2426 const DatumMutableMapOwningKeysRef& rhs) = default;
2427
2428 // ACCESSORS
2429
2430 /// Return the number of bytes allocated for the map.
2431 SizeType allocatedSize() const;
2432
2433 /// Return pointer to the memory allocated for the map.
2434 void *allocatedPtr() const;
2435
2436 /// Return pointer to the first element in the held map.
2437 DatumMapEntry *data() const;
2438
2439 /// Return pointer to the start of the buffer where keys are stored.
2440 char *keys() const;
2441
2442 /// Return pointer to the location where the (held) map's size is
2443 /// stored.
2444 SizeType *size() const;
2445
2446 /// Return pointer to the location where the (held) map's *sorted* flag
2447 /// is stored.
2448 bool *sorted() const;
2449};
2450
2451 // ===================
2452 // class DatumArrayRef
2453 // ===================
2454
2455/// This `class` provides a read-only view to an array of datums. It holds
2456/// the array by a `const` pointer and an integral length value. It acts as
2457/// return value for accessors inside the `Datum` class that return an array
2458/// of datums. Note that zero-length arrays are valid.
2459///
2460/// See @ref bdld_datum
2462
2463 public:
2464 // PUBLIC TYPES
2467
2468 typedef bsl::size_t size_type;
2469 typedef bsl::ptrdiff_t difference_type;
2470
2473
2476
2479
2480 typedef bsl::reverse_iterator<iterator> reverse_iterator;
2481 typedef bsl::reverse_iterator<const_iterator> const_reverse_iterator;
2482
2483 /// `SizeType` is an alias for an unsigned integral value, representing
2484 /// the length of a datum array.
2486
2487 private:
2488 // DATA
2489 const Datum *d_data_p; // pointer to the first array element (not owned)
2490 SizeType d_length; // length of the array of
2491
2492 public:
2493 // TRAITS
2496
2497
2498 // CREATORS
2499
2500 /// Create a `DatumArrayRef` object representing an empty array.
2501 DatumArrayRef();
2502
2503 /// Create a `DatumArrayRef` object having the specified `data` and
2504 /// `length`. The behavior is undefined unless `0 != data` or `0 ==
2505 /// length`. Note that the pointer to the array is just copied.
2507
2508 /// Create a `DatumArrayRef` object having the value of the specified
2509 /// `original` object.
2510 DatumArrayRef(const DatumArrayRef& other) = default;
2511
2512 // Destroy this object.
2513 ~DatumArrayRef() = default;
2514
2515 // MANIPULATORS
2516
2517 /// Assign to this object the value of the specified `rhs` object.
2518 DatumArrayRef& operator=(const DatumArrayRef& rhs) = default;
2519
2520 // ACCESSORS
2521
2522 /// Return a reference providing non-modifiable access to the element at
2523 /// the specified `position` in the array this reference object
2524 /// represents. The behavior is undefined unless `position < size()`.
2525 const_reference operator[](size_type position) const;
2526
2528
2529 /// Return an iterator providing non-modifiable access to the first
2530 /// element of the array this reference object represents; return a
2531 /// past-the-end iterator if `size() == 0`.
2533
2535
2536 /// Return an iterator providing non-modifiable access pointing
2537 /// past-the-end of the array this reference object represents.
2539
2541
2542 /// Return a reverse iterator providing non-modifiable access to the
2543 /// last element of the array this reference object represents, and the
2544 /// past-the-end reverse iterator if `size() == 0`.
2546
2548
2549 /// Return a reverse iterator providing non-modifiable access pointing
2550 /// past-the-end of the array this reference object represents.
2552
2553 /// Return `size() == 0`.
2554 bool empty() const BSLS_KEYWORD_NOEXCEPT;
2555
2556 /// Return a const-pointer to the number of elements of the array this
2557 /// reference object represents.
2559
2560 /// Return a reference providing non-modifiable access to the first
2561 /// element of the array this reference object represents. The behavior
2562 /// is undefined unless `size() > 0`.
2563 const_reference front() const;
2564
2565 /// Return a reference providing non-modifiable access to the last
2566 /// element of the array this reference object represents. The behavior
2567 /// is undefined unless `size() > 0`.
2568 const_reference back() const;
2569
2570 /// Return the address providing non-modifiable access to the first
2571 /// element of the array this reference object represents. Return a
2572 /// valid pointer which cannot be dereferenced if the `size() == 0`.
2574
2575 /// Return a const pointer to the length of the array.
2576 size_type length() const;
2577
2578 /// Write the value of this object to the specified output `stream` in a
2579 /// human-readable format, and return a reference to the modifiable
2580 /// `stream`. Optionally specify an initial indentation `level`, whose
2581 /// absolute value is incremented recursively for nested objects. If
2582 /// `level` is specified, optionally specify `spacesPerLevel`, whose
2583 /// absolute value indicates the number of spaces per indentation level
2584 /// for this and all of its nested objects. If `level` is negative,
2585 /// suppress indentation of the first line. If `spacesPerLevel` is
2586 /// negative, format the entire output on one line, suppressing all but
2587 /// the initial indentation (as governed by `level`). If `stream` is
2588 /// not valid on entry, this operation has no effect. Note that this
2589 /// human-readable format is not fully specified, and can change without
2590 /// notice.
2591 bsl::ostream& print(bsl::ostream& stream,
2592 int level = 0,
2593 int spacesPerLevel = 4) const;
2594};
2595
2596// FREE OPERATORS
2597
2598/// Return `true` if the specified `lhs` and `rhs` have the same value, and
2599/// `false` otherwise. Two `DatumArrayRef` objects have the same value if
2600/// they hold arrays of the same length and all the corresponding `Datum`
2601/// objects in the two arrays also compare equal.
2602bool operator==(const DatumArrayRef& lhs, const DatumArrayRef& rhs);
2603
2604/// Return `true` if the specified `lhs` and `rhs` have different values,
2605/// and `false` otherwise. Two `DatumArrayRef` objects have different
2606/// values if they hold arrays of different lengths or invoking operator
2607/// `==` returns false for at least one of the corresponding elements in the
2608/// arrays.
2609bool operator!=(const DatumArrayRef& lhs, const DatumArrayRef& rhs);
2610
2611/// Write the specified `rhs` value to the specified output `stream` in the
2612/// format shown below:
2613/// @code
2614/// [aa,bb,cc] - aa, bb and cc are the result of invoking operator `<<`
2615/// on the individual elements in the array
2616/// @endcode
2617/// and return a reference to the modifiable `stream`. The function will
2618/// have no effect if the `stream` is not valid.
2619bsl::ostream& operator<<(bsl::ostream& stream, const DatumArrayRef& rhs);
2620
2621 // ======================
2622 // class DatumIntMapEntry
2623 // ======================
2624
2625/// This class represents an entry in a datum map keyed by string values.
2626///
2627/// See @ref bdld_datum
2629
2630 BSLMF_ASSERT(sizeof(int) == 4 && CHAR_BIT == 8);
2631
2632 private:
2633 // DATA
2634 int d_key; // key for this entry
2635 Datum d_value; // value for this entry
2636
2637 public:
2638 // TRAITS
2642
2643 // CREATORS
2644
2645 /// Create a `DatumIntMapEntry` object.
2647
2648 /// Create a `DatumIntMapEntry` object using the specified `key` and
2649 /// `value`.
2650 DatumIntMapEntry(int key, const Datum& value);
2651
2652 /// Destroy this object.
2654
2655 // MANIPULATORS
2656
2657 /// Set the key for this entry to the specified `key`.
2658 void setKey(int key);
2659
2660 /// Set the value for this entry to the specified `value`.
2661 void setValue(const Datum& value);
2662
2663 // ACCESSORS
2664
2665 /// Return the key for this entry.
2666 int key() const;
2667
2668 /// Return the value for this entry.
2669 const Datum& value() const;
2670
2671 /// Write the value of this object to the specified output `stream` in a
2672 /// human-readable format, and return a reference to the modifiable
2673 /// `stream`. Optionally specify an initial indentation `level`, whose
2674 /// absolute value is incremented recursively for nested objects. If
2675 /// `level` is specified, optionally specify `spacesPerLevel`, whose
2676 /// absolute value indicates the number of spaces per indentation level
2677 /// for this and all of its nested objects. If `level` is negative,
2678 /// suppress indentation of the first line. If `spacesPerLevel` is
2679 /// negative, format the entire output on one line, suppressing all but
2680 /// the initial indentation (as governed by `level`). If `stream` is
2681 /// not valid on entry, this operation has no effect. Note that this
2682 /// human-readable format is not fully specified, and can change without
2683 /// notice.
2684 bsl::ostream& print(bsl::ostream& stream,
2685 int level = 0,
2686 int spacesPerLevel = 4) const;
2687
2688};
2689
2690// FREE OPERATORS
2691
2692/// Return `true` if the specified `lhs` and `rhs` have the same value, and
2693/// `false` otherwise. Two `DatumIntMapEntry` objects have the same value
2694/// if their keys and values compare equal.
2695bool operator==(const DatumIntMapEntry& lhs, const DatumIntMapEntry& rhs);
2696
2697/// Return `true` if the specified `lhs` and `rhs` have different values,
2698/// and `false` otherwise. Two `DatumIntMapEntry` objects have different
2699/// values if either the keys or values are not equal.
2700bool operator!=(const DatumIntMapEntry& lhs, const DatumIntMapEntry& rhs);
2701
2702/// Write the specified `rhs` value to the specified output `stream` in the
2703/// format shown below:
2704/// @code
2705/// (nnn,aa) - nnn is key integer, while aa is the result of invoking
2706/// operator `<<` on the value
2707/// @endcode
2708/// and return a reference to the modifiable `stream`. The function will
2709/// have no effect if the `stream` is not valid.
2710bsl::ostream& operator<<(bsl::ostream& stream, const DatumIntMapEntry& rhs);
2711
2712 // ====================
2713 // class DatumIntMapRef
2714 // ====================
2715
2716/// This class provides a read-only view to a map of datums (an array of
2717/// `DatumIntMapEntry` objects). It holds the array by a `const` pointer
2718/// and an integral size value. It acts as return value for accessors
2719/// inside the `Datum` class that return a map of `Datum` objects. Note
2720/// that zero-size maps are valid.
2721///
2722/// See @ref bdld_datum
2724
2725 public:
2726 // PUBLIC TYPES
2729
2730 typedef bsl::size_t size_type;
2731 typedef bsl::ptrdiff_t difference_type;
2732
2735
2738
2741
2742 typedef bsl::reverse_iterator<iterator> reverse_iterator;
2743 typedef bsl::reverse_iterator<const_iterator> const_reverse_iterator;
2744
2745 /// `SizeType` is an alias for an unsigned integral value, representing
2746 /// the capacity of a datum array, the capacity of a datum map, the
2747 /// capacity of the *keys-capacity* of a datum-key-owning map or the
2748 /// length of a string.
2750
2751 private:
2752 // DATA
2753 const DatumIntMapEntry *d_data_p; // entry-array pointer (not owned)
2754 SizeType d_size; // length of the map
2755 bool d_sorted; // flag indicating whether the array is
2756 // sorted or not
2757 public:
2758 // TRAITS
2761
2762 // CREATORS
2763
2764 /// Create a `DatumIntMapRef` object having the specified `data` of the
2765 /// specified `size` and the specified `sorted` flag. The behavior is
2766 /// undefined unless `0 != data` or `0 == size`. Note that the pointer
2767 /// to the array is just copied.
2768 DatumIntMapRef(const DatumIntMapEntry *data,
2769 SizeType size,
2770 bool sorted);
2771
2772 /// Destroy this object.
2773 ~DatumIntMapRef() = default;
2774
2775 // ACCESSORS
2776
2777 /// Return a reference providing non-modifiable access to the element at
2778 /// the specified `position` in the array of map entries this reference
2779 /// object represents. The behavior is undefined unless
2780 /// `position < size()`.
2781 const_reference operator[](size_type position) const;
2782
2784
2785 /// Return an iterator providing non-modifiable access to the first
2786 /// element of the array of map entries this reference object
2787 /// represents; return a past-the-end iterator if `size() == 0`.
2789
2791
2792 /// Return an iterator providing non-modifiable access pointing
2793 /// past-the-end of the array this reference object represents.
2795
2797
2798 /// Return a reverse iterator providing non-modifiable access to the
2799 /// last element of the array this reference object represents, and the
2800 /// past-the-end reverse iterator if `size() == 0`.
2802
2804
2805 /// Return a reverse iterator providing non-modifiable access pointing
2806 /// past-the-end of the array this reference object represents.
2808
2809 /// Return `size() == 0`.
2810 bool empty() const BSLS_KEYWORD_NOEXCEPT;
2811
2812 /// Return a const-pointer to the number of elements of the array this
2813 /// reference object represents.
2814 size_type size() const BSLS_KEYWORD_NOEXCEPT;
2815
2816 /// Return a reference providing non-modifiable access to the first
2817 /// element of the array this reference object represents. The behavior
2818 /// is undefined unless `size() > 0`.
2819 const_reference front() const;
2820
2821 /// Return a reference providing non-modifiable access to the last
2822 /// element of the array this reference object represents. The behavior
2823 /// is undefined unless `size() > 0`.
2824 const_reference back() const;
2825
2826 /// Return the address providing non-modifiable access to the first
2827 /// element of the array this reference object represents. Return a
2828 /// valid pointer which cannot be dereferenced if the `size() == 0`.
2829 pointer data() const BSLS_KEYWORD_NOEXCEPT;
2830
2831 /// Return `true` if underlying map is sorted and `false` otherwise.
2832 bool isSorted() const;
2833
2834 /// Return a const pointer to the datum having the specified `key`, if
2835 /// it exists and 0 otherwise. Note that the `find` has order of `O(n)`
2836 /// if the data is not sorted based on the keys; if the data is sorted,
2837 /// it has order of `O(log(n))`. Also note that if multiple entries
2838 /// with matching keys are present, which matching record is found is
2839 /// unspecified.
2840 const Datum *find(int key) const;
2841
2842 /// Write the value of this object to the specified output `stream` in a
2843 /// human-readable format, and return a reference to the modifiable
2844 /// `stream`. Optionally specify an initial indentation `level`, whose
2845 /// absolute value is incremented recursively for nested objects. If
2846 /// `level` is specified, optionally specify `spacesPerLevel`, whose
2847 /// absolute value indicates the number of spaces per indentation level
2848 /// for this and all of its nested objects. If `level` is negative,
2849 /// suppress indentation of the first line. If `spacesPerLevel` is
2850 /// negative, format the entire output on one line, suppressing all but
2851 /// the initial indentation (as governed by `level`). If `stream` is
2852 /// not valid on entry, this operation has no effect. Note that this
2853 /// human-readable format is not fully specified, and can change without
2854 /// notice.
2855 bsl::ostream& print(bsl::ostream& stream,
2856 int level = 0,
2857 int spacesPerLevel = 4) const;
2858};
2859
2860// FREE OPERATORS
2861
2862/// Return `true` if the specified `lhs` and `rhs` have the same value, and
2863/// `false` otherwise. Two `DatumIntMapRef` objects have the same value if
2864/// they hold maps of the same size and all the corresponding
2865/// `DatumIntMapEntry` elements in the two maps also compare equal.
2866bool operator==(const DatumIntMapRef& lhs, const DatumIntMapRef& rhs);
2867
2868/// Return `true` if the specified `lhs` and `rhs` have different values,
2869/// and `false` otherwise. Two `DatumIntMapRef` objects have different
2870/// values if they hold maps of different sizes or operator `==` returns
2871/// `false` for at least one of the corresponding elements in the maps.
2872bool operator!=(const DatumIntMapRef& lhs, const DatumIntMapRef& rhs);
2873
2874/// Write the specified `rhs` value to the specified output `stream` in the
2875/// format shown below:
2876/// @code
2877/// [ nnn = aa, mmm = bb] - nnn and mmm are key ints, while aa and bb
2878/// are the result of invoking operator `<<` on the
2879/// individual value elements in the map
2880/// @endcode
2881/// and return a reference to the modifiable `stream`. The function will
2882/// have no effect if the `stream` is not valid.
2883bsl::ostream& operator<<(bsl::ostream& stream, const DatumIntMapRef& rhs);
2884
2885 // ===================
2886 // class DatumMapEntry
2887 // ===================
2888
2889/// This class represents an entry in a datum map keyed by string values.
2890///
2891/// See @ref bdld_datum
2893
2894 private:
2895 // DATA
2896 bslstl::StringRef d_key_p; // key for this entry (not owned)
2897 Datum d_value; // value for this entry
2898
2899 public:
2900 // TRAITS
2903
2904 // CREATORS
2905
2906 /// Create a `DatumMapEntry` object.
2907 DatumMapEntry();
2908
2909 /// Create a `DatumMapEntry` object using the specified `key` and
2910 /// `value`.
2911 DatumMapEntry(const bslstl::StringRef& key, const Datum& value);
2912
2913 /// Destroy this object.
2914 ~DatumMapEntry() = default;
2915
2916 // MANIPULATORS
2917
2918 /// Set the key for this entry to the specified `key`.
2919 void setKey(const bslstl::StringRef& key);
2920
2921 /// Set the value for this entry to the specified `value`.
2922 void setValue(const Datum& value);
2923
2924 // ACCESSORS
2925
2926 /// Return the key for this entry.
2927 const bslstl::StringRef& key() const;
2928
2929 /// Return the value for this entry.
2930 const Datum& value() const;
2931
2932 /// Write the value of this object to the specified output `stream` in a
2933 /// human-readable format, and return a reference to the modifiable
2934 /// `stream`. Optionally specify an initial indentation `level`, whose
2935 /// absolute value is incremented recursively for nested objects. If
2936 /// `level` is specified, optionally specify `spacesPerLevel`, whose
2937 /// absolute value indicates the number of spaces per indentation level
2938 /// for this and all of its nested objects. If `level` is negative,
2939 /// suppress indentation of the first line. If `spacesPerLevel` is
2940 /// negative, format the entire output on one line, suppressing all but
2941 /// the initial indentation (as governed by `level`). If `stream` is
2942 /// not valid on entry, this operation has no effect. Note that this
2943 /// human-readable format is not fully specified, and can change without
2944 /// notice.
2945 bsl::ostream& print(bsl::ostream& stream,
2946 int level = 0,
2947 int spacesPerLevel = 4) const;
2948};
2949
2950// FREE OPERATORS
2951
2952/// Return `true` if the specified `lhs` and `rhs` have the same value, and
2953/// `false` otherwise. Two `DatumMapEntry` objects have the same value if
2954/// their keys and values compare equal.
2955bool operator==(const DatumMapEntry& lhs, const DatumMapEntry& rhs);
2956
2957/// Return `true` if the specified `lhs` and `rhs` have different values,
2958/// and `false` otherwise. Two `DatumMapEntry` objects have different
2959/// values if either the keys or values are not equal.
2960bool operator!=(const DatumMapEntry& lhs, const DatumMapEntry& rhs);
2961
2962/// Write the specified `rhs` value to the specified output `stream` in the
2963/// format shown below:
2964/// @code
2965/// (abc,aa) - abc is key string, while aa is the result of invoking
2966/// operator `<<` on the value
2967/// @endcode
2968/// and return a reference to the modifiable `stream`. The function will
2969/// have no effect if the `stream` is not valid.
2970bsl::ostream& operator<<(bsl::ostream& stream, const DatumMapEntry& rhs);
2971
2972 // =================
2973 // class DatumMapRef
2974 // =================
2975
2976/// This class provides a read-only view to a map of datums (an array of
2977/// `DatumMapEntry` objects). It holds the array by a `const` pointer and
2978/// an integral size value. It acts as return value for accessors inside
2979/// the `Datum` class that return a map of `Datum` objects. Note that
2980/// zero-size maps are valid.
2981///
2982/// See @ref bdld_datum
2984
2985 public:
2986 // PUBLIC TYPES
2989
2990 typedef bsl::size_t size_type;
2991 typedef bsl::ptrdiff_t difference_type;
2992
2995
2998
3001
3002 typedef bsl::reverse_iterator<iterator> reverse_iterator;
3003 typedef bsl::reverse_iterator<const_iterator> const_reverse_iterator;
3004
3005 /// `SizeType` is an alias for an unsigned integral value, representing
3006 /// the capacity of a datum array, the capacity of a datum map, the
3007 /// capacity of the *keys-capacity* of a datum-key-owning map or the
3008 /// length of a string.
3010
3011 private:
3012 // DATA
3013 const DatumMapEntry *d_data_p; // pointer to the entry-array (not owned)
3014 SizeType d_size; // length of the map
3015 bool d_sorted; // flag indicating whether the array is
3016 // sorted or not
3017 bool d_ownsKeys; // flag indicating whether the map owns
3018 // the keys or not
3019 public:
3020 // TRAITS
3023
3024 // CREATORS
3025
3026 /// Create a `DatumMapRef` object having the specified `data` of the
3027 /// specified `size` and the specified `sorted` and `ownsKeys` flags.
3028 /// The behavior is undefined unless `0 != data` or `0 == size`. Note
3029 /// that the pointer to the array is just copied.
3030 DatumMapRef(const DatumMapEntry *data,
3031 SizeType size,
3032 bool sorted,
3033 bool ownsKeys);
3034
3035 /// Destroy this object.
3036 ~DatumMapRef() = default;
3037
3038 // ACCESSORS
3039
3040 /// Return a reference providing non-modifiable access to the element at
3041 /// the specified `position` in the array of map entries this reference
3042 /// object represents. The behavior is undefined unless
3043 /// `position < size()`.
3044 const_reference operator[](size_type position) const;
3045
3047
3048 /// Return an iterator providing non-modifiable access to the first
3049 /// element of the array of map entries this reference object
3050 /// represents; return a past-the-end iterator if `size() == 0`.
3052
3054
3055 /// Return an iterator providing non-modifiable access pointing
3056 /// past-the-end of the array this reference object represents.
3058
3060
3061 /// Return a reverse iterator providing non-modifiable access to the
3062 /// last element of the array this reference object represents, and the
3063 /// past-the-end reverse iterator if `size() == 0`.
3065
3067
3068 /// Return a reverse iterator providing non-modifiable access pointing
3069 /// past-the-end of the array this reference object represents.
3071
3072 /// Return `size() == 0`.
3073 bool empty() const BSLS_KEYWORD_NOEXCEPT;
3074
3075 /// Return a const-pointer to the number of elements of the map this
3076 /// reference object represents.
3077 size_type size() const BSLS_KEYWORD_NOEXCEPT;
3078
3079 /// Return a reference providing non-modifiable access to the first
3080 /// element of the map this reference object represents. The behavior
3081 /// is undefined unless `size() > 0`.
3082 const_reference front() const;
3083
3084 /// Return a reference providing non-modifiable access to the last
3085 /// element of the map this reference object represents. The behavior
3086 /// is undefined unless `size() > 0`.
3087 const_reference back() const;
3088
3089 /// Return the address providing non-modifiable access to the first
3090 /// element of the map this reference object represents. Return a
3091 /// valid pointer which cannot be dereferenced if the `size() == 0`.
3092 pointer data() const BSLS_KEYWORD_NOEXCEPT;
3093
3094 /// Return `true` if underlying map is sorted and `false` otherwise.
3095 bool isSorted() const;
3096
3097 /// Return `true` if underlying map owns the keys and `false` otherwise.
3098 /// Note that `false` is always returned for zero-sized `DatumMapRef`.
3099 bool ownsKeys() const;
3100
3101 /// Return a const pointer to the datum having the specified `key`, if
3102 /// it exists and 0 otherwise. Note that the `find` has order of `O(n)`
3103 /// if the data is not sorted based on the keys. If the data is sorted,
3104 /// it has order of `O(log(n))`. Also note that if multiple entries
3105 /// with matching keys are present, which matching record is found is
3106 /// unspecified.
3107 const Datum *find(const bslstl::StringRef& key) const;
3108
3109 /// Write the value of this object to the specified output `stream` in a
3110 /// human-readable format, and return a reference to the modifiable
3111 /// `stream`. Optionally specify an initial indentation `level`, whose
3112 /// absolute value is incremented recursively for nested objects. If
3113 /// `level` is specified, optionally specify `spacesPerLevel`, whose
3114 /// absolute value indicates the number of spaces per indentation level
3115 /// for this and all of its nested objects. If `level` is negative,
3116 /// suppress indentation of the first line. If `spacesPerLevel` is
3117 /// negative, format the entire output on one line, suppressing all but
3118 /// the initial indentation (as governed by `level`). If `stream` is
3119 /// not valid on entry, this operation has no effect. Note that this
3120 /// human-readable format is not fully specified, and can change without
3121 /// notice.
3122 bsl::ostream& print(bsl::ostream& stream,
3123 int level = 0,
3124 int spacesPerLevel = 4) const;
3125};
3126
3127// FREE OPERATORS
3128
3129/// Return `true` if the specified `lhs` and `rhs` have the same value, and
3130/// `false` otherwise. Two `DatumMapRef` objects have the same value if
3131/// they hold maps of the same size and all the corresponding
3132/// `DatumMapEntry` elements in the two maps also compare equal.
3133bool operator==(const DatumMapRef& lhs, const DatumMapRef& rhs);
3134
3135/// Return `true` if the specified `lhs` and `rhs` have different values,
3136/// and `false` otherwise. Two `DatumMapRef` objects have different values
3137/// if they hold maps of different sizes or operator `==` returns false for
3138/// at least one of the corresponding elements in the maps.
3139bool operator!=(const DatumMapRef& lhs, const DatumMapRef& rhs);
3140
3141/// Write the specified `rhs` value to the specified output `stream` in the
3142/// format shown below:
3143/// @code
3144/// [ abc = aa, pqr = bb] - abc and pqr are key strings, while aa and bb
3145/// are the result of invoking operator '<<' on the
3146/// individual value elements in the map
3147/// @endcode
3148/// and return a reference to the modifiable `stream`. The function will
3149/// have no effect if the `stream` is not valid.
3150bsl::ostream& operator<<(bsl::ostream& stream, const DatumMapRef& rhs);
3151
3152
3153 // ====================
3154 // struct Datum_Helpers
3155 // ====================
3156
3157/// This struct contains helper functions used to access typed objects
3158/// within a buffer. The functions assume that objects within the buffers
3159/// have proper alignment and use casts to suppress compiler warnings about
3160/// possible alignment problems.
3162
3163 /// Return the typed value found at the specified `offset` within the
3164 /// specified `source`.
3165 template <class t_TYPE>
3166 static t_TYPE load(const void *source, int offset);
3167
3168 /// Store the specified typed `value` at the specified `offset` within
3169 /// the specified `destination` and return `value`.
3170 template <class t_TYPE>
3171 static t_TYPE store(void *destination, int offset, t_TYPE value);
3172};
3173
3174#ifdef BSLS_PLATFORM_CPU_32_BIT
3175
3176 // ======================
3177 // struct Datum_Helpers32
3178 // ======================
3179
3180/// This struct contains helper functions used in the 32-bit variation. The
3181/// functions are for internal use only and may change or disappear without
3182/// notice.
3183struct Datum_Helpers32 : Datum_Helpers {
3184
3185 // CLASS DATA
3186#ifdef BSLS_PLATFORM_IS_LITTLE_ENDIAN
3187 static const int b00 = 0; // Bits 0 to 32.
3188 static const int b32 = 4; // Bits 32 to 48.
3189 static const int b48 = 6; // Bits 48 to 64.
3190#else // end - little endian / begin - big endian
3191 static const int b00 = 4;
3192 static const int b32 = 2;
3193 static const int b48 = 0;
3194#endif // end - big endian
3195
3196 // CLASS METHODS
3197
3198 /// Load an Int64 from the specified `high16` and `low32` values created
3199 /// by storeSmallInt48. This method is public for testing purpose only.
3200 /// It may change or be removed without notice.
3201 static bsls::Types::Int64 loadInt48(short high16, int low32);
3202
3203 /// Store an Int64 in short at `phigh16` and int at `plow32` if its
3204 /// highest order 16 bits are zero. Return true if it fits. This
3205 /// method is public for testing purpose only. It may change or be
3206 /// removed without notice.
3207 static bool storeInt48(bsls::Types::Int64 value,
3208 short *phigh16,
3209 int *plow32);
3210
3211 /// Load an Int64 from the specified `high16` and `low32` values created
3212 /// by storeSmallInt64. This method is public for testing purpose only.
3213 /// It may change or be removed without notice.
3214 static bsls::Types::Int64 loadSmallInt64(short high16, int low32);
3215
3216 /// Store an Int64 in short at `phigh16` and int at `plow32`. Return
3217 /// true if it fits. This method is public for testing purpose only.
3218 /// It may change or be removed without notice.
3219 static bool storeSmallInt64(bsls::Types::Int64 value,
3220 short *phigh16,
3221 int *plow32);
3222};
3223
3224#endif // end - 32 bit
3225
3226// ============================================================================
3227// INLINE DEFINITIONS
3228// ============================================================================
3229
3230 // --------------------
3231 // struct Datum_Helpers
3232 // --------------------
3233
3234// CLASS METHODS
3235template <class t_TYPE>
3236inline
3237t_TYPE Datum_Helpers::load(const void *source, int offset)
3238{
3239 // The intermediate cast to `void *` avoids warnings about the cast to a
3240 // pointer of stricter alignment.
3241 return *static_cast<const t_TYPE *>(
3242 static_cast<const void *>(
3243 static_cast<const char *>(source) + offset));
3244}
3245
3246template <class t_TYPE>
3247inline
3248t_TYPE Datum_Helpers::store(void *destination, int offset, t_TYPE value)
3249{
3250 // The intermediate cast to `void *` avoids warnings about the cast to a
3251 // pointer of stricter alignment.
3252 return *static_cast<t_TYPE *>(
3253 static_cast<void *>(
3254 static_cast<char *>(destination) + offset)) = value;
3255}
3256
3257#ifdef BSLS_PLATFORM_CPU_32_BIT
3258
3259 // ----------------------
3260 // struct Datum32_Helpers
3261 // ----------------------
3262
3263// CLASS METHODS
3264inline
3265bsls::Types::Int64 Datum_Helpers32::loadSmallInt64(short high16, int low32)
3266{
3267 bsls::Types::Int64 value;
3268
3269 store<short>(&value, b48, store<short>(&value, b32, high16) < 0 ? -1 : 0);
3270 store<long> (&value, b00, low32);
3271
3272 return value;
3273}
3274
3275inline
3276bool Datum_Helpers32::storeSmallInt64(bsls::Types::Int64 value,
3277 short *phigh16,
3278 int *plow32)
3279{
3280 // Check that the sign can be inferred from the compressed 6-byte integer.
3281 // It is the case if the upper 16 bits are the same as the 17th bit.
3282
3283 if ((load<short>(&value, b48) == 0 && load<short>(&value, b32) >= 0) ||
3284 (load<short>(&value, b48) == -1 && load<short>(&value, b32) < 0)) {
3285 *phigh16 = load<short>(&value, b32);
3286 *plow32 = load<long> (&value, b00);
3287 return true; // RETURN
3288 }
3289 return false;
3290}
3291
3292inline
3293bsls::Types::Int64 Datum_Helpers32::loadInt48(short high16, int low32)
3294{
3295 bsls::Types::Int64 value;
3296
3297 store<short>(&value, b48, 0);
3298 store<short>(&value, b32, high16);
3299 store<long>(&value, b00, low32);
3300
3301 return value;
3302}
3303
3304inline
3305bool Datum_Helpers32::storeInt48(bsls::Types::Int64 value,
3306 short *phigh16,
3307 int *plow32)
3308{
3309 // Check 'value' is a 6-byte integer. It is the case if the upper 16 bits
3310 // are zero.
3311
3312 if (load<short>(&value, b48) == 0) {
3313 *phigh16 = load<short>(&value, b32);
3314 *plow32 = load<long>(&value, b00);
3315 return true; // RETURN
3316 }
3317 return false;
3318}
3319#endif // end - 32 bit
3320
3321 // -----------
3322 // class Datum
3323 // -----------
3324
3325// This section contains all class methods and private accessors that are used
3326// only in implementation for specific platform.
3327
3328#ifdef BSLS_PLATFORM_CPU_32_BIT
3329// PRIVATE CLASS METHODS
3330// 32-bit only
3331inline
3332Datum Datum::createExtendedDataObject(ExtendedInternalDataType type,
3333 void *data)
3334{
3335 Datum result;
3336 result.d_exp.d_value = (k_DOUBLE_MASK | e_INTERNAL_EXTENDED)
3337 << k_TYPE_MASK_BITS | type;
3338 result.d_as.d_cvp = data;
3339 return result;
3340}
3341
3342inline
3343Datum Datum::createExtendedDataObject(ExtendedInternalDataType type,
3344 int data)
3345{
3346 Datum result;
3347 result.d_exp.d_value = (k_DOUBLE_MASK | e_INTERNAL_EXTENDED)
3348 << k_TYPE_MASK_BITS | type;
3349 result.d_as.d_int = data;
3350 return result;
3351}
3352
3353// PRIVATE ACCESSORS
3354// 32-bit only
3355inline
3356Datum::ExtendedInternalDataType Datum::extendedInternalType() const
3357{
3358 BSLS_ASSERT_SAFE(e_INTERNAL_EXTENDED == internalType());
3359 return static_cast<ExtendedInternalDataType>(d_as.d_short);
3360}
3361
3362inline
3363Datum::DataType Datum::typeFromExtendedInternalType() const
3364{
3365 BSLS_ASSERT_SAFE(e_INTERNAL_EXTENDED == internalType());
3366
3367 static const DataType convert[] = {
3368 Datum::e_MAP // e_EXTENDED_INTERNAL_MAP = 0
3369 , Datum::e_MAP // e_EXTENDED_INTERNAL_OWNED_MAP = 1
3370 , Datum::e_DOUBLE // e_EXTENDED_INTERNAL_NAN2 = 2
3371 , Datum::e_ERROR // e_EXTENDED_INTERNAL_ERROR = 3
3372 , Datum::e_ERROR // e_EXTENDED_INTERNAL_ERROR_ALLOC = 4
3373 , Datum::e_STRING // e_EXTENDED_INTERNAL_SREF_ALLOC = 5
3374 , Datum::e_ARRAY // e_EXTENDED_INTERNAL_AREF_ALLOC = 6
3375 , Datum::e_DATETIME // e_EXTENDED_INTERNAL_DATETIME_ALLOC = 7
3376 , Datum::e_DATETIME_INTERVAL
3377 // e_EXTENDED_INTERNAL_DATETIME_INTERVAL_ALLOC = 8
3378 , Datum::e_INTEGER64 // e_EXTENDED_INTERNAL_INTEGER64_ALLOC = 9
3379 , Datum::e_BINARY // e_EXTENDED_INTERNAL_BINARY_ALLOC = 10
3380 , Datum::e_DECIMAL64 // e_EXTENDED_INTERNAL_DECIMAL64 = 11
3381 , Datum::e_DECIMAL64 // e_EXTENDED_INTERNAL_DECIMAL64_SPECIAL = 12
3382 , Datum::e_DECIMAL64 // e_EXTENDED_INTERNAL_DECIMAL64_ALLOC = 13
3383 , Datum::e_NIL // e_EXTENDED_INTERNAL_NIL = 14
3384 , Datum::e_INT_MAP // e_EXTENDED_INTERNAL_INT_MAP = 15
3385 };
3386
3387 BSLMF_ASSERT(sizeof(convert)/sizeof(convert[0]) ==
3388 k_NUM_EXTENDED_INTERNAL_TYPES);
3389
3390 const ExtendedInternalDataType type = extendedInternalType();
3391
3392 BSLS_ASSERT_OPT(static_cast<int>(type) <
3393 static_cast<int>(k_NUM_EXTENDED_INTERNAL_TYPES));
3394
3395 return convert[type];
3396}
3397
3398inline
3399bsls::Types::Int64 Datum::theLargeInteger64() const
3400{
3401 BSLS_ASSERT_SAFE(internalType() == e_INTERNAL_EXTENDED);
3403 extendedInternalType() == e_EXTENDED_INTERNAL_INTEGER64_ALLOC);
3404 return Datum_Helpers::load<bsls::Types::Int64>(d_as.d_cvp, 0);
3405}
3406
3407inline
3408DatumArrayRef Datum::theLongArrayReference() const
3409{
3410 return DatumArrayRef(
3411 Datum_Helpers::load<Datum *> (d_as.d_cvp, 0),
3412 Datum_Helpers::load<SizeType>(d_as.d_cvp, sizeof(Datum *)));
3413}
3414
3415inline
3416bslstl::StringRef Datum::theLongestShortString() const
3417{
3418 return bslstl::StringRef(d_string6.d_chars, sizeof d_string6.d_chars);
3419}
3420
3421inline
3422bslstl::StringRef Datum::theLongStringReference() const
3423{
3424 return bslstl::StringRef(
3425 Datum_Helpers::load<char *> (d_as.d_cvp, 0),
3426 Datum_Helpers::load<SizeType>(d_as.d_cvp, sizeof(char *)));
3427}
3428
3429inline
3430bsls::Types::Int64 Datum::theSmallInteger64() const
3431{
3432 BSLS_ASSERT_SAFE(internalType() == e_INTERNAL_INTEGER64);
3433 return Datum_Helpers32::loadSmallInt64(d_as.d_short, d_as.d_int);
3434}
3435#else // end - 32 bit / begin - 64 bit
3436// PRIVATE CLASS METHODS
3437
3438// 64-bit only
3439inline
3440Datum Datum::createDatum(InternalDataType type, void *data)
3441{
3442 Datum result;
3443 result.d_as.d_type = type;
3444 result.d_as.d_ptr = data;
3445 return result;
3446}
3447
3448inline
3449Datum Datum::createDatum(InternalDataType type, int data)
3450{
3451 Datum result;
3452 result.d_as.d_type = type;
3453 result.d_as.d_int64 = data;
3454 return result;
3455}
3456
3457// PRIVATE ACCESSORS
3458
3459// 64-bit only
3460inline
3461void* Datum::theInlineStorage()
3462{
3463 return d_data.buffer();
3464}
3465
3466inline
3467const void* Datum::theInlineStorage() const
3468{
3469 return d_data.buffer();
3470}
3471#endif // end - 64 bit
3472
3473// This section contains all methods that are common for all platforms, but may
3474// have platform-specific implementation.
3475
3476// PRIVATE ACCESSORS
3477inline
3478void Datum::safeDeallocateBytes(const AllocatorType& allocator,
3479 bsl::size_t nBytes) const
3480{
3481 void *ptr = allocatedPtr<void>();
3482
3483 if (ptr) {
3484 AllocUtil::deallocateBytes(allocator, ptr, nBytes);
3485 }
3486}
3487
3488inline
3489void Datum::safeDeallocateBytes(const AllocatorType& allocator,
3490 bsl::size_t nBytes,
3491 bsl::size_t alignment) const
3492{
3493 void *ptr = allocatedPtr<void>();
3494
3495 if (ptr) {
3496 AllocUtil::deallocateBytes(allocator, ptr, nBytes, alignment);
3497 }
3498}
3499
3500template <class t_TYPE>
3501inline
3502t_TYPE *Datum::allocatedPtr() const
3503{
3504#ifdef BSLS_PLATFORM_CPU_32_BIT
3505 return static_cast<t_TYPE *>(const_cast<void*>(d_as.d_cvp));
3506#else // end - 32 bit / begin - 64 bit
3507 return static_cast<t_TYPE *>(d_as.d_ptr);
3508#endif // end - 64 bit
3509}
3510inline
3511Datum::InternalDataType Datum::internalType() const
3512{
3513#ifdef BSLS_PLATFORM_CPU_32_BIT
3514 if (0x7f == d_data[k_EXPONENT_MSB] &&
3515 0xf0 == (d_data[k_EXPONENT_LSB] & 0xf0)) {
3516 return static_cast<InternalDataType>(d_data[k_EXPONENT_LSB] & 0x0f);
3517 }
3518 return e_INTERNAL_DOUBLE;
3519#else // end - 32 bit / begin - 64 bit
3520 return static_cast<InternalDataType>(d_as.d_type);
3521#endif // end - 64 bit
3522}
3523
3524inline
3525DatumArrayRef Datum::theArrayReference() const
3526{
3527#ifdef BSLS_PLATFORM_CPU_32_BIT
3528 return DatumArrayRef(allocatedPtr<const Datum>(), d_as.d_ushort);
3529#else // end - 32 bit / begin - 64 bit
3530 return DatumArrayRef(allocatedPtr<const Datum>(), d_as.d_int32);
3531#endif // end - 64 bit
3532}
3533
3534inline
3535DatumArrayRef Datum::theInternalArray() const
3536{
3537 const Datum *data = allocatedPtr<const Datum>();
3538 if (data) {
3539 const SizeType size = *reinterpret_cast<const SizeType *>(data);
3540 return DatumArrayRef(data + 1, size); // RETURN
3541 }
3542 return DatumArrayRef(0, 0);
3543}
3544
3545inline
3546bslstl::StringRef Datum::theInternalString() const
3547{
3548#ifdef BSLS_PLATFORM_CPU_32_BIT
3549 const char *data = allocatedPtr<const char>();
3550 return bslstl::StringRef(data + sizeof(SizeType),
3551 Datum_Helpers::load<SizeType>(data, 0));
3552#else // end - 32 bit / begin - 64 bit
3553 return bslstl::StringRef(allocatedPtr<const char>(),
3554 d_as.d_int32);
3555#endif // end - 64 bit
3556}
3557
3559bslstl::StringRef Datum::theShortString() const
3560{
3561#ifdef BSLS_PLATFORM_CPU_32_BIT
3562 return bslstl::StringRef(d_string5.d_chars, d_string5.d_length);
3563#else // end - 32 bit / begin - 64 bit
3564 const char *str = reinterpret_cast<const char *>(theInlineStorage());
3565 const SizeType len = *str++;
3566 return bslstl::StringRef(str, static_cast<int>(len));
3567#endif // end - 64 bit
3568}
3569
3570inline
3571bslstl::StringRef Datum::theStringReference() const
3572{
3573#ifdef BSLS_PLATFORM_CPU_32_BIT
3574 return bslstl::StringRef(allocatedPtr<const char>(), d_as.d_ushort);
3575#else // end - 32 bit / begin - 64 bit
3576 return bslstl::StringRef(allocatedPtr<const char>(), d_as.d_int32);
3577#endif // BSLS_PLATFORM_CPU_32_BIT
3578}
3579
3580inline
3581bsl::size_t Datum::theMapAllocNumBytes() const
3582{
3583 BSLS_ASSERT_SAFE(isMap());
3584
3585 // Map header is stored in the place of the first DatumMapEntry
3586 const Datum_MapHeader *header = allocatedPtr<const Datum_MapHeader>();
3587
3588 return header ? header->d_allocatedSize : 0;
3589}
3590
3591inline
3592bsl::size_t Datum::theIntMapAllocNumBytes() const
3593{
3594 BSLS_ASSERT_SAFE(isIntMap());
3595
3596 // Map header is stored in the place of the first DatumIntMapEntry
3597 const Datum_IntMapHeader *hdr = allocatedPtr<const Datum_IntMapHeader>();
3598
3599 return hdr ? (hdr->d_capacity + 1) * sizeof(DatumIntMapEntry) : 0;
3600}
3601
3602inline
3603bsl::size_t Datum::theErrorAllocNumBytes() const
3604{
3605 BSLS_ASSERT(isError());
3606
3607#ifdef BSLS_PLATFORM_CPU_32_BIT
3608 // If the extended type is 'e_EXTENDED_INTERNAL_ERROR', we are storing
3609 // just a code, at the data offset. Otherwise, we're storing an allocated
3610 // object.
3611
3613 e_EXTENDED_INTERNAL_ERROR_ALLOC == extendedInternalType());
3614#else // end - 32 bit / begin - 64 bit
3615 BSLS_ASSERT_SAFE(e_INTERNAL_ERROR_ALLOC == internalType());
3616#endif // end - 64 bit
3617
3618 const char* data = allocatedPtr<const char>();
3619
3620 const bsl::size_t msgLen = Datum_Helpers::load<int>(data, sizeof(int));
3621 const bsl::size_t align = sizeof(int);
3622 const bsl::size_t headLen = 2 * sizeof(int);
3623
3624 return headLen + ((msgLen + align - 1) & ~(align - 1));
3625}
3626
3627inline
3628bsl::size_t Datum::theBinaryAllocNumBytes() const
3629{
3630 BSLS_ASSERT_SAFE(isBinary());
3631
3632#ifdef BSLS_PLATFORM_CPU_32_BIT
3634 e_EXTENDED_INTERNAL_BINARY_ALLOC == extendedInternalType());
3635 return *allocatedPtr<const SizeType>() + sizeof(double);
3636#else // end - 32 bit / begin - 64 bit
3637 BSLS_ASSERT_SAFE(e_INTERNAL_BINARY_ALLOC == internalType());
3638 return d_as.d_int32;
3639#endif // end - 64 bit
3640}
3641
3642inline
3643bsl::size_t Datum::theInternalStringAllocNumBytes() const
3644{
3645 BSLS_ASSERT_SAFE(isString());
3646 BSLS_ASSERT_SAFE(e_INTERNAL_STRING == internalType());
3647
3648#ifdef BSLS_PLATFORM_CPU_32_BIT
3649 const char *data = allocatedPtr<const char>();
3650 const bsl::size_t msgLen = Datum_Helpers::load<SizeType>(data, 0);
3651 const bsl::size_t align = sizeof(SizeType);
3652 const bsl::size_t headLen = sizeof(SizeType);
3653
3654 return headLen + ((msgLen + align - 1) & ~(align - 1));
3655#else // end - 32 bit / begin - 64 bit
3656
3657 return d_as.d_int32;
3658#endif // end - 64 bit
3659 }
3660
3661inline
3662bsl::size_t Datum::theInternalArrayAllocNumBytes() const
3663{
3664 BSLS_ASSERT_SAFE(isArray());
3665 BSLS_ASSERT_SAFE(e_INTERNAL_ARRAY == internalType());
3666
3667 const Datum *data = allocatedPtr<const Datum>();
3668 if (data) {
3669 const bsl::size_t length = *reinterpret_cast<const SizeType*>(data);
3670 return (length + 1) * sizeof(Datum); // RETURN
3671 }
3672 return 0;
3673
3674}
3675
3676// CLASS METHODS
3677inline
3678Datum Datum::createArrayReference(const Datum *array,
3679 SizeType length,
3680 const AllocatorType& allocator)
3681{
3682 BSLS_ASSERT(array || 0 == length);
3683
3684#ifdef BSLS_PLATFORM_CPU_32_BIT
3685 // If the length will fit in the 'd_ushort' area, store everything inline;
3686 // otherwise, must allocate space.
3687
3688 if (bsl::numeric_limits<unsigned short>::max() >= length) {
3689 Datum result;
3690 result.d_as.d_exponent = k_DOUBLE_MASK | e_INTERNAL_ARRAY_REFERENCE;
3691 result.d_as.d_ushort = static_cast<unsigned short>(length);
3692 result.d_as.d_cvp = array;
3693 return result; // RETURN
3694 }
3695
3696 void *mem = AllocUtil::allocateBytes(allocator,
3697 sizeof(array) + sizeof(length));
3698 Datum_Helpers::store<const Datum *>(mem, 0, array);
3699 Datum_Helpers::store<SizeType> (mem, sizeof(array), length);
3700
3701 return createExtendedDataObject(e_EXTENDED_INTERNAL_AREF_ALLOC, mem);
3702#else // end - 32 bit / begin - 64 bit
3703 (void)allocator;
3704
3705 BSLS_ASSERT(length <= bsl::numeric_limits<unsigned int>::max());
3706
3707 Datum result;
3708 result.d_as.d_type = e_INTERNAL_ARRAY_REFERENCE;
3709 result.d_as.d_int32 = static_cast<int>(length);
3710 result.d_as.d_ptr = reinterpret_cast<void*>(const_cast<Datum*>(array));
3711 return result;
3712#endif // end - 64 bit
3713}
3714
3715inline
3716Datum Datum::createArrayReference(const DatumArrayRef& value,
3717 const AllocatorType& allocator)
3718{
3719 return createArrayReference(value.data(), value.length(), allocator);
3720}
3721
3722inline
3723Datum Datum::createBoolean(bool value)
3724{
3725 Datum result;
3726#ifdef BSLS_PLATFORM_CPU_32_BIT
3727 result.d_exp.d_value = (k_DOUBLE_MASK | e_INTERNAL_BOOLEAN)
3728 << k_TYPE_MASK_BITS;
3729 result.d_as.d_int = value;
3730#else // end - 32 bit / begin - 64 bit
3731 result.d_as.d_type = e_INTERNAL_BOOLEAN;
3732 result.d_as.d_int32 = value;
3733#endif // end - 64 bit
3734 return result;
3735}
3736
3737inline
3738Datum Datum::createDate(const bdlt::Date& value)
3739{
3740 Datum result;
3741#ifdef BSLS_PLATFORM_CPU_32_BIT
3742 BSLMF_ASSERT(sizeof(value) == sizeof(result.d_as.d_int));
3744
3745 result.d_exp.d_value = (k_DOUBLE_MASK | e_INTERNAL_DATE)
3746 << k_TYPE_MASK_BITS;
3747 *reinterpret_cast<bdlt::Date*>(&result.d_as.d_int) = value;
3748#else // end - 32 bit / begin - 64 bit
3749 result.d_as.d_type = e_INTERNAL_DATE;
3750 new (result.theInlineStorage()) bdlt::Date(value);
3751#endif // end - 64 bit
3752 return result;
3753}
3754
3755inline
3756Datum Datum::createDatetime(const bdlt::Datetime& value,
3757 const AllocatorType& allocator)
3758{
3759 Datum result;
3760#ifdef BSLS_PLATFORM_CPU_32_BIT
3761 // Check if number of days from now fits in two bytes.
3762
3763 int dateOffsetFromEpoch = (value.date() - bdlt::EpochUtil::epoch().date())
3764 - k_DATETIME_OFFSET_FROM_EPOCH;
3765 short shortDateOffsetFromEpoch = static_cast<short>(dateOffsetFromEpoch);
3766
3767 if (static_cast<int>(shortDateOffsetFromEpoch) == dateOffsetFromEpoch &&
3768 value.microsecond() == 0) {
3769 result.d_exp.d_value =
3770 (k_DOUBLE_MASK | e_INTERNAL_DATETIME) << k_TYPE_MASK_BITS
3771 | (0xffff & dateOffsetFromEpoch);
3772 bdlt::DatetimeInterval interval = value.time() - bdlt::Time();
3773 result.d_as.d_int = static_cast<int>(interval.totalMilliseconds());
3774 } else {
3775 void *mem = AllocUtil::newObject<bdlt::Datetime>(allocator, value);
3776 result = createExtendedDataObject(e_EXTENDED_INTERNAL_DATETIME_ALLOC,
3777 mem);
3778 }
3779#else // end - 32 bit / begin - 64 bit
3780 (void)allocator;
3781
3782 result.d_as.d_type = e_INTERNAL_DATETIME;
3783 new (result.theInlineStorage()) bdlt::Datetime(value);
3784#endif // end - 64 bit
3785 return result;
3786}
3787
3788inline
3789Datum Datum::createDatetimeInterval(const bdlt::DatetimeInterval& value,
3790 const AllocatorType& allocator)
3791{
3792 Datum result;
3793#ifdef BSLS_PLATFORM_CPU_32_BIT
3794 const int usValue = value.microseconds();
3795 const bsls::Types::Int64 msValue = value.totalMilliseconds();
3796
3797 if (usValue == 0 && // Low-resolution (old) interval
3798 Datum_Helpers32::storeSmallInt64(msValue,
3799 &result.d_as.d_short,
3800 &result.d_as.d_int)) {
3801 result.d_as.d_exponent = k_DOUBLE_MASK | e_INTERNAL_DATETIME_INTERVAL;
3802 } else {
3803 void *mem = AllocUtil::newObject<bdlt::DatetimeInterval>(allocator,
3804 value);
3805 result = createExtendedDataObject(
3806 e_EXTENDED_INTERNAL_DATETIME_INTERVAL_ALLOC,
3807 mem);
3808 }
3809#else // end - 32 bit / begin - 64 bit
3810 (void)allocator;
3811
3812 result.d_as.d_type = e_INTERNAL_DATETIME_INTERVAL;
3813 result.d_as.d_int32 = value.days();
3814 result.d_as.d_int64 = value.fractionalDayInMicroseconds();
3815#endif // end - 64 bit
3816 return result;
3817}
3818
3819inline
3820Datum Datum::createDouble(double value)
3821{
3822 Datum result;
3823#ifdef BSLS_PLATFORM_CPU_32_BIT
3824 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!(value == value))) {
3826 return createExtendedDataObject(e_EXTENDED_INTERNAL_NAN2, 0); // RETURN
3827 } else {
3828 result.d_double = value;
3829 }
3830#else // end - 32 bit / begin - 64 bit
3831 result.d_as.d_type = e_INTERNAL_DOUBLE;
3832 result.d_as.d_double = value;
3833#endif // end - 64 bit
3834 return result;
3835}
3836
3837inline
3838Datum Datum::createError(int code)
3839{
3840#ifdef BSLS_PLATFORM_CPU_32_BIT
3841 return createExtendedDataObject(e_EXTENDED_INTERNAL_ERROR, code);
3842#else // end - 32 bit / begin - 64 bit
3843 return createDatum(e_INTERNAL_ERROR, code);
3844#endif // end - 64 bit
3845}
3846
3847inline
3848Datum Datum::createInteger(int value)
3849{
3850 Datum result;
3851#ifdef BSLS_PLATFORM_CPU_32_BIT
3852 result.d_exp.d_value = (k_DOUBLE_MASK | e_INTERNAL_INTEGER)
3853 << k_TYPE_MASK_BITS;
3854 result.d_as.d_int = value;
3855#else // end - 32 bit / begin - 64 bit
3856 result.d_as.d_type = e_INTERNAL_INTEGER;
3857 result.d_as.d_int32 = value;
3858#endif // end - 64 bit
3859 return result;
3860}
3861
3862inline
3863Datum Datum::createInteger64(bsls::Types::Int64 value,
3864 const AllocatorType& allocator)
3865{
3866 Datum result;
3867#ifdef BSLS_PLATFORM_CPU_32_BIT
3868 if (Datum_Helpers32::storeSmallInt64(value,
3869 &result.d_as.d_short,
3870 &result.d_as.d_int)) {
3871 result.d_as.d_exponent = k_DOUBLE_MASK | e_INTERNAL_INTEGER64;
3872 } else {
3873 void *mem = AllocUtil::newObject<bsls::Types::Int64>(allocator, value);
3874 result = createExtendedDataObject(e_EXTENDED_INTERNAL_INTEGER64_ALLOC,
3875 mem);
3876 }
3877#else // end - 32 bit / begin - 64 bit
3878 (void)allocator;
3879
3880 result.d_as.d_type = e_INTERNAL_INTEGER64;
3881 result.d_as.d_int64 = value;
3882#endif // end - 64 bit
3883 return result;
3884}
3885
3886inline
3887Datum Datum::createNull()
3888{
3889 Datum result;
3890#ifdef BSLS_PLATFORM_CPU_32_BIT
3891 // Setting exponent using half-word is faster, maybe the compiler folds the
3892 // two statements into one?
3893
3894 result.d_as.d_exponent = k_DOUBLE_MASK | Datum::e_INTERNAL_EXTENDED;
3895 result.d_as.d_ushort = e_EXTENDED_INTERNAL_NIL;
3896#else // end - 32 bit / begin - 64 bit
3897 result.d_as.d_type = e_INTERNAL_NIL;
3898#endif // end - 64 bit
3899 return result;
3900}
3901
3902inline
3903Datum Datum::createStringRef(const char *string,
3904 SizeType length,
3905 const AllocatorType& allocator)
3906{
3907 BSLS_ASSERT(string || 0 == length);
3908
3909#ifdef BSLS_PLATFORM_CPU_32_BIT
3910 // If the length will fit in the 'k_SHORT_OFFSET' area, store everything
3911 // inline; otherwise allocate space.
3912
3913 if (bsl::numeric_limits<unsigned short>::max() >= length) {
3914 Datum result;
3915 result.d_exp.d_value = (k_DOUBLE_MASK | e_INTERNAL_STRING_REFERENCE)
3916 << k_TYPE_MASK_BITS | length;
3917 result.d_as.d_cvp = string;
3918 return result; // RETURN
3919 }
3920
3921 void *mem = AllocUtil::allocateBytes(allocator,
3922 sizeof(length) + sizeof(string));
3923 Datum_Helpers::store<const char *>(mem, 0, string);
3924 Datum_Helpers::store<SizeType> (mem, sizeof(string), length);
3925
3926 return createExtendedDataObject(e_EXTENDED_INTERNAL_SREF_ALLOC, mem);
3927#else // end - 32 bit / begin - 64 bit
3928 (void)allocator;
3929
3930 BSLS_ASSERT(length <= bsl::numeric_limits<unsigned int>::max());
3931
3932 Datum result;
3933 result.d_as.d_type = e_INTERNAL_STRING_REFERENCE;
3934 result.d_as.d_int32 = static_cast<int>(length);
3935 result.d_as.d_ptr = const_cast<char*>(string);
3936 return result;
3937#endif // end - 64 bit
3938}
3939
3940inline
3941Datum Datum::createStringRef(const char *string,
3942 const AllocatorType& allocator)
3943{
3944 BSLS_ASSERT(string);
3945
3946 return createStringRef(string, bsl::strlen(string), allocator);
3947}
3948
3949inline
3950Datum Datum::createStringRef(const bslstl::StringRef& value,
3951 const AllocatorType& allocator)
3952{
3953 return createStringRef(value.data(), value.length(), allocator);
3954}
3955
3956inline
3957Datum Datum::createTime(const bdlt::Time& value)
3958{
3959 Datum result;
3960#ifdef BSLS_PLATFORM_CPU_32_BIT
3961 result.d_exp.d_value = (k_DOUBLE_MASK | e_INTERNAL_TIME)
3962 << k_TYPE_MASK_BITS;
3963 bsls::Types::Int64 rawTime;
3965 *reinterpret_cast<bdlt::Time*>(&rawTime) = value;
3966 const bool rc = Datum_Helpers32::storeInt48(rawTime,
3967 &result.d_as.d_short,
3968 &result.d_as.d_int);
3969 BSLS_ASSERT(rc); (void)rc;
3970#else // end - 32 bit / begin - 64 bit
3971 result.d_as.d_type = e_INTERNAL_TIME;
3972 new (result.theInlineStorage()) bdlt::Time(value);
3973#endif // end - 64 bit
3974 return result;
3975}
3976
3977inline
3978Datum Datum::createUdt(void *data, int type)
3979{
3980 BSLS_ASSERT(0 <= type && type <= 65535);
3981
3982 Datum result;
3983#ifdef BSLS_PLATFORM_CPU_32_BIT
3984 result.d_as.d_exponent = k_DOUBLE_MASK | e_INTERNAL_USERDEFINED;
3985 result.d_as.d_ushort = static_cast<unsigned short>(type);
3986 result.d_as.d_cvp = data;
3987#else // end - 32 bit / begin - 64 bit
3988 result.d_as.d_type = e_INTERNAL_USERDEFINED;
3989 result.d_as.d_int32 = type;
3990 result.d_as.d_ptr = data;
3991#endif // end - 64 bit
3992 return result;
3993}
3994
3995inline
3996Datum Datum::adoptArray(const DatumMutableArrayRef& array)
3997{
3998 // Note that 'array.length' contains the *address* of the 'length'
3999 // information for the array, which precedes the 'array' data in a
4000 // contiguously allocated block (see 'DatumMutableArrayRef').
4001
4002 Datum result;
4003#ifdef BSLS_PLATFORM_CPU_32_BIT
4004 result.d_as.d_exponent = k_DOUBLE_MASK | e_INTERNAL_ARRAY;
4005 result.d_as.d_cvp = array.length();
4006#else // end - 32 bit / begin - 64 bit
4007 result.d_as.d_type = e_INTERNAL_ARRAY;
4008 result.d_as.d_ptr = array.length();
4009#endif // end - 64 bit
4010 return result;
4011}
4012
4013inline
4014Datum Datum::adoptMap(const DatumMutableMapRef& map)
4015{
4016 // Note that 'map.size' contains the *address* of the 'size' information
4017 // for the map, which precedes the 'map' data in a contiguously allocated
4018 // block (see 'DatumMutableMapRef').
4019
4020#ifdef BSLS_PLATFORM_CPU_32_BIT
4021 return createExtendedDataObject(e_EXTENDED_INTERNAL_MAP, map.size());
4022#else // end - 32 bit / begin - 64 bit
4023 return createDatum(e_INTERNAL_MAP, map.size());
4024#endif // end - 64 bit
4025}
4026
4027inline
4028Datum Datum::adoptIntMap(const DatumMutableIntMapRef& map)
4029{
4030 // Note that 'map.size' contains the *address* of the 'size' information
4031 // for the map, which precedes the 'map' data in a contiguously allocated
4032 // block (see 'DatumMutableIntMapRef').
4033
4034#ifdef BSLS_PLATFORM_CPU_32_BIT
4035 return createExtendedDataObject(e_EXTENDED_INTERNAL_INT_MAP, map.size());
4036#else // end - 32 bit / begin - 64 bit
4037 return createDatum(e_INTERNAL_INT_MAP, map.size());
4038#endif // end - 64 bit
4039}
4040
4041inline
4042Datum Datum::adoptMap(const DatumMutableMapOwningKeysRef& map)
4043{
4044 // Note that 'map.size' contains the *address* of the 'size' information
4045 // for the map, which precedes the 'map' data in a contiguously allocated
4046 // block (see 'DatumMutableMapOwningKeysRefRef').
4047
4048#ifdef BSLS_PLATFORM_CPU_32_BIT
4049 return createExtendedDataObject(e_EXTENDED_INTERNAL_OWNED_MAP,
4050 map.size());
4051#else // end - 32 bit / begin - 64 bit
4052 return createDatum(e_INTERNAL_OWNED_MAP, map.size());
4053#endif // end - 64 bit
4054}
4055
4056inline
4057Datum Datum::copyString(const bslstl::StringRef& value,
4058 const AllocatorType& allocator)
4059{
4060 return copyString(value.data(), value.length(), allocator);
4061}
4062
4063inline
4064void Datum::disposeUninitializedArray(const DatumMutableArrayRef& array,
4065 const AllocatorType& allocator)
4066{
4067 void *ptr = array.allocatedPtr();
4068
4069 if (ptr) {
4070 AllocUtil::deallocateBytes(allocator, ptr, array.capacity());
4071 }
4072}
4073
4074inline
4075void Datum::disposeUninitializedIntMap(const DatumMutableIntMapRef& map,
4076 const AllocatorType& allocator)
4077{
4078 void *ptr = map.allocatedPtr();
4079
4080 if (ptr) {
4081 Datum_IntMapHeader *hdr = static_cast<Datum_IntMapHeader*>(ptr);
4082
4083 AllocUtil::deallocateBytes(
4084 allocator,
4085 ptr,
4086 (hdr->d_capacity + 1) * sizeof(DatumIntMapEntry));
4087 }
4088}
4089
4090inline
4091void Datum::disposeUninitializedMap(const DatumMutableMapRef& map,
4092 const AllocatorType& allocator)
4093{
4094 void *ptr = map.allocatedPtr();
4095
4096 if (ptr) {
4097 Datum_MapHeader *hdr = static_cast<Datum_MapHeader*>(ptr);
4098
4099 AllocUtil::deallocateBytes(allocator, ptr, hdr->d_allocatedSize);
4100 }
4101}
4102
4103inline
4104void Datum::disposeUninitializedMap(
4106 const AllocatorType& allocator)
4107{
4108 void *ptr = map.allocatedPtr();
4109
4110 if (ptr) {
4111 Datum_MapHeader *hdr = static_cast<Datum_MapHeader*>(ptr);
4112
4113 AllocUtil::deallocateBytes(allocator, ptr, hdr->d_allocatedSize);
4114 }
4115}
4116
4117// ACCESSORS
4118inline
4119bool Datum::isArray() const
4120{
4121 return (e_ARRAY == type());
4122}
4123
4124inline
4125bool Datum::isBinary() const
4126{
4127 return (e_BINARY == type());
4128}
4129
4130inline
4131bool Datum::isBoolean() const
4132{
4133 return (e_BOOLEAN == type());
4134}
4135
4136inline
4137bool Datum::isDate() const
4138{
4139 return (e_DATE == type());
4140}
4141
4142inline
4143bool Datum::isDatetime() const
4144{
4145 return (e_DATETIME == type());
4146}
4147
4148inline
4149bool Datum::isDatetimeInterval() const
4150{
4151 return (e_DATETIME_INTERVAL == type());
4152}
4153
4154inline
4155bool Datum::isDecimal64() const
4156{
4157 return (e_DECIMAL64 == type());
4158}
4159
4160inline
4161bool Datum::isDouble() const
4162{
4163 return (e_DOUBLE == type());
4164}
4165
4166inline
4167bool Datum::isError() const
4168{
4169 return (e_ERROR == type());
4170}
4171
4172inline
4173bool Datum::isExternalReference() const
4174{
4175#ifdef BSLS_PLATFORM_CPU_32_BIT
4176 switch (internalType()) {
4177 case e_INTERNAL_STRING_REFERENCE:
4178 case e_INTERNAL_ARRAY_REFERENCE:
4179 case e_INTERNAL_USERDEFINED:
4180 return true; // RETURN
4181 case e_INTERNAL_EXTENDED:
4182 switch (extendedInternalType()) {
4183 case e_EXTENDED_INTERNAL_SREF_ALLOC:
4184 case e_EXTENDED_INTERNAL_AREF_ALLOC:
4185 return true; // RETURN
4186 default:
4187 break;
4188 }
4189 default:
4190 break;
4191 }
4192#else // end - 32 bit / begin - 64 bit
4193 switch (internalType()) {
4194 case e_INTERNAL_STRING_REFERENCE:
4195 case e_INTERNAL_ARRAY_REFERENCE:
4196 case e_INTERNAL_USERDEFINED:
4197 return true; // RETURN
4198 case e_INTERNAL_UNINITIALIZED:
4199 BSLS_ASSERT(0 == "Uninitialized Datum");
4200 break;
4201 default:
4202 break;
4203 }
4204#endif // end - 64 bit
4205 return false;
4206}
4207
4208inline
4209bool Datum::isInteger() const
4210{
4211 return (e_INTEGER == type());
4212}
4213
4214inline
4215bool Datum::isInteger64() const
4216{
4217 return (e_INTEGER64 == type());
4218}
4219
4220inline
4221bool Datum::isIntMap() const
4222{
4223 return (e_INT_MAP == type());
4224}
4225
4226inline
4227bool Datum::isMap() const
4228{
4229 return (e_MAP == type());
4230}
4231
4232inline
4233bool Datum::isNull() const
4234{
4235 return (e_NIL == type());
4236}
4237
4238inline
4239bool Datum::isString() const
4240{
4241 return (e_STRING == type());
4242}
4243
4244inline
4245bool Datum::isTime() const
4246{
4247 return (e_TIME == type());
4248}
4249
4250inline
4251bool Datum::isUdt() const
4252{
4253 return (e_USERDEFINED == type());
4254}
4255
4256inline
4257DatumArrayRef Datum::theArray() const
4258{
4259 BSLS_ASSERT_SAFE(isArray());
4260
4261 const InternalDataType type = internalType();
4262 if (e_INTERNAL_ARRAY == type) {
4263 return theInternalArray(); // RETURN
4264 }
4265
4266#ifdef BSLS_PLATFORM_CPU_32_BIT
4267 if (e_INTERNAL_EXTENDED == type) {
4268 return theLongArrayReference(); // RETURN
4269 }
4270#endif // end - 32 bit
4271
4272 return theArrayReference();
4273}
4274
4275inline
4276DatumBinaryRef Datum::theBinary() const
4277{
4278 BSLS_ASSERT_SAFE(isBinary());
4279
4280#ifdef BSLS_PLATFORM_CPU_32_BIT
4281 return DatumBinaryRef(allocatedPtr<const double>() + 1,
4282 *allocatedPtr<const SizeType>()); // RETURN
4283#else // end - 32 bit / begin - 64 bit
4284 const InternalDataType type = internalType();
4285 switch(type) {
4286 case e_INTERNAL_BINARY:
4287 return DatumBinaryRef(d_data.buffer(), // RETURN
4288 d_data.buffer()[k_SMALLBINARY_SIZE_OFFSET]);
4289 case e_INTERNAL_BINARY_ALLOC:
4290 return DatumBinaryRef(d_as.d_ptr, d_as.d_int32); // RETURN
4291 default:
4292 BSLS_ASSERT(0 == "Bad binary internal-type (memory corruption?)");
4293 }
4294 return DatumBinaryRef();
4295#endif // end - 64 bit
4296}
4297
4298inline
4299bool Datum::theBoolean() const
4300{
4301 BSLS_ASSERT_SAFE(isBoolean());
4302
4303#ifdef BSLS_PLATFORM_CPU_32_BIT
4304 return static_cast<bool>(d_as.d_int);
4305#else // end - 32 bit / begin - 64 bit
4306 return d_as.d_int32;
4307#endif // end - 64 bit
4308}
4309
4310inline
4311bdlt::Date Datum::theDate() const
4312{
4313 BSLS_ASSERT_SAFE(isDate());
4314
4315#ifdef BSLS_PLATFORM_CPU_32_BIT
4316 return *reinterpret_cast<const bdlt::Date *>(&d_as.d_int);
4317#else // end - 32 bit / begin - 64 bit
4318 return *reinterpret_cast<const bdlt::Date *>(theInlineStorage());
4319#endif // end - 64 bit
4320}
4321
4322inline
4323bdlt::Datetime Datum::theDatetime() const
4324{
4325 BSLS_ASSERT_SAFE(isDatetime());
4326
4327#ifdef BSLS_PLATFORM_CPU_32_BIT
4328 const InternalDataType type = internalType();
4329
4330 if (type == e_INTERNAL_DATETIME) {
4331 bdlt::Time time;
4332 time.addMilliseconds(d_as.d_int);
4333 return bdlt::Datetime(
4334 bdlt::EpochUtil::epoch().date() + k_DATETIME_OFFSET_FROM_EPOCH +
4335 d_as.d_short,
4336 time); // RETURN
4337 }
4338
4339 BSLS_ASSERT_SAFE(type == e_INTERNAL_EXTENDED);
4341 extendedInternalType() == e_EXTENDED_INTERNAL_DATETIME_ALLOC);
4342 return *allocatedPtr<const bdlt::Datetime>();
4343#else // end - 32 bit / begin - 64 bit
4344 return *reinterpret_cast<const bdlt::Datetime *>(theInlineStorage());
4345#endif // end - 64 bit
4346}
4347
4348inline // BDLD_DATUM_FORCE_INLINE
4349bdlt::DatetimeInterval Datum::theDatetimeInterval() const
4350{
4351 BSLS_ASSERT_SAFE(isDatetimeInterval());
4352
4353#ifdef BSLS_PLATFORM_CPU_32_BIT
4354 const InternalDataType type = internalType();
4355
4356 if (type == e_INTERNAL_DATETIME_INTERVAL) {
4358 result.setTotalMilliseconds(
4359 Datum_Helpers32::loadSmallInt64(d_as.d_short, d_as.d_int));
4360 return result; // RETURN
4361 }
4362
4363 BSLS_ASSERT_SAFE(type == e_INTERNAL_EXTENDED);
4365 extendedInternalType() == e_EXTENDED_INTERNAL_DATETIME_INTERVAL_ALLOC);
4366 return *allocatedPtr<const bdlt::DatetimeInterval>();
4367#else // end - 32 bit / begin - 64 bit
4368 return bdlt::DatetimeInterval(d_as.d_int32, // days
4369 0, // hours
4370 0, // minutes
4371 0, // seconds
4372 0, // milliseconds
4373 d_as.d_int64); // microseconds
4374#endif // end - 64 bit
4375}
4376
4377inline
4378double Datum::theDouble() const
4379{
4380 BSLS_ASSERT_SAFE(isDouble());
4381
4382#ifdef BSLS_PLATFORM_CPU_32_BIT
4384 0x7f != d_data[k_EXPONENT_MSB] || // exponent is not the
4385 0xf0 != (d_data[k_EXPONENT_LSB] & 0xf0) || // special '7ff' value
4386 e_INTERNAL_INF == (d_data[k_EXPONENT_LSB] & 0x0f))) { // or infinity
4387 return d_double; // RETURN
4388 }
4390 return bsl::numeric_limits<double>::quiet_NaN(); // RETURN
4391#else // end - 32 bit / begin - 64 bit
4392 return d_as.d_double;
4393#endif // end - 64 bit
4394}
4395
4396inline
4397DatumError Datum::theError() const
4398{
4399 BSLS_ASSERT(isError());
4400
4401#ifdef BSLS_PLATFORM_CPU_32_BIT
4402 // If the extended type is 'e_EXTENDED_INTERNAL_ERROR', we are storing
4403 // just a code, at the data offset. Otherwise, we're storing an allocated
4404 // object.
4405
4406 if (e_EXTENDED_INTERNAL_ERROR == extendedInternalType()) {
4407 return DatumError(d_as.d_int); // RETURN
4408 }
4409
4410 const char *data = allocatedPtr<const char>();
4411#else // end - 32 bit / begin - 64 bit
4412 if (e_INTERNAL_ERROR == internalType()) {
4413 return DatumError(static_cast<int>(d_as.d_int64)); // RETURN
4414 }
4415
4416 const char *data = allocatedPtr<const char>();
4417#endif // end - 64 bit
4418
4419 return DatumError(
4420 Datum_Helpers::load<int>(data, 0),
4421 bslstl::StringRef(data + 2 * sizeof(int),
4422 Datum_Helpers::load<int>(data, sizeof(int))));
4423}
4424
4425inline
4426int Datum::theInteger() const
4427{
4428 BSLS_ASSERT_SAFE(isInteger());
4429
4430#ifdef BSLS_PLATFORM_CPU_32_BIT
4431 return d_as.d_int;
4432#else // end - 32 bit / begin - 64 bit
4433 return d_as.d_int32;
4434#endif // end - 64 bit
4435}
4436
4437inline
4438bsls::Types::Int64 Datum::theInteger64() const
4439{
4440 BSLS_ASSERT_SAFE(isInteger64());
4441
4442#ifdef BSLS_PLATFORM_CPU_32_BIT
4443 const InternalDataType type = internalType();
4444
4445 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(e_INTERNAL_INTEGER64 == type)) {
4446 return theSmallInteger64(); // RETURN
4447 }
4448 BSLS_ASSERT_SAFE(e_INTERNAL_EXTENDED == type);
4450 e_EXTENDED_INTERNAL_INTEGER64_ALLOC == extendedInternalType());
4451 return theLargeInteger64(); // RETURN
4452#else // end - 32 bit / begin - 64 bit
4453 return d_as.d_int64;
4454#endif // end - 64 bit
4455}
4456
4457inline
4458DatumMapRef Datum::theMap() const
4459{
4460 BSLS_ASSERT_SAFE(isMap());
4461
4462 const DatumMapEntry *map = allocatedPtr<const DatumMapEntry>();
4463
4464 if (map) {
4465 // Map header takes first DatumMapEntry
4466 const Datum_MapHeader *header =
4467 reinterpret_cast<const Datum_MapHeader *>(map);
4468
4469 return DatumMapRef(map + 1,
4470 header->d_size,
4471 header->d_sorted,
4472 header->d_ownsKeys); // RETURN
4473 }
4474 return DatumMapRef(0, 0, false, false);
4475}
4476
4477inline
4478DatumIntMapRef Datum::theIntMap() const
4479{
4480 BSLS_ASSERT_SAFE(isIntMap());
4481
4482 const DatumIntMapEntry *map = allocatedPtr<const DatumIntMapEntry>();
4483
4484 if (map) {
4485 // Map header takes first DatumMapEntry
4486 const Datum_IntMapHeader *header =
4487 reinterpret_cast<const Datum_IntMapHeader *>(map);
4488
4489 return DatumIntMapRef(map + 1,
4490 header->d_size,
4491 header->d_sorted); // RETURN
4492 }
4493 return DatumIntMapRef(0, 0, false);
4494}
4495
4496inline
4497bslstl::StringRef Datum::theString() const
4498{
4499 BSLS_ASSERT_SAFE(isString());
4500
4501 const InternalDataType type = internalType();
4502 switch(type) {
4503 case e_INTERNAL_SHORTSTRING:
4504 return theShortString(); // RETURN
4505 case e_INTERNAL_STRING:
4506 return theInternalString(); // RETURN
4507 case e_INTERNAL_STRING_REFERENCE:
4508 return theStringReference(); // RETURN
4509#ifdef BSLS_PLATFORM_CPU_32_BIT
4510 case e_INTERNAL_LONGEST_SHORTSTRING:
4511 return theLongestShortString(); // RETURN
4512 default:
4513 return theLongStringReference(); // RETURN
4514#else // end - 32 bit / begin - 64 bit
4515 default: {
4516 BSLS_ASSERT(0 == "Bad string internal-type (memory corruption?)");
4517 return bslstl::StringRef(); // RETURN
4518 }
4519#endif // end - 64 bit
4520 }
4521}
4522
4523inline
4524bdlt::Time Datum::theTime() const
4525{
4526 BSLS_ASSERT_SAFE(isTime());
4527
4528#ifdef BSLS_PLATFORM_CPU_32_BIT
4530 bsls::Types::Int64 rawTime;
4531 rawTime = Datum_Helpers32::loadInt48(d_as.d_short, d_as.d_int);
4532 return *reinterpret_cast<bdlt::Time*>(&rawTime);
4533#else // end - 32 bit / begin - 64 bit
4534 return *reinterpret_cast<const bdlt::Time *>(theInlineStorage());
4535#endif // end - 64 bit
4536}
4537
4538inline
4539DatumUdt Datum::theUdt() const
4540{
4541 BSLS_ASSERT_SAFE(isUdt());
4542#ifdef BSLS_PLATFORM_CPU_32_BIT
4543 return DatumUdt(allocatedPtr<void>(), d_as.d_ushort);
4544#else // end - 32 bit / begin - 64 bit
4545 return DatumUdt(allocatedPtr<void>(), d_as.d_int32);
4546#endif // end - 64 bit
4547}
4548
4549inline
4550Datum::DataType Datum::type() const
4551{
4552#ifdef BSLS_PLATFORM_CPU_32_BIT
4553 static const DataType convert[] = {
4554 e_DOUBLE // e_INTERNAL_INF = 0x00
4555 , e_STRING // e_INTERNAL_LONGEST_SHORTSTR = 0x01
4556 , e_BOOLEAN // e_INTERNAL_BOOLEAN = 0x02
4557 , e_STRING // e_INTERNAL_SHORTSTRING = 0x03
4558 , e_STRING // e_INTERNAL_STRING = 0x04
4559 , e_DATE // e_INTERNAL_DATE = 0x05
4560 , e_TIME // e_INTERNAL_TIME = 0x06
4561 , e_DATETIME // e_INTERNAL_DATETIME = 0x07
4562 , e_DATETIME_INTERVAL // e_INTERNAL_DATETIME_INTERVAL = 0x08
4563 , e_INTEGER // e_INTERNAL_INTEGER = 0x09
4564 , e_INTEGER64 // e_INTERNAL_INTEGER64 = 0x0a
4565 , e_USERDEFINED // e_INTERNAL_USERDEFINED = 0x0b
4566 , e_ARRAY // e_INTERNAL_ARRAY = 0x0c
4567 , e_STRING // e_INTERNAL_STRING_REFERENCE = 0x0d
4568 , e_ARRAY // e_INTERNAL_ARRAY_REFERENCE = 0x0e
4569 , e_NIL // e_INTERNAL_EXTENDED = 0x0f
4570 , e_DOUBLE // e_INTERNAL_DOUBLE = 0x10
4571 };
4572
4573 const InternalDataType type = internalType();
4574 if (e_INTERNAL_EXTENDED == type) {
4575 return typeFromExtendedInternalType(); // RETURN
4576 }
4577 return convert[type];
4578#else // end - 32 bit / begin - 64 bit
4579 static const DataType convert[] = {
4580 e_ERROR // e_INTERNAL_UNINITIALIZED; invalid
4581 , e_DOUBLE // e_INTERNAL_INF = 1
4582 , e_NIL // e_INTERNAL_NIL = 2
4583 , e_BOOLEAN // e_INTERNAL_BOOLEAN = 3
4584 , e_STRING // e_INTERNAL_SHORTSTRING = 4
4585 , e_STRING // e_INTERNAL_STRING = 5
4586 , e_DATE // e_INTERNAL_DATE = 6
4587 , e_TIME // e_INTERNAL_TIME = 7
4588 , e_DATETIME // e_INTERNAL_DATETIME = 8
4589 , e_DATETIME_INTERVAL // e_INTERNAL_DATETIME_INTERVAL = 9
4590 , e_INTEGER // e_INTERNAL_INTEGER = 10
4591 , e_INTEGER64 // e_INTERNAL_INTEGER64 = 11
4592 , e_USERDEFINED // e_INTERNAL_USERDEFINED = 12
4593 , e_ARRAY // e_INTERNAL_ARRAY = 13
4594 , e_STRING // e_INTERNAL_STRING_REFERENCE = 14
4595 , e_ARRAY // e_INTERNAL_ARRAY_REFERENCE = 15
4596 , e_DOUBLE // e_INTERNAL_DOUBLE = 16
4597 , e_MAP // e_INTERNAL_MAP = 17
4598 , e_MAP // e_INTERNAL_OWNED_MAP = 18
4599 , e_ERROR // e_INTERNAL_ERROR = 19
4600 , e_ERROR // e_INTERNAL_ERROR_ALLOC = 20
4601 , e_BINARY // e_INTERNAL_BINARY = 21
4602 , e_BINARY // e_INTERNAL_BINARY_ALLOC = 22
4603 , e_DECIMAL64 // e_INTERNAL_DECIMAL64 = 23
4604 , e_INT_MAP // e_INTERNAL_INT_MAP = 24
4605 };
4606
4607 const InternalDataType type = internalType();
4608
4609 BSLS_ASSERT_SAFE(e_INTERNAL_UNINITIALIZED != type);
4610
4611 return convert[type];
4612#endif // end - 64 bit
4613}
4614
4615template <class t_VISITOR>
4616void Datum::apply(t_VISITOR& visitor) const
4617{
4618#ifdef BSLS_PLATFORM_CPU_32_BIT
4619 switch (internalType()) {
4620 case e_INTERNAL_INF:
4621 visitor(bsl::numeric_limits<double>::infinity());
4622 break;
4623 case e_INTERNAL_BOOLEAN:
4624 visitor(theBoolean());
4625 break;
4626 case e_INTERNAL_SHORTSTRING:
4627 visitor(theShortString());
4628 break;
4629 case e_INTERNAL_LONGEST_SHORTSTRING:
4630 visitor(theLongestShortString());
4631 break;
4632 case e_INTERNAL_STRING:
4633 visitor(theInternalString());
4634 break;
4635 case e_INTERNAL_DATE:
4636 visitor(theDate());
4637 break;
4638 case e_INTERNAL_TIME:
4639 visitor(theTime());
4640 break;
4641 case e_INTERNAL_DATETIME:
4642 visitor(theDatetime());
4643 break;
4644 case e_INTERNAL_DATETIME_INTERVAL:
4645 visitor(theDatetimeInterval());
4646 break;
4647 case e_INTERNAL_INTEGER:
4648 visitor(theInteger());
4649 break;
4650 case e_INTERNAL_INTEGER64:
4651 visitor(theInteger64());
4652 break;
4653 case e_INTERNAL_USERDEFINED:
4654 visitor(theUdt());
4655 break;
4656 case e_INTERNAL_ARRAY:
4657 visitor(theInternalArray());
4658 break;
4659 case e_INTERNAL_STRING_REFERENCE:
4660 visitor(theStringReference());
4661 break;
4662 case e_INTERNAL_ARRAY_REFERENCE:
4663 visitor(theArrayReference());
4664 break;
4665 case e_INTERNAL_EXTENDED:
4666 switch (extendedInternalType()) {
4667 case e_EXTENDED_INTERNAL_INT_MAP:
4668 visitor(theIntMap());
4669 break;
4670 case e_EXTENDED_INTERNAL_MAP:
4672 case e_EXTENDED_INTERNAL_OWNED_MAP:
4673 visitor(theMap());
4674 break;
4675 case e_EXTENDED_INTERNAL_NAN2:
4676 visitor(theDouble());
4677 break;
4678 case e_EXTENDED_INTERNAL_ERROR:
4680 case e_EXTENDED_INTERNAL_ERROR_ALLOC:
4681 visitor(theError());
4682 break;
4683 case e_EXTENDED_INTERNAL_SREF_ALLOC:
4684 visitor(theLongStringReference());
4685 break;
4686 case e_EXTENDED_INTERNAL_AREF_ALLOC:
4687 visitor(theLongArrayReference());
4688 break;
4689 case e_EXTENDED_INTERNAL_DATETIME_ALLOC:
4690 visitor(theDatetime());
4691 break;
4692 case e_EXTENDED_INTERNAL_DATETIME_INTERVAL_ALLOC:
4693 visitor(theDatetimeInterval());
4694 break;
4695 case e_EXTENDED_INTERNAL_INTEGER64_ALLOC:
4696 visitor(theInteger64());
4697 break;
4698 case e_EXTENDED_INTERNAL_BINARY_ALLOC:
4699 visitor(theBinary());
4700 break;
4701 case e_EXTENDED_INTERNAL_DECIMAL64:
4702 case e_EXTENDED_INTERNAL_DECIMAL64_SPECIAL:
4703 case e_EXTENDED_INTERNAL_DECIMAL64_ALLOC: {
4704 // Code below is identical to 'visitor(theDecimal64())' but
4705 // postpones the name lookup for 'theDecimal64()' to the second
4706 // (instantiation) phase, so that we can use only a forward
4707 // declaration of 'bdldfp::Decimal64' in this header. Without this
4708 // workaround clang won't compile calls to 'apply' or 'hashAppend'
4709 // even if '<bdldfp_decimal.h>' is included after this header. See
4710 // the test driver for more information.
4711 typedef bdldfp::Decimal64 (Datum::*Dec64MemFunPtr)() const;
4712 const typename Datum_MakeDependent<
4713 Dec64MemFunPtr,
4714 t_VISITOR>::type dec64MemFunPtr = &Datum::theDecimal64;
4715 visitor((this->*dec64MemFunPtr)());
4716 } break;
4717 case e_EXTENDED_INTERNAL_NIL:
4718 visitor(bslmf::Nil());
4719 break;
4720 default:
4722 0 == "Unknown extended-type (memory corruption?)");
4723 }
4724 break;
4725 case e_INTERNAL_DOUBLE:
4726 visitor(d_double);
4727 break;
4728 default:
4729 BSLS_ASSERT_SAFE(0 == "Unknown type (memory corruption?)");
4730 }
4731#else // end - 32 bit / begin - 64 bit
4732 switch (internalType()) {
4733 case e_INTERNAL_INF:
4734 visitor(bsl::numeric_limits<double>::infinity());
4735 break;
4736 case e_INTERNAL_NIL:
4737 visitor(bslmf::Nil());
4738 break;
4739 case e_INTERNAL_BOOLEAN:
4740 visitor(theBoolean());
4741 break;
4742 case e_INTERNAL_SHORTSTRING:
4743 visitor(theShortString());
4744 break;
4745 case e_INTERNAL_STRING:
4746 visitor(theInternalString());
4747 break;
4748 case e_INTERNAL_DATE:
4749 visitor(theDate());
4750 break;
4751 case e_INTERNAL_TIME:
4752 visitor(theTime());
4753 break;
4754 case e_INTERNAL_DATETIME:
4755 visitor(theDatetime());
4756 break;
4757 case e_INTERNAL_DATETIME_INTERVAL:
4758 visitor(theDatetimeInterval());
4759 break;
4760 case e_INTERNAL_INTEGER:
4761 visitor(theInteger());
4762 break;
4763 case e_INTERNAL_INTEGER64:
4764 visitor(theInteger64());
4765 break;
4766 case e_INTERNAL_USERDEFINED:
4767 visitor(theUdt());
4768 break;
4769 case e_INTERNAL_ARRAY:
4770 visitor(theInternalArray());
4771 break;
4772 case e_INTERNAL_STRING_REFERENCE:
4773 visitor(theStringReference());
4774 break;
4775 case e_INTERNAL_ARRAY_REFERENCE:
4776 visitor(theArrayReference());
4777 break;
4778 case e_INTERNAL_MAP:
4780 case e_INTERNAL_OWNED_MAP:
4781 visitor(theMap());
4782 break;
4783 case e_INTERNAL_ERROR:
4785 case e_INTERNAL_ERROR_ALLOC:
4786 visitor(theError());
4787 break;
4788 case e_INTERNAL_DOUBLE:
4789 visitor(d_as.d_double);
4790 break;
4791 case e_INTERNAL_BINARY:
4793 case e_INTERNAL_BINARY_ALLOC:
4794 visitor(theBinary());
4795 break;
4796 case e_INTERNAL_DECIMAL64: {
4797 // Code below is identical to 'visitor(theDecimal64())' but postpones
4798 // the name lookup for 'theDecimal64()' to the second (instantiation)
4799 // phase, so that we can use only forward declaration of
4800 // 'bdldfp::Decimal64' in this header. Without this workaround clang
4801 // won't compile calls to 'apply' or 'hashAppend' even if
4802 // '<bdldfp_decimal.h>' is included after this header. See the test
4803 // driver for more information.
4804 typedef bdldfp::Decimal64 (Datum::*Dec64MemFunPtr)() const;
4805 const typename Datum_MakeDependent<
4806 Dec64MemFunPtr,
4807 t_VISITOR>::type dec64MemFunPtr = &Datum::theDecimal64;
4808 visitor((this->*dec64MemFunPtr)());
4809 } break;
4810 case e_INTERNAL_INT_MAP:
4811 visitor(theIntMap());
4812 break;
4813 case e_INTERNAL_UNINITIALIZED:
4814 BSLS_ASSERT(0 == "Uninitialized Datum");
4815 break;
4816 default:
4817 BSLS_ASSERT_SAFE(0 == "Unknown type (memory corruption?)");
4818 }
4819#endif // end - 64 bit
4820}
4821
4822#ifndef BDE_OMIT_INTERNAL_DEPRECATED
4823inline
4824void Datum::createUninitializedMapOwningKeys(
4826 SizeType capacity,
4827 SizeType keysCapacity,
4828 const AllocatorType& allocator)
4829{
4830 createUninitializedMap(result, capacity, keysCapacity, allocator);
4831}
4832
4833inline
4834Datum Datum::adoptMapOwningKeys(const DatumMutableMapOwningKeysRef& mapping)
4835{
4836 return adoptMap(mapping);
4837}
4838
4839inline
4840void Datum::disposeUninitializedMapOwningKeys(
4841 const DatumMutableMapOwningKeysRef& mapping,
4842 const AllocatorType& allocator)
4843{
4844 return disposeUninitializedMap(mapping, allocator);
4845}
4846#endif // end - do not omit internal deprecated
4847
4848 // -------------------
4849 // class DatumArrayRef
4850 // -------------------
4851
4852// CREATORS
4853inline
4854DatumArrayRef::DatumArrayRef()
4855: d_data_p(0)
4856, d_length(0)
4857{
4858}
4859
4860inline
4862 SizeType length)
4863: d_data_p(data)
4864, d_length(length)
4865{
4866 BSLS_ASSERT(data || 0 == length);
4867}
4868
4869// ACCESSORS
4870inline
4872{
4873 BSLS_ASSERT_SAFE(index < d_length);
4874 return d_data_p[index];
4875}
4876
4877inline
4880{
4881 return d_data_p;
4882}
4883
4884inline
4887{
4888 return d_length;
4889}
4890
4891inline
4894{
4895 return d_length;
4896}
4897
4898inline
4901{
4902 return d_data_p;
4903}
4904
4905inline
4908{
4909 return d_data_p;
4910}
4911
4912inline
4918
4919inline
4925
4926inline
4929{
4930 return d_data_p + d_length;
4931}
4932
4933inline
4936{
4937 return end();
4938}
4939
4940inline
4946
4947inline
4953
4954
4955inline
4958{
4959 BSLS_ASSERT(!empty());
4960 return *begin();
4961}
4962
4963inline
4966{
4967 BSLS_ASSERT(!empty());
4968 return *(end() - 1);
4969}
4970
4971inline
4973{
4974 return 0 == d_length;
4975}
4976
4977 // ----------------------
4978 // class DatumIntMapEntry
4979 // ----------------------
4980// CREATORS
4981inline
4985
4986inline
4988 const Datum& value)
4989: d_key(key)
4990, d_value(value)
4991{
4992}
4993
4994// MANIPULATORS
4995inline
4997{
4998 d_key = key;
4999}
5000
5001inline
5003{
5004 d_value = value;
5005}
5006
5007// ACCESSORS
5008inline
5010{
5011 return d_key;
5012}
5013
5014inline
5016{
5017 return d_value;
5018}
5019
5020 // --------------------
5021 // class DatumIntMapRef
5022 // --------------------
5023// CREATORS
5024inline
5026 SizeType size,
5027 bool sorted)
5028: d_data_p(data)
5029, d_size(size)
5030, d_sorted(sorted)
5031{
5032 BSLS_ASSERT((size && data) || !size);
5033}
5034
5035// ACCESSORS
5036inline
5038{
5039 BSLS_ASSERT_SAFE(index < d_size);
5040 return d_data_p[index];
5041}
5042
5043inline
5046{
5047 return d_data_p;
5048}
5049
5050inline
5056
5057inline
5060{
5061 return d_data_p;
5062}
5063
5064inline
5067{
5068 return d_data_p;
5069}
5070
5071inline
5077
5078inline
5084
5085inline
5088{
5089 return d_data_p + d_size;
5090}
5091
5092inline
5095{
5096 return end();
5097}
5098
5099inline
5105
5106inline
5112
5113
5114inline
5117{
5118 BSLS_ASSERT(!empty());
5119 return *begin();
5120}
5121
5122inline
5125{
5126 BSLS_ASSERT(!empty());
5127 return *(end() - 1);
5128}
5129
5130inline
5132{
5133 return 0 == d_size;
5134}
5135
5136inline
5138{
5139 return d_sorted;
5140}
5141
5142 // -------------------
5143 // class DatumMapEntry
5144 // -------------------
5145// CREATORS
5146inline
5150
5151inline
5153 const Datum& value)
5154: d_key_p(key)
5155, d_value(value)
5156{
5157}
5158
5159// MANIPULATORS
5160inline
5162{
5163 d_key_p = key;
5164}
5165
5166inline
5168{
5169 d_value = value;
5170}
5171
5172// ACCESSORS
5173inline
5175{
5176 return d_key_p;
5177}
5178
5179inline
5181{
5182 return d_value;
5183}
5184
5185 // -----------------
5186 // class DatumMapRef
5187 // -----------------
5188// CREATORS
5189inline
5191 SizeType size,
5192 bool sorted,
5193 bool ownsKeys)
5194: d_data_p(data)
5195, d_size(size)
5196, d_sorted(sorted)
5197, d_ownsKeys(ownsKeys)
5198{
5199 BSLS_ASSERT((size && data) || !size);
5200 if (0 == size) {
5201 d_ownsKeys = false;
5202 }
5203}
5204
5205// ACCESSORS
5206inline
5208{
5209 BSLS_ASSERT_SAFE(index < d_size);
5210 return d_data_p[index];
5211}
5212
5213inline
5216{
5217 return d_data_p;
5218}
5219
5220inline
5223{
5224 return d_size;
5225}
5226
5227inline
5230{
5231 return d_data_p;
5232}
5233
5234inline
5237{
5238 return d_data_p;
5239}
5240
5241inline
5247
5248inline
5254
5255inline
5258{
5259 return d_data_p + d_size;
5260}
5261
5262inline
5265{
5266 return end();
5267}
5268
5269inline
5275
5276inline
5282
5283
5284inline
5287{
5288 BSLS_ASSERT(!empty());
5289 return *begin();
5290}
5291
5292inline
5295{
5296 BSLS_ASSERT(!empty());
5297 return *(end() - 1);
5298}
5299
5300inline
5302{
5303 return 0 == d_size;
5304}
5305
5306inline
5308{
5309 return d_sorted;
5310}
5311
5312inline
5314{
5315 return d_ownsKeys;
5316}
5317
5318 // --------------------------
5319 // class DatumMutableArrayRef
5320 // --------------------------
5321
5322// CREATORS
5323inline
5325: d_data_p(0)
5326, d_length_p(0)
5327{
5328}
5329
5330inline
5332 SizeType *length,
5333 SizeType capacity)
5334: d_data_p(data)
5335, d_length_p(length)
5336, d_capacity(capacity)
5337{
5338}
5339
5340// ACCESSORS
5341inline
5343{
5344 return d_length_p;
5345}
5346
5347inline
5349{
5350 return d_data_p;
5351}
5352
5353inline
5355{
5356 return d_length_p;
5357}
5358
5359inline
5361{
5362 return d_capacity;
5363}
5364
5365 // ---------------------------
5366 // class DatumMutableIntMapRef
5367 // ---------------------------
5368
5369// CREATORS
5370inline
5372: d_data_p(0)
5373, d_size_p(0)
5374, d_sorted_p(0)
5375{
5376}
5377
5378inline
5380 SizeType *size,
5381 bool *sorted)
5382: d_data_p(data)
5383, d_size_p(size)
5384, d_sorted_p(sorted)
5385{
5386}
5387
5388// ACCESSORS
5389inline
5391{
5392 return d_size_p;
5393}
5394
5395inline
5397{
5398 return d_data_p;
5399}
5400
5401inline
5403{
5404 return d_size_p;
5405}
5406
5407inline
5409{
5410 return d_sorted_p;
5411}
5412
5413 // ------------------------
5414 // class DatumMutableMapRef
5415 // ------------------------
5416
5417// CREATORS
5418inline
5420: d_data_p(0)
5421, d_size_p(0)
5422, d_sorted_p(0)
5423{
5424}
5425
5426inline
5428 SizeType *size,
5429 bool *sorted)
5430: d_data_p(data)
5431, d_size_p(size)
5432, d_sorted_p(sorted)
5433{
5434}
5435
5436// ACCESSORS
5437inline
5439{
5440 return d_size_p;
5441}
5442
5443inline
5445{
5446 return d_data_p;
5447}
5448
5449inline
5451{
5452 return d_size_p;
5453}
5454
5455inline
5457{
5458 return d_sorted_p;
5459}
5460
5461 // ----------------------------------
5462 // class DatumMutableMapOwningKeysRef
5463 // ----------------------------------
5464
5465// CREATORS
5466inline
5468: d_data_p(0)
5469, d_size_p(0)
5470, d_keys_p(0)
5471, d_sorted_p(0)
5472{
5473}
5474
5475inline
5477 DatumMapEntry *data,
5478 SizeType *size,
5479 SizeType allocatedSize,
5480 char *keys,
5481 bool *sorted)
5482: d_data_p(data)
5483, d_size_p(size)
5484, d_allocatedSize(allocatedSize)
5485, d_keys_p(keys)
5486, d_sorted_p(sorted)
5487{
5488}
5489
5490// ACCESSORS
5491inline
5493{
5494 return d_size_p;
5495}
5496
5497inline
5500{
5501 return d_allocatedSize;
5502}
5503
5504inline
5506{
5507 return d_data_p;
5508}
5509
5510inline
5512{
5513 return d_keys_p;
5514}
5515
5516inline
5519{
5520 return d_size_p;
5521}
5522
5523inline
5525{
5526 return d_sorted_p;
5527}
5528
5529} // close package namespace
5530
5531// FREE OPERATORS
5532inline
5533bool bdld::operator!=(const Datum& lhs, const Datum& rhs)
5534{
5535 return !(lhs == rhs);
5536}
5537
5538inline
5539bool bdld::operator!=(const DatumArrayRef& lhs, const DatumArrayRef& rhs)
5540{
5541 return !(lhs == rhs);
5542}
5543
5544inline
5545bool bdld::operator==(const DatumIntMapEntry& lhs, const DatumIntMapEntry& rhs)
5546{
5547 return (lhs.key() == rhs.key()) && (lhs.value() == rhs.value());
5548}
5549
5550inline
5551bool bdld::operator!=(const DatumIntMapEntry& lhs, const DatumIntMapEntry& rhs)
5552{
5553 return !(lhs == rhs);
5554}
5555
5556inline
5557bool bdld::operator!=(const DatumIntMapRef& lhs, const DatumIntMapRef& rhs)
5558{
5559 return !(lhs == rhs);
5560}
5561
5562inline
5563bool bdld::operator==(const DatumMapEntry& lhs, const DatumMapEntry& rhs)
5564{
5565 return (lhs.key() == rhs.key()) && (lhs.value() == rhs.value());
5566}
5567
5568inline
5569bool bdld::operator!=(const DatumMapEntry& lhs, const DatumMapEntry& rhs)
5570{
5571 return !(lhs == rhs);
5572}
5573
5574inline
5575bool bdld::operator!=(const DatumMapRef& lhs, const DatumMapRef& rhs)
5576{
5577 return !(lhs == rhs);
5578}
5579
5580inline
5581bsl::ostream& bdld::operator<<(bsl::ostream& stream, const Datum& rhs)
5582{
5583 return rhs.print(stream, 0, -1);
5584}
5585
5586template <class t_HASH_ALGORITHM>
5587void bdld::hashAppend(t_HASH_ALGORITHM& hashAlg, const bdld::Datum& input)
5588{
5589 using bslh::hashAppend;
5590 hashAppend(hashAlg, input.type());
5591
5592 switch (input.type()) {
5593 case bdld::Datum::e_NIL: {
5594 // Do nothing. This is sufficient because 'type' has already been
5595 // hashed (differentiating the nil value).
5596 } break;
5598 hashAppend(hashAlg, input.theInteger());
5599 } break;
5600 case bdld::Datum::e_DOUBLE: {
5601 hashAppend(hashAlg, input.theDouble());
5602 } break;
5603 case bdld::Datum::e_STRING: {
5604 hashAppend(hashAlg, input.theString());
5605 } break;
5607 hashAppend(hashAlg, input.theBoolean());
5608 } break;
5609 case bdld::Datum::e_ERROR: {
5610 hashAppend(hashAlg, input.theError().code());
5611 hashAppend(hashAlg, input.theError().message());
5612 } break;
5613 case bdld::Datum::e_DATE: {
5614 hashAppend(hashAlg, input.theDate());
5615 } break;
5616 case bdld::Datum::e_TIME: {
5617 hashAppend(hashAlg, input.theTime());
5618 } break;
5620 hashAppend(hashAlg, input.theDatetime());
5621 } break;
5623 hashAppend(hashAlg, input.theDatetimeInterval());
5624 } break;
5626 hashAppend(hashAlg, input.theInteger64());
5627 } break;
5629 hashAppend(hashAlg, input.theUdt().type());
5630 hashAppend(hashAlg, input.theUdt().data());
5631 } break;
5632 case bdld::Datum::e_ARRAY: {
5633 hashAppend(hashAlg, input.theArray().length());
5634 for (bsl::size_t i = 0; i < input.theArray().length(); ++i) {
5635 bdld::hashAppend(hashAlg, input.theArray()[i]);
5636 }
5637 } break;
5638 case bdld::Datum::e_MAP: {
5639 hashAppend(hashAlg, input.theMap().size());
5640 for (bsl::size_t i = 0; i < input.theMap().size(); ++i) {
5641 hashAppend(hashAlg, input.theMap()[i].key());
5642 bdld::hashAppend(hashAlg, input.theMap()[i].value());
5643 }
5644 } break;
5645 case bdld::Datum::e_BINARY: {
5646 hashAppend(hashAlg, input.theBinary().size());
5647 if (input.theBinary().size() > 0) {
5648 hashAlg(input.theBinary().data(), input.theBinary().size());
5649 }
5650 } break;
5652 // Code below is identical to
5653 // 'hashAppend(hashAlg, input.theDecimal64())', but postpones the
5654 // name lookup for 'theDecimal64()' to the second (instantiation)
5655 // phase so that we can use only forward declaration of
5656 // 'bdldfp::Decimal64' in this header. Without this workaround clang
5657 // won't compile calls to 'apply' or 'hashAppend' even if
5658 // '<bdldfp_decimal.h>' is included after this header. See the test
5659 // driver for more information.
5660 typedef bdldfp::Decimal64 (Datum::*Dec64MemFunPtr)() const;
5661 const typename Datum_MakeDependent<Dec64MemFunPtr,
5662 t_HASH_ALGORITHM>::type
5663 dec64MemFunPtr = &Datum::theDecimal64;
5664 hashAppend(hashAlg, (input.*dec64MemFunPtr)());
5665 } break;
5667 hashAppend(hashAlg, input.theIntMap().size());
5668 for (bsl::size_t i = 0; i < input.theIntMap().size(); ++i) {
5669 hashAppend(hashAlg, input.theIntMap()[i].key());
5670 bdld::hashAppend(hashAlg, input.theIntMap()[i].value());
5671 }
5672 } break;
5673 default: {
5674 BSLS_ASSERT(0 == "Unknown type (memory corruption?)");
5675 }
5676 }
5677}
5678
5679inline
5680bsl::ostream& bdld::operator<<(bsl::ostream& stream, const DatumArrayRef& rhs)
5681{
5682 return rhs.print(stream, 0 , -1);
5683}
5684
5685inline
5686bsl::ostream& bdld::operator<<(bsl::ostream& stream, const DatumMapEntry& rhs)
5687{
5688 return rhs.print(stream, 0 , -1);
5689}
5690
5691inline
5692bsl::ostream& bdld::operator<<(bsl::ostream& stream,
5693 const DatumIntMapEntry& rhs)
5694{
5695 return rhs.print(stream, 0 , -1);
5696}
5697
5698inline
5699bsl::ostream& bdld::operator<<(bsl::ostream& stream, const DatumIntMapRef& rhs)
5700{
5701 return rhs.print(stream, 0 , -1);
5702}
5703
5704inline
5705bsl::ostream& bdld::operator<<(bsl::ostream& stream, const DatumMapRef& rhs)
5706{
5707 return rhs.print(stream, 0 , -1);
5708}
5709
5710
5711
5712#endif
5713
5714// ----------------------------------------------------------------------------
5715// Copyright 2020 Bloomberg Finance L.P.
5716//
5717// Licensed under the Apache License, Version 2.0 (the "License");
5718// you may not use this file except in compliance with the License.
5719// You may obtain a copy of the License at
5720//
5721// http://www.apache.org/licenses/LICENSE-2.0
5722//
5723// Unless required by applicable law or agreed to in writing, software
5724// distributed under the License is distributed on an "AS IS" BASIS,
5725// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
5726// See the License for the specific language governing permissions and
5727// limitations under the License.
5728// ----------------------------- END-OF-FILE ----------------------------------
5729
5730/** @} */
5731/** @} */
5732/** @} */
Definition bdld_datum.h:2461
size_type length() const
Return a const pointer to the length of the array.
Definition bdld_datum.h:4886
~DatumArrayRef()=default
const_iterator begin() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:4900
bsl::ostream & print(bsl::ostream &stream, int level=0, int spacesPerLevel=4) const
BSLMF_NESTED_TRAIT_DECLARATION(DatumArrayRef, bdlb::HasPrintMethod)
bsl::reverse_iterator< const_iterator > const_reverse_iterator
Definition bdld_datum.h:2481
size_type size() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:4893
DatumArrayRef()
Create a DatumArrayRef object representing an empty array.
Definition bdld_datum.h:4854
bsl::size_t size_type
Definition bdld_datum.h:2468
const_iterator end() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:4928
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:4914
bsl::ptrdiff_t difference_type
Definition bdld_datum.h:2469
const_reverse_iterator crbegin() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:4921
element_type & reference
Definition bdld_datum.h:2474
pointer data() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:4879
bsl::reverse_iterator< iterator > reverse_iterator
Definition bdld_datum.h:2480
const_reference operator[](size_type position) const
Definition bdld_datum.h:4871
Datum::SizeType SizeType
Definition bdld_datum.h:2485
const bdld::Datum element_type
Definition bdld_datum.h:2465
const_reverse_iterator rend() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:4942
element_type * pointer
Definition bdld_datum.h:2471
bool empty() const BSLS_KEYWORD_NOEXCEPT
Return size() == 0.
Definition bdld_datum.h:4972
pointer iterator
Definition bdld_datum.h:2477
const_iterator cbegin() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:4907
const_reference back() const
Definition bdld_datum.h:4965
BSLMF_NESTED_TRAIT_DECLARATION(DatumArrayRef, bsl::is_trivially_copyable)
const_iterator cend() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:4935
const_reverse_iterator crend() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:4949
const element_type & const_reference
Definition bdld_datum.h:2475
bdld::Datum value_type
Definition bdld_datum.h:2466
const_reference front() const
Definition bdld_datum.h:4957
const element_type * const_pointer
Definition bdld_datum.h:2472
const_pointer const_iterator
Definition bdld_datum.h:2478
Definition bdld_datumbinaryref.h:157
const void * data() const
Return the pointer to the non-modifiable binary data.
Definition bdld_datumbinaryref.h:290
SizeType size() const
Return the size of the binary data.
Definition bdld_datumbinaryref.h:296
Definition bdld_datumerror.h:160
bslstl::StringRef message() const
Definition bdld_datumerror.h:321
int code() const
Return the error code.
Definition bdld_datumerror.h:315
Definition bdld_datum.h:2628
const Datum & value() const
Return the value for this entry.
Definition bdld_datum.h:5015
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:5002
DatumIntMapEntry()
Create a DatumIntMapEntry object.
Definition bdld_datum.h:4982
void setKey(int key)
Set the key for this entry to the specified key.
Definition bdld_datum.h:4996
~DatumIntMapEntry()=default
Destroy this object.
int key() const
Return the key for this entry.
Definition bdld_datum.h:5009
Definition bdld_datum.h:2723
const_iterator begin() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5059
const_reverse_iterator crbegin() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5080
const element_type * const_pointer
Definition bdld_datum.h:2734
~DatumIntMapRef()=default
Destroy this object.
Datum::SizeType SizeType
Definition bdld_datum.h:2749
element_type * pointer
Definition bdld_datum.h:2733
const_iterator cbegin() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5066
element_type & reference
Definition bdld_datum.h:2736
const_pointer const_iterator
Definition bdld_datum.h:2740
bsl::reverse_iterator< iterator > reverse_iterator
Definition bdld_datum.h:2742
pointer data() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5045
bsl::ptrdiff_t difference_type
Definition bdld_datum.h:2731
const element_type & const_reference
Definition bdld_datum.h:2737
const_reference back() const
Definition bdld_datum.h:5124
const_iterator cend() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5094
bdld::DatumIntMapEntry value_type
Definition bdld_datum.h:2728
bool empty() const BSLS_KEYWORD_NOEXCEPT
Return size() == 0.
Definition bdld_datum.h:5131
const_reverse_iterator crend() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5108
const_iterator end() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5087
const_reverse_iterator rbegin() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5073
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:5137
const_reference operator[](size_type position) const
Definition bdld_datum.h:5037
size_type size() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5051
bsl::size_t size_type
Definition bdld_datum.h:2730
DatumIntMapRef(const DatumIntMapEntry *data, SizeType size, bool sorted)
Definition bdld_datum.h:5025
const bdld::DatumIntMapEntry element_type
Definition bdld_datum.h:2727
bsl::reverse_iterator< const_iterator > const_reverse_iterator
Definition bdld_datum.h:2743
pointer iterator
Definition bdld_datum.h:2739
BSLMF_NESTED_TRAIT_DECLARATION(DatumIntMapRef, bdlb::HasPrintMethod)
const_reference front() const
Definition bdld_datum.h:5116
const_reverse_iterator rend() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5101
Definition bdld_datum.h:2892
DatumMapEntry()
Create a DatumMapEntry object.
Definition bdld_datum.h:5147
BSLMF_NESTED_TRAIT_DECLARATION(DatumMapEntry, bsl::is_trivially_copyable)
const Datum & value() const
Return the value for this entry.
Definition bdld_datum.h:5180
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:5161
const bslstl::StringRef & key() const
Return the key for this entry.
Definition bdld_datum.h:5174
void setValue(const Datum &value)
Set the value for this entry to the specified value.
Definition bdld_datum.h:5167
~DatumMapEntry()=default
Destroy this object.
Definition bdld_datum.h:2983
bsl::size_t size_type
Definition bdld_datum.h:2990
const_pointer const_iterator
Definition bdld_datum.h:3000
bsl::reverse_iterator< const_iterator > const_reverse_iterator
Definition bdld_datum.h:3003
element_type * pointer
Definition bdld_datum.h:2993
bool empty() const BSLS_KEYWORD_NOEXCEPT
Return size() == 0.
Definition bdld_datum.h:5301
const_iterator cbegin() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5236
size_type size() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5221
DatumMapRef(const DatumMapEntry *data, SizeType size, bool sorted, bool ownsKeys)
Definition bdld_datum.h:5190
const_reverse_iterator crbegin() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5250
const element_type & const_reference
Definition bdld_datum.h:2997
pointer data() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5215
BSLMF_NESTED_TRAIT_DECLARATION(DatumMapRef, bdlb::HasPrintMethod)
const_reverse_iterator crend() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5278
const_reference front() const
Definition bdld_datum.h:5286
bdld::DatumMapEntry value_type
Definition bdld_datum.h:2988
bool ownsKeys() const
Definition bdld_datum.h:5313
bsl::ptrdiff_t difference_type
Definition bdld_datum.h:2991
bsl::reverse_iterator< iterator > reverse_iterator
Definition bdld_datum.h:3002
const_reverse_iterator rend() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5271
pointer iterator
Definition bdld_datum.h:2999
const bdld::DatumMapEntry element_type
Definition bdld_datum.h:2987
element_type & reference
Definition bdld_datum.h:2996
Datum::SizeType SizeType
Definition bdld_datum.h:3009
const_iterator end() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5257
const_reverse_iterator rbegin() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5243
bool isSorted() const
Return true if underlying map is sorted and false otherwise.
Definition bdld_datum.h:5307
const_iterator cend() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5264
const_iterator begin() const BSLS_KEYWORD_NOEXCEPT
Definition bdld_datum.h:5229
const element_type * const_pointer
Definition bdld_datum.h:2994
~DatumMapRef()=default
Destroy this object.
BSLMF_NESTED_TRAIT_DECLARATION(DatumMapRef, bsl::is_trivially_copyable)
const_reference back() const
Definition bdld_datum.h:5294
const_reference operator[](size_type position) const
Definition bdld_datum.h:5207
Definition bdld_datum.h:2137
DatumMutableArrayRef & operator=(const DatumMutableArrayRef &rhs)=default
SizeType capacity() const
Return the allocated capacity of the array.
Definition bdld_datum.h:5360
Datum::SizeType SizeType
Definition bdld_datum.h:2144
void * allocatedPtr() const
Return pointer to the memory allocated for the array.
Definition bdld_datum.h:5342
DatumMutableArrayRef()
Create a DatumMutableArrayRef object that refers to no array.
Definition bdld_datum.h:5324
SizeType * length() const
Return pointer to the length of the array.
Definition bdld_datum.h:5354
Datum * data() const
Return pointer to the first element of the held array.
Definition bdld_datum.h:5348
DatumMutableArrayRef(const DatumMutableArrayRef &original)=default
Definition bdld_datum.h:2302
void * allocatedPtr() const
Return pointer to the memory allocated for the map.
Definition bdld_datum.h:5390
bool * sorted() const
Definition bdld_datum.h:5408
Datum::SizeType SizeType
Definition bdld_datum.h:2310
DatumMutableIntMapRef(const DatumMutableIntMapRef &original)=default
SizeType * size() const
Definition bdld_datum.h:5402
DatumMutableIntMapRef()
Create a DatumMutableIntMapRef object.
Definition bdld_datum.h:5371
DatumMutableIntMapRef & operator=(const DatumMutableIntMapRef &rhs)=default
DatumIntMapEntry * data() const
Return pointer to the first element in the (held) map.
Definition bdld_datum.h:5396
Definition bdld_datum.h:2376
DatumMutableMapOwningKeysRef()
Create a DatumMutableMapOwningKeysRef object.
Definition bdld_datum.h:5467
Datum::SizeType SizeType
Definition bdld_datum.h:2384
SizeType * size() const
Definition bdld_datum.h:5518
~DatumMutableMapOwningKeysRef()=default
Destroy this object.
DatumMapEntry * data() const
Return pointer to the first element in the held map.
Definition bdld_datum.h:5505
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:5492
char * keys() const
Return pointer to the start of the buffer where keys are stored.
Definition bdld_datum.h:5511
bool * sorted() const
Definition bdld_datum.h:5524
SizeType allocatedSize() const
Return the number of bytes allocated for the map.
Definition bdld_datum.h:5499
Definition bdld_datum.h:2232
DatumMapEntry * data() const
Return pointer to the first element in the (held) map.
Definition bdld_datum.h:5444
Datum::SizeType SizeType
Definition bdld_datum.h:2240
SizeType * size() const
Definition bdld_datum.h:5450
DatumMutableMapRef & operator=(const DatumMutableMapRef &rhs)=default
DatumMutableMapRef()
Create a DatumMutableMapRef object.
Definition bdld_datum.h:5419
DatumMutableMapRef(const DatumMutableMapRef &original)=default
void * allocatedPtr() const
Return pointer to the memory allocated for the map.
Definition bdld_datum.h:5438
bool * sorted() const
Definition bdld_datum.h:5456
Definition bdld_datumudt.h:144
void * data() const
Return the pointer to the user-defined object.
Definition bdld_datumudt.h:272
int type() const
Return the type of the user-defined object.
Definition bdld_datumudt.h:278
Definition bdld_datum.h:787
DatumArrayRef theArray() const
Definition bdld_datum.h:4257
bsls::AlignedBuffer< 16 > d_data
Definition bdld_datum.h:1349
bool isArray() const
Definition bdld_datum.h:4119
friend bool operator==(const Datum &lhs, const Datum &rhs)
static Datum adoptMapOwningKeys(const DatumMutableMapOwningKeysRef &mapping)
[DEPRECATED] Use adoptMap instead.
Definition bdld_datum.h:4834
static Datum createTime(const bdlt::Time &value)
Return, by value, a datum having the specified Time value.
Definition bdld_datum.h:3957
static void createUninitializedMap(DatumMutableMapOwningKeysRef *result, SizeType capacity, SizeType keysCapacity, const AllocatorType &allocator)
bdlt::Datetime theDatetime() const
Definition bdld_datum.h:4323
static Datum adoptIntMap(const DatumMutableIntMapRef &intMap)
Definition bdld_datum.h:4028
static Datum createStringRef(const char *string, SizeType length, const AllocatorType &allocator)
Definition bdld_datum.h:3903
@ k_NUM_TYPES
Definition bdld_datum.h:843
@ DLCT_NUM_TYPES
Definition bdld_datum.h:845
bool isError() const
Definition bdld_datum.h:4167
static Datum createNull()
Return, by value, a datum having no value.
Definition bdld_datum.h:3887
DatumMapRef theMap() const
Definition bdld_datum.h:4458
bsls::Types::size_type SizeType
Definition bdld_datum.h:1462
static void createUninitializedMap(DatumMutableMapRef *result, SizeType capacity, const AllocatorType &allocator)
bool isString() const
Definition bdld_datum.h:4239
static Datum createError(int code)
Definition bdld_datum.h:3838
bool isBoolean() const
Definition bdld_datum.h:4131
DatumBinaryRef theBinary() const
Definition bdld_datum.h:4276
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:4550
static Datum createInteger64(bsls::Types::Int64 value, const AllocatorType &allocator)
Definition bdld_datum.h:3863
bdlt::DatetimeInterval theDatetimeInterval() const
Definition bdld_datum.h:4349
bslstl::StringRef theString() const
Definition bdld_datum.h:4497
bsl::allocator AllocatorType
Definition bdld_datum.h:795
Datum()=default
static Datum createUdt(void *data, int type)
Definition bdld_datum.h:3978
TypedAccess d_as
Definition bdld_datum.h:1350
static void createUninitializedArray(DatumMutableArrayRef *result, SizeType capacity, const AllocatorType &allocator)
bool isInteger() const
Definition bdld_datum.h:4209
bool isMap() const
Definition bdld_datum.h:4227
bdlt::Time theTime() const
Definition bdld_datum.h:4524
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:3678
DatumError theError() const
Definition bdld_datum.h:4397
static void destroy(const Datum &value, const AllocatorType &allocator)
bdldfp::Decimal64 theDecimal64() const
bool theBoolean() const
Definition bdld_datum.h:4299
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:3820
static Datum createInteger(int value)
Return, by value, a datum having the specified int value.
Definition bdld_datum.h:3848
static Datum adoptArray(const DatumMutableArrayRef &array)
Definition bdld_datum.h:3996
bool isExternalReference() const
Definition bdld_datum.h:4173
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:3756
bool isDouble() const
Definition bdld_datum.h:4161
BSLMF_NESTED_TRAIT_DECLARATION(Datum, bsl::is_trivially_default_constructible)
bdlt::Date theDate() const
Definition bdld_datum.h:4311
static void disposeUninitializedIntMap(const DatumMutableIntMapRef &intMap, const AllocatorType &allocator)
Definition bdld_datum.h:4075
static Datum copyBinary(const void *value, SizeType size, const AllocatorType &allocator)
static void disposeUninitializedMapOwningKeys(const DatumMutableMapOwningKeysRef &mapping, const AllocatorType &allocator)
[DEPRECATED] Use disposeUninitializedMap instead.
Definition bdld_datum.h:4840
DatumIntMapRef theIntMap() const
Definition bdld_datum.h:4478
static void createUninitializedIntMap(DatumMutableIntMapRef *result, SizeType capacity, const AllocatorType &allocator)
double theDouble() const
Definition bdld_datum.h:4378
static void createUninitializedMapOwningKeys(DatumMutableMapOwningKeysRef *result, SizeType capacity, SizeType keysCapacity, const AllocatorType &allocator)
[DEPRECATED] Use createUninitializedMap instead.
Definition bdld_datum.h:4824
bsls::Types::Int64 theInteger64() const
Definition bdld_datum.h:4438
static Datum createError(int code, const bslstl::StringRef &message, const AllocatorType &allocator)
bool isNull() const
Definition bdld_datum.h:4233
static Datum createDatetimeInterval(const bdlt::DatetimeInterval &value, const AllocatorType &allocator)
Definition bdld_datum.h:3789
bool isDecimal64() const
Definition bdld_datum.h:4155
bool isInteger64() const
Definition bdld_datum.h:4215
static void disposeUninitializedMap(const DatumMutableMapRef &map, const AllocatorType &allocator)
Definition bdld_datum.h:4091
bool isBinary() const
Definition bdld_datum.h:4125
friend bsl::ostream & operator<<(bsl::ostream &stream, const Datum &rhs)
void apply(t_VISITOR &visitor) const
Definition bdld_datum.h:4616
static Datum createDate(const bdlt::Date &value)
Return, by value, a datum having the specified Date value.
Definition bdld_datum.h:3738
DataType
Definition bdld_datum.h:799
@ DLCT_BOOLEAN
Definition bdld_datum.h:825
@ e_MAP
Definition bdld_datum.h:813
@ e_BINARY
Definition bdld_datum.h:814
@ DLCT_ERROR_VALUE
Definition bdld_datum.h:826
@ DLCT_DATETIME_INTERVAL
Definition bdld_datum.h:830
@ DLCT_DECIMAL64
Definition bdld_datum.h:836
@ DLCT_NIL
Definition bdld_datum.h:821
@ DLCT_DATETIME
Definition bdld_datum.h:829
@ DLCT_TIME
Definition bdld_datum.h:828
@ e_DATETIME_INTERVAL
Definition bdld_datum.h:809
@ e_ARRAY
Definition bdld_datum.h:812
@ e_TIME
Definition bdld_datum.h:807
@ DLCT_ARRAY
Definition bdld_datum.h:833
@ DLCT_INTEGER64
Definition bdld_datum.h:831
@ e_INTEGER
Definition bdld_datum.h:801
@ e_USERDEFINED
Definition bdld_datum.h:811
@ e_DATE
Definition bdld_datum.h:806
@ DLCT_BINARY
Definition bdld_datum.h:835
@ DLCT_USERDEFINED
Definition bdld_datum.h:832
@ DLCT_INTEGER
Definition bdld_datum.h:822
@ DLCT_REAL
Definition bdld_datum.h:823
@ e_ERROR_VALUE
Definition bdld_datum.h:820
@ DLCT_STRING
Definition bdld_datum.h:824
@ e_INT_MAP
Definition bdld_datum.h:816
@ DLCT_MAP
Definition bdld_datum.h:834
@ DLCT_DATE
Definition bdld_datum.h:827
@ e_DECIMAL64
Definition bdld_datum.h:815
@ e_BOOLEAN
Definition bdld_datum.h:804
@ e_DATETIME
Definition bdld_datum.h:808
@ e_REAL
Definition bdld_datum.h:819
@ e_INTEGER64
Definition bdld_datum.h:810
@ e_STRING
Definition bdld_datum.h:803
@ e_DOUBLE
Definition bdld_datum.h:802
@ e_NIL
Definition bdld_datum.h:800
@ e_ERROR
Definition bdld_datum.h:805
bool isDate() const
Definition bdld_datum.h:4137
bool isUdt() const
Definition bdld_datum.h:4251
DatumUdt theUdt() const
Definition bdld_datum.h:4539
static char * createUninitializedString(Datum *result, SizeType length, const AllocatorType &allocator)
static void disposeUninitializedArray(const DatumMutableArrayRef &array, const AllocatorType &allocator)
Definition bdld_datum.h:4064
bool isDatetimeInterval() const
Definition bdld_datum.h:4149
static Datum adoptMap(const DatumMutableMapRef &map)
Definition bdld_datum.h:4014
static Datum createBoolean(bool value)
Return, by value, a datum having the specified bool value.
Definition bdld_datum.h:3723
Datum(const Datum &original)=default
Create a datum having the value of the specified original.
bool isDatetime() const
Definition bdld_datum.h:4143
bool isIntMap() const
Definition bdld_datum.h:4221
bool isTime() const
Definition bdld_datum.h:4245
int theInteger() const
Definition bdld_datum.h:4426
Definition bdldfp_decimal.h:1834
Definition bdlt_date.h:294
Definition bdlt_datetimeinterval.h:201
int days() const
Definition bdlt_datetimeinterval.h:1105
void setTotalMilliseconds(bsls::Types::Int64 milliseconds)
Definition bdlt_datetimeinterval.h:919
bsls::Types::Int64 fractionalDayInMicroseconds() const
Definition bdlt_datetimeinterval.h:1111
int microseconds() const
Definition bdlt_datetimeinterval.h:1144
bsls::Types::Int64 totalMilliseconds() const
Definition bdlt_datetimeinterval.h:1185
Definition bdlt_datetime.h:331
Date date() const
Return the value of the "date" part of this object.
Definition bdlt_datetime.h:2164
int microsecond() const
Return the value of the microsecond attribute of this object.
Definition bdlt_datetime.h:2231
Time time() const
Return the value of the "time" part of this object.
Definition bdlt_datetime.h:2275
Definition bdlt_time.h:196
int addMilliseconds(int milliseconds)
Definition bslma_bslallocator.h:580
Definition bsls_alignedbuffer.h:261
Definition bslstl_stringref.h:372
const CHAR_TYPE * data() const
Definition bslstl_stringref.h:936
size_type length() const
Definition bslstl_stringref.h:958
bsl::ostream & operator<<(bsl::ostream &stream, const bdlat_AttributeInfo &attributeInfo)
BSLS_PLATFORM_COMPILER_ERROR
Definition bdld_datum.h:719
#define BDLD_DATUM_FORCE_INLINE
Definition bdld_datum.h:725
#define BSLMF_ASSERT(expr)
Definition bslmf_assert.h:229
#define BSLS_ANNOTATION_FALLTHROUGH
Definition bsls_annotation.h:412
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1804
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1762
#define BSLS_ASSERT_OPT(X)
Definition bsls_assert.h:1856
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
#define BSLS_KEYWORD_NOEXCEPT
Definition bsls_keyword.h:632
#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
void hashAppend(HASH_ALGORITHM &hashAlg, const baljsn::EncoderTestAddress &object)
Definition baljsn_encoder_testtypes.h:9236
bsl::size_t size(const TYPE &array)
Return the number of elements in the specified array.
Definition bdld_datum.h:730
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:715
Definition bdlb_printmethods.h:283
BSLS_KEYWORD_CONSTEXPR CONTAINER::value_type * data(CONTAINER &container)
Definition bslstl_iterator.h:1231
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:638
Definition bslstl_algorithm.h:82
StringRefImp< char > StringRef
Definition bslstl_stringref.h:699
Definition bdlb_printmethods.h:306
Definition bdld_datum.h:3161
Definition bdld_datum.h:2199
Datum::SizeType d_size
Definition bdld_datum.h:2202
bool d_sorted
Definition bdld_datum.h:2204
Datum::SizeType d_capacity
Definition bdld_datum.h:2203
Definition bdld_datum.h:747
t_WANT_TO_BE_DEPENDENT type
Definition bdld_datum.h:748
Definition bdld_datum.h:2213
Datum::SizeType d_allocatedSize
Definition bdld_datum.h:2218
Datum::SizeType d_capacity
Definition bdld_datum.h:2217
bool d_ownsKeys
Definition bdld_datum.h:2220
bool d_sorted
Definition bdld_datum.h:2219
Datum::SizeType d_size
Definition bdld_datum.h:2216
static const Datetime & epoch()
Definition bdlt_epochutil.h:375
Definition bslmf_istriviallycopyable.h:329
Definition bslmf_istriviallydefaultconstructible.h:293
Namespace for utility functions on allocators.
Definition bslma_allocatorutil.h:405
Definition bslmf_isbitwisecopyable.h:298
Definition bslmf_isbitwisemoveable.h:718
This struct is empty and represents a nil type.
Definition bslmf_nil.h:131
std::size_t size_type
Definition bsls_types.h:124
long long Int64
Definition bsls_types.h:132