diff options
Diffstat (limited to 'gnuradio-runtime/lib/pmt/pmt_serialize.cc')
-rw-r--r-- | gnuradio-runtime/lib/pmt/pmt_serialize.cc | 835 |
1 files changed, 835 insertions, 0 deletions
diff --git a/gnuradio-runtime/lib/pmt/pmt_serialize.cc b/gnuradio-runtime/lib/pmt/pmt_serialize.cc new file mode 100644 index 0000000000..4036b8d8bd --- /dev/null +++ b/gnuradio-runtime/lib/pmt/pmt_serialize.cc @@ -0,0 +1,835 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007,2009 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <vector> +#include <pmt/pmt.h> +#include "pmt_int.h" +#include "pmt/pmt_serial_tags.h" + +namespace pmt { + +static pmt_t parse_pair(std::streambuf &sb); + +// ---------------------------------------------------------------- +// output primitives +// ---------------------------------------------------------------- + +static bool +serialize_untagged_u8(unsigned int i, std::streambuf &sb) +{ + return sb.sputc((i >> 0) & 0xff) != std::streambuf::traits_type::eof(); +} + +// always writes big-endian +static bool +serialize_untagged_u16(unsigned int i, std::streambuf &sb) +{ + sb.sputc((i >> 8) & 0xff); + return sb.sputc((i >> 0) & 0xff) != std::streambuf::traits_type::eof(); +} + +// always writes big-endian +static bool +serialize_untagged_u32(unsigned int i, std::streambuf &sb) +{ + sb.sputc((i >> 24) & 0xff); + sb.sputc((i >> 16) & 0xff); + sb.sputc((i >> 8) & 0xff); + return sb.sputc((i >> 0) & 0xff) != std::streambuf::traits_type::eof(); +} + +static bool +serialize_untagged_f64(double i, std::streambuf &sb) +{ + typedef union { + double id; + uint64_t ii; + } iu_t; + iu_t iu; + iu.id = i; + sb.sputc((iu.ii >> 56) & 0xff); + sb.sputc((iu.ii >> 48) & 0xff); + sb.sputc((iu.ii >> 40) & 0xff); + sb.sputc((iu.ii >> 32) & 0xff); + sb.sputc((iu.ii >> 24) & 0xff); + sb.sputc((iu.ii >> 16) & 0xff); + sb.sputc((iu.ii >> 8) & 0xff); + return sb.sputc((iu.ii >> 0) & 0xff) != std::streambuf::traits_type::eof(); +} + + +// always writes big-endian +static bool +serialize_untagged_u64(uint64_t i, std::streambuf &sb) +{ + sb.sputc((i >> 56) & 0xff); + sb.sputc((i >> 48) & 0xff); + sb.sputc((i >> 40) & 0xff); + sb.sputc((i >> 32) & 0xff); + sb.sputc((i >> 24) & 0xff); + sb.sputc((i >> 16) & 0xff); + sb.sputc((i >> 8) & 0xff); + return sb.sputc((i >> 0) & 0xff) != std::streambuf::traits_type::eof(); +} + +// ---------------------------------------------------------------- +// input primitives +// ---------------------------------------------------------------- + + +// always reads big-endian +static bool +deserialize_untagged_u8(uint8_t *ip, std::streambuf &sb) +{ + std::streambuf::traits_type::int_type t; + int i; + + t = sb.sbumpc(); + i = t & 0xff; + + *ip = i; + return t != std::streambuf::traits_type::eof(); +} + +// always reads big-endian +static bool +deserialize_untagged_u16(uint16_t *ip, std::streambuf &sb) +{ + std::streambuf::traits_type::int_type t; + int i; + + t = sb.sbumpc(); + i = t & 0xff; + + t = sb.sbumpc(); + i = (i << 8) | (t & 0xff); + + *ip = i; + return t != std::streambuf::traits_type::eof(); +} + +// always reads big-endian +static bool +deserialize_untagged_u32(uint32_t *ip, std::streambuf &sb) +{ + std::streambuf::traits_type::int_type t; + int i; + + t = sb.sbumpc(); + i = t & 0xff; + + t = sb.sbumpc(); + i = (i << 8) | (t & 0xff); + t = sb.sbumpc(); + i = (i << 8) | (t & 0xff); + t = sb.sbumpc(); + i = (i << 8) | (t & 0xff); + + *ip = i; + return t != std::streambuf::traits_type::eof(); +} + +// always reads big-endian +static bool +deserialize_untagged_u64(uint64_t *ip, std::streambuf &sb) +{ + std::streambuf::traits_type::int_type t; + uint64_t i; + + t = sb.sbumpc(); + i = t & 0xff; + + t = sb.sbumpc(); + i = (i << 8) | (t & 0xff); + t = sb.sbumpc(); + i = (i << 8) | (t & 0xff); + t = sb.sbumpc(); + i = (i << 8) | (t & 0xff); + t = sb.sbumpc(); + i = (i << 8) | (t & 0xff); + t = sb.sbumpc(); + i = (i << 8) | (t & 0xff); + t = sb.sbumpc(); + i = (i << 8) | (t & 0xff); + t = sb.sbumpc(); + i = (i << 8) | (t & 0xff); + + *ip = i; + return t != std::streambuf::traits_type::eof(); +} + +static bool +deserialize_untagged_f64(double *ip, std::streambuf &sb) +{ + std::streambuf::traits_type::int_type t; + + typedef union { + double id; + uint64_t ii; + } iu_t; + + iu_t iu; + + t = sb.sbumpc(); + iu.ii = t & 0xff; + + t = sb.sbumpc(); + iu.ii = (iu.ii<<8) | (t & 0xff); + t = sb.sbumpc(); + iu.ii = (iu.ii<<8) | (t & 0xff); + t = sb.sbumpc(); + iu.ii = (iu.ii<<8) | (t & 0xff); + t = sb.sbumpc(); + iu.ii = (iu.ii<<8) | (t & 0xff); + t = sb.sbumpc(); + iu.ii = (iu.ii<<8) | (t & 0xff); + t = sb.sbumpc(); + iu.ii = (iu.ii<<8) | (t & 0xff); + t = sb.sbumpc(); + iu.ii = (iu.ii<<8) | (t & 0xff); + + *ip = iu.id; + return t != std::streambuf::traits_type::eof(); +} + +static bool +deserialize_tuple(pmt_t *tuple, std::streambuf &sb) +{ + uint32_t nitems; + bool ok = deserialize_untagged_u32(&nitems, sb); + pmt_t list(PMT_NIL); + for(uint32_t i=0; i<nitems; i++) { + pmt_t item = deserialize(sb); + if(eq(list, PMT_NIL)) { + list = list1(item); + } + else { + list = list_add(list, item); + } + } + (*tuple) = to_tuple(list); + return ok; +} + + +/* + * Write portable byte-serial representation of \p obj to \p sb + * + * N.B., Circular structures cause infinite recursion. + */ +bool +serialize(pmt_t obj, std::streambuf &sb) +{ + bool ok = true; + + tail_recursion: + + if(is_bool(obj)) { + if(eq(obj, PMT_T)) + return serialize_untagged_u8(PST_TRUE, sb); + else + return serialize_untagged_u8(PST_FALSE, sb); + } + + if(is_null(obj)) + return serialize_untagged_u8(PST_NULL, sb); + + if(is_symbol(obj)) { + const std::string s = symbol_to_string(obj); + size_t len = s.size(); + ok = serialize_untagged_u8(PST_SYMBOL, sb); + ok &= serialize_untagged_u16(len, sb); + for(size_t i = 0; i < len; i++) + ok &= serialize_untagged_u8(s[i], sb); + return ok; + } + + if(is_pair(obj)) { + ok = serialize_untagged_u8(PST_PAIR, sb); + ok &= serialize(car(obj), sb); + if(!ok) + return false; + obj = cdr(obj); + goto tail_recursion; + } + + if(is_number(obj)) { + + if(is_uint64(obj)) { + uint64_t i = to_uint64(obj); + ok = serialize_untagged_u8(PST_UINT64, sb); + ok &= serialize_untagged_u64(i, sb); + return ok; + } + else { + if(is_integer(obj)) { + long i = to_long(obj); + if(sizeof(long) > 4) { + if(i < -2147483647 || i > 2147483647) + throw notimplemented("pmt::serialize (64-bit integers)", obj); + } + ok = serialize_untagged_u8(PST_INT32, sb); + ok &= serialize_untagged_u32(i, sb); + return ok; + } + } + + if(is_real(obj)) { + float i = to_double(obj); + ok = serialize_untagged_u8(PST_DOUBLE, sb); + ok &= serialize_untagged_f64(i, sb); + return ok; + } + + if(is_complex(obj)) { + std::complex<double> i = to_complex(obj); + ok = serialize_untagged_u8(PST_COMPLEX, sb); + ok &= serialize_untagged_f64(i.real(), sb); + ok &= serialize_untagged_f64(i.imag(), sb); + return ok; + } + } + + if(is_vector(obj)) { + size_t vec_len = pmt::length(obj); + ok = serialize_untagged_u8(PST_VECTOR, sb); + ok &= serialize_untagged_u32(vec_len, sb); + for(size_t i=0; i<vec_len; i++) { + ok &= serialize(vector_ref(obj, i), sb); + } + return ok; + } + + if(is_uniform_vector(obj)) { + size_t npad = 1; + size_t vec_len = pmt::length(obj); + + if(is_u8vector(obj)) { + ok = serialize_untagged_u8(PST_UNIFORM_VECTOR, sb); + ok &= serialize_untagged_u8(UVI_U8, sb); + ok &= serialize_untagged_u32(vec_len, sb); + ok &= serialize_untagged_u8(npad, sb); + for(size_t i=0; i<npad; i++) { + ok &= serialize_untagged_u8(0, sb); + } + for(size_t i=0; i<vec_len; i++) { + ok &= serialize_untagged_u8(u8vector_ref(obj, i), sb); + } + return ok; + } + + if(is_s8vector(obj)) { + ok = serialize_untagged_u8(PST_UNIFORM_VECTOR, sb); + ok &= serialize_untagged_u8(UVI_S8, sb); + ok &= serialize_untagged_u32(vec_len, sb); + ok &= serialize_untagged_u8(npad, sb); + for(size_t i=0; i<npad; i++) { + ok &= serialize_untagged_u8(0, sb); + } + for(size_t i=0; i<vec_len; i++) { + ok &= serialize_untagged_u8(s8vector_ref(obj, i), sb); + } + return ok; + } + + if(is_u16vector(obj)) { + ok = serialize_untagged_u8(PST_UNIFORM_VECTOR, sb); + ok &= serialize_untagged_u8(UVI_U16, sb); + ok &= serialize_untagged_u32(vec_len, sb); + ok &= serialize_untagged_u8(npad, sb); + for(size_t i=0; i<npad; i++) { + ok &= serialize_untagged_u8(0, sb); + } + for(size_t i=0; i<vec_len; i++) { + ok &= serialize_untagged_u16(u16vector_ref(obj, i), sb); + } + return ok; + } + + if(is_s16vector(obj)) { + ok = serialize_untagged_u8(PST_UNIFORM_VECTOR, sb); + ok &= serialize_untagged_u8(UVI_S16, sb); + ok &= serialize_untagged_u32(vec_len, sb); + ok &= serialize_untagged_u8(npad, sb); + for(size_t i=0; i<npad; i++) { + ok &= serialize_untagged_u8(0, sb); + } + for(size_t i=0; i<vec_len; i++) { + ok &= serialize_untagged_u16(s16vector_ref(obj, i), sb); + } + return ok; + } + + if(is_u32vector(obj)) { + ok = serialize_untagged_u8(PST_UNIFORM_VECTOR, sb); + ok &= serialize_untagged_u8(UVI_U32, sb); + ok &= serialize_untagged_u32(vec_len, sb); + ok &= serialize_untagged_u8(npad, sb); + for(size_t i=0; i<npad; i++) { + ok &= serialize_untagged_u8(0, sb); + } + for(size_t i=0; i<vec_len; i++) { + ok &= serialize_untagged_u32(u32vector_ref(obj, i), sb); + } + return ok; + } + + if(is_s32vector(obj)) { + ok = serialize_untagged_u8(PST_UNIFORM_VECTOR, sb); + ok &= serialize_untagged_u8(UVI_S32, sb); + ok &= serialize_untagged_u32(vec_len, sb); + ok &= serialize_untagged_u8(npad, sb); + for(size_t i=0; i<npad; i++) { + ok &= serialize_untagged_u8(0, sb); + } + for(size_t i=0; i<vec_len; i++) { + ok &= serialize_untagged_u32(s32vector_ref(obj, i), sb); + } + return ok; + } + + if(is_u64vector(obj)) { + ok = serialize_untagged_u8(PST_UNIFORM_VECTOR, sb); + ok &= serialize_untagged_u8(UVI_U64, sb); + ok &= serialize_untagged_u32(vec_len, sb); + ok &= serialize_untagged_u8(npad, sb); + for(size_t i=0; i<npad; i++) { + ok &= serialize_untagged_u8(0, sb); + } + for(size_t i=0; i<vec_len; i++) { + ok &= serialize_untagged_u64(u64vector_ref(obj, i), sb); + } + return ok; + } + + if(is_s64vector(obj)) { + ok = serialize_untagged_u8(PST_UNIFORM_VECTOR, sb); + ok &= serialize_untagged_u8(UVI_S64, sb); + ok &= serialize_untagged_u32(vec_len, sb); + ok &= serialize_untagged_u8(npad, sb); + for(size_t i=0; i<npad; i++) { + ok &= serialize_untagged_u8(0, sb); + } + for(size_t i=0; i<vec_len; i++) { + ok &= serialize_untagged_u64(s64vector_ref(obj, i), sb); + } + return ok; + } + + if(is_f32vector(obj)) { + ok = serialize_untagged_u8(PST_UNIFORM_VECTOR, sb); + ok &= serialize_untagged_u8(UVI_F32, sb); + ok &= serialize_untagged_u32(vec_len, sb); + ok &= serialize_untagged_u8(npad, sb); + for(size_t i=0; i<npad; i++) { + ok &= serialize_untagged_u8(0, sb); + } + for(size_t i=0; i<vec_len; i++) { + ok &= serialize_untagged_f64(f32vector_ref(obj, i), sb); + } + return ok; + } + + if(is_f64vector(obj)) { + ok = serialize_untagged_u8(PST_UNIFORM_VECTOR, sb); + ok &= serialize_untagged_u8(UVI_F64, sb); + ok &= serialize_untagged_u32(vec_len, sb); + ok &= serialize_untagged_u8(npad, sb); + for(size_t i=0; i<npad; i++) { + ok &= serialize_untagged_u8(0, sb); + } + for(size_t i=0; i<vec_len; i++) { + ok &= serialize_untagged_f64(f64vector_ref(obj, i), sb); + } + return ok; + } + + if(is_c32vector(obj)) { + ok = serialize_untagged_u8(PST_UNIFORM_VECTOR, sb); + ok &= serialize_untagged_u8(UVI_C32, sb); + ok &= serialize_untagged_u32(vec_len, sb); + ok &= serialize_untagged_u8(npad, sb); + for(size_t i=0; i<npad; i++) { + ok &= serialize_untagged_u8(0, sb); + } + for(size_t i=0; i<vec_len; i++) { + std::complex<float> c = c32vector_ref(obj, i); + ok &= serialize_untagged_f64(c.real(), sb); + ok &= serialize_untagged_f64(c.imag(), sb); + } + return ok; + } + + if(is_c64vector(obj)) { + ok = serialize_untagged_u8(PST_UNIFORM_VECTOR, sb); + ok &= serialize_untagged_u8(UVI_C64, sb); + ok &= serialize_untagged_u32(vec_len, sb); + ok &= serialize_untagged_u8(npad, sb); + for(size_t i=0; i<npad; i++) { + ok &= serialize_untagged_u8(0, sb); + } + for(size_t i=0; i<vec_len; i++) { + std::complex<double> c = c64vector_ref(obj, i); + ok &= serialize_untagged_f64(c.real(), sb); + ok &= serialize_untagged_f64(c.imag(), sb); + } + return ok; + } + } + + if (is_dict(obj)) + throw notimplemented("pmt::serialize (dict)", obj); + + if (is_tuple(obj)){ + size_t tuple_len = pmt::length(obj); + ok = serialize_untagged_u8(PST_TUPLE, sb); + ok &= serialize_untagged_u32(tuple_len, sb); + for(size_t i=0; i<tuple_len; i++){ + ok &= serialize(tuple_ref(obj, i), sb); + } + return ok; + } + //throw pmt_notimplemented("pmt::serialize (tuple)", obj); + + throw 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 +deserialize(std::streambuf &sb) +{ + uint8_t tag; + uint8_t u8; + uint16_t u16; + uint32_t u32; + uint64_t u64; + double f64; + static char tmpbuf[1024]; + + if (!deserialize_untagged_u8(&tag, sb)) + return PMT_EOF; + + switch (tag){ + case PST_TRUE: + return PMT_T; + + case PST_FALSE: + return PMT_F; + + case PST_NULL: + return PMT_NIL; + + case PST_SYMBOL: + if (!deserialize_untagged_u16(&u16, sb)) + goto error; + if (u16 > sizeof(tmpbuf)) + throw notimplemented("pmt::deserialize: very long symbol", + PMT_F); + if (sb.sgetn(tmpbuf, u16) != u16) + goto error; + return intern(std::string(tmpbuf, u16)); + + case PST_INT32: + if (!deserialize_untagged_u32(&u32, sb)) + goto error; + return from_long((int32_t) u32); + + case PST_UINT64: + if(!deserialize_untagged_u64(&u64, sb)) + goto error; + return from_uint64(u64); + + case PST_PAIR: + return parse_pair(sb); + + case PST_DOUBLE: + if(!deserialize_untagged_f64(&f64, sb)) + goto error; + return from_double( f64 ); + + case PST_COMPLEX: + { + double r,i; + if(!deserialize_untagged_f64(&r, sb) && !deserialize_untagged_f64(&i, sb)) + goto error; + return make_rectangular( r,i ); + } + + case PST_TUPLE: + { + pmt_t tuple; + if(!deserialize_tuple(&tuple, sb)){ + goto error; + } + return tuple; + } + + case PST_VECTOR: + { + uint32_t nitems; + if(!deserialize_untagged_u32(&nitems, sb)) + goto error; + pmt_t vec = make_vector(nitems, PMT_NIL); + for(uint32_t i=0; i<nitems; i++) { + pmt_t item = deserialize(sb); + vector_set(vec, i, item); + } + return vec; + } + + case PST_UNIFORM_VECTOR: + { + uint8_t utag, npad; + uint32_t nitems; + + if(!deserialize_untagged_u8(&utag, sb)) + return PMT_EOF; + + if(!deserialize_untagged_u32(&nitems, sb)) + goto error; + + deserialize_untagged_u8(&npad, sb); + for(size_t i; i < npad; i++) + deserialize_untagged_u8(&u8, sb); + + switch(utag) { + case(UVI_U8): + { + pmt_t vec = make_u8vector(nitems, 0); + for(uint32_t i=0; i<nitems; i++) { + deserialize_untagged_u8(&u8, sb); + u8vector_set(vec, i, u8); + } + return vec; + } + case(UVI_S8): + { + pmt_t vec = make_s8vector(nitems, 0); + for(uint32_t i=0; i<nitems; i++) { + deserialize_untagged_u8(&u8, sb); + s8vector_set(vec, i, u8); + } + return vec; + } + case(UVI_U16): + { + pmt_t vec = make_u16vector(nitems, 0); + for(uint32_t i=0; i<nitems; i++) { + deserialize_untagged_u16(&u16, sb); + u16vector_set(vec, i, u16); + } + return vec; + } + case(UVI_S16): + { + pmt_t vec = make_s16vector(nitems, 0); + for(uint32_t i=0; i<nitems; i++) { + deserialize_untagged_u16(&u16, sb); + s16vector_set(vec, i, u16); + } + return vec; + } + case(UVI_U32): + { + pmt_t vec = make_u32vector(nitems, 0); + for(uint32_t i=0; i<nitems; i++) { + deserialize_untagged_u32(&u32, sb); + u32vector_set(vec, i, u32); + } + return vec; + } + case(UVI_S32): + { + pmt_t vec = make_s32vector(nitems, 0); + for(uint32_t i=0; i<nitems; i++) { + deserialize_untagged_u32(&u32, sb); + s32vector_set(vec, i, u32); + } + return vec; + } + case(UVI_U64): + { + pmt_t vec = make_u64vector(nitems, 0); + for(uint32_t i=0; i<nitems; i++) { + deserialize_untagged_u64(&u64, sb); + u64vector_set(vec, i, u64); + } + return vec; + } + case(UVI_S64): + { + pmt_t vec = make_s64vector(nitems, 0); + for(uint32_t i=0; i<nitems; i++) { + deserialize_untagged_u64(&u64, sb); + s64vector_set(vec, i, u64); + } + return vec; + } + case(UVI_F32): + { + pmt_t vec = make_f32vector(nitems, 0); + for(uint32_t i=0; i<nitems; i++) { + deserialize_untagged_f64(&f64, sb); + f32vector_set(vec, i, static_cast<float>(f64)); + } + return vec; + } + case(UVI_F64): + { + pmt_t vec = make_f64vector(nitems, 0); + for(uint32_t i=0; i<nitems; i++) { + deserialize_untagged_f64(&f64, sb); + f64vector_set(vec, i, f64); + } + return vec; + } + case(UVI_C32): + { + pmt_t vec = make_c32vector(nitems, 0); + for(uint32_t i=0; i<nitems; i++) { + float re, im; + deserialize_untagged_f64(&f64, sb); + re = static_cast<float>(f64); + deserialize_untagged_f64(&f64, sb); + im = static_cast<float>(f64); + c32vector_set(vec, i, std::complex<float>(re, im)); + } + return vec; + } + + case(UVI_C64): + { + pmt_t vec = make_c64vector(nitems, 0); + for(uint32_t i=0; i<nitems; i++) { + double re, im; + deserialize_untagged_f64(&f64, sb); + re = f64; + deserialize_untagged_f64(&f64, sb); + im = f64; + c64vector_set(vec, i, std::complex<double>(re, im)); + } + return vec; + } + + default: + throw exception("pmt::deserialize: malformed input stream, tag value = ", + from_long(tag)); + } + } + + case PST_DICT: + case PST_COMMENT: + throw notimplemented("pmt::deserialize: tag value = ", + from_long(tag)); + + default: + throw exception("pmt::deserialize: malformed input stream, tag value = ", + from_long(tag)); + } + + error: + throw exception("pmt::deserialize: malformed input stream", PMT_F); +} + + +/* + * provide a simple string accessor to the serialized pmt form + */ +std::string +serialize_str(pmt_t obj){ + std::stringbuf sb; + serialize(obj, sb); + return sb.str(); +} + + +/* + * provide a simple string accessor to the deserialized pmt form + */ +pmt_t +deserialize_str(std::string s){ + std::stringbuf sb(s); + return deserialize(sb); +} + + +/* + * 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 = deserialize(sb); // read the car + + nptr = cons(expr, PMT_NIL); // build new cell + if (is_null(lastnptr)) + val = nptr; + else + set_cdr(lastnptr, nptr); + lastnptr = nptr; + + if (!deserialize_untagged_u8(&tag, sb)) // get tag of cdr + throw exception("pmt::deserialize: malformed input stream", PMT_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 = deserialize(sb); + break; + } + + // + // At this point, expr contains the value of the final cdr in the list. + // + set_cdr(lastnptr, expr); + return val; +} + +} /* namespace pmt */ |