#pragma once /* * Copyright Onix Solutions Limited [OnixS]. All rights reserved. * * This software owned by Onix Solutions Limited [OnixS] and is protected by copyright law * and international copyright treaties. * * Access to and use of the software is governed by the terms of the applicable OnixS Software * Services Agreement (the Agreement) and Customer end user license agreements granting * a non-assignable, non-transferable and non-exclusive license to use the software * for it's own data processing purposes under the terms defined in the Agreement. * * Except as otherwise granted within the terms of the Agreement, copying or reproduction of any part * of this source code or associated reference material to any other location for further reproduction * or redistribution, and any amendments to this copyright notice, are expressly prohibited. * * Any reproduction or redistribution for sale or hiring of the Software not in accordance with * the terms of the Agreement is a violation of copyright law. */ #include #include #include #include #include #include #ifdef ONIXS_FIXENGINE_CXX17 #include #endif namespace OnixS { namespace FIX { #ifdef ONIXS_FIXENGINE_CXX17 using StringRef = std::basic_string_view; #else /// Provides an efficient way of accessing text-based FIX field values. /// /// By default, OnixS::FIX::Message and OnixS::FIX::GroupInstance classes /// convert all values assigned to the fields into their text presentations /// and store textual data. This approach optimizes message reuse when the same /// message instance is used to update a few fields and is sent over the FIX /// session multiple times. Also, when a message comes from the network and is /// deserialized from its raw (tag=value) presentation, all field values /// represent text segments. To access textual values, the StringRef class /// was added together with new access members (FieldSet::getStringRef()). /// If value is accessed using FieldSet::getStringRef() member, instance of /// StringRef class is returned. That instance holds a reference to a read-only /// segment of text. An important aspect is that no memory is allocated and /// copied while accessing field values that way. class ONIXS_FIXENGINE_API StringRef { public: /// An immutable iterator over chars. typedef const char * ConstIterator; /// Initializes the blank instance. StringRef() : chars_(ONIXS_FIXENGINE_NULLPTR), size_(0) { } /// The full initialization. ONIXS_FIXENGINE_CONSTEXPR StringRef( const char * chars, size_t size) : chars_(chars), size_(size) { } /// Initializes an instance from the string content. explicit StringRef( const std::string & stdStr) : chars_(stdStr.c_str()), size_(stdStr.size()) { } /// Initializes an instance from the zero-terminated string. StringRef(const char * cStr) : chars_(cStr), size_(cStr ? strlen(cStr) : 0) { } /// Indicates whether the array has zero length. bool empty() const { return (0 == size_); } /// Returns the read-only content. const char * data() const { return chars_; } /// The STL-like begin(). ConstIterator begin() const { return chars_; } /// The STL-like end(). ConstIterator end() const { return chars_ + size_; } /// The number of chars. size_t size() const { return size_; } /// The number of chars. size_t length() const { return size_; } /// Resets the reference to nothing. void reset() { reset(ONIXS_FIXENGINE_NULLPTR, 0); } /// Updates data being referenced. void reset( const char * chars, size_t size) { chars_ = chars; size_ = size; } const char & operator [](size_t index) const { return chars_[index]; } const char & at(size_t index) const { if(index < size_) return chars_[index]; throw std::invalid_argument("index"); } /// Returns the number if the text is a string /// representation of an integer. template < typename NumericType > bool toNumber(NumericType & number) const { return OnixS::FIX::Number:: tryParse(chars_, size_, number); } // Appends a copy of the text to the std::string. void toString(std::string & str) const { str.append(chars_, size_); } // Returns a copy of the text as the std::string. std::string toString() const { return std::string(chars_, size_); } /// Compares with another instance. bool operator == ( const StringRef & other) const { return ( size_ == other.size_ && 0 == std::memcmp( chars_, other.chars_, size_)); } /// Compares with another instance. bool operator != ( const StringRef & other) const { return ( size_ != other.size_ || 0 != std::memcmp( chars_, other.chars_, size_)); } /// Swaps the content with another instance. void swap(StringRef & other) { std::swap(chars_, other.chars_); std::swap(size_, other.size_); } friend std::ostream & operator<< (std::ostream & out, const StringRef & ref); private: /// Items being referenced. const char * chars_; /// The number of chars being referenced. size_t size_; }; inline bool operator == ( const StringRef & ref, const std::string & str) { return ref == StringRef(str); } inline bool operator != ( const StringRef & ref, const std::string & str) { return ref != StringRef(str); } inline bool operator == ( const std::string & str, const StringRef & ref) { return ref == StringRef(str); } inline bool operator != ( const std::string & str, const StringRef & ref) { return ref != StringRef(str); } // inline bool operator == ( const StringRef & ref, const char * str) { return ref == StringRef(str); } inline bool operator != ( const StringRef & ref, const char * str) { return ref != StringRef(str); } inline bool operator == ( const char * str, const StringRef & ref) { return ref == StringRef(str); } inline bool operator != ( const char * str, const StringRef & ref) { return ref != StringRef(str); } inline std::ostream & operator<< (std::ostream & out, const StringRef & ref) { if(! ref.empty()) out.write(ref.chars_, ref.size_); return out; } #endif template ONIXS_FIXENGINE_NODISCARD inline ONIXS_FIXENGINE_CONSTEXPR StringRef constructStrRef(const char (&value)[Size]) ONIXS_FIXENGINE_NOTHROW { return StringRef(value, Size - 1); } } } namespace std { /// Allows the use of the StringRef in collections like std::map. template<> struct ONIXS_FIXENGINE_API less { bool operator()( const OnixS::FIX::StringRef & left, const OnixS::FIX::StringRef & right) const { ptrdiff_t compareResult = std::memcmp( left.data(), right.data(), left.size() < right.size() ? left.size() : right.size()); if(0 == compareResult) { compareResult = static_cast( left.size() - right.size()); } return (0 > compareResult); } }; }