Files
2024-09-23 12:00:04 -04:00

337 lines
7.6 KiB
C++

#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 <cstring>
#include <functional>
#include <ostream>
#include <string>
#include <OnixS/FIXEngine/Compiler.h>
#include <OnixS/FIXEngine/FIX/Numeric.h>
#ifdef ONIXS_FIXENGINE_CXX17
#include <string_view>
#endif
namespace OnixS {
namespace FIX {
#ifdef ONIXS_FIXENGINE_CXX17
using StringRef = std::basic_string_view<Char>;
#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 <size_t Size>
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<OnixS::FIX::StringRef> {
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<ptrdiff_t>(
left.size() - right.size());
}
return (0 > compareResult);
}
};
}