commit-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Commit-gnuradio] r4839 - gnuradio/branches/developers/eb/ibu/pmt/src/li


From: eb
Subject: [Commit-gnuradio] r4839 - gnuradio/branches/developers/eb/ibu/pmt/src/lib
Date: Sun, 1 Apr 2007 15:05:45 -0600 (MDT)

Author: eb
Date: 2007-04-01 15:05:44 -0600 (Sun, 01 Apr 2007)
New Revision: 4839

Modified:
   gnuradio/branches/developers/eb/ibu/pmt/src/lib/pmt_serial_tags.dat
   gnuradio/branches/developers/eb/ibu/pmt/src/lib/pmt_serialize.cc
   gnuradio/branches/developers/eb/ibu/pmt/src/lib/qa_pmt_prims.cc
   gnuradio/branches/developers/eb/ibu/pmt/src/lib/qa_pmt_prims.h
Log:
useful subset of serialize/deserialize is working

Modified: gnuradio/branches/developers/eb/ibu/pmt/src/lib/pmt_serial_tags.dat
===================================================================
--- gnuradio/branches/developers/eb/ibu/pmt/src/lib/pmt_serial_tags.dat 
2007-04-01 20:51:52 UTC (rev 4838)
+++ gnuradio/branches/developers/eb/ibu/pmt/src/lib/pmt_serial_tags.dat 
2007-04-01 21:05:44 UTC (rev 4839)
@@ -21,18 +21,18 @@
 
 ;;; definitions of tag values used for marshalling pmt data
 
-(pst-true           #x00)
-(pst-false         #x01)
-(pst-symbol        #x02)   ; untagged-int16 n; followed by n bytes of symbol 
name
-(pst-int32         #x03)
-(pst-double        #x04)
-(pst-complex       #x05)   ; complex<double>: real, imag
-(pst-null          #x06)
-(pst-pair          #x07)   ; followed by two objects
-(pst-vector        #x08)   ; untagged-int32 n; followed by n objects
-(pst-dict          #x09)   ; untagged-int32 n; followed by n key/value tuples
+(pst-true              #x00)
+(pst-false             #x01)
+(pst-symbol            #x02)   ; untagged-int16 n; followed by n bytes of 
symbol name
+(pst-int32             #x03)
+(pst-double            #x04)
+(pst-complex           #x05)   ; complex<double>: real, imag
+(pst-null              #x06)
+(pst-pair              #x07)   ; followed by two objects
+(pst-vector            #x08)   ; untagged-int32 n; followed by n objects
+(pst-dict              #x09)   ; untagged-int32 n; followed by n key/value 
tuples
 
-(pst-uniform-vector #x0a)
+(pst-uniform-vector    #x0a)
 
 ;; u8, s8, u16, s16, u32, s32, u64, s64, f32, f64, c32, c64
 ;;
@@ -41,7 +41,7 @@
 ;;   untagged-int32  n-items
 ;;   untagged-uint8  npad
 ;;   npad bytes of zeros to align binary data
-;;   followed by n-items binary numeric items
+;;   n-items binary numeric items
 ;;
 ;; uvi:
 ;; +-+-+-+-+-+-+-+-+
@@ -70,3 +70,7 @@
     (uvi-c32           #x0a)
     (uvi-c64           #x0b)
 
+
+(pst-comment           #x3b)           ; ascii ';'
+(pst-comment-end       #x0a)           ; ascii '\n'
+

Modified: gnuradio/branches/developers/eb/ibu/pmt/src/lib/pmt_serialize.cc
===================================================================
--- gnuradio/branches/developers/eb/ibu/pmt/src/lib/pmt_serialize.cc    
2007-04-01 20:51:52 UTC (rev 4838)
+++ gnuradio/branches/developers/eb/ibu/pmt/src/lib/pmt_serialize.cc    
2007-04-01 21:05:44 UTC (rev 4839)
@@ -27,6 +27,8 @@
 #include "pmt_int.h"
 #include "pmt_serial_tags.h"
 
+static pmt_t parse_pair(std::streambuf &sb);
+
 // ----------------------------------------------------------------
 // output primitives
 // ----------------------------------------------------------------
@@ -157,19 +159,22 @@
 
 /*
  * Write portable byte-serial representation of \p obj to \p sb
+ *
+ * N.B., Circular structures cause infinite recursion.
  */
 bool
 pmt_serialize(pmt_t obj, std::streambuf &sb)
 {
   bool ok = true;
 
-  // tail_recursion:
+ tail_recursion:
 
-  if (pmt_eq(obj, PMT_BOOL_T))
-    return serialize_untagged_u8(PST_TRUE, sb);
-    
-  if (pmt_eq(obj, PMT_BOOL_F))
-    return serialize_untagged_u8(PST_FALSE, sb);
+  if (pmt_is_bool(obj)){
+    if (pmt_eq(obj, PMT_BOOL_T))
+      return serialize_untagged_u8(PST_TRUE, sb);
+    else
+      return serialize_untagged_u8(PST_FALSE, sb);
+  }
   
   if (pmt_is_null(obj))
     return serialize_untagged_u8(PST_NULL, sb);
@@ -184,32 +189,161 @@
     return ok;
   }
 
+  if (pmt_is_pair(obj)){
+    ok = serialize_untagged_u8(PST_PAIR, sb);
+    ok &= pmt_serialize(pmt_car(obj), sb);
+    if (!ok)
+      return false;
+    obj = pmt_cdr(obj);
+    goto tail_recursion;
+  }
+
   if (pmt_is_number(obj)){
 
     if (pmt_is_integer(obj)){
-      int i = (int) pmt_to_long(obj);  // FIXME: trouble on values bigger than 
32-bits
+      long i = pmt_to_long(obj);
+      if (sizeof(long) > 4){
+       if (i < -2147483648 || i > 2147483647)
+         throw pmt_notimplemented("pmt_serialize (64-bit integers)", obj);
+      }
       ok = serialize_untagged_u8(PST_INT32, sb);
       ok &= serialize_untagged_u32(i, sb);
       return ok;
     }
 
     if (pmt_is_real(obj))
-      throw pmt_notimplemented("pmt_serialize for real", obj);
+      throw pmt_notimplemented("pmt_serialize (real)", obj);
 
     if (pmt_is_complex(obj))
-      throw pmt_notimplemented("pmt_serialize for complex", obj);
-
+      throw pmt_notimplemented("pmt_serialize (complex)", obj);
   }
 
-  throw pmt_notimplemented("pmt_serialize for ???", obj);
+  if (pmt_is_vector(obj))
+    throw pmt_notimplemented("pmt_serialize (vector)", obj);
+
+  if (pmt_is_uniform_vector(obj))
+    throw pmt_notimplemented("pmt_serialize (uniform-vector)", obj);
+    
+  if (pmt_is_dict(obj))
+    throw pmt_notimplemented("pmt_serialize (dict)", obj);
+    
+
+  throw pmt_notimplemented("pmt_serialize (?)", obj);
 }
 
-
 /*
  * Create obj from portable byte-serial representation
+ *
+ * Returns next obj from streambuf, or PMT_EOF at end of file.
+ * Throws exception on malformed input.
  */
 pmt_t
 pmt_deserialize(std::streambuf &sb)
 {
-  return PMT_EOF;
+  uint8_t      tag;
+  uint8_t      u8;
+  uint16_t     u16;
+  uint32_t     u32;
+  uint32_t     u64;
+  static char   tmpbuf[1024];
+
+  if (!deserialize_untagged_u8(&tag, sb))
+    return PMT_EOF;
+
+  switch (tag){
+  case PST_TRUE:
+    return PMT_BOOL_T;
+    
+  case PST_FALSE:
+    return PMT_BOOL_F;
+
+  case PST_NULL:
+    return PMT_NIL;
+
+  case PST_SYMBOL:
+    if (!deserialize_untagged_u16(&u16, sb))
+      goto error;
+    if (u16 > sizeof(tmpbuf))
+      throw pmt_notimplemented("pmt_deserialize: very long symbol",
+                              PMT_BOOL_F);
+    if (sb.sgetn(tmpbuf, u16) != u16)
+      goto error;
+    return pmt_intern(std::string(tmpbuf, u16));
+
+  case PST_INT32:
+    if (!deserialize_untagged_u32(&u32, sb))
+      goto error;
+    return pmt_from_long((int32_t) u32);
+
+  case PST_PAIR:
+    return parse_pair(sb);
+
+  case PST_DOUBLE:
+  case PST_COMPLEX:
+  case PST_VECTOR:
+  case PST_DICT:
+  case PST_UNIFORM_VECTOR:
+  case PST_COMMENT:
+    throw pmt_notimplemented("pmt_deserialize: tag value = ",
+                            pmt_from_long(tag));
+    
+  default:
+    throw pmt_exception("pmt_deserialize: malformed input stream, tag value = 
",
+                       pmt_from_long(tag));
+  }
+
+ error:
+  throw pmt_exception("pmt_deserialize: malformed input stream", PMT_BOOL_F);
 }
+
+/*
+ * This is a mostly non-recursive implementation that allows us to
+ * deserialize very long lists w/o exhausting the evaluation stack.
+ *
+ * On entry we've already eaten the PST_PAIR tag.
+ */
+pmt_t
+parse_pair(std::streambuf &sb)
+{
+  uint8_t tag;
+  pmt_t        val, expr, lastnptr, nptr;
+
+  //
+  // Keep appending nodes until we get a non-PAIR cdr.
+  //
+  lastnptr = PMT_NIL;
+  while (1){
+    expr = pmt_deserialize(sb);                // read the car
+
+    nptr = pmt_cons(expr, PMT_NIL);    // build new cell
+    if (pmt_is_null(lastnptr))
+      val = nptr;
+    else
+      pmt_set_cdr(lastnptr, nptr);
+    lastnptr = nptr;
+
+    if (!deserialize_untagged_u8(&tag, sb))  // get tag of cdr
+      throw pmt_exception("pmt_deserialize: malformed input stream", 
PMT_BOOL_F);
+
+    if (tag == PST_PAIR)
+      continue;                        // keep on looping...
+
+    if (tag == PST_NULL){
+      expr = PMT_NIL;
+      break;
+    }
+
+    //
+    // default: push tag back and use pmt_deserialize to get the cdr
+    //
+    sb.sungetc();
+    expr = pmt_deserialize(sb);
+    break;
+  }
+
+  //
+  // At this point, expr contains the value of the final cdr in the list.
+  //
+  pmt_set_cdr(lastnptr, expr);
+  return val;
+}

Modified: gnuradio/branches/developers/eb/ibu/pmt/src/lib/qa_pmt_prims.cc
===================================================================
--- gnuradio/branches/developers/eb/ibu/pmt/src/lib/qa_pmt_prims.cc     
2007-04-01 20:51:52 UTC (rev 4838)
+++ gnuradio/branches/developers/eb/ibu/pmt/src/lib/qa_pmt_prims.cc     
2007-04-01 21:05:44 UTC (rev 4839)
@@ -24,6 +24,7 @@
 #include <cppunit/TestAssert.h>
 #include <pmt.h>
 #include <stdio.h>
+#include <sstream>
 
 void
 qa_pmt_prims::test_symbols()
@@ -293,3 +294,51 @@
 
   CPPUNIT_ASSERT_EQUAL(std::string("k0"), pmt_write_string(k0));
 }
+
+void
+qa_pmt_prims::test_serialize()
+{
+  std::stringbuf sb;           // fake channel
+  pmt_t a = pmt_intern("a");
+  pmt_t b = pmt_intern("b");
+  pmt_t c = pmt_intern("c");
+
+  sb.str("");                  // reset channel to empty
+
+  // write stuff to channel
+
+  pmt_serialize(PMT_NIL, sb);
+  pmt_serialize(pmt_intern("foobarvia"), sb);
+  pmt_serialize(pmt_from_long(123456789), sb);
+  pmt_serialize(pmt_from_long(-123456789), sb);
+  pmt_serialize(pmt_cons(PMT_NIL, PMT_NIL), sb);
+  pmt_serialize(pmt_cons(a, b), sb);
+  pmt_serialize(pmt_list1(a), sb);
+  pmt_serialize(pmt_list2(a, b), sb);
+  pmt_serialize(pmt_list3(a, b, c), sb);
+  pmt_serialize(pmt_list3(a, pmt_list3(c, b, a), c), sb);
+  pmt_serialize(PMT_BOOL_T, sb);
+  pmt_serialize(PMT_BOOL_F, sb);
+
+  // read it back
+
+  CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), PMT_NIL));
+  CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), pmt_intern("foobarvia")));
+  CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), pmt_from_long(123456789)));
+  CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), pmt_from_long(-123456789)));
+  CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), pmt_cons(PMT_NIL, PMT_NIL)));
+  CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), pmt_cons(a, b)));
+  CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), pmt_list1(a)));
+  CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), pmt_list2(a, b)));
+  CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), pmt_list3(a, b, c)));
+  CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), pmt_list3(a, pmt_list3(c, b, 
a), c)));
+  CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), PMT_BOOL_T));
+  CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), PMT_BOOL_F));
+
+  CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), PMT_EOF));     // last item
+
+
+  // FIXME add tests for real, complex, vector, uniform-vector, dict
+  // FIXME add tests for malformed input too.
+
+}

Modified: gnuradio/branches/developers/eb/ibu/pmt/src/lib/qa_pmt_prims.h
===================================================================
--- gnuradio/branches/developers/eb/ibu/pmt/src/lib/qa_pmt_prims.h      
2007-04-01 20:51:52 UTC (rev 4838)
+++ gnuradio/branches/developers/eb/ibu/pmt/src/lib/qa_pmt_prims.h      
2007-04-01 21:05:44 UTC (rev 4839)
@@ -39,6 +39,7 @@
   CPPUNIT_TEST(test_misc);
   CPPUNIT_TEST(test_dict);
   CPPUNIT_TEST(test_io);
+  CPPUNIT_TEST(test_serialize);
   CPPUNIT_TEST_SUITE_END();
 
  private:
@@ -53,6 +54,7 @@
   void test_misc();
   void test_dict();
   void test_io();
+  void test_serialize();
 };
 
 #endif /* INCLUDED_QA_PMT_PRIMS_H */





reply via email to

[Prev in Thread] Current Thread [Next in Thread]