From 7149260a13def22c236f11a6ecfd09ff6cd22ef7 Mon Sep 17 00:00:00 2001
From: "Sven M. Hallberg" <pesco@khjk.org>
Date: Fri, 25 Jan 2013 21:52:11 +0100
Subject: [PATCH] make h_cast a family of macros, add H_ASSERT family, make
 h_assert_type a macro

---
 examples/dns.c  | 32 ++++++++++++++++----------------
 examples/glue.c | 30 ------------------------------
 examples/glue.h | 35 +++++++++++++++++++++--------------
 examples/rr.c   |  6 +++---
 4 files changed, 40 insertions(+), 63 deletions(-)

diff --git a/examples/dns.c b/examples/dns.c
index c404f6c5..6c572a00 100644
--- a/examples/dns.c
+++ b/examples/dns.c
@@ -52,7 +52,7 @@ bool validate_message(HParseResult *p) {
 void set_rdata(struct dns_rr rr, HCountedArray *rdata) {
   uint8_t *data = h_arena_malloc(rdata->arena, sizeof(uint8_t)*rdata->used);
   for (size_t i=0; i<rdata->used; ++i)
-    data[i] = h_cast_uint(rdata->elements[i]);
+    data[i] = H_CAST_UINT(rdata->elements[i]);
 
   // Parse RDATA if possible.
   const HParseResult *p = NULL;
@@ -66,7 +66,7 @@ void set_rdata(struct dns_rr rr, HCountedArray *rdata) {
 
   // Pack the parsed rdata into rr.
   switch(rr.type) {
-  case 1:  rr.a     = h_cast_uint(p->ast);             break;
+  case 1:  rr.a     = H_CAST_UINT(p->ast);             break;
   case 2:  rr.ns    = *H_CAST(dns_domain_t,   p->ast); break;
   case 3:  rr.md    = *H_CAST(dns_domain_t,   p->ast); break;
   case 4:  rr.md    = *H_CAST(dns_domain_t,   p->ast); break;
@@ -89,18 +89,18 @@ void set_rdata(struct dns_rr rr, HCountedArray *rdata) {
 const HParsedToken* act_header(const HParseResult *p) {
   HParsedToken **fields = h_seq_elements(p->ast);
   dns_header_t header_ = {
-    .id     = h_cast_uint(fields[0]),
-    .qr     = h_cast_uint(fields[1]),
-    .opcode = h_cast_uint(fields[2]),
-    .aa     = h_cast_uint(fields[3]),
-    .tc     = h_cast_uint(fields[4]),
-    .rd     = h_cast_uint(fields[5]),
-    .ra     = h_cast_uint(fields[6]),
-    .rcode  = h_cast_uint(fields[7]),
-    .question_count   = h_cast_uint(fields[8]),
-    .answer_count     = h_cast_uint(fields[9]),
-    .authority_count  = h_cast_uint(fields[10]),
-    .additional_count = h_cast_uint(fields[11])
+    .id     = H_CAST_UINT(fields[0]),
+    .qr     = H_CAST_UINT(fields[1]),
+    .opcode = H_CAST_UINT(fields[2]),
+    .aa     = H_CAST_UINT(fields[3]),
+    .tc     = H_CAST_UINT(fields[4]),
+    .rd     = H_CAST_UINT(fields[5]),
+    .ra     = H_CAST_UINT(fields[6]),
+    .rcode  = H_CAST_UINT(fields[7]),
+    .question_count   = H_CAST_UINT(fields[8]),
+    .answer_count     = H_CAST_UINT(fields[9]),
+    .authority_count  = H_CAST_UINT(fields[10]),
+    .additional_count = H_CAST_UINT(fields[11])
   };
 
   dns_header_t *header = H_ALLOC(dns_header_t);
@@ -147,8 +147,8 @@ const HParsedToken* act_question(const HParseResult *p) {
     q->qname.labels[i] = *H_INDEX(dns_label_t, fields[0], i);
   }
 
-  q->qtype  = h_cast_uint(fields[1]);
-  q->qclass = h_cast_uint(fields[2]);
+  q->qtype  = H_CAST_UINT(fields[1]);
+  q->qclass = H_CAST_UINT(fields[2]);
 
   return H_MAKE(dns_question_t, q);
 }
diff --git a/examples/glue.c b/examples/glue.c
index 3a8f6cb6..7f9c6fa4 100644
--- a/examples/glue.c
+++ b/examples/glue.c
@@ -77,36 +77,6 @@ HParsedToken *h_make_uint(HArena *arena, uint64_t val)
   return ret;
 }
 
-void * h_cast(HTokenType type, const HParsedToken *p)
-{
-  assert(p->token_type == type);
-  return p->user;
-}
-
-HCountedArray *h_cast_seq(const HParsedToken *p)
-{
-  assert(p->token_type == TT_SEQUENCE);
-  return p->seq;
-}
-
-HBytes h_cast_bytes(const HParsedToken *p)
-{
-  assert(p->token_type == TT_BYTES);
-  return p->bytes;
-}
-
-int64_t h_cast_sint(const HParsedToken *p)
-{
-  assert(p->token_type == TT_SINT);
-  return p->sint;
-}
-
-uint64_t h_cast_uint(const HParsedToken *p)
-{
-  assert(p->token_type == TT_UINT);
-  return p->uint;
-}
-
 // XXX -> internal
 HParsedToken *h_carray_index(const HCountedArray *a, size_t i)
 {
diff --git a/examples/glue.h b/examples/glue.h
index 1dc2fbd8..addcf18d 100644
--- a/examples/glue.h
+++ b/examples/glue.h
@@ -61,16 +61,24 @@ HParsedToken *h_make_uint(HArena *arena, uint64_t val);
 #define H_MAKE_SINT(VAL)  h_make_sint(p->arena, VAL)
 #define H_MAKE_UINT(VAL)  h_make_uint(p->arena, VAL)
 
-// Extract type-specific value back from HParsedTokens...
+// Extract (cast) type-specific value back from HParsedTokens...
 
-void *         h_cast      (HTokenType type, const HParsedToken *p);
-HCountedArray *h_cast_seq  (const HParsedToken *p);
-HBytes         h_cast_bytes(const HParsedToken *p);
-int64_t        h_cast_sint (const HParsedToken *p);
-uint64_t       h_cast_uint (const HParsedToken *p);
+// Pass-through assertion that a given token has the expected type.
+#define h_assert_type(T,P)  (assert(P->token_type == (HTokenType)T), P)
 
-// Standard short-hand to cast to a user type.
-#define H_CAST(TYP, TOK)  ((TYP *) h_cast(TT_ ## TYP, TOK))
+// Convenience short-hand forms of h_assert_type.
+#define H_ASSERT(TYP, TOK)   h_assert_type(TT_ ## TYP, TOK)
+#define H_ASSERT_SEQ(TOK)    h_assert_type(TT_SEQUENCE, TOK)
+#define H_ASSERT_BYTES(TOK)  h_assert_type(TT_BYTES, TOK)
+#define H_ASSERT_SINT(TOK)   h_assert_type(TT_SINT, TOK)
+#define H_ASSERT_UINT(TOK)   h_assert_type(TT_UINT, TOK)
+
+// Assert expected type and return contained value.
+#define H_CAST(TYP, TOK)   ((TYP *) H_ASSERT(TYP, TOK)->user)
+#define H_CAST_SEQ(TOK)    (H_ASSERT_SEQ(TOK)->seq)
+#define H_CAST_BYTES(TOK)  (H_ASSERT_BYTES(TOK)->bytes)
+#define H_CAST_SINT(TOK)   (H_ASSERT_SINT(TOK)->sint)
+#define H_CAST_UINT(TOK)   (H_ASSERT_UINT(TOK)->uint)
 
 // Sequence access...
 
@@ -88,12 +96,11 @@ HParsedToken *h_seq_index_path(const HParsedToken *p, size_t i, ...);
 HParsedToken *h_seq_index_vpath(const HParsedToken *p, size_t i, va_list va);
 
 // Convenience macros combining (nested) index access and h_cast.
-#define H_INDEX(TYP, SEQ, ...) \
-  ((TYP *) h_cast(TT_ ## TYP, H_INDEX_TOKEN(SEQ, __VA_ARGS__)))
-#define H_INDEX_SEQ(SEQ, ...)    h_cast_seq(H_INDEX_TOKEN(SEQ, __VA_ARGS__))
-#define H_INDEX_BYTES(SEQ, ...)  h_cast_bytes(H_INDEX_TOKEN(SEQ, __VA_ARGS__))
-#define H_INDEX_SINT(SEQ, ...)   h_cast_sint(H_INDEX_TOKEN(SEQ, __VA_ARGS__))
-#define H_INDEX_UINT(SEQ, ...)   h_cast_uint(H_INDEX_TOKEN(SEQ, __VA_ARGS__))
+#define H_INDEX(TYP, SEQ, ...)   H_CAST(TYP, H_INDEX_TOKEN(SEQ, __VA_ARGS__))
+#define H_INDEX_SEQ(SEQ, ...)    H_CAST_SEQ(H_INDEX_TOKEN(SEQ, __VA_ARGS__))
+#define H_INDEX_BYTES(SEQ, ...)  H_CAST_BYTES(H_INDEX_TOKEN(SEQ, __VA_ARGS__))
+#define H_INDEX_SINT(SEQ, ...)   H_CAST_SINT(H_INDEX_TOKEN(SEQ, __VA_ARGS__))
+#define H_INDEX_UINT(SEQ, ...)   H_CAST_UINT(H_INDEX_TOKEN(SEQ, __VA_ARGS__))
 #define H_INDEX_TOKEN(SEQ, ...)  h_seq_index_path(SEQ, __VA_ARGS__, -1)
 
 // Standard short-hand to access and cast elements on a sequence token.
diff --git a/examples/rr.c b/examples/rr.c
index 1e74370c..8c14e0ae 100644
--- a/examples/rr.c
+++ b/examples/rr.c
@@ -31,7 +31,7 @@ const HParsedToken *act_null(const HParseResult *p) {
 const HParsedToken *act_txt(const HParseResult *p) {
   dns_rr_txt_t *txt = H_ALLOC(dns_rr_txt_t);
 
-  const HCountedArray *arr = h_cast_seq(p->ast);
+  const HCountedArray *arr = H_CAST_SEQ(p->ast);
   uint8_t **ret = h_arena_malloc(arr->arena, sizeof(uint8_t*)*arr->used);
   for (size_t i=0; i<arr->used; ++i) {
     size_t len = h_seq_len(arr->elements[i]);
@@ -50,10 +50,10 @@ const HParsedToken *act_txt(const HParseResult *p) {
 const HParsedToken* act_cstr(const HParseResult *p) {
   dns_cstr_t *cs = H_ALLOC(dns_cstr_t);
 
-  const HCountedArray *arr = h_cast_seq(p->ast);
+  const HCountedArray *arr = H_CAST_SEQ(p->ast);
   uint8_t *ret = h_arena_malloc(arr->arena, sizeof(uint8_t)*arr->used);
   for (size_t i=0; i<arr->used; ++i)
-    ret[i] = h_cast_uint(arr->elements[i]);
+    ret[i] = H_CAST_UINT(arr->elements[i]);
   assert(ret[arr->used-1] == '\0'); // XXX Is this right?! If so, shouldn't it be a validation?
   *cs = ret;
 
-- 
GitLab