// baltzo_zoneinfobinaryheader.h -*-C++-*- #ifndef INCLUDED_BALTZO_ZONEINFOBINARYHEADER #define INCLUDED_BALTZO_ZONEINFOBINARYHEADER #include <bsls_ident.h> BSLS_IDENT("$Id: $") //@PURPOSE: Provide an attribute class for Zoneinfo binary-file header data. // //@CLASSES: // baltzo::ZoneinfoBinaryHeader: attribute class for Zoneinfo header data // //@SEE_ALSO: baltzo_zoneinfobinaryreader // //@DESCRIPTION: This component provides a simply constrained attribute class, // 'baltzo::ZoneinfoBinaryHeader', representing the header data of a Zoneinfo // binary data file. // ///Attributes ///---------- //.. // Name Type Default Simple Constraints // ----------------- ---- ------- ------------------ // version char '\0' == '\0' || == '2' || == '3' // numIsGmt int 0 >= 0 // numIsStd int 0 >= 0 // numLeaps int 0 == 0 // numTransitions int 0 >= 0 // numLocalTimeTypes int 1 >= 1 // abbrevDataSize int 1 >= 1 //.. //: o 'version': Zoneinfo file format version, as of 2013, either '\0', '2', // or '3'. //: //: o 'numIsGmt': number of encoded UTC/local indicators in the file, //: indicating whether a transition time was originally specified as UTC in //: the rule file. //: //: o 'numIsStd': number of encoded standard/wall indicators in the file, //: indicating whether a transition time was originally specified as standard //: time in the rule file. //: //: o 'numLeaps': number of leap corrections stored in the file. //: //: o 'numTransitions': number of local-time type transitions stored in the //: file. //: //: o 'numLocalTimeTypes': number of local-time types stored in the file. //: //: o 'abbrevDataSize': length of the sequence of characters containing the //: ('\0'-separated) abbreviation strings in the file. // ///Usage ///----- // This section illustrates intended use of this component. // ///Example 1: Creating a 'baltzo::ZoneinfoBinaryHeader' from User Input /// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // We define the 'getNextZoneinfoBinaryHeader' helper function, reads data from // a stream, validates the data, and constructs a // 'baltzo::ZoneinfoBinaryHeader' object. //.. // int getNextZoneinfoBinaryHeader(baltzo::ZoneinfoBinaryHeader *object, // bsl::istream& stream) // // Set to the specified 'object' the value extracted from the // // specified 'stream'. Return 0 on success, and a non-zero value // // otherwise, with no change to 'object'. The 'stream' contains // // white-space separated decimal representations of the attributes // // of 'baltzo::ZoneinfoBinaryHeader' in the following order: 'version', // // 'numIsGmt', 'numIsStd', 'numLeaps', 'numTransitions', // // 'numLocalTimeTypes', and 'abbrevDataSize'. // { // int version; // not 'char' // int numIsGmt; // int numIsStd; // int numLeaps; // int numTransitions; // int numLocalTimeTypes; // int abbrevDataSize; // // if (!(stream >> version // && stream >> numIsGmt // && stream >> numIsStd // && stream >> numLeaps // && stream >> numTransitions // && stream >> numLocalTimeTypes // && stream >> abbrevDataSize)) { // return 1; // RETURN // } // // if (!(baltzo::ZoneinfoBinaryHeader::isValidVersion(version) // && baltzo::ZoneinfoBinaryHeader::isValidNumIsGmt(numIsGmt) // && baltzo::ZoneinfoBinaryHeader::isValidNumIsStd(numIsStd) // && baltzo::ZoneinfoBinaryHeader::isValidNumLeaps(numLeaps) // && baltzo::ZoneinfoBinaryHeader::isValidNumTransitions( // numTransitions) // && baltzo::ZoneinfoBinaryHeader::isValidNumLocalTimeTypes( // numLocalTimeTypes) // && baltzo::ZoneinfoBinaryHeader::isValidAbbrevDataSize( // abbrevDataSize))) { // return 2; // RETURN // } // // object->setVersion(version); // object->setNumIsGmt(numIsGmt); // object->setNumIsStd(numIsStd); // object->setNumLeaps(numLeaps); // object->setNumTransitions(numTransitions); // object->setNumLocalTimeTypes(numLocalTimeTypes); // object->setAbbrevDataSize(abbrevDataSize); // // return 0; // } //.. // To use our helper function, we supply it with a stream of (decimal, // whitespace-separated values). The resulting object has the expected value. //.. // bsl::stringstream input("50 1 2 0 3 4 5"); // baltzo::ZoneinfoBinaryHeader header; // int rc; // // rc = getNextZoneinfoBinaryHeader(&header, input); // // assert( 0 == rc); // assert('2' == header.version()); // assert( 1 == header.numIsGmt()); // assert( 2 == header.numIsStd()); // assert( 0 == header.numLeaps()); // assert( 3 == header.numTransitions()); // assert( 4 == header.numLocalTimeTypes()); // assert( 5 == header.abbrevDataSize()); //.. // Since all of the data in the stream has now been consumed, another call to // the function returns an error and leaves the object unchanged. //.. // header.setVersion(0); // header.setNumIsGmt(10); // header.setNumIsStd(20); // header.setNumLeaps(0); // header.setNumTransitions(30); // header.setNumLocalTimeTypes(40); // header.setAbbrevDataSize(50); // // rc = getNextZoneinfoBinaryHeader(&header, input); // // assert( 0 != rc); // assert('\0' == header.version()); // assert( 10 == header.numIsGmt()); // assert( 20 == header.numIsStd()); // assert( 0 == header.numLeaps()); // assert( 30 == header.numTransitions()); // assert( 40 == header.numLocalTimeTypes()); // assert( 50 == header.abbrevDataSize()); //.. #include <balscm_version.h> #include <bsls_assert.h> #include <bsls_review.h> #include <bsl_algorithm.h> #include <bsl_iosfwd.h> namespace BloombergLP { namespace baltzo { // ========================== // class ZoneinfoBinaryHeader // ========================== class ZoneinfoBinaryHeader { // This simply constrained (value-semantic) attribute class represents the // header information found at the start of a Zoneinfo (binary) database // file, which describes the contents of the file. // // See the Attributes section under @DESCRIPTION in the component-level // documentation. Note that the class invariants are identically the // constraints on the individual attributes. // // This class: //: o supports a complete set of *value* *semantic* operations //: o except for 'bdex' serialization //: o is *exception-neutral* //: o is *alias-safe* //: o is 'const' *thread-safe* // For terminology see 'bsldoc_glossary'. // DATA char d_version; // file format version of the Zoneinfo, as of // 2013, it can be either '\0', '2', or '3'. int d_numIsGmt; // number of encoded UTC/local indicators in the // file, indicating whether a transition time // was originally specified as UTC in the rule // file. int d_numIsStd; // number of encoded standard/wall indicators in // the file, indicating whether a transition // time was originally specified as standard the // in the rule file. int d_numLeaps; // number of leap corrections stored in the file int d_numTransitions; // number of local-time type transitions stored // in the file int d_numLocalTimeTypes; // number of local-time types stored in the file int d_abbrevDataSize; // length of the sequence of characters // containing the ('\0' separated) abbreviation // strings in the file public: // CLASS METHODS static bool isValidVersion(char value); // Return 'true' if the specified value equals '\0' or '2', and 'false' // otherwise. static bool isValidNumIsGmt(int value); // Return 'true' if the specified 'value' is greater than or equal to // 0, and 'false' otherwise'. static bool isValidNumIsStd(int value); // Return 'true' if the specified 'value' is greater than or equal to // 0, and 'false' otherwise'. static bool isValidNumLeaps(int value); // Return 'true' if the specified value equals 0, and 'false' // otherwise'. static bool isValidNumTransitions(int value); // Return 'true' if the specified 'value' is greater than or equal to // 0, and 'false' otherwise'. static bool isValidNumLocalTimeTypes(int value); // Return 'true' if the specified 'value' is greater than or equal to // 1, and 'false' otherwise'. static bool isValidAbbrevDataSize(int value); // Return 'true' if the specified 'value' is greater than or equal to // 1, and 'false' otherwise'. // CREATORS ZoneinfoBinaryHeader(); // Create a 'ZoneinfoBinaryHeader' object having the (default) // attribute values: //.. // version() == 0 // numIsGmt() == 0 // numIsStd() == 0 // numLeaps() == 0 // numTransitions() == 0 // numLocalTimeTypes() == 1 // abbrevDataSize() == 1 //.. ZoneinfoBinaryHeader(const ZoneinfoBinaryHeader& original); // Create a 'ZoneInfoBinaryHeader' object with the same value as the // specified 'original'. ZoneinfoBinaryHeader(char version, int numIsGmt, int numIsStd, int numLeaps, int numTransitions, int numLocalTimeTypes, int abbrevDataSize); // Create a 'ZoneinfoBinaryHeader' having the specified 'version', // 'numIsGmt', 'numIsStd', 'numLeaps', 'numTransitions', // 'numLocalTimeTypes', and 'abbrevDataSize' values. The behavior is // undefined unless '0 == version || 50 == version || 51 == version', // '0 <= numIsGmt', '0 <= numIsStd', '0 == numLeaps', // '0 <= numTransitions', '1 <= numLocalTimeTypes', and // '1 <= abbrevDataSize'. Note that 50 is the value of ASCII // character '2' and 51 is the value of ASCII character '3'. ~ZoneinfoBinaryHeader(); // Destroy this object. // MANIPULATORS ZoneinfoBinaryHeader& operator=(const ZoneinfoBinaryHeader& rhs); // Assign to this object the value of the specified 'rhs' object, and // return a reference providing modifiable access to this object. void setVersion(char value); // Set the 'version' attribute of this object to the specified 'value'. // The behavior is undefined unless '0 == value || 50 == value || // 51 == value'. Note that 50 is the value of ASCII character '2' and // 51 is the value of ASCII character '3'. void setNumIsGmt(int value); // Set the 'numIsGmt' attribute of this object to the specified // 'value'. The behavior is undefined unless '0 <= value'. void setNumIsStd(int value); // Set the 'numIsStd' attribute of this object to the specified // 'value'. The behavior is undefined unless '0 <= value'. void setNumLeaps(int value); // Set the 'numLeaps' attribute of this object to the specified // 'value'. The behavior is undefined unless '0 == value'. void setNumTransitions(int value); // Set the 'numTransitions' attribute of this object to the specified // 'value'. The behavior is undefined unless '0 <= value'. void setNumLocalTimeTypes(int value); // Set the 'numLocalTimeTypes' attribute of this object to the // specified 'value'. The behavior is undefined unless '1 <= value'. void setAbbrevDataSize(int value); // Set the 'abbrevDataSize' attribute of this object to the specified // 'value'. The behavior is undefined unless '1 <= value'. void swap(ZoneinfoBinaryHeader& other); // Efficiently exchange the value of this object with the value of the // specified 'other' object. This method provides the no-throw // exception-safety guarantee. // ACCESSORS char version() const; // Return the value of the 'version' attribute of this object. int numIsGmt() const; // Return the value of the 'numIsGmt' attribute of this object. int numIsStd() const; // Return the value of the 'numIsStd' attribute of this object. int numLeaps() const; // Return the value of the 'numLeaps' attribute of this object. int numTransitions() const; // Return the value of the 'numTransitions' attribute of this object. int numLocalTimeTypes() const; // Return the value of the 'numLocalTimeTypes' attribute of this // object. int abbrevDataSize() const; // Return the value of the 'abbrevDataSize' attribute of this object. // Aspects bsl::ostream& print(bsl::ostream& stream, int level = 0, int spacesPerLevel = 4) const; // Write the value of this object to the specified output 'stream' in a // human-readable format, and return a reference to 'stream'. // Optionally specify an initial indentation 'level', whose absolute // value is incremented recursively for nested objects. If 'level' is // specified, optionally specify 'spacesPerLevel', whose absolute value // indicates the number of spaces per indentation level for this and // all of its nested objects. If 'level' is negative, suppress // indentation of the first line. If 'spacesPerLevel' is negative, // format the entire output on one line, suppressing all but the // initial indentation (as governed by 'level'). If 'stream' is not // valid on entry, this operation has no effect. Note that the format // is not fully specified, and can change without notice. }; // FREE OPERATORS bool operator==(const ZoneinfoBinaryHeader& lhs, const ZoneinfoBinaryHeader& rhs); // Return 'true' if the specified 'lhs' and 'rhs' objects have the same // value, and 'false' otherwise. Two 'ZoneinfoBinaryHeader' objects have // the same value if the corresponding values of their 'version', // 'numIsGmt', 'numIsStd', 'numLeaps', 'numTransitions', // 'numLocalTimeTypes', and 'abbrevDataSize' attributes are the same. bool operator!=(const ZoneinfoBinaryHeader& lhs, const ZoneinfoBinaryHeader& rhs); // Return 'true' if the specified 'lhs' and 'rhs' objects have the same // value, and 'false' otherwise. Two 'ZoneinfoBinaryHeader' objects do not // have the same value if the corresponding values of their 'version', // 'numIsGmt', 'numIsStd', 'numLeaps', 'numTransitions', // 'numLocalTimeTypes', or 'abbrevDataSize' attributes are not the same. bsl::ostream& operator<<(bsl::ostream& stream, const ZoneinfoBinaryHeader& object); // Write the value of the specified 'object' to the specified output // 'stream' in a single-line format, and return a reference to 'stream'. // If 'stream' is not valid on entry, this operation has no effect. Note // that this human-readable format is not fully specified and can change // without notice. Also note that this method has the same behavior as // 'object.print(stream, 0, -1)'. // FREE FUNCTIONS void swap(baltzo::ZoneinfoBinaryHeader& a, baltzo::ZoneinfoBinaryHeader& b); // Efficiently exchange the values of the specified 'a' and 'b' objects. // This function provides the no-throw exception-safety guarantee. // ============================================================================ // INLINE DEFINITIONS // ============================================================================ // -------------------------- // class ZoneinfoBinaryHeader // -------------------------- // CLASS METHODS inline bool ZoneinfoBinaryHeader::isValidVersion(char value) { return '\0' == value || '2' == value || '3' == value; } inline bool ZoneinfoBinaryHeader::isValidNumIsGmt(int value) { return value >= 0; } inline bool ZoneinfoBinaryHeader::isValidNumIsStd(int value) { return value >= 0; } inline bool ZoneinfoBinaryHeader::isValidNumLeaps(int value) { return value == 0; } inline bool ZoneinfoBinaryHeader::isValidNumTransitions(int value) { return value >= 0; } inline bool ZoneinfoBinaryHeader::isValidNumLocalTimeTypes(int value) { return value >= 1; } inline bool ZoneinfoBinaryHeader::isValidAbbrevDataSize(int value) { return value >= 1; } // CREATORS inline ZoneinfoBinaryHeader::ZoneinfoBinaryHeader() : d_version(0) , d_numIsGmt(0) , d_numIsStd(0) , d_numLeaps(0) , d_numTransitions(0) , d_numLocalTimeTypes(1) , d_abbrevDataSize(1) { } inline ZoneinfoBinaryHeader::ZoneinfoBinaryHeader( const ZoneinfoBinaryHeader& original) : d_version(original.d_version) , d_numIsGmt(original.d_numIsGmt) , d_numIsStd(original.d_numIsStd) , d_numLeaps(original.d_numLeaps) , d_numTransitions(original.d_numTransitions) , d_numLocalTimeTypes(original.d_numLocalTimeTypes) , d_abbrevDataSize(original.d_abbrevDataSize) { } inline ZoneinfoBinaryHeader::ZoneinfoBinaryHeader(char version, int numIsGmt, int numIsStd, int numLeaps, int numTransitions, int numLocalTimeTypes, int abbrevDataSize) : d_version(version) , d_numIsGmt(numIsGmt) , d_numIsStd(numIsStd) , d_numLeaps(numLeaps) , d_numTransitions(numTransitions) , d_numLocalTimeTypes(numLocalTimeTypes) , d_abbrevDataSize(abbrevDataSize) { BSLS_ASSERT(isValidVersion(version)); BSLS_ASSERT(isValidNumIsGmt(numIsGmt)); BSLS_ASSERT(isValidNumIsStd(numIsStd)); BSLS_ASSERT(isValidNumLeaps(numLeaps)); BSLS_ASSERT(isValidNumTransitions(numTransitions)); BSLS_ASSERT(isValidNumLocalTimeTypes(numLocalTimeTypes)); BSLS_ASSERT(isValidAbbrevDataSize(abbrevDataSize)); } inline ZoneinfoBinaryHeader::~ZoneinfoBinaryHeader() { BSLS_ASSERT(isValidVersion(d_version)); BSLS_ASSERT(isValidNumIsGmt(d_numIsGmt)); BSLS_ASSERT(isValidNumIsStd(d_numIsStd)); BSLS_ASSERT(isValidNumLeaps(d_numLeaps)); BSLS_ASSERT(isValidNumTransitions(d_numTransitions)); BSLS_ASSERT(isValidNumLocalTimeTypes(d_numLocalTimeTypes)); BSLS_ASSERT(isValidAbbrevDataSize(d_abbrevDataSize)); } // MANIPULATORS inline ZoneinfoBinaryHeader& baltzo::ZoneinfoBinaryHeader::operator=( const ZoneinfoBinaryHeader& rhs) { d_version = rhs.d_version; d_numIsGmt = rhs.d_numIsGmt; d_numIsStd = rhs.d_numIsStd; d_numLeaps = rhs.d_numLeaps; d_numTransitions = rhs.d_numTransitions; d_numLocalTimeTypes = rhs.d_numLocalTimeTypes; d_abbrevDataSize = rhs.d_abbrevDataSize; return *this; } inline void ZoneinfoBinaryHeader::setVersion(char value) { BSLS_ASSERT(isValidVersion(value)); d_version = value; } inline void ZoneinfoBinaryHeader::setNumIsGmt(int value) { BSLS_ASSERT(isValidNumIsGmt(value)); d_numIsGmt = value; } inline void ZoneinfoBinaryHeader::setNumIsStd(int value) { BSLS_ASSERT(isValidNumIsStd(value)); d_numIsStd = value; } inline void ZoneinfoBinaryHeader::setNumLeaps(int value) { BSLS_ASSERT(isValidNumLeaps(value)); d_numLeaps = value; } inline void ZoneinfoBinaryHeader::setNumTransitions(int value) { BSLS_ASSERT(isValidNumTransitions(value)); d_numTransitions = value; } inline void ZoneinfoBinaryHeader::setNumLocalTimeTypes(int value) { BSLS_ASSERT(isValidNumLocalTimeTypes(value)); d_numLocalTimeTypes = value; } inline void ZoneinfoBinaryHeader::setAbbrevDataSize(int value) { BSLS_ASSERT(isValidAbbrevDataSize(value)); d_abbrevDataSize = value; } inline void ZoneinfoBinaryHeader::swap(ZoneinfoBinaryHeader& other) { bsl::swap(d_version, other.d_version); bsl::swap(d_numIsGmt, other.d_numIsGmt); bsl::swap(d_numIsStd, other.d_numIsStd); bsl::swap(d_numLeaps, other.d_numLeaps); bsl::swap(d_numTransitions, other.d_numTransitions); bsl::swap(d_numLocalTimeTypes, other.d_numLocalTimeTypes); bsl::swap(d_abbrevDataSize, other.d_abbrevDataSize); } // ACCESSORS inline char ZoneinfoBinaryHeader::version() const { return d_version; } inline int ZoneinfoBinaryHeader::numIsGmt() const { return d_numIsGmt; } inline int ZoneinfoBinaryHeader::numIsStd() const { return d_numIsStd; } inline int ZoneinfoBinaryHeader::numLeaps() const { return d_numLeaps; } inline int ZoneinfoBinaryHeader::numTransitions() const { return d_numTransitions; } inline int ZoneinfoBinaryHeader::numLocalTimeTypes() const { return d_numLocalTimeTypes; } inline int ZoneinfoBinaryHeader::abbrevDataSize() const { return d_abbrevDataSize; } } // close package namespace // FREE OPERATORS inline bool baltzo::operator==(const ZoneinfoBinaryHeader& lhs, const ZoneinfoBinaryHeader& rhs) { return lhs.version() == rhs.version() && lhs.numIsGmt() == rhs.numIsGmt() && lhs.numIsStd() == rhs.numIsStd() && lhs.numLeaps() == rhs.numLeaps() && lhs.numTransitions() == rhs.numTransitions() && lhs.numLocalTimeTypes() == rhs.numLocalTimeTypes() && lhs.abbrevDataSize() == rhs.abbrevDataSize(); } inline bool baltzo::operator!=(const ZoneinfoBinaryHeader& lhs, const ZoneinfoBinaryHeader& rhs) { return !(lhs == rhs); } inline bsl::ostream& baltzo::operator<<(bsl::ostream& stream, const ZoneinfoBinaryHeader& object) // Write a single line description of the specified 'description' to the // specified 'stream' and a reference to the modifiable 'stream'. { return object.print(stream, 0, -1); } // FREE FUNCTIONS inline void baltzo::swap(ZoneinfoBinaryHeader& a, ZoneinfoBinaryHeader& b) { a.swap(b); } } // close enterprise namespace #endif // ---------------------------------------------------------------------------- // Copyright 2018 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 ----------------------------------