/* Copyright 2012. Bloomberg Finance L.P. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: The above * copyright notice and this permission notice shall be included in all copies * or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ // blpapi_name.h -*-C++-*- #ifndef INCLUDED_BLPAPI_NAME #define INCLUDED_BLPAPI_NAME //@PURPOSE: Provide a representation of strings for use as container keys. // //@CLASSES: // blpapi::Name: constant string in an efficient form for use as container keys // //@DESCRIPTION: This component implements a representation of a string which is // efficient for use as a key in a container (constant-time hashing and // ordering operations using the standard "intern string" technique). #ifndef INCLUDED_BLPAPI_TYPES #include <blpapi_types.h> #endif #ifndef INCLUDED_BLPAPI_DEFS #include <blpapi_defs.h> #endif #include <stddef.h> #ifdef __cplusplus extern "C" { #endif BLPAPI_EXPORT blpapi_Name_t* blpapi_Name_create( const char* nameString); BLPAPI_EXPORT void blpapi_Name_destroy( blpapi_Name_t *name); BLPAPI_EXPORT blpapi_Name_t* blpapi_Name_duplicate( const blpapi_Name_t *src); BLPAPI_EXPORT int blpapi_Name_equalsStr( const blpapi_Name_t *name, const char *string); BLPAPI_EXPORT const char* blpapi_Name_string( const blpapi_Name_t *name); BLPAPI_EXPORT size_t blpapi_Name_length( const blpapi_Name_t *name); BLPAPI_EXPORT blpapi_Name_t* blpapi_Name_findName( const char* nameString); #ifdef __cplusplus } #include <algorithm> // for swap #include <iostream> #include <cstring> // for strcmp namespace BloombergLP { namespace blpapi { // ========== // class Name // ========== class Name { // 'Name' represents a string in a form which is efficient for hashing and // comparison, thus providing efficient lookup when used as a key in either // ordered or hash-based containers. // // 'Name' objects are used to identify and access the classes which define // a schema - 'SchemaTypeDefinition', 'SchemaElementDefinition', // 'Constant', and 'ConstantList'. They are also used to access the values // in 'Element' objects and 'Message' objects. // // The 'Name' class is an efficient substitute for a string when used as a // key, providing constant-time hashing and comparision. Two 'Name' // objects constructed from strings for which 'strcmp()' would return 0 // will always compare equal. // // The ordering of 'Name' objects (as defined by 'operator<(Name,Name)') is // consistent during a particular instance of a single application. // However, the ordering is not lexical and is not necessarily consistent // with the ordering of the same 'Name' objects in any other process. // // Where possible, 'Name' objects should be initialized once and then // reused. Creating a 'Name' object from a 'const char*' involves a search // in a container requiring multiple string comparison operations. // // Note: Each 'Name' instance refers to an entry in a global static table. // 'Name' instances for identical strings will refer to the same data. // There is no provision for removing entries from the static table so // 'Name' objects should be used only when the set of input strings is // bounded. // // For example, creating a 'Name' for every possible field name and type in // a data model is reasonable (in fact, the API will do this whenever it // receives schema information). Converting sequence numbers from incoming // messages to strings and creating a 'Name' from each one of those // strings, however, will cause the static table to grow in an unbounded // manner, and is tantamount to a memory leak. blpapi_Name_t *d_impl_p; public: // CLASS METHODS static Name findName(const char *nameString); // If a 'Name' already exists which matches the specified // 'nameString', then return a copy of that 'Name'; otherwise return a // 'Name' which will compare equal to a 'Name' created using the // default constructor. The behavior is undefined if 'nameString' does // not point to a null-terminated string. static bool hasName(const char *nameString); // Return 'true' if a 'Name' has been created which matches the // specified 'nameString'; otherwise return 'false'. The behavior is // undefined if 'nameString' does not point to a null-terminated // string. Name(); // Construct an uninitialized 'Name'. An uninitialized 'Name' can be // assigned to, destroyed, or tested for equality. The behavior for all // other operations is undefined. Name(blpapi_Name_t *handle); Name(const Name& original); // Create a 'Name' object having the same value as the specified // 'original'. explicit Name(const char* nameString); // Construct a 'Name' from the specified 'nameString'. The behavior is // undefined unless 'nameString' is a null-terminated string. Note that // any null-terminated string can be specified, including an empty // string. Note also that constructing a 'Name' from a 'const char *' // is a relatively expensive operation. If a 'Name' will be used // repeatedly it is preferable to create it once and re-use (or copy) // the object. ~Name(); // Destroy this object. // MANIPULATORS Name& operator=(const Name& rhs); // Assign to this object the value of the specified 'rhs', and return a // reference to this modifiable object. // ACCESSORS const char *string() const; // Return a pointer to the null-terminated string value of this 'Name'. // The pointer returned will be valid at least until main() exits. size_t length() const; // Return the length of the string value of this 'Name', // (excluding a terminating null). Note that 'name.length()' is // logically equivalent to 'strlen(name.string())', however the former // is potentially more efficient. size_t hash() const; // Return an integral value such that for two 'Name' objects 'a' and // 'b', if 'a == b' then 'a.hash() == b.hash()', and if 'a != b' then // it is unlikely that 'a.hash() == b.hash()'. blpapi_Name_t* impl() const; }; // FREE OPERATORS bool operator==(const Name& lhs, const Name& rhs); // Return true if the specified 'lhs' and 'rhs' name objects have // the same value, and false otherwise. Two 'Name' objects 'a' and 'b' have // the same value if and only if 'strcmp(a.string(), b.string()) == 0'. bool operator!=(const Name& lhs, const Name& rhs); // Return false if the specified 'lhs' and 'rhs' name objects have the same // value, and true otherwise. Two 'Name' objects 'a' and 'b' have the same // value if and only if 'strcmp(a.string(), b.string()) == 0'. Note that // 'lhs != rhs' is equivalent to '!(lhs==rhs)'. bool operator==(const Name& lhs, const char *rhs); // Return true if the specified 'lhs' and 'rhs' have the same value, and // false otherwise. A 'Name' object 'a' and a null-terminated string 'b' // have the same value if and only if 'strcmp(a.string(), b) == 0'. The // behavior is undefined unless 'rhs' is a null-terminated string. bool operator!=(const Name& lhs, const char *rhs); // Return false if the specified 'lhs' and 'rhs' have the same value, and // true otherwise. A 'Name' object 'a' and a null-terminated string 'b' // have the same value if and only if 'strcmp(a.string(), b) == 0'. The // behavior is undefined unless 'rhs' is a null-terminated string. bool operator==(const char *lhs, const Name& rhs); // Return true if the specified 'lhs' and 'rhs' have the same value, and // false otherwise. A 'Name' object 'a' and a null-terminated string 'b' // have the same value if and only if 'strcmp(a.string(), b) == 0'. The // behavior is undefined unless 'lhs' is a null-terminated string. bool operator!=(const char *lhs, const Name& rhs); // Return false if the specified 'lhs' and 'rhs' have the same value, and // true otherwise. A 'Name' object 'a' and a null-terminated string 'b' // have the same value if and only if 'strcmp(a.string(), b) == 0'. The // behavior is undefined unless 'lhs' is a null-terminated string. bool operator<(const Name& lhs, const Name& rhs); // Return 'true' if the specified 'lhs' is ordered before the specified // 'rhs', and 'false' otherwise. The ordering used is stable within the // lifetime of a single process and is compatible with // 'operator==(const Name&, const Name&)', however this order is neither // guaranteed to be consistent across different processes (including // repeated runs of the same process), nor guaranteed to be lexical (i.e. // compatible with 'strcmp'). bool operator<=(const Name& lhs, const Name& rhs); // Return 'false' if the specified 'rhs' is ordered before the specified // 'lhs', and 'true' otherwise. The ordering used is stable within the // lifetime of a single process and is compatible with // 'operator==(const Name&, const Name&)', however this order is neither // guaranteed to be consistent across different processes (including // repeated runs of the same process), nor guaranteed to be lexical (i.e. // compatible with 'strcmp'). bool operator>(const Name& lhs, const Name& rhs); // Return 'true' if the specified 'rhs' is ordered before the specified // 'lhs', and 'false' otherwise. The ordering used is stable within the // lifetime of a single process and is compatible with // 'operator==(const Name&, const Name&)', however this order is neither // guaranteed to be consistent across different processes (including // repeated runs of the same process), nor guaranteed to be lexical (i.e. // compatible with 'strcmp'). bool operator>=(const Name& lhs, const Name& rhs); // Return 'false' if the specified 'lhs' is ordered before the specified // 'rhs', and 'true' otherwise. The ordering used is stable within the // lifetime of a single process and is compatible with // 'operator==(const Name&, const Name&)', however this order is neither // guaranteed to be consistent across different processes (including // repeated runs of the same process), nor guaranteed to be lexical (i.e. // compatible with 'strcmp'). std::ostream& operator<<(std::ostream& stream, const Name& name); // Write the value of the specified 'name' object to the specified output // 'stream', and return a reference to 'stream'. Note that this // human-readable format is not fully specified and can change without // notice. //============================================================================= // INLINE FUNCTION DEFINITIONS //============================================================================= // ---------- // class Name // ---------- inline Name::Name(blpapi_Name_t *handle) : d_impl_p(handle) { } inline Name::Name() : d_impl_p(0) { } inline Name::Name(const Name& original) : d_impl_p(blpapi_Name_duplicate(original.d_impl_p)) { } inline Name::Name(const char *nameString) { d_impl_p = blpapi_Name_create(nameString); } inline Name::~Name() { if (d_impl_p) { blpapi_Name_destroy(d_impl_p); } } inline Name& Name::operator=(const Name& rhs) { if (&rhs != this) { Name tmp(rhs); std::swap(tmp.d_impl_p, d_impl_p); } return *this; } inline const char *Name::string() const { return blpapi_Name_string(d_impl_p); } inline size_t Name::length() const { return blpapi_Name_length(d_impl_p); } inline blpapi_Name_t *Name::impl() const { return d_impl_p; } inline Name Name::findName(const char *nameString) { return Name(blpapi_Name_findName(nameString)); } inline bool Name::hasName(const char *nameString) { return blpapi_Name_findName(nameString) ? true : false; } inline size_t Name::hash() const { return reinterpret_cast<size_t>(impl()); } } // close namespace blpapi inline bool blpapi::operator==(const Name& lhs, const Name& rhs) { return (lhs.impl() == rhs.impl()); } inline bool blpapi::operator!=(const Name& lhs, const Name& rhs) { return !(lhs == rhs); } inline bool blpapi::operator==(const Name& lhs, const char *rhs) { return blpapi_Name_equalsStr(lhs.impl(), rhs) != 0; } inline bool blpapi::operator!=(const Name& lhs, const char *rhs) { return !(lhs == rhs); } inline bool blpapi::operator==(const char *lhs, const Name& rhs) { return rhs == lhs; } inline bool blpapi::operator!=(const char *lhs, const Name& rhs) { return !(rhs == lhs); } inline bool blpapi::operator<(const Name& lhs, const Name& rhs) { return lhs.impl() < rhs.impl(); } inline bool blpapi::operator<=(const Name& lhs, const Name& rhs) { return !(rhs < lhs); } inline bool blpapi::operator>(const Name& lhs, const Name& rhs) { return rhs < lhs; } inline bool blpapi::operator>=(const Name& lhs, const Name& rhs) { return !(lhs < rhs); } inline std::ostream& blpapi::operator<<(std::ostream& stream, const Name& name) { return stream << name.string(); } } // close namespace BloombergLP #endif // __cplusplus #endif // #ifndef INCLUDED_BLPAPI_NAME