46#if __cplusplus >= 201703L
49#if __cplusplus >= 201103L
54#ifndef HFFIX_NO_BOOST_DATETIME
55#ifdef DATE_TIME_TIME_HPP___
56#ifdef DATE_TIME_DATE_HPP___
57#define HFFIX_BOOST_DATETIME
71inline void throw_range_error() {
72 throw std::out_of_range(
"hffix message_writer buffer full");
75template <std::
size_t N>
76std::ptrdiff_t len(
char const (&)[N]) {
return std::ptrdiff_t(N - 1); }
88template<
typename Int_type> Int_type atoi(
char const* begin,
char const* end)
91 bool isnegative(
false);
93 if (begin < end && *begin ==
'-') {
98 for(; begin<end; ++begin) {
100 val += (Int_type)(*begin -
'0');
103 return isnegative ? -val : val;
117template<
typename U
int_type> Uint_type atou(
char const* begin,
char const* end)
121 for(; begin<end; ++begin) {
123 val += (Uint_type)(*begin -
'0');
141template<
typename Int_type>
char* itoa(Int_type number,
char* buffer,
char* end)
144 bool isnegative(
false);
152 if (b >= end) details::throw_range_error();
153 *b++ =
'0' + (number % 10);
158 if (b >= end) details::throw_range_error();
163 std::reverse(buffer, b);
180template<
typename U
int_type>
char* utoa(Uint_type number,
char* buffer,
char* end)
185 if (b >= end) details::throw_range_error();
186 *b++ =
'0' + (number % 10);
191 std::reverse(buffer, b);
210template<
typename Int_type>
void atod(
char const* begin,
char const* end, Int_type& mantissa, Int_type& exponent)
212 Int_type mantissa_ = 0;
213 Int_type exponent_ = 0;
214 bool isdecimal(
false);
215 bool isnegative(
false);
217 if (begin < end && *begin ==
'-') {
222 for(; begin < end; ++begin) {
227 mantissa_ += (*begin -
'0');
228 if (isdecimal) --exponent_;
232 if (isnegative) mantissa_ = -mantissa_;
233 mantissa = mantissa_;
234 exponent = exponent_;
251template<
typename Int_type>
char* dtoa(Int_type mantissa, Int_type exponent,
char* buffer,
char* end)
254 bool isnegative(
false);
257 mantissa = -mantissa;
262 if (b >= end) details::throw_range_error();
263 *b++ =
'0' + (mantissa % 10);
265 if (++exponent == 0) {
266 if (b >= end) details::throw_range_error();
269 }
while(mantissa > 0 || exponent < 1);
272 if (b >= end) details::throw_range_error();
277 std::reverse(buffer, b);
303 if (end - begin != 8)
return false;
305 year = details::atoi<int>(begin, begin + 4);
306 month = details::atoi<int>(begin + 4, begin + 6);
307 day = details::atoi<int>(begin + 6, begin + 8);
335 if (end - begin != 8 && end - begin != 12)
return false;
337 hour = details::atoi<int>(begin, begin + 2);
338 minute = details::atoi<int>(begin + 3, begin + 5);
339 second = details::atoi<int>(begin + 6, begin + 8);
341 if (end - begin == 12)
342 millisecond = details::atoi<int>(begin + 9, begin + 12);
361inline bool atotime_nano(
373 hour = details::atoi<int>(begin, begin + 2);
374 minute = details::atoi<int>(begin + 3, begin + 5);
375 second = details::atoi<int>(begin + 6, begin + 8);
377 switch (end - begin) {
378 case 12: nanosecond = details::atoi<int>(begin + 9, begin + 12) * 1000000L;
break;
379 case 15: nanosecond = details::atoi<int>(begin + 9, begin + 15) * 1000L;
break;
380 case 18: nanosecond = details::atoi<int>(begin + 9, begin + 18);
break;
381 default: nanosecond = 0;
386#if __cplusplus >= 201103L
394struct is_time_point : std::false_type {};
396template<
typename Clock,
typename Duration>
397struct is_time_point<std::chrono::time_point<Clock, Duration>> : std::true_type {};
409template <
typename TimePo
int>
410inline typename std::enable_if<details::is_time_point<TimePoint>::value,
bool>::type
419 int year, month, day, hour, minute, second, millisecond;
420 if (!atotime(begin + 9, end, hour, minute, second, millisecond))
422 if (!atodate(begin, begin + 8, year, month, day))
427 const unsigned era = (year >= 0 ? year : year - 399) / 400;
428 const unsigned yoe =
static_cast<unsigned>(year - era * 400);
429 const unsigned doy = (153 * (month + (month > 2 ? -3 : 9)) + 2) / 5 + day - 1;
430 const unsigned doe = yoe * 365 + yoe / 4 - yoe / 100 + doy;
431 const unsigned long days_since_epoch = era * 146097 +
static_cast<unsigned>(doe) - 719468;
433 tp = TimePoint(std::chrono::seconds(days_since_epoch * 24 * 3600) +
434 std::chrono::hours(hour) +
435 std::chrono::minutes(minute) +
436 std::chrono::seconds(second) +
437 std::chrono::milliseconds(millisecond));
452template <
typename TimePo
int>
453inline typename std::enable_if<details::is_time_point<TimePoint>::value,
bool>::type
462 int year, month, day, hour, minute, second, nanosecond;
463 if (!atotime_nano(begin + 9, end, hour, minute, second, nanosecond))
465 if (!atodate(begin, begin + 8, year, month, day))
470 const unsigned era = (year >= 0 ? year : year - 399) / 400;
471 const unsigned yoe =
static_cast<unsigned>(year - era * 400);
472 const unsigned doy = (153 * (month + (month > 2 ? -3 : 9)) + 2) / 5 + day - 1;
473 const unsigned doe = yoe * 365 + yoe / 4 - yoe / 100 + doy;
474 const unsigned long days_since_epoch = era * 146097 +
static_cast<unsigned>(doe) - 719468;
476 tp = TimePoint(std::chrono::seconds(days_since_epoch * 24 * 3600) +
477 std::chrono::hours(hour) +
478 std::chrono::minutes(minute) +
479 std::chrono::seconds(second) +
480 std::chrono::nanoseconds(nanosecond));
499template <
typename TimePo
int>
500inline typename std::enable_if<details::is_time_point<TimePoint>::value,
void>::type
501timepointtoparts(TimePoint tp,
int& year,
int& month,
int& day,
502 int& hour,
int& minute,
int& second,
int& millisecond)
noexcept
504 auto epoch_sec = std::chrono::time_point_cast<
505 std::chrono::seconds>(tp).time_since_epoch().count();
506 auto day_sec = epoch_sec - (epoch_sec % 86400);
507 auto days_since_epoch = day_sec / 86400;
510 days_since_epoch += 719468;
511 const unsigned era = (days_since_epoch >= 0 ? days_since_epoch : days_since_epoch - 146096) / 146097;
512 const unsigned doe =
static_cast<unsigned>(days_since_epoch - era * 146097);
513 const unsigned yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365;
514 year =
static_cast<unsigned>(yoe) + era * 400;
515 const unsigned doy = doe - (365 * yoe + yoe / 4 - yoe / 100);
516 const unsigned mp = (5 * doy + 2) / 153;
517 day = doy - (153 * mp + 2) / 5 + 1;
518 month = mp + (mp < 10 ? 3 : -9);
521 auto in_day = tp - std::chrono::seconds(day_sec);
522 millisecond = std::chrono::time_point_cast<std::chrono::milliseconds>(
523 in_day).time_since_epoch().count();
524 hour = millisecond / (60 * 60 * 1000);
525 millisecond -= hour * 60 * 60 * 1000;
526 minute = millisecond / (60 * 1000);
527 millisecond -= minute * 60 * 1000;
528 second = millisecond / 1000;
529 millisecond -= second * 1000;
546template <
typename TimePo
int>
547inline typename std::enable_if<details::is_time_point<TimePoint>::value,
void>::type
548timepointtoparts_nano(TimePoint tp,
int& year,
int& month,
int& day,
549 int& hour,
int& minute,
int& second,
int& nanosecond)
noexcept
551 auto epoch_sec = std::chrono::time_point_cast<
552 std::chrono::seconds>(tp).time_since_epoch().count();
553 auto day_sec = epoch_sec - (epoch_sec % 86400);
554 auto days_since_epoch = day_sec / 86400;
557 days_since_epoch += 719468;
558 const unsigned era = (days_since_epoch >= 0 ? days_since_epoch : days_since_epoch - 146096) / 146097;
559 const unsigned doe =
static_cast<unsigned>(days_since_epoch - era * 146097);
560 const unsigned yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365;
561 year =
static_cast<unsigned>(yoe) + era * 400;
562 const unsigned doy = doe - (365 * yoe + yoe / 4 - yoe / 100);
563 const unsigned mp = (5 * doy + 2) / 153;
564 day = doy - (153 * mp + 2) / 5 + 1;
565 month = mp + (mp < 10 ? 3 : -9);
569 auto in_day = tp - std::chrono::seconds(day_sec);
570 long lnanosecond = std::chrono::time_point_cast<std::chrono::nanoseconds>(
571 in_day).time_since_epoch().count();
572 hour = lnanosecond / (60 * 60 * 1000000000L);
573 lnanosecond -= hour * 60 * 60 * 1000000000L;
574 minute = lnanosecond / (60 * 1000000000L);
575 lnanosecond -= minute * 60 * 1000000000L;
576 second = lnanosecond / 1000000000L;
577 lnanosecond -= second * 1000000000L;
578 nanosecond =
static_cast<int>(lnanosecond);
632 buffer_end_(buffer + size),
657 buffer_end_(&(buffer[N])),
677 return next_ - buffer_;
701 return buffer_end_ - buffer_;
708 return buffer_end_ - next_;
728 if (body_length_)
throw std::logic_error(
"hffix message_writer.push_back_header called twice");
729 if (buffer_end_ - next_ < 2 + std::ptrdiff_t(strlen(begin_string_version)) + 3 + 7) {
730 details::throw_range_error();
732 memcpy(next_,
"8=", 2);
734 memcpy(next_, begin_string_version, std::strlen(begin_string_version));
735 next_ += std::strlen(begin_string_version);
737 memcpy(next_,
"9=", 2);
739 body_length_ = next_;
744#if __cplusplus >= 201703L
757 if (body_length_)
throw std::logic_error(
"hffix message_writer.push_back_header called twice");
758 if (buffer_end_ - next_ < 2 + std::ptrdiff_t(begin_string_version.size()) + 3 + 7) {
759 details::throw_range_error();
761 memcpy(next_,
"8=", 2);
763 memcpy(next_, begin_string_version.data(), begin_string_version.size());
764 next_ += begin_string_version.size();
766 memcpy(next_,
"9=", 2);
768 body_length_ = next_;
795 throw std::logic_error(
"hffix message_writer.push_back_trailer called before message_writer.push_back_header");
798 size_t const len = next_ - (body_length_ + 7);
799 body_length_[0] =
'0' + (len / 100000) % 10;
800 body_length_[1] =
'0' + (len / 10000) % 10;
801 body_length_[2] =
'0' + (len / 1000) % 10;
802 body_length_[3] =
'0' + (len / 100) % 10;
803 body_length_[4] =
'0' + (len / 10) % 10;
804 body_length_[5] =
'0' + len % 10;
806 if (buffer_end_ - next_ < 7) {
807 details::throw_range_error();
811 if (calculate_checksum) {
812#if __cplusplus >= 201103L
815 typedef unsigned char uint8_t;
817 uint8_t
const checksum = std::accumulate(buffer_, next_, uint8_t(0));
819 memcpy(next_,
"10=", 3);
821 next_[0] =
'0' + ((checksum / 100) % 10);
822 next_[1] =
'0' + ((checksum / 10) % 10);
823 next_[2] =
'0' + (checksum % 10);
828 memcpy(next_,
"10=000\x01", 7);
849 next_ = details::itoa(tag, next_, buffer_end_);
850 if (buffer_end_ - next_ < (end - begin) + 2) {
851 details::throw_range_error();
854 memcpy(next_, begin, end - begin);
855 next_ += (end - begin);
870 char const* cstring_end = (
char const*)memchr(cstring, 0, buffer_end_ - next_);
872 else details::throw_range_error();
891#if __cplusplus >= 201703L
916 next_ = details::itoa(tag, next_, buffer_end_);
917 if (buffer_end_ - next_ < 3) {
918 details::throw_range_error();
921 *next_++ = character;
938 next_ = details::itoa(tag, next_, buffer_end_);
939 if (next_ >= buffer_end_) details::throw_range_error();
941 next_ = details::itoa(number, next_, buffer_end_);
942 if (next_ >= buffer_end_) details::throw_range_error();
966 template<
typename Int_type>
void push_back_decimal(
int tag, Int_type mantissa, Int_type exponent) {
967 next_ = details::itoa(tag, next_, buffer_end_);
968 if (next_ >= buffer_end_) details::throw_range_error();
970 next_ = details::dtoa(mantissa, exponent, next_, buffer_end_);
971 if (next_ >= buffer_end_) details::throw_range_error();
991 next_ = details::itoa(tag, next_, buffer_end_);
992 if (buffer_end_ - next_ < details::len(
"=YYYYMMDD|")) {
993 details::throw_range_error();
996 itoa_padded(year, next_, next_ + 4);
998 itoa_padded(month, next_, next_ + 2);
1000 itoa_padded(day, next_, next_ + 2);
1014 next_ = details::itoa(tag, next_, buffer_end_);
1015 if (buffer_end_ - next_ < details::len(
"=YYYYMM|")) {
1016 details::throw_range_error();
1019 itoa_padded(year, next_, next_ + 4);
1021 itoa_padded(month, next_, next_ + 2);
1041 next_ = details::itoa(tag, next_, buffer_end_);
1042 if (buffer_end_ - next_ < details::len(
"=HH:MM:SS|")) {
1043 details::throw_range_error();
1046 itoa_padded(hour, next_, next_ + 2);
1049 itoa_padded(minute, next_, next_ + 2);
1052 itoa_padded(second, next_, next_ + 2);
1071 next_ = details::itoa(tag, next_, buffer_end_);
1072 if (buffer_end_ - next_ < details::len(
"=HH:MM:SS.sss|")) {
1073 details::throw_range_error();
1076 itoa_padded(hour, next_, next_ + 2);
1079 itoa_padded(minute, next_, next_ + 2);
1082 itoa_padded(second, next_, next_ + 2);
1085 itoa_padded(millisecond, next_, next_ + 3);
1104 next_ = details::itoa(tag, next_, buffer_end_);
1105 if (buffer_end_ - next_ < details::len(
"=HH:MM:SS.sssssssss|")) {
1106 details::throw_range_error();
1109 itoa_padded(hour, next_, next_ + 2);
1112 itoa_padded(minute, next_, next_ + 2);
1115 itoa_padded(second, next_, next_ + 2);
1118 itoa_padded(nanosecond, next_, next_ + 9);
1141 next_ = details::itoa(tag, next_, buffer_end_);
1143 if (buffer_end_ - next_ < details::len(
"=YYYYMMDD-HH:MM:SS|")) {
1144 details::throw_range_error();
1147 itoa_padded(year, next_, next_ + 4);
1149 itoa_padded(month, next_, next_ + 2);
1151 itoa_padded(day, next_, next_ + 2);
1154 itoa_padded(hour, next_, next_ + 2);
1157 itoa_padded(minute, next_, next_ + 2);
1160 itoa_padded(second, next_, next_ + 2);
1181 void push_back_timestamp(
int tag,
int year,
int month,
int day,
int hour,
int minute,
int second,
int millisecond) {
1182 next_ = details::itoa(tag, next_, buffer_end_);
1183 if (buffer_end_ - next_ < details::len(
"=YYYYMMDD-HH:MM:SS.sss|")) {
1184 details::throw_range_error();
1187 itoa_padded(year, next_, next_ + 4);
1189 itoa_padded(month, next_, next_ + 2);
1191 itoa_padded(day, next_, next_ + 2);
1194 itoa_padded(hour, next_, next_ + 2);
1197 itoa_padded(minute, next_, next_ + 2);
1200 itoa_padded(second, next_, next_ + 2);
1203 itoa_padded(millisecond, next_, next_ + 3);
1225 next_ = details::itoa(tag, next_, buffer_end_);
1226 if (buffer_end_ - next_ < details::len(
"=YYYYMMDD-HH:MM:SS.sssssssss|")) {
1227 details::throw_range_error();
1230 itoa_padded(year, next_, next_ + 4);
1232 itoa_padded(month, next_, next_ + 2);
1234 itoa_padded(day, next_, next_ + 2);
1237 itoa_padded(hour, next_, next_ + 2);
1240 itoa_padded(minute, next_, next_ + 2);
1243 itoa_padded(second, next_, next_ + 2);
1246 itoa_padded(nanosecond, next_, next_ + 9);
1252#ifdef HFFIX_BOOST_DATETIME
1268 if (!date.is_not_a_date())
1287 if (!timeonly.is_not_a_date_time())
1293 static_cast<int>(timeonly.fractional_seconds() * 1000 / boost::posix_time::time_duration::ticks_per_second())
1312 if (!timeonly.is_not_a_date_time())
1318 static_cast<int>(timeonly.fractional_seconds() * 1000000000L / boost::posix_time::time_duration::ticks_per_second())
1337 if (!timestamp.is_not_a_date_time())
1340 timestamp.date().year(),
1341 timestamp.date().month(),
1342 timestamp.date().day(),
1343 timestamp.time_of_day().hours(),
1344 timestamp.time_of_day().minutes(),
1345 timestamp.time_of_day().seconds(),
1346 static_cast<int>(timestamp.time_of_day().fractional_seconds() * 1000 / boost::posix_time::time_duration::ticks_per_second())
1349 throw std::logic_error(
"push_back_timestamp called with not_a_date_time.");
1367 if (!timestamp.is_not_a_date_time())
1370 timestamp.date().year(),
1371 timestamp.date().month(),
1372 timestamp.date().day(),
1373 timestamp.time_of_day().hours(),
1374 timestamp.time_of_day().minutes(),
1375 timestamp.time_of_day().seconds(),
1376 static_cast<int>(timestamp.time_of_day().fractional_seconds() * 1000000000L / boost::posix_time::time_duration::ticks_per_second())
1379 throw std::logic_error(
"push_back_timestamp_nano called with not_a_date_time.");
1384#if __cplusplus >= 201103L
1402 template<
typename Clock,
typename Duration>
1405 int year, month, day, hour, minute, second, millisecond;
1406 details::timepointtoparts(tp, year, month, day, hour, minute, second, millisecond);
1424 template<
typename Clock,
typename Duration>
1427 int year, month, day, hour, minute, second, nanosecond;
1428 details::timepointtoparts_nano(tp, year, month, day, hour, minute, second, nanosecond);
1444 template<
typename Rep,
typename Period>
1446 using namespace std::chrono;
1450 duration_cast<hours> (timeonly).count(),
1451 duration_cast<minutes> (timeonly % hours(1)).count(),
1452 duration_cast<seconds> (timeonly % minutes(1)).count(),
1453 duration_cast<milliseconds>(timeonly % seconds(1)).count()
1469 template<
typename Rep,
typename Period>
1471 using namespace std::chrono;
1475 duration_cast<hours> (timeonly).count(),
1476 duration_cast<minutes> (timeonly % hours(1)).count(),
1477 duration_cast<seconds> (timeonly % minutes(1)).count(),
1478 duration_cast<nanoseconds>(timeonly % seconds(1)).count()
1513 void push_back_data(
int tag_data_length,
int tag_data,
char const* begin,
char const* end) {
1514 next_ = details::itoa(tag_data_length, next_, buffer_end_);
1515 if (next_ == buffer_end_) details::throw_range_error();
1517 next_ = details::itoa(end - begin, next_, buffer_end_);
1518 if (next_ == buffer_end_) details::throw_range_error();
1520 next_ = details::itoa(tag_data, next_, buffer_end_);
1522 if (buffer_end_ - next_ < (end - begin) + 2) {
1523 details::throw_range_error();
1526 memcpy(next_, begin, end - begin);
1527 next_ += end - begin;
1534 static void itoa_padded(
int x,
char* b,
char* e) {
1536 *--e =
'0' + (x % 10);
1547class message_reader;
1548class message_reader_const_iterator;
1590 return end_ - begin_;
1598 return !strncmp(that.
begin(), cstring, that.
size()) && !cstring[that.
size()];
1606 return that == cstring;
1613 return !(that == cstring);
1620 return !(that == cstring);
1627 return that.
size() == s.size() && !strncmp(that.
begin(), s.data(), that.
size());
1641 return !(that == s);
1648 return !(that == s);
1651#if __cplusplus >= 201703L
1656 return std::equal(that.
begin(), that.
end(), s.begin(), s.end());
1670 return !(that == s);
1677 return !(that == s);
1685 return os.write(that.
begin(), that.
size());
1700 return std::string(
begin(),
end());
1703#if __cplusplus >= 201703L
1710 return std::string_view(
begin(),
size());
1741 template<
typename Int_type>
void as_decimal(Int_type& mantissa, Int_type& exponent)
const {
1742 details::atod<Int_type>(
begin(),
end(), mantissa, exponent);
1747 template <
typename Int_type,
bool Is_
signed_
integer>
1748 struct as_int_selector {
1751 template <
typename Int_type>
1752 struct as_int_selector<Int_type, true> {
1753 static Int_type call_as_int(
char const*
begin,
char const*
end) {
1754 return details::atoi<Int_type>(
begin,
end);
1758 template <
typename Int_type>
1759 struct as_int_selector<Int_type, false> {
1760 static Int_type call_as_int(
char const*
begin,
char const*
end) {
1761 return details::atou<Int_type>(
begin,
end);
1778 template<
typename Int_type> Int_type
as_int()
const {
1779 return as_int_selector<Int_type, std::numeric_limits<Int_type>::is_signed>::call_as_int(
begin(),
end());
1802 return details::atodate(
begin(),
end(), year, month, day);
1819 if (
end() -
begin() != 6)
return false;
1821 year = details::atoi<int>(
begin(),
begin() + 4);
1822 month = details::atoi<int>(
begin() + 4,
begin() + 6);
1845 return details::atotime(
begin(),
end(), hour, minute, second, millisecond);
1865 return details::atotime_nano(
begin(),
end(), hour, minute, second, nanosecond);
1892 details::atotime(
begin() + 9,
end(), hour, minute, second, millisecond)
1893 && details::atodate(
begin(),
begin() + 8, year, month, day);
1920 details::atotime_nano(
begin() + 9,
end(), hour, minute, second, nanosecond)
1921 && details::atodate(
begin(),
begin() + 8, year, month, day);
1926#ifdef HFFIX_BOOST_DATETIME
1939 int year, month, day;
1940 if (
as_date(year, month, day)) {
1942 return boost::gregorian::date(year, month, day);
1943 }
catch(std::exception& ex) {
1944 return boost::gregorian::date(boost::posix_time::not_a_date_time);
1947 return boost::gregorian::date(boost::posix_time::not_a_date_time);
1958 int hour, minute, second, millisecond;
1959 if (
as_timeonly(hour, minute, second, millisecond)) {
1961 return boost::posix_time::time_duration(hour, minute, second, boost::posix_time::time_duration::ticks_per_second() * millisecond / 1000);
1962 }
catch(std::exception& ex) {
1963 return boost::posix_time::time_duration(boost::posix_time::not_a_date_time);
1966 return boost::posix_time::time_duration(boost::posix_time::not_a_date_time);
1977 int hour, minute, second, nanosecond;
1980 return boost::posix_time::time_duration(hour, minute, second, boost::posix_time::time_duration::ticks_per_second() * nanosecond / 1000000000L);
1981 }
catch(std::exception& ex) {
1982 return boost::posix_time::time_duration(boost::posix_time::not_a_date_time);
1985 return boost::posix_time::time_duration(boost::posix_time::not_a_date_time);
1996 int year, month, day, hour, minute, second, millisecond;
1998 if (details::atotime(
begin() + 9,
end(), hour, minute, second, millisecond)
1999 && details::atodate(
begin(),
begin() + 8, year, month, day)) {
2001 return boost::posix_time::ptime(
2002 boost::gregorian::date(year, month, day),
2003 boost::posix_time::time_duration(hour, minute, second, boost::posix_time::time_duration::ticks_per_second() * millisecond / 1000)
2005 }
catch(std::exception& ex) {
2006 return boost::posix_time::not_a_date_time;
2009 return boost::posix_time::not_a_date_time;
2020 int year, month, day, hour, minute, second, nanosecond;
2022 if (details::atotime_nano(
begin() + 9,
end(), hour, minute, second, nanosecond)
2023 && details::atodate(
begin(),
begin() + 8, year, month, day)) {
2025 return boost::posix_time::ptime(
2026 boost::gregorian::date(year, month, day),
2027 boost::posix_time::time_duration(hour, minute, second, boost::posix_time::time_duration::ticks_per_second() * nanosecond / 1000000000L)
2029 }
catch(std::exception& ex) {
2030 return boost::posix_time::not_a_date_time;
2033 return boost::posix_time::not_a_date_time;
2040#if __cplusplus >= 201103L
2057 template<
typename Clock,
typename Duration>
2059 if (details::atotimepoint(
begin(),
end(), tp))
2078 template<
typename Clock,
typename Duration>
2080 if (details::atotimepoint_nano(
begin(),
end(), tp))
2096 template<
typename Rep,
typename Period>
2098 int hour, minute, second, millisecond;
2099 if (
as_timeonly(hour, minute, second, millisecond)) {
2100 dur = std::chrono::hours(hour) +
2101 std::chrono::minutes(minute) +
2102 std::chrono::seconds(second) +
2103 std::chrono::milliseconds(millisecond);
2120 template<
typename Rep,
typename Period>
2122 int hour, minute, second, nanosecond;
2124 dur = std::chrono::hours(hour) +
2125 std::chrono::minutes(minute) +
2126 std::chrono::seconds(second) +
2127 std::chrono::nanoseconds(nanosecond);
2165 os << that.tag_ <<
"=";
2166 return os.write(that.value_.
begin(), that.value_.
size());
2193 message_reader_(&container),
2229 return a.buffer_ == b.buffer_;
2234 return a.buffer_ != b.buffer_;
2239 return a.buffer_ < b.buffer_;
2244 return a.buffer_ > b.buffer_;
2249 return a.buffer_ <= b.buffer_;
2254 return a.buffer_ >= b.buffer_;
2279 if (addend < 0)
throw std::logic_error(
"message_reader::const_iterator is a Forward Iterator, so only positive addends are allowed.");
2280 for (
int i = 0; i < addend; ++i)
2295 char const* buffer_;
2308 bool operator()(
field const& v)
const {
2309 return v.
tag() == tag;
2351template <
typename ForwardIterator,
typename UnaryPredicate>
2352inline bool find_with_hint(ForwardIterator begin, ForwardIterator end, UnaryPredicate predicate, ForwardIterator & i) {
2353 ForwardIterator j = std::find_if(i, end, predicate);
2358 j = std::find_if(begin, i, predicate);
2401 typedef field const& const_reference;
2403 typedef field const* const_pointer;
2404 typedef size_t size_type;
2413 buffer_end_(buffer + size),
2416 is_complete_(false),
2431 is_complete_(false),
2440 buffer_(that.buffer_),
2441 buffer_end_(that.buffer_end_),
2444 is_complete_(that.is_complete_),
2445 is_valid_(that.is_valid_) {
2454 buffer_= that.buffer_;
2455 buffer_end_ = that.buffer_end_;
2460 is_complete_ = that.is_complete_;
2461 is_valid_ = that.is_valid_;
2478 is_complete_(false),
2491 buffer_end_(&(buffer[N])),
2494 is_complete_(false),
2509 return is_complete_;
2544 if (!is_complete_) {
2545 throw std::logic_error(
"Can't call next_message_reader on an incomplete message.");
2549 char const* b = buffer_ + 1;
2550 while(b < buffer_end_ - 10) {
2551 if (!std::memcmp(b,
"8=FIX", 5))
2558 return message_reader(end_.current_.value_.end_ + 1, buffer_end_);
2583 if (!is_valid_)
throw std::logic_error(
"hffix Cannot calculate checksum for an invalid message.");
2584 return std::accumulate(buffer_, end_.buffer_, (
unsigned char)(0));
2595 if (!is_valid_)
throw std::logic_error(
"hffix Cannot return iterator for an invalid message.");
2605 if (!is_valid_)
throw std::logic_error(
"hffix Cannot return iterator for an invalid message.");
2615 if (!is_valid_)
throw std::logic_error(
"hffix Cannot return iterator for an invalid message.");
2625 if (!is_valid_)
throw std::logic_error(
"hffix Cannot return iterator for an invalid message.");
2647 return prefix_end_ - buffer_ - 2;
2698 return buffer_end_ - buffer_;
2716 if (!is_valid_)
throw std::logic_error(
"hffix Cannot determine size of an invalid message.");
2717 return end_.current_.value_.end_ + 1;
2725 if (!is_valid_)
throw std::logic_error(
"hffix Cannot determine size of an invalid message.");
2726 return end_.current_.value_.end_ - buffer_ + 1;
2737 char const* b = buffer_ + 9;
2740 if (b >= buffer_end_) {
2741 is_complete_ =
false;
2748 if (b - buffer_ > 11) {
2755 if (b + 1 >= buffer_end_) {
2756 is_complete_ =
false;
2765 size_t bodylength(0);
2768 if (b >= buffer_end_) {
2769 is_complete_ =
false;
2772 if (*b ==
'\x01')
break;
2773 if (*b <
'0' || *b >
'9') {
2778 bodylength += *b++ -
'0';
2782 if (b + 3 >= buffer_end_) {
2783 is_complete_ =
false;
2787 if (*b !=
'3' || b[1] !=
'5') {
2792 char const* checksum = b + bodylength;
2794 if (checksum + 7 > buffer_end_) {
2795 is_complete_ =
false;
2799 if (*(checksum - 1) !=
'\x01') {
2810 if (*(checksum + 6) !=
'\x01') {
2816 begin_.current_.tag_ = 35;
2818 begin_.current_.value_.begin_ = b;
2819 while(*++b !=
'\x01') {
2820 if (b >= checksum) {
2825 begin_.current_.value_.end_ = b;
2827 end_.buffer_ = checksum;
2828 end_.current_.tag_ = 10;
2829 end_.current_.value_.begin_ = checksum + 3;
2830 end_.current_.value_.end_ = checksum + 6;
2832 is_complete_ =
true;
2835 char const* buffer_;
2836 char const* buffer_end_;
2837 const_iterator begin_;
2838 const_iterator end_;
2841 char const* prefix_end_;
2844 is_complete_ =
true;
2852bool is_tag_a_data_length(
int tag);
2857inline void message_reader_const_iterator::increment()
2859 buffer_ = current_.value_.end_ + 1;
2860 current_.value_.begin_ = buffer_;
2863 while(*current_.value_.begin_ !=
'=' && *current_.value_.begin_ !=
'\x01') {
2864 current_.tag_ *= 10;
2865 current_.tag_ += (*current_.value_.begin_ -
'0');
2866 ++current_.value_.begin_;
2873 if (*current_.value_.begin_ ==
'\x01') {
2874 current_.value_.end_ = current_.value_.begin_;
2879 ++current_.value_.begin_;
2882 current_.value_.end_ = std::find(current_.value_.begin_, message_reader_->
message_end(),
'\x01');
2883 if (details::is_tag_a_data_length(current_.tag_)) {
2884 size_t data_len = details::atou<size_t>(current_.value_.begin_, current_.value_.end_);
2886 buffer_ = current_.value_.end_ + 1;
2887 current_.value_.begin_ = buffer_;
2890 while(*current_.value_.begin_ !=
'=') {
2891 current_.tag_ *= 10;
2892 current_.tag_ += (*current_.value_.begin_ -
'0');
2893 ++current_.value_.begin_;
2896 current_.value_.end_ = ++current_.value_.begin_ + data_len;
2908 int_gte(
int tag) : tag(tag) {}
2910 bool operator()(
int that)
const {
2928inline bool is_tag_a_data_length(
int tag)
2931 int* i = std::find_if(length_fields, length_fields_end, int_gte(tag));
2932 if (i == length_fields_end)
return false;
2937template <
typename AssociativeContainer>
struct field_name_streamer {
2939 AssociativeContainer
const& field_dictionary;
2940 bool number_alternative;
2942 field_name_streamer(
int tag, AssociativeContainer
const& field_dictionary,
bool number_alternative) : tag(tag), field_dictionary(field_dictionary), number_alternative(number_alternative) {}
2944 friend std::ostream& operator<<(std::ostream& os, field_name_streamer that) {
2945 typename AssociativeContainer::const_iterator i = that.field_dictionary.find(that.tag);
2946 if (i != that.field_dictionary.end())
2948 else if (that.number_alternative)
2974template <
typename AssociativeContainer> details::field_name_streamer<AssociativeContainer>
field_name(
int tag, AssociativeContainer
const& field_dictionary,
bool or_number =
true)
2976 return details::field_name_streamer<AssociativeContainer>(tag, field_dictionary, or_number);
FIX field value for hffix::message_reader.
friend bool operator==(std::string_view s, field_value const &that)
True if the value of the field is equal to the string_view argument.
char const * begin() const
Pointer to the beginning of the field value in the buffer.
std::string_view as_string_view() const
Ascii value as std::string_view.
friend bool operator==(char const *cstring, field_value const &that)
True if the value of the field is equal to the C-string argument.
boost::posix_time::time_duration as_timeonly_nano() const
Ascii-to-time conversion with nanosecond precision.
bool as_timeonly(int &hour, int &minute, int &second, int &millisecond) const
Ascii-to-time conversion with millisecond precision.
friend bool operator!=(field_value const &that, std::string const &s)
True if the value of the field is not equal to the string argument.
friend bool operator==(field_value const &that, std::string_view s)
True if the value of the field is equal to the string_view argument.
bool as_timeonly_nano(std::chrono::duration< Rep, Period > &dur) const
Ascii-to-time conversion with nanosecond precision.
bool as_monthyear(int &year, int &month) const
Ascii-to-month-year conversion.
boost::posix_time::time_duration as_timeonly() const
Ascii-to-time conversion with millisecond precision.
bool as_date(int &year, int &month, int &day) const
Ascii-to-date conversion.
bool as_timestamp_nano(std::chrono::time_point< Clock, Duration > &tp) const
Ascii-to-time-point conversion with nanosecond precision.
std::string as_string() const
Ascii value as std::string.
friend bool operator!=(std::string const &s, field_value const &that)
True if the value of the field is not equal to the string argument.
char as_char() const
Ascii value as char.
bool as_timestamp(std::chrono::time_point< Clock, Duration > &tp) const
Ascii-to-time-point conversion with millisecond precision.
bool as_timeonly_nano(int &hour, int &minute, int &second, int &nanosecond) const
Ascii-to-time conversion with nanosecond precision.
friend bool operator==(std::string const &s, field_value const &that)
True if the value of the field is equal to the string argument.
boost::posix_time::ptime as_timestamp() const
Ascii-to-timestamp conversion with millisecond precision.
bool as_timestamp(int &year, int &month, int &day, int &hour, int &minute, int &second, int &millisecond) const
Ascii-to-timestamp conversion with millisecond precision.
boost::gregorian::date as_date() const
Ascii-to-date conversion.
void as_decimal(Int_type &mantissa, Int_type &exponent) const
Ascii-to-decimal conversion.
Int_type as_int() const
Ascii-to-integer conversion.
size_t size() const
Size of the field value, in bytes.
friend bool operator!=(char const *cstring, field_value const &that)
True if the value of the field is not equal to the C-string argument.
friend bool operator!=(field_value const &that, char const *cstring)
True if the value of the field is not equal to the C-string argument.
friend std::ostream & operator<<(std::ostream &os, field_value const &that)
Stream out the raw text value of the field.
friend bool operator!=(std::string_view s, field_value const &that)
True if the value of the field is not equal to the string_view argument.
boost::posix_time::ptime as_timestamp_nano() const
Ascii-to-timestamp conversion with nanosecond precision.
friend bool operator!=(field_value const &that, std::string_view s)
True if the value of the field is not equal to the string_view argument.
friend bool operator==(field_value const &that, std::string const &s)
True if the value of the field is equal to the string argument.
bool as_timeonly(std::chrono::duration< Rep, Period > &dur) const
Ascii-to-time conversion.
bool as_timestamp_nano(int &year, int &month, int &day, int &hour, int &minute, int &second, int &nanosecond) const
Ascii-to-timestamp conversion with nanosecond precision.
char const * end() const
Pointer to past-the-end of the field value in the buffer.
friend bool operator==(field_value const &that, char const *cstring)
True if the value of the field is equal to the C-string argument.
A FIX field for hffix::message_reader, with tag and hffix::field_value.
friend std::ostream & operator<<(std::ostream &os, field const &that)
Output stream operator. Output format is "[tag number]=[value]".
int tag() const
Tag of the field.
field_value const & value() const
Weakly-typed value of the field.
The iterator type for hffix::message_reader. Typedef'd as hffix::message_reader::const_iterator.
friend bool operator==(message_reader_const_iterator const &a, message_reader_const_iterator const &b)
Equal.
field const & operator*() const
Returns a hffix::message_reader::const_reference to a field.
field & reference
For std::iterator_traits.
field * pointer
For std::iterator_traits.
field value_type
For std::iterator_traits.
friend bool operator>=(message_reader_const_iterator const &a, message_reader_const_iterator const &b)
Greater-than or equal.
friend bool operator<(message_reader_const_iterator const &a, message_reader_const_iterator const &b)
Less-than.
std::ptrdiff_t difference_type
For std::iterator_traits.
message_reader_const_iterator()
field const * operator->() const
Returns a hffix::message_reader::const_pointer to a field.
friend bool operator<=(message_reader_const_iterator const &a, message_reader_const_iterator const &b)
Less-than or equal.
friend message_reader_const_iterator operator+(int addend, message_reader_const_iterator a)
Addition.
message_reader_const_iterator operator++(int)
Postfix increment.
friend message_reader_const_iterator operator+(message_reader_const_iterator a, int addend)
Addition.
message_reader_const_iterator & operator++()
Prefix increment.
::std::input_iterator_tag iterator_category
For std::iterator_traits.
friend bool operator>(message_reader_const_iterator const &a, message_reader_const_iterator const &b)
Greater-than.
friend bool operator!=(message_reader_const_iterator const &a, message_reader_const_iterator const &b)
Not equal.
One FIX message for reading.
size_t message_size() const
The entire size of the FIX message in bytes.
message_reader(message_reader const &that)
Copy constructor. The hffix::message_reader is immutable, so copying it is fine.
~message_reader()
Owns no resources, so destruction is no-op.
char const * message_begin() const
A pointer to the beginning of the FIX message in the buffer.
message_reader & operator=(const message_reader &that)
Copy assignment operator. The hffix::message_reader is immutable, so copying it is fine.
char const * message_end() const
A pointer to past-the-end of the FIX message in the buffer.
bool find_with_hint(int tag, const_iterator &i) const
Convenient synonym for hffix::find_with_hint(reader.begin(), reader.end(), hffix::tag_equal(tag),...
size_t buffer_size() const
The size of the buffer in bytes.
char const * buffer_end() const
A pointer to past-the-end of the buffer.
size_t prefix_size() const
Returns the FIX version prefix BeginString field value size. (Example: returns 7 for "FIX....
message_reader next_message_reader() const
Returns a new message_reader for the next FIX message in the buffer.
const_iterator end() const
An iterator to the CheckSum field in the FIX message. Same as hffix::message_reader::check_sum().
message_reader(char const *buffer, size_t size)
Construct by buffer size.
const_iterator message_type() const
An iterator to the MsgType field in the FIX message. Same as hffix::message_reader::begin().
message_reader(const char(&buffer)[N])
Construct on an array reference to a buffer.
char const * prefix_end() const
Returns the FIX version prefix BeginString field value end pointer.
bool is_valid() const
True if the message is valid.
message_reader(char const *begin, char const *end)
Construct by buffer begin and end.
char const * prefix_begin() const
Returns the FIX version prefix BeginString field value begin pointer. (Example: "FIX....
bool is_complete() const
True if the buffer contains a complete FIX message.
char const * buffer_begin() const
A pointer to the begining of the buffer.
message_reader(message_writer const &that)
Construct a message_reader from a message_writer. Equivalent to.
unsigned char calculate_check_sum()
Calulate the checksum for this message.
const_iterator begin() const
An iterator to the MsgType field in the FIX message. Same as hffix::message_reader::message_type().
const_iterator check_sum() const
An iterator to the CheckSum field in the FIX message. Same as hffix::message_reader::end().
One FIX message for writing.
void push_back_date(int tag, boost::gregorian::date date)
Append a LocalMktDate or UTCDate field to the message.
void push_back_timeonly(int tag, int hour, int minute, int second)
Append a UTCTimeOnly field to the message.
void push_back_timestamp(int tag, int year, int month, int day, int hour, int minute, int second)
Append a UTCTimestamp field to the message.
void push_back_timeonly(int tag, boost::posix_time::time_duration timeonly)
Append a UTCTimeOnly field to the message with millisecond precision.
void push_back_data(int tag_data_length, int tag_data, char const *begin, char const *end)
Append a data length field and a data field to the message.
void push_back_timeonly_nano(int tag, std::chrono::duration< Rep, Period > timeonly)
Append a UTCTimeOnly field to the message with nanosecond precision.
void push_back_header(char const *begin_string_version)
Write the BeginString and BodyLength fields to the buffer.
size_t buffer_size() const
Total available buffer size, including buffer already written to by this message.
size_t buffer_size_remaining() const
Remaining available buffer size. Excludes buffer already written to by this message.
void push_back_string(int tag, std::string const &s)
Append a string field to the message.
void push_back_header(std::string_view begin_string_version)
Write the BeginString and BodyLength fields to the buffer.
void push_back_trailer(bool calculate_checksum=true)
Write the CheckSum field to the buffer.
void push_back_timestamp_nano(int tag, boost::posix_time::ptime timestamp)
Append a UTCTimestamp field to the message with nanosecond precision.
void push_back_timeonly(int tag, std::chrono::duration< Rep, Period > timeonly)
Append a UTCTimeOnly field to the message with millisecond precision.
void push_back_timestamp_nano(int tag, int year, int month, int day, int hour, int minute, int second, int nanosecond)
Append a UTCTimestamp field to the message with nanosecond precision.
void push_back_timeonly_nano(int tag, int hour, int minute, int second, int nanosecond)
Append a UTCTimeOnly field to the message with up to nanosecond precision.
void push_back_timestamp_nano(int tag, std::chrono::time_point< Clock, Duration > tp)
Append a std::chrono::time_point field to the message with nanosecond precision.
void push_back_timeonly_nano(int tag, boost::posix_time::time_duration timeonly)
Append a UTCTimeOnly field to the message with nanosecond precision.
message_writer(char *begin, char *end)
Construct by buffer begin and end.
void push_back_int(int tag, Int_type number)
Append an integer field to the message.
void push_back_monthyear(int tag, int year, int month)
Append a month-year field to the message.
void push_back_timeonly(int tag, int hour, int minute, int second, int millisecond)
Append a UTCTimeOnly field to the message with millisecond precision.
message_writer(char(&buffer)[N])
Construct on an array reference to a buffer.
void push_back_date(int tag, int year, int month, int day)
Append a LocalMktDate or UTCDate field to the message.
void push_back_string(int tag, char const *cstring)
Append a string field to the message.
void push_back_timestamp(int tag, int year, int month, int day, int hour, int minute, int second, int millisecond)
Append a UTCTimestamp field to the message with millisecond precision.
~message_writer()
Owns no resources, so destruction is no-op.
char * message_end() const
Pointer to past-the-end of the message.
void push_back_string(int tag, std::string_view s)
Append a string field to the message.
void push_back_string(int tag, char const *begin, char const *end)
Append a string field to the message.
void push_back_decimal(int tag, Int_type mantissa, Int_type exponent)
Append a decimal float field to the message.
char * message_begin() const
Pointer to beginning of the message.
size_t message_size() const
Size of the message in bytes.
void push_back_char(int tag, char character)
Append a char field to the message.
void push_back_timestamp(int tag, std::chrono::time_point< Clock, Duration > tp)
Append a std::chrono::time_point field to the message with millisecond precision.
void push_back_timestamp(int tag, boost::posix_time::ptime timestamp)
Append a UTCTimestamp field to the message with millisecond precision.
message_writer(char *buffer, size_t size)
Construct by buffer size.
The hffix_fields.hpp file is generated by the fixspec/spec-parse-fields Haskell program from the FIX ...
int length_fields[]
Sorted list of all field tags which are of type Length.
Namespace for all types and functions of High Frequency FIX Parser.
details::field_name_streamer< AssociativeContainer > field_name(int tag, AssociativeContainer const &field_dictionary, bool or_number=true)
Given a field tag number and a field name dictionary, returns a type which provides operator<< to wri...
bool find_with_hint(ForwardIterator begin, ForwardIterator end, UnaryPredicate predicate, ForwardIterator &i)
An algorithm similar to std::find_if for forward-searching over a range and finding items which match...
A predicate constructed with a FIX tag which returns true if the tag of the hffix::field passed to th...