From 2408106191956f20360c3663e4ba0d11ee6cb0d8 Mon Sep 17 00:00:00 2001 From: "Meredith L. Patterson" <mlp@thesmartpolitenerd.com> Date: Fri, 9 Aug 2013 18:45:26 +0200 Subject: [PATCH] C++ bindings getting underway. --- src/hammer.cxx | 152 +++++++++++++++ src/hammer.h | 10 + src/hammer.hxx | 493 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 655 insertions(+) create mode 100644 src/hammer.cxx create mode 100644 src/hammer.hxx diff --git a/src/hammer.cxx b/src/hammer.cxx new file mode 100644 index 00000000..dc2b1045 --- /dev/null +++ b/src/hammer.cxx @@ -0,0 +1,152 @@ +#include "hammer.hxx" + +namespace hammer { + + typedef variant<BytesResult, UintResult, IntResult, NullResult, SequenceResult> AnyResult; + + const BytesResult::result_type BytesResult::result() { return _bytes; } + const UintResult::result_type UintResult::result() { return _uint; } + const IntResult::result_type IntResult::result() { return _sint; } + const SequenceResult::result_type SequenceResult::result() { return _seq; } + + template<> + BytesResult Parser<BytesResult>::parse(const string &input) { + HParseResult *res = h_parse(_parser, reinterpret_cast<const uint8_t*>(input.c_str()), input.size()); + return BytesResult(vector<uint8_t>(res->ast->bytes.token, res->ast->bytes.token+res->ast->bytes.len)); + } + + template<> + BytesResult Parser<BytesResult>::parse(const uint8_t *input, size_t length) { + HParseResult *res = h_parse(_parser, input, length); + return BytesResult(vector<uint8_t>(res->ast->bytes.token, res->ast->bytes.token+res->ast->bytes.len)); + } + + template<> + UintResult Parser<UintResult>::parse(const string &input) { + HParseResult *res = h_parse(_parser, reinterpret_cast<const uint8_t*>(input.c_str()), input.size()); + return UintResult(res->ast->uint); + } + + template<> + UintResult Parser<UintResult>::parse(const uint8_t *input, size_t length) { + HParseResult *res = h_parse(_parser, input, length); + return UintResult(res->ast->uint); + } + + template<> + IntResult Parser<IntResult>::parse(const string &input) { + HParseResult *res = h_parse(_parser, reinterpret_cast<const uint8_t*>(input.c_str()), input.size()); + return IntResult(res->ast->sint); + } + + template<> + IntResult Parser<IntResult>::parse(const uint8_t *input, size_t length) { + HParseResult *res = h_parse(_parser, input, length); + return IntResult(res->ast->sint); + } + + template<> + NullResult Parser<NullResult>::parse(const string &input) { + HParseResult *res = h_parse(_parser, reinterpret_cast<const uint8_t*>(input.c_str()), input.size()); + return NullResult(); + } + + template<> + NullResult Parser<NullResult>::parse(const uint8_t *input, size_t length) { + HParseResult *res = h_parse(_parser, input, length); + return NullResult(); + } + + vector<AnyResult> make_seq(HCountedArray *seq) { + vector<AnyResult> ret; + for (size_t i=0; i<seq->used; ++i) { + switch(seq->elements[i]->token_type) { + case TT_NONE: + ret.push_back(NullResult()); + break; + case TT_BYTES: + ret.push_back(BytesResult(vector<uint8_t>(seq->elements[i]->bytes.token, seq->elements[i]->bytes.token+seq->elements[i]->bytes.len))); + break; + case TT_SINT: + ret.push_back(IntResult(seq->elements[i]->sint)); + break; + case TT_UINT: + ret.push_back(UintResult(seq->elements[i]->uint)); + break; + case TT_SEQUENCE: + ret.push_back(make_seq(seq->elements[i]->seq)); + break; + default: + //TODO some kind of error + break; + } + } + return ret; + } + + template<> + SequenceResult Parser<SequenceResult>::parse(const string &input) { + HParseResult *res = h_parse(_parser, reinterpret_cast<const uint8_t*>(input.c_str()), input.size()); + return SequenceResult(make_seq(res->ast->seq)); + } + + template<> + SequenceResult Parser<SequenceResult>::parse(const uint8_t *input, size_t length) { + HParseResult *res = h_parse(_parser, input, length); + return SequenceResult(make_seq(res->ast->seq)); + } + + template<class T> + Many<T> Parser<T>::many() { + return Many<T>(this); + } + + template<class T> + RepeatN<T> Parser<T>::many(size_t n) { + return RepeatN<T>(this, n); + } + + template<class T> + Optional<T> Parser<T>::optional() { + return Optional<T>(this); + } + + template<class T> + RepeatN<T> Parser<T>::operator[](size_t n) { + return RepeatN<T>(this, n); + } + + /* + Int64 Int64::in_range(const int64_t lower, const int64_t upper) { + return IntRange(Int64(), lower, upper); + } + + Int32 Int32::in_range(const int32_t lower, const int32_t upper) { + return IntRange(Int32(), lower, upper); + } + + Int16 Int16::in_range(const int16_t lower, const int16_t upper) { + return IntRange(Int16(), lower, upper); + } + + Int8 Int8::in_range(const int8_t lower, const int8_t upper) { + return IntRange(Int8(), lower, upper); + } + + Uint64 Uint64::in_range(const uint64_t lower, const uint64_t upper) { + return IntRange(Uint64(), lower, upper); + } + + Uint32 Uint32::in_range(const uint32_t lower, const uint32_t upper) { + return IntRange(Uint32(), lower, upper); + } + + Uint16 Uint16::in_range(const uint16_t lower, const uint16_t upper) { + return IntRange(Uint16(), lower, upper); + } + + Uint8 Uint8::in_range(const uint8_t lower, const uint8_t upper) { + return IntRange(Uint8(), lower, upper); + } + */ +} diff --git a/src/hammer.h b/src/hammer.h index 67fb8e4b..89a9570f 100644 --- a/src/hammer.h +++ b/src/hammer.h @@ -27,7 +27,13 @@ #define BIT_LITTLE_ENDIAN 0x0 #define BYTE_LITTLE_ENDIAN 0x0 +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef __cplusplus typedef int bool; +#endif typedef struct HParseState_ HParseState; @@ -617,4 +623,8 @@ void h_benchmark_report(FILE* stream, HBenchmarkResults* results); void h_benchmark_dump_optimized_code(FILE* stream, HBenchmarkResults* results); // }}} +#ifdef __cplusplus +} +#endif + #endif // #ifndef HAMMER_HAMMER__H diff --git a/src/hammer.hxx b/src/hammer.hxx new file mode 100644 index 00000000..0baee866 --- /dev/null +++ b/src/hammer.hxx @@ -0,0 +1,493 @@ +#ifndef HAMMER_HAMMER__HXX +#define HAMMER_HAMMER__HXX + +#include "hammer.h" +#include <list> +#include <string> +#include <vector> +#include <boost/variant.hpp> + +using std::list; using std::string; using std::vector; +using boost::variant; + +namespace hammer { + + template<typename T> + class ParseResult { + public: + typedef T result_type; + protected: + ParseResult() { } + }; + + class BytesResult : public ParseResult<vector<uint8_t> > { + public: + typedef vector<uint8_t> result_type; + BytesResult(const vector<uint8_t> res) : _bytes(res) { } + const result_type result(); + private: + BytesResult() { } + result_type _bytes; + }; + + class UintResult : public ParseResult<uint64_t> { + public: + typedef uint64_t result_type; + UintResult(const uint64_t res) : _uint(res) { } + const result_type result(); + private: + UintResult() { } + result_type _uint; + }; + + class IntResult : public ParseResult<int64_t> { + public: + typedef int64_t result_type; + IntResult(const int64_t res) : _sint(res) { } + const result_type result(); + private: + IntResult() { } + result_type _sint; + }; + + class NullResult: public ParseResult<void*> { + public: + NullResult() { } + typedef void* result_type; + const result_type result() { return NULL; } + }; + + class SequenceResult : public ParseResult<vector<variant<BytesResult, UintResult, IntResult, NullResult, SequenceResult> > > { + public: + typedef vector<variant<BytesResult, UintResult, IntResult, NullResult, SequenceResult> > result_type; + SequenceResult(result_type res) : _seq(res) { } + const result_type result(); + private: + SequenceResult() { } + result_type _seq; + }; + + /* forward declarations */ + template<class T> class Many; + template<class T> class Many1; + template<class T> class Optional; + template<class T> class RepeatN; + + template<typename T> + class Parser { + public: + typedef T result_type; + result_type parse(const string &input); + result_type parse(const uint8_t *input, size_t length); + Many<T> many(); + RepeatN<T> many(size_t n); + Optional<T> optional(); + RepeatN<T> operator[](size_t n); + HParser* parser() { return _parser; } + HParser* _parser; + Parser() { } + }; + + class Token : public Parser<BytesResult> { + public: + Token(string &str) : _tok(str) { + _parser = h_token(reinterpret_cast<const uint8_t*>(str.c_str()), str.size()); + } + Token(const uint8_t *str, size_t length) : _tok(reinterpret_cast<const char*>(str), length) { + _parser = h_token(str, length); + } + private: + string _tok; + }; + + class Ch : public Parser<UintResult> { + public: + Ch(const uint8_t c) : _c(c) { + _parser = h_ch(c); + } + private: + uint8_t _c; + }; + + class ChRange : public Parser<UintResult> { + public: + ChRange(const uint8_t lower, const uint8_t upper) : _lower(lower), _upper(upper) { + _parser = h_ch_range(lower, upper); + } + private: + uint8_t _lower, _upper; + }; + + class IntRange : public Parser<IntResult> { + public: + IntRange(Parser &p, const int64_t lower, const int64_t upper) : _p(p), _lower(lower), _upper(upper) { + _parser = h_int_range(p.parser(), lower, upper); + } + private: + Parser _p; + int64_t _lower, _upper; + }; + + class SignedBits : public Parser<IntResult> { + public: + SignedBits(size_t len) : _len(len) { + _parser = h_bits(len, true); + } + private: + size_t _len; + }; + + class UnsignedBits : public Parser<UintResult> { + public: + UnsignedBits(size_t len) : _len(len) { + _parser = h_bits(len, false); + } + private: + size_t _len; + }; + + class Int64 : public Parser<IntResult> { + public: + Int64() { + _parser = h_int64(); + } + Int64 in_range(const int64_t lower, const int64_t upper); + }; + + class Int32 : public Parser<IntResult> { + public: + Int32() { + _parser = h_int32(); + } + Int32 in_range(const int32_t lower, const int32_t upper); + }; + + class Int16 : public Parser<IntResult> { + public: + Int16() { + _parser = h_int16(); + } + Int16 in_range(const int16_t lower, const int16_t upper); + }; + + class Int8 : public Parser<IntResult> { + public: + Int8() { + _parser = h_int8(); + } + Int8 in_range(const int8_t lower, const int8_t upper); + }; + + class Uint64 : public Parser<UintResult> { + public: + Uint64() { + _parser = h_uint64(); + } + Uint64 in_range(const uint64_t lower, const uint64_t upper); + }; + + class Uint32 : public Parser<UintResult> { + public: + Uint32() { + _parser = h_uint32(); + } + Uint32 in_range(const uint32_t lower, const uint32_t upper); + }; + + class Uint16 : public Parser<UintResult> { + public: + Uint16() { + _parser = h_uint16(); + } + Uint16 in_range(const uint16_t lower, const uint16_t upper); + }; + + class Uint8 : public Parser<UintResult> { + public: + Uint8() { + _parser = h_uint8(); + } + Uint8 in_range(const uint8_t lower, const uint8_t upper); + }; + + template<class T> + class Whitespace : public Parser<T> { + public: + typedef typename T::result_type result_type; + Whitespace(Parser<T> &p) : _p(p) { + this->_parser = h_whitespace(p.parser()); + } + private: + Parser<T> _p; + }; + + template<class T, class U> + class Left : public Parser<T> { + public: + typedef typename T::result_type result_type; + Left(Parser<T> &p, Parser<U> &q) : _p(p), _q(q) { + this->_parser = h_left(p.parser(), q.parser()); + } + private: + Parser<T> _p; + Parser<U> _q; + }; + + template<class T, class U> + class Right : public Parser<U> { + public: + typedef typename U::result_type result_type; + Right(Parser<T> &p, Parser<U> &q) : _p(p), _q(q) { + this->_parser = h_right(p.parser(), q.parser()); + } + private: + Parser<T> _p; + Parser<U> _q; + }; + + template <class T, class U, class V> + class Middle : public Parser<U> { + public: + typedef typename U::result_type result_type; + Middle(Parser<T> &p, Parser<U> &x, Parser<V> &q) : _p(p), _x(x), _q(q) { + this->_parser = h_middle(p.parser(), x.parser(), q.parser()); + } + private: + Parser<T> _p; + Parser<U> _x; + Parser<V> _q; + }; + + /* what are we doing about h_action? */ + + class In : public Parser<UintResult> { + public: + In(string &charset) : _charset(charset) { + _parser = h_in(reinterpret_cast<const uint8_t*>(charset.c_str()), charset.size()); + } + In(const uint8_t *charset, size_t length) : _charset(reinterpret_cast<const char*>(charset), length) { + _parser = h_in(charset, length); + } + private: + string _charset; + }; + + class NotIn : public Parser<UintResult> { + public: + NotIn(string &charset) : _charset(charset) { + _parser = h_not_in(reinterpret_cast<const uint8_t*>(charset.c_str()), charset.size()); + } + NotIn(const uint8_t *charset, size_t length) : _charset(reinterpret_cast<const char*>(charset), length) { + _parser = h_not_in(charset, length); + } + private: + string _charset; + }; + + class End : public Parser<NullResult> { + public: + End() { + _parser = h_end_p(); + } + }; + + class Nothing : public Parser<NullResult> { + public: + Nothing() { + _parser = h_nothing_p(); + } + }; + + class Sequence : public Parser<SequenceResult> { + public: + Sequence(list<Parser> &ps) : _ps(ps) { + void *parsers[ps.size()]; + size_t i = 0; + for (list<Parser>::iterator it=ps.begin(); it != ps.end(); ++it, ++i) { + parsers[i] = it->parser(); + } + _parser = h_sequence__a(parsers); + } + // maybe also a begin and end iterator version + private: + list<Parser> _ps; + }; + + class Choice : public Parser<SequenceResult> { + public: + Choice(list<Parser<SequenceResult> > &ps) : _ps(ps) { + void *parsers[ps.size()]; + size_t i = 0; + for (list<Parser<SequenceResult> >::iterator it=ps.begin(); it != ps.end(); ++it, ++i) { + parsers[i] = it->parser(); + } + _parser = h_choice__a(parsers); + } + private: + list<Parser<SequenceResult> > _ps; + }; + + template<class T, class U> + class ButNot : public Parser<T> { + public: + typedef typename T::result_type result_type; + ButNot(Parser<T> &p, Parser<U> &q) : _p(p), _q(q) { + this->_parser = h_butnot(p.parser(), q.parser()); + } + private: + Parser<T> _p; + Parser<U> _q; + }; + + template<class T, class U> + class Difference : public Parser<T> { + public: + typedef typename T::result_type result_type; + Difference(Parser<T> &p, Parser<U> &q) : _p(p), _q(q) { + this->_parser = h_difference(p.parser(), q.parser()); + } + private: + Parser<T> _p; + Parser<U> _q; + }; + + template<class T, class U> + class Xor : public Parser<variant<T, U> > { + public: + typedef variant<T, U> result_type; + Xor(Parser<T> &p, Parser<U> &q) : _p(p), _q(q) { + this->_parser = h_xor(p.parser(), q.parser()); + } + private: + Parser<T> _p; + Parser<U> _q; + }; + + template<class T> + class Many : public Parser<SequenceResult> { + public: + Many(Parser<T> &p) : _p(p) { + _parser = h_many(p.parser()); + } + private: + Parser<T> _p; + }; + + template<class T> + class Many1 : public Parser<SequenceResult> { + public: + Many1(Parser<T> &p) : _p(p) { + _parser = h_many1(p.parser()); + } + private: + Parser<T> _p; + }; + + template<class T> + class RepeatN: public Parser<SequenceResult> { + public: + RepeatN(Parser<T> &p, const size_t n) : _p(p), _n(n) { + _parser = h_repeat_n(p.parser(), n); + } + private: + Parser<T> _p; + size_t _n; + }; + + template<class T> + class Optional : public Parser<T> { + public: + typedef typename T::result_type result_type; + Optional(Parser<T> &p) : _p(p) { + this->_parser = h_optional(p.parser()); + } + private: + Parser<T> _p; + }; + + template<class T> + class Ignore : public Parser<NullResult> { + public: + Ignore(Parser<T> &p) : _p(p) { + _parser = h_ignore(p.parser()); + } + private: + Parser<T> _p; + }; + + template<class T, class U> + class SepBy : public Parser<SequenceResult> { + public: + SepBy(Parser<T> &p, Parser<U> &sep) : _p(p), _sep(sep) { + _parser = h_sepBy(p.parser(), sep.parser()); + } + private: + Parser<T> _p; + Parser<U> _sep; + }; + + template<class T, class U> + class SepBy1 : public Parser<SequenceResult> { + public: + SepBy1(Parser<T> &p, Parser<U> &sep) : _p(p), _sep(sep) { + _parser = h_sepBy1(p.parser(), sep.parser()); + } + private: + Parser<T> _p; + Parser<U> _sep; + }; + + class Epsilon : public Parser<NullResult> { + public: + Epsilon() { + _parser = h_epsilon_p(); + } + }; + + template<class T> + class LengthValue : public Parser<SequenceResult> { + public: + LengthValue(Parser<UintResult> &length, Parser<T> &value) : _length(length), _value(value) { + _parser = h_length_value(length.parser(), value.parser()); + } + private: + Parser<UintResult> _length; + Parser<T> _value; + }; + + /* FIXME attr_bool */ + + template<class T> + class And : public Parser<NullResult> { + public: + And(Parser<T> &p) : _p(p) { + _parser = h_and(p.parser()); + } + private: + Parser<T> _p; + }; + + template<class T> + class Not : public Parser<NullResult> { + public: + Not(Parser &p) : _p(p) { + _parser = h_not(p.parser()); + } + private: + Parser<T> _p; + }; + + template<class T> + class Indirect : public Parser<T> { + public: + Indirect(Parser<T> &p) : _p(p) { + this->_parser = h_indirect(); + h_bind_indirect(this->_parser, p.parser()); + } + private: + Parser<T> _p; + }; + +} + +#endif -- GitLab