// bdld_datummapowningkeysbuilder.h -*-C++-*- #ifndef INCLUDED_BDLD_DATUMMAPOWNINGKEYSBUILDER #define INCLUDED_BDLD_DATUMMAPOWNINGKEYSBUILDER #include <bsls_ident.h> BSLS_IDENT("$Id$ $CSID$") //@PURPOSE: Provide a utility to build a 'Datum' object holding a map. // //@CLASSES: // bdld::DatumMapOwningKeysBuilder: utility to build a 'Datum' map value // //@SEE_ALSO: bdld_datum, bdld_datummapbuilder // //@DESCRIPTION: This component defines a mechanism, // 'bdld::DatumMapOwningKeysBuilder', used to populate a 'Datum' map value in // an exception-safe manner. In addition to providing exception safety, a // 'DatumMapOwningKeysBuilder' is particularly useful when the size of the map // to be constructed is not known in advance. The user can append elements to // the datum map as needed, and when there are no more elements to append the // user calls 'commit' or 'sortAndCommit' and ownership of the populated // 'Datum' object is transferred to the caller. After calling 'commit' or // 'sortAndCommit', no additional elements can be appended to the 'Datum' map // value. Note that 'sortAndCommit' method will sort the populated map (by // keys) and tag the resulting 'Datum' map value as sorted. Also note that the // user can insert elements in a (ascending) sorted order and tag the map as // sorted. The behaviour is undefined if unsorted map is tagged sorted. // // The only difference between this component and 'bdld_datummapbuilder' is // that this component makes a copy of the map entries keys and the resulting // 'Datum' object owns memory for the map entries keys. // ///Usage ///----- // This section illustrates intended use of this component. // ///Example 1: Basic Syntax ///- - - - - - - - - - - - // Suppose we need a map for some personal data. The values in that map can be // different types and keys must be protected from destruction as this map // object can be passed out of scope. The following code illustrates how to // use 'bdld::DatumMapOwningKeysBuilder' to create such map easily. // // First, we need data to fill our map: //.. // bslma::TestAllocator ta("test", veryVeryVerbose); // // bsl::string firstName = "firstName"; // bsl::string lastName = "lastName"; // bsl::string gender = "gender"; // bsl::string age = "age"; // // DatumMapEntry bartData[] = { // DatumMapEntry(firstName, Datum::createStringRef("Bart", &ta)), // DatumMapEntry(lastName, Datum::createStringRef("Simpson", &ta)), // DatumMapEntry(gender, Datum::createStringRef("male", &ta)), // DatumMapEntry(age, Datum::createInteger(10)) // }; // // const size_t DATA_SIZE = sizeof(bartData) / sizeof(DatumMapEntry); // const size_t KEYS_SIZE = firstName.length() // + lastName.length() // + gender.length() // + age.length(); //.. // Next, we create an object of 'DatumMapOwningKeysBuilder' class with initial // capacity sufficient for storing all our data: //.. // DatumMapOwningKeysBuilder builder(DATA_SIZE, KEYS_SIZE, &ta); //.. // Then, we load our builder with these data: //.. // for (size_t i = 0; i < DATA_SIZE; ++i) { // builder.pushBack(bartData[i].key(), bartData[i].value()); // } //.. // Next, we adopt the map, held by our builder, by newly created 'Datum' // object: //.. // Datum bart = builder.commit(); //.. // Now, we can check that all data have been correctly added to the map at the // required order: //.. // assert(true == bart.isMap()); // assert(DATA_SIZE == bart.theMap().size()); // // assert("firstName" == bart.theMap()[0].key()); // assert(true == bart.theMap()[0].value().isString()); // assert("Bart" == bart.theMap()[0].value().theString()); // // assert("lastName" == bart.theMap()[1].key()); // assert(true == bart.theMap()[1].value().isString()); // assert("Simpson" == bart.theMap()[1].value().theString()); // // assert("gender" == bart.theMap()[2].key()); // assert(true == bart.theMap()[2].value().isString()); // assert("male" == bart.theMap()[2].value().theString()); // // assert("age" == bart.theMap()[3].key()); // assert(true == bart.theMap()[3].value().isInteger()); // assert(10 == bart.theMap()[3].value().theInteger()); //.. // Finally, we destroy the 'Datum' object to release all allocated memory // correctly: //.. // Datum::destroy(bart, &ta); // assert(0 == ta.numBytesInUse()); //.. #include <bdlscm_version.h> #include <bdld_datum.h> #include <bslma_allocator.h> #include <bslma_stdallocator.h> #include <bslma_usesbslmaallocator.h> #include <bslmf_nestedtraitdeclaration.h> #include <bsls_types.h> namespace BloombergLP { namespace bdld { // =============================== // class DatumMapOwningKeysBuilder // =============================== class DatumMapOwningKeysBuilder { // This 'class' provides a mechanism to build a 'Datum' object having a map // (owning keys) value in an exception-safe manner. public: // TYPES typedef Datum::SizeType SizeType; // 'SizeType' is an alias for a signed value, representing the // capacity, *keys-capacity*, size or *keys-size* of a datum-key-owning // map. typedef bsl::allocator<char> allocator_type; private: // DATA DatumMutableMapOwningKeysRef d_mapping; // mutable access to the // datum-key-owning map SizeType d_capacity; // capacity of the // datum-key-owning map SizeType d_keysCapacity; // keys-capacity of the // datum-key-owning map (in // bytes) bool d_sorted; // underlying map is sorted // or not allocator_type d_allocator; // allocator private: // NOT IMPLEMENTED DatumMapOwningKeysBuilder(const DatumMapOwningKeysBuilder&); DatumMapOwningKeysBuilder& operator=(const DatumMapOwningKeysBuilder&); public: // TRAITS BSLMF_NESTED_TRAIT_DECLARATION(DatumMapOwningKeysBuilder, bslma::UsesBslmaAllocator); // 'DatumMapOwningKeysBuilder' is allocator-aware. // CREATORS explicit DatumMapOwningKeysBuilder(const allocator_type& allocator); // Create a 'DatumMapOwningKeysBuilder' object that will administer the // process of building a 'Datum' map (owning keys) using the specified // 'allocator' (e.g., the address of a 'bslma::Allocator' object) to // supply memory. Note that no memory is allocated until 'append' or // 'pushBack' methods are called on this object. DatumMapOwningKeysBuilder(SizeType initialCapacity, SizeType initialKeysCapacity, const allocator_type& allocator); // Create a 'DatumMapBuilder' object managing the ownership of 'Datum' // map (owning keys) having the specified 'initialCapacity' and // 'initialKeysCapacity' (in bytes) using the specified // 'allocator' (e.g., the address of a 'bslma::Allocator' object) to // supply memory. ~DatumMapOwningKeysBuilder(); // Destroy this object. If this object is holding a datum-key-owning // map that has not been adopted, then the datum-key-owning map is // disposed after destroying each of its elements. // MANIPULATORS void append(const DatumMapEntry *entries, SizeType size); // Append the specified array 'entries' having the specified 'size' to // the 'Datum' map (owning keys) being build by this object. The // behavior is undefined unless and '0 != entries && 0 != size' and // each element in 'entries' that needs dynamic memory, is allocated // with the same allocator that was used to construct this object. The // behavior is undefined if 'commit' or 'sortAndCommit' has already // been called on this object. Datum commit(); // Return a 'Datum' map (owning keys) value holding the elements // supplied to 'pushBack' or 'append'. The caller is responsible for // releasing the resources of the returned 'Datum' object. Calling // this method indicates that the caller is finished building the // 'Datum' map (owning keys) and no further values shall be appended. // The behavior is undefined if any method of this object, other than // its destructor, is called after 'commit' invocation. void pushBack(const bslstl::StringRef& key, const Datum& value); // Append the entry with the specified 'key' and the specified 'value' // to the 'Datum' map being build by this object. The behavior is // undefined if 'value' needs dynamic memory and was allocated using a // different allocator than the one used to construct this object. The // behavior is also undefined if 'commit' or 'sortAndCommit' has // already been called on this object. void setSorted(bool value); // Mark the Datum map (owning keys) being built by this object as // sorted if the specified 'value' is 'true' and mark it unsorted // otherwise. This function does not sort the map entries, or mark // them to be sorted later; the function should be used to indicate if // the entries are being appended in sorted order. The behavior is // undefined if 'commit' or 'sortAndCommit' has already been called on // this object. The behavior is also undefined if the map being // constructed is marked sorted, but the entries are not appended in // sorted order. Note also that the map being constructed is marked // unsorted by default. Datum sortAndCommit(); // Return a 'Datum' map (owning keys) value holding the elements // supplied to 'pushBack' or 'append' sorted by their keys. The caller // is responsible for releasing the resources of the returned 'Datum' // object. Calling this method indicates that the caller is finished // building the 'Datum' map (owning keys) and no further values shall // be appended. The behavior is undefined if any method of this // object, other than its destructor, is called after 'sortAndCommit' // invocation. // ACCESSORS SizeType capacity() const; // Return the capacity of the held 'Datum' map (owning keys). The // behavior is undefined if 'commit' or 'sortAndCommit' has already // been called on this object. Note that similar to the capacity of a // 'vector', the returned capacity has no bearing on the value of the // 'Datum' being constructed, but does indicate at which point // additional memory will be required to grow the 'Datum' map being // built. SizeType keysCapacity() const; // Return the keys-capacity of the held 'Datum' map (owning keys). The // behavior is undefined if 'commit' or 'sortAndCommit' has already // been called on this object. Note that similar to the capacity of a // 'vector', the returned capacity has no bearing on the value of the // 'Datum' being constructed, but does indicate at which point // additional memory will be required to grow the 'Datum' map being // built. SizeType size() const; // Return the size of the held 'Datum' map (owning keys). The behavior // is undefined if 'commit' or 'sortAndCommit' has already been called // on this object. // Aspects bslma::Allocator *allocator() const; // !DEPRECATED!: Use 'get_allocator()' instead. // // Return 'get_allocator().mechanism()'. allocator_type get_allocator() const; // Return the allocator used by this object to supply memory. Note // that if no allocator was supplied at construction the default // allocator in effect at construction is used. }; // ============================================================================ // INLINE DEFINITIONS // ============================================================================ // ------------------------------- // class DatumMapOwningKeysBuilder // ------------------------------- // ACCESSORS inline DatumMapOwningKeysBuilder::SizeType DatumMapOwningKeysBuilder::capacity() const { return d_capacity; } inline DatumMapOwningKeysBuilder::SizeType DatumMapOwningKeysBuilder::keysCapacity() const { return d_keysCapacity; } inline DatumMapOwningKeysBuilder::SizeType DatumMapOwningKeysBuilder::size() const { if (d_capacity) { return *d_mapping.size(); // RETURN } return 0; } // Aspects inline bslma::Allocator *DatumMapOwningKeysBuilder::allocator() const { return get_allocator().mechanism(); } inline DatumMapOwningKeysBuilder::allocator_type DatumMapOwningKeysBuilder::get_allocator() const { return d_allocator; } } // close package namespace } // close enterprise namespace #endif // ---------------------------------------------------------------------------- // Copyright 2020 Bloomberg Finance L.P. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ----------------------------- END-OF-FILE ----------------------------------