Skip to content

Instantly share code, notes, and snippets.

@scraimer
Last active December 13, 2016 19:04
Show Gist options
  • Save scraimer/35dfd89208d6c7778548c48730d6c495 to your computer and use it in GitHub Desktop.
Save scraimer/35dfd89208d6c7778548c48730d6c495 to your computer and use it in GitHub Desktop.
#include <stdint.h>
/*
Problem Space:
--------------
FIXT1.1 is a protocol where FIX data is sent in fields separated by a 0x01.
In each field, the format is "tag=value", where "tag" is a number
from 1 upwards.
Goal:
-----
Create a FIXT1.1 "parser" that reads a FIX string,
and provides pointers to the value at each tag.
In this case, we'll assume the flat case: each tag only appears once.
(I'm calling it flat because there's no "depth" due to nesting)
Later one, we'll handle the none-flat case, where tags can be part of
"repeating groups", and therefore may repeat more than once.
Reading through that might require using an interator instead
of allowing random access.
Ideas:
- Create depth by extending the flat parser to be able to
have pointers into other flat parsers. And we can do this
by using the pointer to either point at char* or at
another flat or another complex_parser.
- Allow random access: using the NoEntries as the key for the group.
For example, if we do get<268>(), it'll return the
the subgroup as another parser, etc:
// Get the first MDEntryType (tag 269) as integer:
int MDEntryType_first = parser.get<268>().get<269,int>();
// Get the second MDEntryType (tag 269) as integer:
int MDEntryType second = parser.get<268>().get<parser::next>().get<269,int>();
fix_simple_parser<277,278> parser;
char* f277 = parser.get<277>(); // Good
char* f279 = parser.get<279>(); // Compile time error, since 279 wasn't in the list
*/
#define NULL ((void*)0)
/**
The flat parser assumes only a single instance of each FIx field, and
assumes that only the FIX fields with the tags specified in F1..FN are
to be made readable. Other FIX fields are to be ignored.
Usage:
fix_flat_parser parser;
...
parser.parse(fix_string);
int int_value = parser.get<34,int>()
char const * str_value = parser.get<49>();
*/
template <int F1 = 0, int F2 = 0, int F3 = 0, int F4 = 0, int F5 = 0,
int F6 = 0, int F7 = 0, int F8 = 0, int F9 = 0>
class fix_flat_parser
{
// This is just a base class that allows us to cast thingy<K> inside get_thingy<K>(),
// so that we don't a compilation error trying to return differing types.
struct thingy_base { };
// 'thingy' is a pointer to a position on the FIX string where the value of FIX tag 'K' is.
// TODO: expand it so that thingy can hold sub-groups (repeating groups) of tags
template <int K>
struct thingy : thingy_base
{
char const * _ptr;
thingy() : _ptr( static_cast<char const *>(NULL) )
{
}
char const * val() const
{
return _ptr;
}
};
thingy<F1> _t1;
thingy<F2> _t2;
thingy<F3> _t3;
thingy<F4> _t4;
thingy<F5> _t5;
thingy<F6> _t6;
thingy<F7> _t7;
thingy<F8> _t8;
thingy<F9> _t9;
public:
fix_flat_parser(char const * const fix_string)
{
}
template <int K>
thingy<K> const & get_thingy() const
{
static_assert( K == F1 || K == F2 || K == F3 || K == F4 ||
K == F5 || K == F6 || K == F7 || K == F8 || K == F9,
"Value of K must be one of the FIX tags specified"
" in the template instantiation");
thingy_base const * return_value_unforced = static_cast<thingy_base const *>(NULL);
switch( K )
{
case F1: return_value_unforced = &_t1; break;
case F2: return_value_unforced = &_t2; break;
case F3: return_value_unforced = &_t3; break;
case F4: return_value_unforced = &_t4; break;
case F5: return_value_unforced = &_t5; break;
case F6: return_value_unforced = &_t6; break;
case F7: return_value_unforced = &_t7; break;
case F8: return_value_unforced = &_t8; break;
case F9: return_value_unforced = &_t9; break;
}
return *(static_cast< thingy<K> const * >( return_value_unforced ));
}
// XXX This is only here to allow short and easy initialization.
// I need to re-write the parser that tokanized the tag=value pairs.
void set1(char const * s)
{
_t1._ptr = _t2._ptr = _t3._ptr = _t4._ptr = _t5._ptr = _t6._ptr = _t7._ptr = _t8._ptr = _t9._ptr = s;
}
};
extern char data[100];
int main()
{
fix_flat_parser<277,279,330,4,5,6,7,8,9> p( data );
p.set1( data );
char const * s = p.get_thingy<8>().val();
if( s == NULL )
{
return 0;
}
else
{
// TODO: make the parser smaller
// - switch to integers as offsets
return sizeof(p);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment