[Gd-chatter] r11634 - in trunk/libraries/packetizer: . packetizer-test

hannes at gwydiondylan.org hannes at gwydiondylan.org
Fri Jan 18 03:19:33 CET 2008


Author: hannes
Date: Fri Jan 18 03:19:32 2008
New Revision: 11634

Modified:
   trunk/libraries/packetizer/fields.dylan
   trunk/libraries/packetizer/module.dylan
   trunk/libraries/packetizer/packetizer-test/packetizer-test.dylan
   trunk/libraries/packetizer/packetizer.dylan
   trunk/libraries/packetizer/protocol-definer-macro.dylan
Log:
Bug: 7299
implement enum fields


Modified: trunk/libraries/packetizer/fields.dylan
==============================================================================
--- trunk/libraries/packetizer/fields.dylan	(original)
+++ trunk/libraries/packetizer/fields.dylan	Fri Jan 18 03:19:32 2008
@@ -103,6 +103,10 @@
 define class <layering-field> (<single-field>)
 end;
 
+define class <enum-field> (<single-field>)
+  slot mappings, required-init-keyword: mappings:;
+end;
+
 define method static-field-size (field :: <single-field>) => (res :: <integer-or-unknown>)
   if (field.static-length ~= $unknown-at-compile-time)
     field.static-length

Modified: trunk/libraries/packetizer/module.dylan
==============================================================================
--- trunk/libraries/packetizer/module.dylan	(original)
+++ trunk/libraries/packetizer/module.dylan	Fri Jan 18 03:19:32 2008
@@ -139,7 +139,8 @@
   export protocol-definer;
   //XXX: we shouldn't need to export those
   export real-class-definer, decoded-class-definer, gen-classes,
-    frame-field-generator, summary-generator, unparsed-frame-field-generator;
+    frame-field-generator, summary-generator, enum-frame-field-generator,
+    unparsed-frame-field-generator;
 
   export protocol-module-definer;
 end module packetizer;

Modified: trunk/libraries/packetizer/packetizer-test/packetizer-test.dylan
==============================================================================
--- trunk/libraries/packetizer/packetizer-test/packetizer-test.dylan	(original)
+++ trunk/libraries/packetizer/packetizer-test/packetizer-test.dylan	Fri Jan 18 03:19:32 2008
@@ -430,10 +430,11 @@
   check-equal("assembling of dynlength[1] works correct", 2, as.packet[1]);
   let g = make(<dyn-length-in-container>, mylength: 3);
   let as = assemble-frame(g);
+  //for now, I assume that padding does not need to work here this way
+  //somehow, we should be able to add padding-frames to dynamically
+  //length fields -- any takers on a pad api? --  Hannes, 18.1.2008
   check-equal("assembly of dynlength[0] works correct", 0, as.packet[0]);
-  //hah, no padding support!
   check-equal("assembly of dynlength[1] works correct", 3, as.packet[1]);
-  check-equal("assembly of dynlength[2] works correct", 0, as.packet[2]);
 end;
 
 define protocol dyn-length-as-client-field (container-frame)
@@ -459,28 +460,31 @@
 end;
 
 define protocol enum-field-test (container-frame)
-  enum field foo :: <unsigned-byte>,
+  enum field foobar :: <unsigned-byte>,
     mappings: { 1 <=> #"hello",
                 2 <=> #"foobar" };
 end;
 
 define test enum-assemble-test ()
-  let frame = make(<enum-field-test>, foo: #"hello");
+  let frame = make(<enum-field-test>, foobar: #"hello");
+  check-equal("enum field value", #"hello", frame.foobar);
   let assembled-frame = assemble-frame(frame);
   check-equal("enum field value", 1, assembled-frame.packet[0]);
-  assembled-frame.foo := #"foobar";
+  assembled-frame.foobar := #"foobar";
   check-equal("enum field value", 2, assembled-frame.packet[0]);
-  assembled-frame.foo := 23;
+  assembled-frame.foobar := 23;
   check-equal("enum field value", 23, assembled-frame.packet[0]);
 end;
 
 define test enum-parse-test ()
   let f = parse-frame(<enum-field-test>, #[#x01]);
-  check-equal("enum field parses correct to symbol", #"hello", f.foo);
+  check-equal("enum field parses correct to symbol", #"hello", f.foobar);
   let g = parse-frame(<enum-field-test>, #[#x03]);
-  check-equal("enum field parses correct to integer", 3, g.foo);
-  g.foo := #"foobar";
-  g.foo := 23;
+  check-equal("enum field parses correct to integer", 3, g.foobar);
+  g.foobar := 23;
+  check-equal("enum field parses correct to changed integer", 23, g.foobar);
+  g.foobar := #"foobar";
+  check-equal("enum field parses correct to changed symbol", #"foobar", g.foobar);
 end;
 
 define suite packetizer-suite ()
@@ -525,7 +529,7 @@
 end;
 
 begin
-  run-test-application(packetizer-suite, arguments: #("-debug"));
-  run-test-application(packetizer-assemble-suite, arguments: #("-debug"));
+  run-test-application(packetizer-suite); //, arguments: #("-debug"));
+  run-test-application(packetizer-assemble-suite); //, arguments: #("-debug"));
 end;
 

Modified: trunk/libraries/packetizer/packetizer.dylan
==============================================================================
--- trunk/libraries/packetizer/packetizer.dylan	(original)
+++ trunk/libraries/packetizer/packetizer.dylan	Fri Jan 18 03:19:32 2008
@@ -528,6 +528,19 @@
   frame.packet.size * 8;
 end;
 
+define method assemble-field-into(field :: <enum-field>,
+                                  frame :: <container-frame>,
+                                  packet :: <stretchy-vector-subsequence>)
+  let value = field.getter(frame);
+  if (instance?(value, <symbol>))
+    value := enum-field-symbol-to-int(field, value)
+  end;
+  let length = assemble-aux(field.type, value, packet);
+  let ff = make(<frame-field>, field: field, frame: frame, length: length);
+  frame.concrete-frame-fields[field.index] := ff;
+  length;  
+end;
+
 define method assemble-field-into(field :: <single-field>,
                                   frame :: <container-frame>,
                                   packet :: <stretchy-vector-subsequence>)

Modified: trunk/libraries/packetizer/protocol-definer-macro.dylan
==============================================================================
--- trunk/libraries/packetizer/protocol-definer-macro.dylan	(original)
+++ trunk/libraries/packetizer/protocol-definer-macro.dylan	Fri Jan 18 03:19:32 2008
@@ -32,6 +32,25 @@
 
 end;
 
+define inline function filter-enums!(key/value-pairs :: <collection>,
+                                     fields :: <collection>)
+  for (ele in fields)
+    if (instance?(ele, <enum-field>))
+      let (key, pos)
+        = block(ret)
+            for (i :: <integer> from 0 below key/value-pairs.size by 2)
+              if (key/value-pairs[i] == ele.field-name)
+                ret(values(key/value-pairs[i + 1], i + 1))
+              end;
+            end;
+          end;
+            
+      key/value-pairs[pos] := enum-field-symbol-to-int(ele, key);
+    end;
+  end;
+end;
+
+
 define macro real-class-definer
   { real-class-definer(?attrs:*; ?:name; ?superclasses:*; ?fields-aux:*) }
  => { define abstract class ?name (?superclasses)
@@ -95,6 +114,7 @@
         end;
       end;
       define method make (class == ?name, #rest rest, #key, #all-keys) => (res :: ?name)
+        filter-enums!(rest, "$" ## ?name ## "-fields");
         let frame = apply(make, decoded-class(?name), rest);
         for (field in fields(frame))
           if (field.getter(frame) = #f)
@@ -153,6 +173,7 @@
     { } => { <single-field> }
     { layering } => { <layering-field> }
     { repeated } => { <repeated-field> }
+    { enum } => { <enum-field> }
 
   args: //FIXME: better types, not <frame>!
     { } => { }
@@ -176,6 +197,13 @@
       => { static-length: ?length, ... }
     { static-end: ?end:expression, ... }
       => { static-end: ?end, ... }
+    { mappings: { ?mappings }, ... }
+      => { mappings: #( ?mappings ), ... }
+
+  mappings:
+    { } => { }
+    { ?key:expression <=> ?value:expression, ... }
+      => { ?key, ?value, ... }
 end;
 
 
@@ -194,6 +222,9 @@
     { repeated field ?:name ?rest:* }
       => { slot ?name :: false-or(<collection>) = #f,
       init-keyword: ?#"name" }
+    { enum field ?:name \:: ?field-type:name ?rest:* }
+    => { slot "%" ## ?name :: false-or(high-level-type(?field-type)) = #f,
+         init-keyword: ?#"name" }
     { ?attrs:* field ?:name \:: ?field-type:name ?rest:* }
     => { slot ?name :: false-or(high-level-type(?field-type)) = #f,
       init-keyword: ?#"name" }
@@ -246,6 +277,55 @@
  }
 end;
 
+define inline function enum-field-symbol-to-int
+    (field :: <enum-field>, key :: <symbol>) => (res :: <integer>)
+  block(ret)
+    for (i from 1 below field.mappings.size by 2)
+      if (field.mappings[i] == key)
+        ret(field.mappings[i - 1])
+      end;
+    end;
+    error("unknown symbol for enum field");
+  end;
+end;
+
+define macro enum-frame-field-generator
+  { enum-frame-field-generator(?:name,
+                               "<unparsed-" ## ?frame-type:name,
+                               ?field-index:expression) }
+ => { define inline method ?name (mframe :: "<decoded-" ## ?frame-type) => (res)
+        let field = fields(mframe)[?field-index];
+        let val = "%" ## ?name (mframe);
+        block(ret)
+          for (i from 0 below field.mappings.size by 2)
+            if (field.mappings[i] == val)
+              ret(field.mappings[i + 1])
+            end;
+          end;
+          val
+        end;
+      end;
+      define inline method ?name ## "-setter"
+          (value :: <symbol>, mframe :: "<decoded-" ## ?frame-type) => (res)
+        let field = fields(mframe)[?field-index];
+        let val :: <integer> = enum-field-symbol-to-int(field, value);
+        "%" ## ?name ## "-setter"(val , mframe);
+      end;
+      define inline method ?name ## "-setter"
+          (value :: false-or(<integer>),
+           mframe :: "<decoded-" ## ?frame-type) => (res)
+        "%" ## ?name ## "-setter"(value, mframe);
+      end;
+      define inline method ?name ## "-setter"
+          (value :: <symbol>, mframe :: "<unparsed-" ## ?frame-type) => (res)
+        let field = fields(mframe)[?field-index];
+        let val :: <integer> = enum-field-symbol-to-int(field, value);
+        ?name ## "-setter" (val, mframe)
+      end;
+ }
+end;
+
+
 define method parse-frame-field
    (frame-field :: <frame-field>)
  => (res, length);
@@ -433,7 +513,17 @@
 end;
 
 define macro frame-field-generator
-    { frame-field-generator(?type:name; ?count:expression; ?args:* field ?field-name:name ?foo:*  ; ?rest:*) }
+    { frame-field-generator(?type:name; ?count:expression; enum field ?field-name:name ?foo:*  ; ?rest:*) }
+    => { enum-frame-field-generator(?field-name, ?type, ?count);
+         unparsed-frame-field-generator(?field-name, ?type, ?count);
+         frame-field-generator(?type; ?count + 1; ?rest) }
+    { frame-field-generator(?type:name; ?count:expression; repeated field ?field-name:name ?foo:*  ; ?rest:*) }
+    => { unparsed-frame-field-generator(?field-name, ?type, ?count);
+         frame-field-generator(?type; ?count + 1; ?rest) }
+    { frame-field-generator(?type:name; ?count:expression; layering field ?field-name:name ?foo:*  ; ?rest:*) }
+    => { unparsed-frame-field-generator(?field-name, ?type, ?count);
+         frame-field-generator(?type; ?count + 1; ?rest) }
+    { frame-field-generator(?type:name; ?count:expression; field ?field-name:name ?foo:*  ; ?rest:*) }
     => { unparsed-frame-field-generator(?field-name, ?type, ?count);
          frame-field-generator(?type; ?count + 1; ?rest) }
     { frame-field-generator(?type:name; ?count:expression; variably-typed-field ?field-name:name ?foo:* ; ?rest:*) }



More information about the chatter mailing list