You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by rh...@apache.org on 2007/09/27 20:56:24 UTC

svn commit: r580122 - in /incubator/qpid/trunk/qpid/python: qpid/codec.py qpid/spec.py tests/codec.py

Author: rhs
Date: Thu Sep 27 11:56:23 2007
New Revision: 580122

URL: http://svn.apache.org/viewvc?rev=580122&view=rev
Log:
added support for 0-10 field table encoding

Modified:
    incubator/qpid/trunk/qpid/python/qpid/codec.py
    incubator/qpid/trunk/qpid/python/qpid/spec.py
    incubator/qpid/trunk/qpid/python/tests/codec.py

Modified: incubator/qpid/trunk/qpid/python/qpid/codec.py
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/python/qpid/codec.py?rev=580122&r1=580121&r2=580122&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/python/qpid/codec.py (original)
+++ incubator/qpid/trunk/qpid/python/qpid/codec.py Thu Sep 27 11:56:23 2007
@@ -34,6 +34,11 @@
 class EOF(Exception):
   pass
 
+TYPE_ALIASES = {
+  "long_string": "longstr",
+  "unsigned_int": "long"
+  }
+
 class Codec:
 
   """
@@ -51,6 +56,40 @@
     self.incoming_bits = []
     self.outgoing_bits = []
 
+    self.types = {}
+    self.codes = {}
+    self.encodings = {
+      basestring: "longstr",
+      int: "long",
+      long: "long",
+      None.__class__:"void",
+      list: "sequence",
+      tuple: "sequence",
+      dict: "table"
+      }
+
+    if False:
+      for constant in self.spec.constants:
+        if constant.klass == "field-table-type":
+          type = constant.name.replace("field_table_", "")
+          self.typecode(constant.id, TYPE_ALIASES.get(type, type))
+
+    if not self.types:
+      self.typecode(ord('S'), "longstr")
+      self.typecode(ord('I'), "long")
+
+  def typecode(self, code, type):
+    self.types[code] = type
+    self.codes[type] = code
+
+  def resolve(self, klass):
+    if self.encodings.has_key(klass):
+      return self.encodings[klass]
+    for base in klass.__bases__:
+      result = self.resolve(base)
+      if result != None:
+        return result
+
   def read(self, n):
     """
     reads in 'n' bytes from the stream. Can raise EOF exception
@@ -265,15 +304,14 @@
     codec = Codec(enc, self.spec)
     if tbl:
       for key, value in tbl.items():
-        if len(key) > 128:
+        if self.spec.major == 8 and self.spec.minor == 0 and len(key) > 128:
           raise ValueError("field table key too long: '%s'" % key)
+        type = self.resolve(value.__class__)
+        if type == None:
+          raise ValueError("no encoding for: " + value.__class__)
         codec.encode_shortstr(key)
-        if isinstance(value, basestring):
-          codec.write("S")
-          codec.encode_longstr(value)
-        else:
-          codec.write("I")
-          codec.encode_long(value)
+        codec.encode_octet(self.codes[type])
+        codec.encode(type, value)
     s = enc.getvalue()
     self.encode_long(len(s))
     self.write(s)
@@ -287,13 +325,21 @@
     result = {}
     while self.nread - start < size:
       key = self.decode_shortstr()
-      type = self.read(1)
-      if type == "S":
-        value = self.decode_longstr()
-      elif type == "I":
-        value = self.decode_long()
+      code = self.decode_octet()
+      if self.types.has_key(code):
+        value = self.decode(self.types[code])
       else:
-        raise ValueError(repr(type))
+        w = width(code)
+        if fixed(code):
+          value = self.read(w)
+        elif w == 1:
+          value = self.decode_shortstr()
+        elif w == 2:
+          value = self.dec_str("!H")
+        elif w == 4:
+          value = self.decode_longstr()
+        else:
+          raise ValueError("illegal width: " + w)
       result[key] = value
     return result
 
@@ -390,3 +436,27 @@
     codec = Codec(StringIO(self.decode_longstr()), self.spec)
     type = self.spec.structs[codec.decode_short()]
     return codec.decode_struct(type)
+
+def fixed(code):
+  return (code >> 6) != 2
+
+def width(code):
+  # decimal
+  if code >= 192:
+    decsel = (code >> 4) & 3
+    if decsel == 0:
+      return 5
+    elif decsel == 1:
+      return 9
+    elif decsel == 3:
+      return 0
+    else:
+      raise ValueError(code)
+  # variable width
+  elif code < 192 and code >= 128:
+    lenlen = (self.code >> 4) & 3
+    if lenlen == 3: raise ValueError(code)
+    return 2 ** lenlen
+  # fixed width
+  else:
+    return (self.code >> 4) & 7

Modified: incubator/qpid/trunk/qpid/python/qpid/spec.py
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/python/qpid/spec.py?rev=580122&r1=580121&r2=580122&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/python/qpid/spec.py (original)
+++ incubator/qpid/trunk/qpid/python/qpid/spec.py Thu Sep 27 11:56:23 2007
@@ -348,9 +348,10 @@
     # constants
     for nd in root.query["constant"]:
       val = nd["@value"]
-      if val.startswith("0x"): continue
-      const = Constant(spec, pythonize(nd["@name"]), int(val),
-                       nd["@class"], get_docs(nd))
+      if val.startswith("0x"): val = int(val, 16)
+      else: val = int(val)
+      const = Constant(spec, pythonize(nd["@name"]), val, nd["@class"],
+                       get_docs(nd))
       try:
         spec.constants.add(const)
       except ValueError, e:

Modified: incubator/qpid/trunk/qpid/python/tests/codec.py
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/python/tests/codec.py?rev=580122&r1=580121&r2=580122&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/python/tests/codec.py (original)
+++ incubator/qpid/trunk/qpid/python/tests/codec.py Thu Sep 27 11:56:23 2007
@@ -442,13 +442,6 @@
         """
         self.failUnlessEqual(self.callFunc('encode_table', {'$key1':'value1'}), '\x00\x00\x00\x11\x05$key1S\x00\x00\x00\x06value1', 'valid name value pair encoding FAILED...')
 
-    # ----------------------------------------------------
-    def test_field_table_invalid_field_name_length(self):
-        """
-        field names can have a maximum length of 128 chars
-        """
-        self.failUnlessRaises(Exception, self.codec.encode_table, {'x'*129:'value1'})
-
     # ---------------------------------------------------
     def test_field_table_multiple_name_value_pair(self):
         """