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