X-Git-Url: http://git.dolda2000.com/gitweb/?a=blobdiff_plain;f=coe%2Fbin.py;h=08e521e19ce83aa53538150a173460eccc7f3174;hb=e39561b7a9e74d39d061f8e153e48334a4facf3f;hp=de3d6fae74e8d1d2aa541ade6f601d5e6f3f5eff;hpb=8dc0c47abac97c689406a014945e5f605dd762e1;p=coe.git diff --git a/coe/bin.py b/coe/bin.py index de3d6fa..08e521e 100644 --- a/coe/bin.py +++ b/coe/bin.py @@ -1,3 +1,4 @@ +import io, math from . import data T_END = 0 @@ -70,6 +71,30 @@ class encoder(object): dst.write(text.encode("utf-8")) dst.write(b'\0') + @staticmethod + def writefloat(dst, x): + if x == 0.0: + mnt, exp = (0, 0) + elif math.isinf(x): + if x > 0: + mnt, exp = (0, 2) + else: + mnt, exp = (0, 3) + elif math.isnan(x): + mnt, exp = (0, 4) + else: + mnt, exp = math.frexp(x) + mnt *= 2 + exp -= 1 + while mnt != int(mnt): + mnt *= 2 + mnt = int(mnt) + buf = bytearray() + buf.extend(encoder.encint(mnt)) + buf.extend(encoder.encint(exp)) + dst.write(encoder.encint(len(buf))) + dst.write(buf) + def dumpseq(self, dst, seq): for v in seq: self.dump(dst, v) @@ -89,9 +114,9 @@ class encoder(object): return if datum == None: self.writetag(dst, T_NIL, 0, None) - elif datum == False: + elif datum is False: self.writetag(dst, T_NIL, NIL_FALSE, None) - elif datum == True: + elif datum is True: self.writetag(dst, T_NIL, NIL_TRUE, None) elif isinstance(datum, int): self.writetag(dst, T_INT, 0, None) @@ -103,6 +128,9 @@ class encoder(object): self.writetag(dst, T_BIT, 0, datum) dst.write(self.encint(len(datum))) dst.write(datum) + elif isinstance(datum, float): + self.writetag(dst, T_BIT, BIT_BFLOAT, datum) + self.writefloat(dst, datum) elif isinstance(datum, data.symbol): if datum.ns == "": self.writetag(dst, T_STR, STR_SYM, datum) @@ -223,7 +251,7 @@ class decoder(object): buf[key] = self.loadtagged(fp, tag) def makeobjtype(self, nm): - return data.namedtype(str(nm), (data.obj, object), {}, typename=nm) + return data.namedtype.make(str(nm), (data.obj, object), {}, typename=nm) def loadobj(self, fp, ref=False): if ref: @@ -259,16 +287,34 @@ class decoder(object): return self.reftab[idx] return self.addref(self.loadint(fp)) elif pri == T_STR: - ret = self.addref(self.loadstr(fp)) + ret = self.loadstr(fp) if sec == STR_SYM: - return data.symbol.get("", ret) - return ret + return self.addref(data.symbol.get("", ret)) + return self.addref(ret) elif pri == T_BIT: ln = self.loadint(fp) - ret = self.addref(fp.read(ln)) + ret = fp.read(ln) if len(ret) < ln: raise eoferror() - return ret + if sec == BIT_BFLOAT: + buf = io.BytesIO(ret) + mnt = self.loadint(buf) + exp = self.loadint(buf) + if mnt == 0: + if exp == 0: + return 0.0 + elif exp == 1: + return -0.0 + elif exp == 2: + return float("inf") + elif exp == 3: + return -float("inf") + else: + return float("nan") + else: + ret = math.ldexp(mnt, exp - (mnt.bit_length() - 1)) + return self.addref(ret) + return self.addref(ret) elif pri == T_NIL: if sec == NIL_TRUE: return self.addref(True) @@ -292,4 +338,4 @@ class decoder(object): return self.loadtagged(fp, tag) def load(fp): - decoder().load(fp) + return decoder().load(fp)