// bdlt_fixutilconfiguration.h -*-C++-*- #ifndef INCLUDED_BDLT_FIXUTILCONFIGURATION #define INCLUDED_BDLT_FIXUTILCONFIGURATION #include <bsls_ident.h> BSLS_IDENT("$Id: $") //@PURPOSE: Provide an attribute class to configure FIX string generation. // //@CLASSES: // bdlt::FixUtilConfiguration: configuration for FIX strings // //@SEE_ALSO: bdlt_fixutil // //@DESCRIPTION: This component provides an unconstrained (value-semantic) // attribute class, 'bdlt::FixUtilConfiguration', that may be used to configure // various aspects of generated FIX strings. // ///Attributes ///---------- //.. // Name Type Default // ------------------------- ---- ------- // fractionalSecondPrecision int 3 // useZAbbreviationForUtc bool false //.. //: o 'fractionalSecondPrecision': number of digits used to represent //: fractional seconds; must be in the range '0 .. 6'. //: //: o 'useZAbbreviationForUtc': 'true' if 'Z' should be used for the timezone //: offset instead of '+00:00' (specific to UTC). // ///Default Configuration ///--------------------- // This component also provides a (process-wide) default configuration that may // be set and retrieved via the 'setDefaultConfiguration' and // 'defaultConfiguration' class methods, respectively. See Usage Example 2 for // further details. // ///Usage ///----- // This section illustrates intended use of this component. // ///Example 1: Configuring FIX String Generation ///- - - - - - - - - - - - - - - - - - - - - - // This example demonstrates creation of a 'bdlt::FixUtilConfiguration' object // that may be used to influence the format of the output produced by a // hypothetical utility, 'my::FixUtil', that generates and parses FIX strings // for 'bdlt' vocabulary types (see 'bdlt_fixutil', which provides just such // functionality). In particular, suppose that given a sample // 'bdlt::DatetimeTz' object: //.. // const bdlt::DatetimeTz datetimeTz( // bdlt::Datetime(2005, 1, 31, 8, 59, 59, 123), 0); //.. // 'my::FixUtil' produces, by default, the following string (which is a valid // FIX string): //.. // 20050131-08:59:59.123+00:00 //.. // However, we would like to produce the following (also valid FIX) string // instead: //.. // 20050131-08:59:59.123000Z //.. // 'bdlt::FixUtilConfiguration' can be used to obtain the desired result // assuming that 'my::FixUtil' uses 'bdlt::FixUtilConfiguration' to affect the // format of generated strings in this fashion (e.g., again see // 'bdlt_fixutil'). // // First, we construct a 'bdlt::FixUtilConfiguration' object that has the // default value: //.. // bdlt::FixUtilConfiguration configuration; // assert( configuration.fractionalSecondPrecision() == 3); // assert(!configuration.useZAbbreviationForUtc()); //.. // Then, we modify 'configuration' to indicate that we want to use 6 digits of // precision in the fractional seconds: //.. // configuration.setFractionalSecondPrecision(6); // assert( configuration.fractionalSecondPrecision() == 6); // assert(!configuration.useZAbbreviationForUtc()); //.. // Finally, we modify 'configuration' to indicate that we want to use 'Z' as an // abbreviation for UTC: //.. // configuration.setUseZAbbreviationForUtc(true); // assert( configuration.fractionalSecondPrecision() == 6); // assert( configuration.useZAbbreviationForUtc()); //.. // Our 'configuration' object can now be supplied to 'my::FixUtil' to produce // the desired result. // ///Example 2: Setting the Process-Wide Default Configuration ///- - - - - - - - - - - - - - - - - - - - - - - - - - - - - // This example demonstrates how to establish the process-wide default // configuration. // // First, we retrieve the default configuration in effect at process start-up // and note that it has the default-constructed value: //.. // bdlt::FixUtilConfiguration configuration = // bdlt::FixUtilConfiguration::defaultConfiguration(); // assert(bdlt::FixUtilConfiguration() == configuration); // assert( configuration.fractionalSecondPrecision() == 3); // assert(!configuration.useZAbbreviationForUtc()); //.. // Next, we modify 'configuration' to indicate that we want to output 'Z' when // the timezone offset is UTC (i.e., instead of '+00:00'): //.. // configuration.setUseZAbbreviationForUtc(true); // assert( configuration.fractionalSecondPrecision() == 3); // assert( configuration.useZAbbreviationForUtc()); //.. // Then, we modify 'configuration' to display milliseconds: //.. // configuration.setFractionalSecondPrecision(6); // assert( configuration.fractionalSecondPrecision() == 6); // assert( configuration.useZAbbreviationForUtc()); //.. // Now, we set the default configuration to the value of our 'configuration' // object: //.. // bdlt::FixUtilConfiguration::setDefaultConfiguration(configuration); //.. // Finally, we verify that the default configuration was updated as expected: //.. // const bdlt::FixUtilConfiguration newConfiguration = // bdlt::FixUtilConfiguration::defaultConfiguration(); // assert( newConfiguration.fractionalSecondPrecision() == 6); // assert( newConfiguration.useZAbbreviationForUtc()); //.. // Note that the expected usage is that the process-wide configuration will be // established *once*, early in 'main', and not changed throughout the lifetime // of a process. #include <bdlscm_version.h> #include <bsls_assert.h> #include <bsls_atomicoperations.h> #include <bsls_review.h> #include <bsl_iosfwd.h> namespace BloombergLP { namespace bdlt { // ========================== // class FixUtilConfiguration // ========================== class FixUtilConfiguration { // This unconstrained (value-semantic) attribute class characterizes how to // configure certain behavior in 'FixUtil' functions. Currently, only the // 'generate' and 'generateRaw' methods of that utility are affected by // 'FixUtilConfiguration' settings. See the Attributes section under // @DESCRIPTION in the component-level documentation for information on the // class attributes. private: // PRIVATE TYPES enum { // This enumeration denotes the distinct bits that define the values of // each of the two configuration attributes. k_FRACTIONAL_SECOND_PRECISION_MASK = 0x07, k_USE_Z_ABBREVIATION_FOR_UTC_BIT = 0x08 }; // CLASS DATA static bsls::AtomicOperations::AtomicTypes::Int s_defaultConfiguration; // process-wide configuration // DATA int d_configurationMask; // bitmask defining configuration // FRIENDS friend bool operator==(const FixUtilConfiguration&, const FixUtilConfiguration&); friend bool operator!=(const FixUtilConfiguration&, const FixUtilConfiguration&); private: // PRIVATE CREATORS explicit FixUtilConfiguration(int configurationMask); // Create a 'FixUtilConfiguration' object having the value indicated by // the specified 'configurationMask'. The behavior is undefined unless // 'configurationMask' represents a valid 'FixUtilConfiguration' value. public: // CLASS METHODS static FixUtilConfiguration defaultConfiguration(); // Return the value of the process-wide 'FixUtilConfiguration' that is // currently in effect. static void setDefaultConfiguration( const FixUtilConfiguration& configuration); // Set the value of the process-wide 'FixUtilConfiguration' to the // specified 'configuration'. Note that the expected usage is that the // process-wide configuration will be established *once*, early in // 'main', and not changed throughout the lifetime of a process. // CREATORS FixUtilConfiguration(); // Create a 'FixUtilConfiguration' object having the (default) // attribute values: //.. // fractionalSecondPrecision() == 3 // useZAbbreviationForUtc() == false //.. FixUtilConfiguration(const FixUtilConfiguration& original); // Create a 'FixUtilConfiguration' object having the value of the // specified 'original' configuration. ~FixUtilConfiguration(); // Destroy this object. // MANIPULATORS FixUtilConfiguration& operator=(const FixUtilConfiguration& rhs); // Assign to this object the value of the specified 'rhs' // configuration, and return a reference providing modifiable access to // this object. void setFractionalSecondPrecision(int value); // Set the 'fractionalSecondPrecision' attribute of this object to the // specified 'value'. The behavior is undefined unless '0 <= value' // and '6 >= value'. Note that the FIX protocol allows for much higher // precision. void setUseZAbbreviationForUtc(bool value); // Set the 'useZAbbreviationForUtc' attribute of this object to the // specified 'value'. // ACCESSORS int fractionalSecondPrecision() const; // Return the value of the 'fractionalSecondPrecision' attribute of // this object. bool useZAbbreviationForUtc() const; // Return the value of the 'useZAbbreviationForUtc' 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 this // human-readable format is not fully specified, and can change without // notice. }; // FREE OPERATORS bool operator==(const FixUtilConfiguration& lhs, const FixUtilConfiguration& rhs); // Return 'true' if the specified 'lhs' and 'rhs' objects have the same // value, and 'false' otherwise. Two 'FixUtilConfiguration' objects have // the same value if each of their 'fractionalSecondPrecision' and // 'useZAbbreviationForUtc' attributes (respectively) have the same value. bool operator!=(const FixUtilConfiguration& lhs, const FixUtilConfiguration& rhs); // Return 'true' if the specified 'lhs' and 'rhs' objects do not have the // same value, and 'false' otherwise. Two 'FixUtilConfiguration' objects // do not have the same value if any of their 'fractionalSecondPrecision' // or 'useZAbbreviationForUtc' attributes (respectively) do not have the // same value. bsl::ostream& operator<<(bsl::ostream& stream, const FixUtilConfiguration& 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)', but with the attribute names elided. // ============================================================================ // INLINE DEFINITIONS // ============================================================================ // -------------------------- // class FixUtilConfiguration // -------------------------- // PRIVATE CREATORS inline FixUtilConfiguration::FixUtilConfiguration(int configurationMask) : d_configurationMask(configurationMask) { BSLS_ASSERT(0 == (configurationMask & ~(k_FRACTIONAL_SECOND_PRECISION_MASK | k_USE_Z_ABBREVIATION_FOR_UTC_BIT))); } // CLASS METHODS inline FixUtilConfiguration FixUtilConfiguration::defaultConfiguration() { return FixUtilConfiguration( bsls::AtomicOperations::getIntRelaxed(&s_defaultConfiguration)); } inline void FixUtilConfiguration::setDefaultConfiguration( const FixUtilConfiguration& configuration) { bsls::AtomicOperations::setIntRelaxed(&s_defaultConfiguration, configuration.d_configurationMask); } // CREATORS inline FixUtilConfiguration::FixUtilConfiguration() : d_configurationMask(3) { } inline FixUtilConfiguration::FixUtilConfiguration( const FixUtilConfiguration& original) : d_configurationMask(original.d_configurationMask) { } inline FixUtilConfiguration::~FixUtilConfiguration() { BSLS_ASSERT(0 == (d_configurationMask & ~(k_FRACTIONAL_SECOND_PRECISION_MASK | k_USE_Z_ABBREVIATION_FOR_UTC_BIT))); } // MANIPULATORS inline FixUtilConfiguration& FixUtilConfiguration::operator=( const FixUtilConfiguration& rhs) { d_configurationMask = rhs.d_configurationMask; return *this; } // ACCESSORS inline int FixUtilConfiguration::fractionalSecondPrecision() const { return d_configurationMask & k_FRACTIONAL_SECOND_PRECISION_MASK; } inline bool FixUtilConfiguration::useZAbbreviationForUtc() const { return d_configurationMask & k_USE_Z_ABBREVIATION_FOR_UTC_BIT; } } // close package namespace // FREE OPERATORS inline bool bdlt::operator==(const FixUtilConfiguration& lhs, const FixUtilConfiguration& rhs) { return lhs.d_configurationMask == rhs.d_configurationMask; } inline bool bdlt::operator!=(const FixUtilConfiguration& lhs, const FixUtilConfiguration& rhs) { return lhs.d_configurationMask != rhs.d_configurationMask; } } // close enterprise namespace #endif // ---------------------------------------------------------------------------- // Copyright 2016 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 ----------------------------------