summaryrefslogtreecommitdiff
path: root/gnuradio-runtime/lib/pmt
diff options
context:
space:
mode:
authorTom Rondeau <trondeau@vt.edu>2013-03-29 17:31:06 -0400
committerJohnathan Corgan <johnathan@corganlabs.com>2013-04-01 16:23:06 -0700
commitf74d3dae8f2ec423c61932b4ad0359f98b996a51 (patch)
tree1e16eb3537829248c177b04209acce3fe2bead96 /gnuradio-runtime/lib/pmt
parenteea0e411411303ea94953c5cd8454c4139a474ff (diff)
gruel: moved gruel into subdirs of gnuradio-runtime.
PMTs are handled slightly different and are installed into their own module and include dir.
Diffstat (limited to 'gnuradio-runtime/lib/pmt')
-rw-r--r--gnuradio-runtime/lib/pmt/CMakeLists.txt91
-rw-r--r--gnuradio-runtime/lib/pmt/gen-serial-tags.py53
-rwxr-xr-xgnuradio-runtime/lib/pmt/generate_unv.py190
-rw-r--r--gnuradio-runtime/lib/pmt/pmt-serial-tags.scm77
-rw-r--r--gnuradio-runtime/lib/pmt/pmt.cc1436
-rw-r--r--gnuradio-runtime/lib/pmt/pmt_int.h247
-rw-r--r--gnuradio-runtime/lib/pmt/pmt_io.cc169
-rw-r--r--gnuradio-runtime/lib/pmt/pmt_pool.cc113
-rw-r--r--gnuradio-runtime/lib/pmt/pmt_serialize.cc835
-rw-r--r--gnuradio-runtime/lib/pmt/qa_pmt.cc40
-rw-r--r--gnuradio-runtime/lib/pmt/qa_pmt.h37
-rw-r--r--gnuradio-runtime/lib/pmt/qa_pmt_prims.cc603
-rw-r--r--gnuradio-runtime/lib/pmt/qa_pmt_prims.h77
-rw-r--r--gnuradio-runtime/lib/pmt/unv_qa_template.cc.t35
-rw-r--r--gnuradio-runtime/lib/pmt/unv_template.cc.t141
-rw-r--r--gnuradio-runtime/lib/pmt/unv_template.h.t23
16 files changed, 4167 insertions, 0 deletions
diff --git a/gnuradio-runtime/lib/pmt/CMakeLists.txt b/gnuradio-runtime/lib/pmt/CMakeLists.txt
new file mode 100644
index 0000000000..9d191df06a
--- /dev/null
+++ b/gnuradio-runtime/lib/pmt/CMakeLists.txt
@@ -0,0 +1,91 @@
+# Copyright 2010-2013 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 GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+########################################################################
+# This file included, use CMake directory variables
+########################################################################
+include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+include_directories(${CMAKE_CURRENT_BINARY_DIR})
+
+########################################################################
+# Generate serial tags header file
+########################################################################
+
+get_filename_component(PMT_SERIAL_TAGS_H
+ ${CMAKE_CURRENT_BINARY_DIR}/../../include/pmt/pmt_serial_tags.h ABSOLUTE
+)
+
+add_custom_command(
+ OUTPUT ${PMT_SERIAL_TAGS_H}
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/gen-serial-tags.py
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/pmt-serial-tags.scm
+ COMMAND ${PYTHON_EXECUTABLE}
+ ${CMAKE_CURRENT_SOURCE_DIR}/gen-serial-tags.py
+ ${CMAKE_CURRENT_SOURCE_DIR}/pmt-serial-tags.scm
+ ${PMT_SERIAL_TAGS_H}
+)
+
+install(
+ FILES ${PMT_SERIAL_TAGS_H}
+ DESTINATION ${GR_INCLUDE_DIR}/pmt
+ COMPONENT "runtime_devel"
+)
+
+include(AddFileDependencies)
+ADD_FILE_DEPENDENCIES(
+ ${CMAKE_CURRENT_SOURCE_DIR}/pmt_serialize.cc
+ ${PMT_SERIAL_TAGS_H}
+)
+
+add_custom_target(pmt_generated DEPENDS ${PMT_SERIAL_TAGS_H})
+
+########################################################################
+# Generate other pmt stuff
+########################################################################
+add_custom_command(
+ OUTPUT
+ ${CMAKE_CURRENT_BINARY_DIR}/pmt_unv_int.h
+ ${CMAKE_CURRENT_BINARY_DIR}/qa_pmt_unv.h
+ ${CMAKE_CURRENT_BINARY_DIR}/pmt_unv.cc
+ ${CMAKE_CURRENT_BINARY_DIR}/qa_pmt_unv.cc
+ DEPENDS
+ ${CMAKE_CURRENT_SOURCE_DIR}/generate_unv.py
+ ${CMAKE_CURRENT_SOURCE_DIR}/unv_template.h.t
+ ${CMAKE_CURRENT_SOURCE_DIR}/unv_template.cc.t
+ ${CMAKE_CURRENT_SOURCE_DIR}/unv_qa_template.cc.t
+ COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} -c
+ \"import os,sys\;srcdir='${CMAKE_CURRENT_SOURCE_DIR}'\;sys.path.append(srcdir)\;os.environ['srcdir']=srcdir\;from generate_unv import main\;main()\"
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+)
+
+list(APPEND gnuradio_runtime_sources
+ ${CMAKE_CURRENT_BINARY_DIR}/pmt_unv.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/pmt.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/pmt_io.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/pmt_pool.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/pmt_serialize.cc
+)
+
+if(ENABLE_TESTING)
+ list(APPEND test_gnuradio_runtime_sources
+ ${CMAKE_CURRENT_BINARY_DIR}/qa_pmt_unv.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/qa_pmt_prims.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/qa_pmt.cc
+ )
+endif(ENABLE_TESTING)
diff --git a/gnuradio-runtime/lib/pmt/gen-serial-tags.py b/gnuradio-runtime/lib/pmt/gen-serial-tags.py
new file mode 100644
index 0000000000..18e927beb5
--- /dev/null
+++ b/gnuradio-runtime/lib/pmt/gen-serial-tags.py
@@ -0,0 +1,53 @@
+"""
+//
+// Copyright 2011 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.
+//
+//
+// THIS FILE IS MACHINE GENERATED FROM %s. DO NOT EDIT BY HAND.
+// See %s for additional commentary.
+//
+
+#ifndef INCLUDED_PMT_SERIAL_TAGS_H
+#define INCLUDED_PMT_SERIAL_TAGS_H
+
+enum pst_tags {
+%s
+};
+#endif /* INCLUDED_PMT_SERIAL_TAGS_H */
+"""
+
+import sys, os, re
+
+if __name__ == '__main__':
+ if len(sys.argv) != 3:
+ print "Usage %s <input_scm_file> <output_hdr_file>"%__file__
+ exit()
+ input_scm_file, output_hdr_file = sys.argv[1:]
+ enums = list()
+ for line in open(input_scm_file).readlines():
+ match = re.match('^\s*\(define\s+([\w|-]+)\s+#x([0-9a-fA-F]+)\)', line)
+ if not match: continue
+ name, value = match.groups()
+ name = name.upper().replace('-', '_')
+ enums.append(' %s = 0x%s'%(name, value))
+ open(output_hdr_file, 'w').write(__doc__%(
+ os.path.basename(__file__),
+ os.path.basename(input_scm_file),
+ ',\n'.join(enums),
+ ))
diff --git a/gnuradio-runtime/lib/pmt/generate_unv.py b/gnuradio-runtime/lib/pmt/generate_unv.py
new file mode 100755
index 0000000000..7562df46f8
--- /dev/null
+++ b/gnuradio-runtime/lib/pmt/generate_unv.py
@@ -0,0 +1,190 @@
+#!/usr/bin/env python
+#
+# Copyright 2006,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 GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+"""
+Generate code for uniform numeric vectors
+"""
+
+import re, os, os.path
+
+
+unv_types = (
+ ('u8', 'uint8_t'),
+ ('s8', 'int8_t'),
+ ('u16', 'uint16_t'),
+ ('s16', 'int16_t'),
+ ('u32', 'uint32_t'),
+ ('s32', 'int32_t'),
+ ('u64', 'uint64_t'),
+ ('s64', 'int64_t'),
+ ('f32', 'float'),
+ ('f64', 'double'),
+ ('c32', 'std::complex<float>'),
+ ('c64', 'std::complex<double>')
+ )
+
+header = """\
+/* -*- c++ -*- */
+/*
+ * Copyright 2006,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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+"""
+
+guard_tail = """
+#endif
+"""
+
+includes = """
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <vector>
+#include <pmt/pmt.h>
+#include "pmt_int.h"
+"""
+
+qa_includes = """
+#include <qa_pmt_unv.h>
+#include <cppunit/TestAssert.h>
+#include <pmt/pmt.h>
+#include <stdio.h>
+
+using namespace pmt;
+"""
+
+
+# set srcdir to the directory that contains Makefile.am
+try:
+ srcdir = os.environ['srcdir']
+except KeyError, e:
+ srcdir = "."
+srcdir = srcdir + '/'
+
+
+def open_src (name, mode):
+ global srcdir
+ return open(os.path.join (srcdir, name), mode)
+
+
+def guard_name(filename):
+ return 'INCLUDED_' + re.sub('\.', '_', filename.upper())
+
+def guard_head(filename):
+ guard = guard_name(filename)
+ return """
+#ifndef %s
+#define %s
+""" % (guard, guard)
+
+
+def do_substitution (d, input, out_file):
+ def repl (match_obj):
+ key = match_obj.group (1)
+ # print key
+ return d[key]
+
+ out = re.sub (r"@([a-zA-Z0-9_]+)@", repl, input)
+ out_file.write (out)
+
+
+def generate_h():
+ template = open_src('unv_template.h.t', 'r').read()
+ output_filename = 'pmt_unv_int.h'
+ output = open(output_filename, 'w')
+ output.write(header)
+ output.write(guard_head(output_filename))
+ for tag, typ in unv_types:
+ d = { 'TAG' : tag, 'TYPE' : typ }
+ do_substitution(d, template, output)
+ output.write(guard_tail)
+
+def generate_cc():
+ template = open_src('unv_template.cc.t', 'r').read()
+ output = open('pmt_unv.cc', 'w')
+ output.write(header)
+ output.write(includes)
+ for tag, typ in unv_types:
+ d = { 'TAG' : tag, 'TYPE' : typ }
+ do_substitution(d, template, output)
+
+
+def generate_qa_h():
+ output_filename = 'qa_pmt_unv.h'
+ output = open(output_filename, 'w')
+ output.write(header)
+ output.write(guard_head(output_filename))
+
+ output.write('''
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestCase.h>
+
+class qa_pmt_unv : public CppUnit::TestCase {
+
+ CPPUNIT_TEST_SUITE(qa_pmt_unv);
+''')
+ for tag, typ in unv_types:
+ output.write(' CPPUNIT_TEST(test_%svector);\n' % (tag,))
+ output.write('''\
+ CPPUNIT_TEST_SUITE_END();
+
+ private:
+''')
+ for tag, typ in unv_types:
+ output.write(' void test_%svector();\n' % (tag,))
+ output.write('};\n')
+ output.write(guard_tail)
+
+def generate_qa_cc():
+ template = open_src('unv_qa_template.cc.t', 'r').read()
+ output = open('qa_pmt_unv.cc', 'w')
+ output.write(header)
+ output.write(qa_includes)
+ for tag, typ in unv_types:
+ d = { 'TAG' : tag, 'TYPE' : typ }
+ do_substitution(d, template, output)
+
+
+def main():
+ generate_h()
+ generate_cc()
+ generate_qa_h()
+ generate_qa_cc()
+
+if __name__ == '__main__':
+ main()
diff --git a/gnuradio-runtime/lib/pmt/pmt-serial-tags.scm b/gnuradio-runtime/lib/pmt/pmt-serial-tags.scm
new file mode 100644
index 0000000000..4f06bf75f8
--- /dev/null
+++ b/gnuradio-runtime/lib/pmt/pmt-serial-tags.scm
@@ -0,0 +1,77 @@
+;;; -*-scheme-*-
+;;;
+;;; Copyright 2007 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 (define 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.
+;;;
+
+;;; definitions of tag values used for marshalling pmt data
+
+(define pst-true #x00)
+(define pst-false #x01)
+(define pst-symbol #x02) ; untagged-int16 n; followed by n bytes of symbol name
+(define pst-int32 #x03)
+(define pst-double #x04)
+(define pst-complex #x05) ; complex<double>: real, imag
+(define pst-null #x06)
+(define pst-pair #x07) ; followed by two objects
+(define pst-vector #x08) ; untagged-int32 n; followed by n objects
+(define pst-dict #x09) ; untagged-int32 n; followed by n key/value tuples
+
+(define pst-uniform-vector #x0a)
+(define pst-uint64 #x0b)
+(define pst-tuple #x0c)
+
+;; u8, s8, u16, s16, u32, s32, u64, s64, f32, f64, c32, c64
+;;
+;; untagged-uint8 tag
+;; untagged-uint8 uvi (define uniform vector info, see below)
+;; untagged-int32 n-items
+;; untagged-uint8 npad
+;; npad bytes of zeros to align binary data
+;; n-items binary numeric items
+;;
+;; uvi:
+;; +-+-+-+-+-+-+-+-+
+;; |B| subtype |
+;; +-+-+-+-+-+-+-+-+
+;;
+;; B == 0, numeric data is little-endian.
+;; B == 1, numeric data is big-endian.
+
+ (define uvi-endian-mask #x80)
+ (define uvi-subtype-mask #x7f)
+
+ (define uvi-little-endian #x00)
+ (define uvi-big-endian #x80)
+
+ (define uvi-u8 #x00)
+ (define uvi-s8 #x01)
+ (define uvi-u16 #x02)
+ (define uvi-s16 #x03)
+ (define uvi-u32 #x04)
+ (define uvi-s32 #x05)
+ (define uvi-u64 #x06)
+ (define uvi-s64 #x07)
+ (define uvi-f32 #x08)
+ (define uvi-f64 #x09)
+ (define uvi-c32 #x0a)
+ (define uvi-c64 #x0b)
+
+
+(define pst-comment #x3b) ; ascii ';'
+(define pst-comment-end #x0a) ; ascii '\n'
diff --git a/gnuradio-runtime/lib/pmt/pmt.cc b/gnuradio-runtime/lib/pmt/pmt.cc
new file mode 100644
index 0000000000..b6b3004331
--- /dev/null
+++ b/gnuradio-runtime/lib/pmt/pmt.cc
@@ -0,0 +1,1436 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006,2009,2010 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <vector>
+#include <pmt/pmt.h>
+#include "pmt_int.h"
+#include <messages/msg_accepter.h>
+#include <pmt/pmt_pool.h>
+#include <stdio.h>
+#include <string.h>
+
+namespace pmt {
+
+static const int CACHE_LINE_SIZE = 64; // good guess
+
+# if (PMT_LOCAL_ALLOCATOR)
+
+static pmt_pool global_pmt_pool(sizeof(pmt_pair), CACHE_LINE_SIZE);
+
+void *
+pmt_base::operator new(size_t size)
+{
+ void *p = global_pmt_pool.malloc();
+
+ // fprintf(stderr, "pmt_base::new p = %p\n", p);
+ assert((reinterpret_cast<intptr_t>(p) & (CACHE_LINE_SIZE - 1)) == 0);
+ return p;
+}
+
+void
+pmt_base::operator delete(void *p, size_t size)
+{
+ global_pmt_pool.free(p);
+}
+
+#endif
+
+void intrusive_ptr_add_ref(pmt_base* p) { ++(p->count_); }
+void intrusive_ptr_release(pmt_base* p) { if (--(p->count_) == 0 ) delete p; }
+
+pmt_base::~pmt_base()
+{
+ // nop -- out of line virtual destructor
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Exceptions
+////////////////////////////////////////////////////////////////////////////
+
+exception::exception(const std::string &msg, pmt_t obj)
+ : logic_error(msg + ": " + write_string(obj))
+{
+}
+
+wrong_type::wrong_type(const std::string &msg, pmt_t obj)
+ : exception(msg + ": wrong_type ", obj)
+{
+}
+
+out_of_range::out_of_range(const std::string &msg, pmt_t obj)
+ : exception(msg + ": out of range ", obj)
+{
+}
+
+notimplemented::notimplemented(const std::string &msg, pmt_t obj)
+ : exception(msg + ": notimplemented ", obj)
+{
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Dynamic Casts
+////////////////////////////////////////////////////////////////////////////
+
+static pmt_symbol *
+_symbol(pmt_t x)
+{
+ return dynamic_cast<pmt_symbol*>(x.get());
+}
+
+static pmt_integer *
+_integer(pmt_t x)
+{
+ return dynamic_cast<pmt_integer*>(x.get());
+}
+
+static pmt_uint64 *
+_uint64(pmt_t x)
+{
+ return dynamic_cast<pmt_uint64*>(x.get());
+}
+
+static pmt_real *
+_real(pmt_t x)
+{
+ return dynamic_cast<pmt_real*>(x.get());
+}
+
+static pmt_complex *
+_complex(pmt_t x)
+{
+ return dynamic_cast<pmt_complex*>(x.get());
+}
+
+static pmt_pair *
+_pair(pmt_t x)
+{
+ return dynamic_cast<pmt_pair*>(x.get());
+}
+
+static pmt_vector *
+_vector(pmt_t x)
+{
+ return dynamic_cast<pmt_vector*>(x.get());
+}
+
+static pmt_tuple *
+_tuple(pmt_t x)
+{
+ return dynamic_cast<pmt_tuple*>(x.get());
+}
+
+static pmt_uniform_vector *
+_uniform_vector(pmt_t x)
+{
+ return dynamic_cast<pmt_uniform_vector*>(x.get());
+}
+
+static pmt_any *
+_any(pmt_t x)
+{
+ return dynamic_cast<pmt_any*>(x.get());
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Globals
+////////////////////////////////////////////////////////////////////////////
+
+const pmt_t PMT_T = pmt_t(new pmt_bool()); // singleton
+const pmt_t PMT_F = pmt_t(new pmt_bool()); // singleton
+const pmt_t PMT_NIL = pmt_t(new pmt_null()); // singleton
+const pmt_t PMT_EOF = cons(PMT_NIL, PMT_NIL); // singleton
+
+////////////////////////////////////////////////////////////////////////////
+// Booleans
+////////////////////////////////////////////////////////////////////////////
+
+pmt_bool::pmt_bool(){}
+
+bool
+is_true(pmt_t obj)
+{
+ return obj != PMT_F;
+}
+
+bool
+is_false(pmt_t obj)
+{
+ return obj == PMT_F;
+}
+
+bool
+is_bool(pmt_t obj)
+{
+ return obj->is_bool();
+}
+
+pmt_t
+from_bool(bool val)
+{
+ return val ? PMT_T : PMT_F;
+}
+
+bool
+to_bool(pmt_t val)
+{
+ if (val == PMT_T)
+ return true;
+ if (val == PMT_F)
+ return false;
+ throw wrong_type("pmt_to_bool", val);
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Symbols
+////////////////////////////////////////////////////////////////////////////
+
+static const unsigned int SYMBOL_HASH_TABLE_SIZE = 701;
+static std::vector<pmt_t> s_symbol_hash_table(SYMBOL_HASH_TABLE_SIZE);
+
+pmt_symbol::pmt_symbol(const std::string &name) : d_name(name){}
+
+
+static unsigned int
+hash_string(const std::string &s)
+{
+ unsigned int h = 0;
+ unsigned int g = 0;
+
+ for (std::string::const_iterator p = s.begin(); p != s.end(); ++p){
+ h = (h << 4) + (*p & 0xff);
+ g = h & 0xf0000000;
+ if (g){
+ h = h ^ (g >> 24);
+ h = h ^ g;
+ }
+ }
+ return h;
+}
+
+bool
+is_symbol(const pmt_t& obj)
+{
+ return obj->is_symbol();
+}
+
+pmt_t
+string_to_symbol(const std::string &name)
+{
+ unsigned hash = hash_string(name) % SYMBOL_HASH_TABLE_SIZE;
+
+ // Does a symbol with this name already exist?
+ for (pmt_t sym = s_symbol_hash_table[hash]; sym; sym = _symbol(sym)->next()){
+ if (name == _symbol(sym)->name())
+ return sym; // Yes. Return it
+ }
+
+ // Nope. Make a new one.
+ pmt_t sym = pmt_t(new pmt_symbol(name));
+ _symbol(sym)->set_next(s_symbol_hash_table[hash]);
+ s_symbol_hash_table[hash] = sym;
+ return sym;
+}
+
+// alias...
+pmt_t
+intern(const std::string &name)
+{
+ return string_to_symbol(name);
+}
+
+const std::string
+symbol_to_string(const pmt_t& sym)
+{
+ if (!sym->is_symbol())
+ throw wrong_type("pmt_symbol_to_string", sym);
+
+ return _symbol(sym)->name();
+}
+
+
+
+////////////////////////////////////////////////////////////////////////////
+// Number
+////////////////////////////////////////////////////////////////////////////
+
+bool
+is_number(pmt_t x)
+{
+ return x->is_number();
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Integer
+////////////////////////////////////////////////////////////////////////////
+
+pmt_integer::pmt_integer(long value) : d_value(value) {}
+
+bool
+is_integer(pmt_t x)
+{
+ return x->is_integer();
+}
+
+
+pmt_t
+from_long(long x)
+{
+ return pmt_t(new pmt_integer(x));
+}
+
+long
+to_long(pmt_t x)
+{
+ pmt_integer* i = dynamic_cast<pmt_integer*>(x.get());
+ if ( i )
+ return i->value();
+
+ throw wrong_type("pmt_to_long", x);
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Uint64
+////////////////////////////////////////////////////////////////////////////
+
+pmt_uint64::pmt_uint64(uint64_t value) : d_value(value) {}
+
+bool
+is_uint64(pmt_t x)
+{
+ return x->is_uint64();
+}
+
+
+pmt_t
+from_uint64(uint64_t x)
+{
+ return pmt_t(new pmt_uint64(x));
+}
+
+uint64_t
+to_uint64(pmt_t x)
+{
+ if(x->is_uint64())
+ return _uint64(x)->value();
+ if(x->is_integer())
+ {
+ long tmp = _integer(x)->value();
+ if(tmp >= 0)
+ return (uint64_t) tmp;
+ }
+
+ throw wrong_type("pmt_to_uint64", x);
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Real
+////////////////////////////////////////////////////////////////////////////
+
+pmt_real::pmt_real(double value) : d_value(value) {}
+
+bool
+is_real(pmt_t x)
+{
+ return x->is_real();
+}
+
+pmt_t
+from_double(double x)
+{
+ return pmt_t(new pmt_real(x));
+}
+
+double
+to_double(pmt_t x)
+{
+ if (x->is_real())
+ return _real(x)->value();
+ if (x->is_integer())
+ return _integer(x)->value();
+
+ throw wrong_type("pmt_to_double", x);
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Complex
+////////////////////////////////////////////////////////////////////////////
+
+pmt_complex::pmt_complex(std::complex<double> value) : d_value(value) {}
+
+bool
+is_complex(pmt_t x)
+{
+ return x->is_complex();
+}
+
+pmt_t
+make_rectangular(double re, double im)
+{
+ return from_complex(re, im);
+}
+
+pmt_t
+from_complex(double re, double im)
+{
+ return pmt_from_complex(re, im);
+}
+
+pmt_t pmt_from_complex(double re, double im)
+{
+ return pmt_t(new pmt_complex(std::complex<double>(re, im)));
+}
+
+pmt_t
+from_complex(const std::complex<double> &z)
+{
+ return pmt_t(new pmt_complex(z));
+}
+
+std::complex<double>
+to_complex(pmt_t x)
+{
+ if (x->is_complex())
+ return _complex(x)->value();
+ if (x->is_real())
+ return _real(x)->value();
+ if (x->is_integer())
+ return _integer(x)->value();
+
+ throw wrong_type("pmt_to_complex", x);
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Pairs
+////////////////////////////////////////////////////////////////////////////
+
+pmt_null::pmt_null() {}
+pmt_pair::pmt_pair(const pmt_t& car, const pmt_t& cdr) : d_car(car), d_cdr(cdr) {}
+
+bool
+is_null(const pmt_t& x)
+{
+ return x == PMT_NIL;
+}
+
+bool
+is_pair(const pmt_t& obj)
+{
+ return obj->is_pair();
+}
+
+pmt_t
+cons(const pmt_t& x, const pmt_t& y)
+{
+ return pmt_t(new pmt_pair(x, y));
+}
+
+pmt_t
+car(const pmt_t& pair)
+{
+ pmt_pair* p = dynamic_cast<pmt_pair*>(pair.get());
+ if ( p )
+ return p->car();
+
+ throw wrong_type("pmt_car", pair);
+}
+
+pmt_t
+cdr(const pmt_t& pair)
+{
+ pmt_pair* p = dynamic_cast<pmt_pair*>(pair.get());
+ if ( p )
+ return p->cdr();
+
+ throw wrong_type("pmt_cdr", pair);
+}
+
+void
+set_car(pmt_t pair, pmt_t obj)
+{
+ if (pair->is_pair())
+ _pair(pair)->set_car(obj);
+ else
+ throw wrong_type("pmt_set_car", pair);
+}
+
+void
+set_cdr(pmt_t pair, pmt_t obj)
+{
+ if (pair->is_pair())
+ _pair(pair)->set_cdr(obj);
+ else
+ throw wrong_type("pmt_set_cdr", pair);
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Vectors
+////////////////////////////////////////////////////////////////////////////
+
+pmt_vector::pmt_vector(size_t len, pmt_t fill)
+ : d_v(len)
+{
+ for (size_t i = 0; i < len; i++)
+ d_v[i] = fill;
+}
+
+pmt_t
+pmt_vector::ref(size_t k) const
+{
+ if (k >= length())
+ throw out_of_range("pmt_vector_ref", from_long(k));
+ return d_v[k];
+}
+
+void
+pmt_vector::set(size_t k, pmt_t obj)
+{
+ if (k >= length())
+ throw out_of_range("pmt_vector_set", from_long(k));
+ d_v[k] = obj;
+}
+
+void
+pmt_vector::fill(pmt_t obj)
+{
+ for (size_t i = 0; i < length(); i++)
+ d_v[i] = obj;
+}
+
+bool
+is_vector(pmt_t obj)
+{
+ return obj->is_vector();
+}
+
+pmt_t
+make_vector(size_t k, pmt_t fill)
+{
+ return pmt_t(new pmt_vector(k, fill));
+}
+
+pmt_t
+vector_ref(pmt_t vector, size_t k)
+{
+ if (!vector->is_vector())
+ throw wrong_type("pmt_vector_ref", vector);
+ return _vector(vector)->ref(k);
+}
+
+void
+vector_set(pmt_t vector, size_t k, pmt_t obj)
+{
+ if (!vector->is_vector())
+ throw wrong_type("pmt_vector_set", vector);
+ _vector(vector)->set(k, obj);
+}
+
+void
+vector_fill(pmt_t vector, pmt_t obj)
+{
+ if (!vector->is_vector())
+ throw wrong_type("pmt_vector_set", vector);
+ _vector(vector)->fill(obj);
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Tuples
+////////////////////////////////////////////////////////////////////////////
+
+pmt_tuple::pmt_tuple(size_t len)
+ : d_v(len)
+{
+}
+
+pmt_t
+pmt_tuple::ref(size_t k) const
+{
+ if (k >= length())
+ throw out_of_range("pmt_tuple_ref", from_long(k));
+ return d_v[k];
+}
+
+bool
+is_tuple(pmt_t obj)
+{
+ return obj->is_tuple();
+}
+
+pmt_t
+tuple_ref(const pmt_t &tuple, size_t k)
+{
+ if (!tuple->is_tuple())
+ throw wrong_type("pmt_tuple_ref", tuple);
+ return _tuple(tuple)->ref(k);
+}
+
+// for (i=0; i < 10; i++)
+// make_constructor()
+
+pmt_t
+make_tuple()
+{
+ return pmt_t(new pmt_tuple(0));
+}
+
+pmt_t
+make_tuple(const pmt_t &e0)
+{
+ pmt_tuple *t = new pmt_tuple(1);
+ t->_set(0, e0);
+ return pmt_t(t);
+}
+
+pmt_t
+make_tuple(const pmt_t &e0, const pmt_t &e1)
+{
+ pmt_tuple *t = new pmt_tuple(2);
+ t->_set(0, e0);
+ t->_set(1, e1);
+ return pmt_t(t);
+}
+
+pmt_t
+make_tuple(const pmt_t &e0, const pmt_t &e1, const pmt_t &e2)
+{
+ pmt_tuple *t = new pmt_tuple(3);
+ t->_set(0, e0);
+ t->_set(1, e1);
+ t->_set(2, e2);
+ return pmt_t(t);
+}
+
+pmt_t
+make_tuple(const pmt_t &e0, const pmt_t &e1, const pmt_t &e2, const pmt_t &e3)
+{
+ pmt_tuple *t = new pmt_tuple(4);
+ t->_set(0, e0);
+ t->_set(1, e1);
+ t->_set(2, e2);
+ t->_set(3, e3);
+ return pmt_t(t);
+}
+
+pmt_t
+make_tuple(const pmt_t &e0, const pmt_t &e1, const pmt_t &e2, const pmt_t &e3, const pmt_t &e4)
+{
+ pmt_tuple *t = new pmt_tuple(5);
+ t->_set(0, e0);
+ t->_set(1, e1);
+ t->_set(2, e2);
+ t->_set(3, e3);
+ t->_set(4, e4);
+ return pmt_t(t);
+}
+
+pmt_t
+make_tuple(const pmt_t &e0, const pmt_t &e1, const pmt_t &e2, const pmt_t &e3, const pmt_t &e4, const pmt_t &e5)
+{
+ pmt_tuple *t = new pmt_tuple(6);
+ t->_set(0, e0);
+ t->_set(1, e1);
+ t->_set(2, e2);
+ t->_set(3, e3);
+ t->_set(4, e4);
+ t->_set(5, e5);
+ return pmt_t(t);
+}
+
+pmt_t
+make_tuple(const pmt_t &e0, const pmt_t &e1, const pmt_t &e2, const pmt_t &e3, const pmt_t &e4, const pmt_t &e5, const pmt_t &e6)
+{
+ pmt_tuple *t = new pmt_tuple(7);
+ t->_set(0, e0);
+ t->_set(1, e1);
+ t->_set(2, e2);
+ t->_set(3, e3);
+ t->_set(4, e4);
+ t->_set(5, e5);
+ t->_set(6, e6);
+ return pmt_t(t);
+}
+
+pmt_t
+make_tuple(const pmt_t &e0, const pmt_t &e1, const pmt_t &e2, const pmt_t &e3, const pmt_t &e4, const pmt_t &e5, const pmt_t &e6, const pmt_t &e7)
+{
+ pmt_tuple *t = new pmt_tuple(8);
+ t->_set(0, e0);
+ t->_set(1, e1);
+ t->_set(2, e2);
+ t->_set(3, e3);
+ t->_set(4, e4);
+ t->_set(5, e5);
+ t->_set(6, e6);
+ t->_set(7, e7);
+ return pmt_t(t);
+}
+
+pmt_t
+make_tuple(const pmt_t &e0, const pmt_t &e1, const pmt_t &e2, const pmt_t &e3, const pmt_t &e4, const pmt_t &e5, const pmt_t &e6, const pmt_t &e7, const pmt_t &e8)
+{
+ pmt_tuple *t = new pmt_tuple(9);
+ t->_set(0, e0);
+ t->_set(1, e1);
+ t->_set(2, e2);
+ t->_set(3, e3);
+ t->_set(4, e4);
+ t->_set(5, e5);
+ t->_set(6, e6);
+ t->_set(7, e7);
+ t->_set(8, e8);
+ return pmt_t(t);
+}
+
+pmt_t
+make_tuple(const pmt_t &e0, const pmt_t &e1, const pmt_t &e2, const pmt_t &e3, const pmt_t &e4, const pmt_t &e5, const pmt_t &e6, const pmt_t &e7, const pmt_t &e8, const pmt_t &e9)
+{
+ pmt_tuple *t = new pmt_tuple(10);
+ t->_set(0, e0);
+ t->_set(1, e1);
+ t->_set(2, e2);
+ t->_set(3, e3);
+ t->_set(4, e4);
+ t->_set(5, e5);
+ t->_set(6, e6);
+ t->_set(7, e7);
+ t->_set(8, e8);
+ t->_set(9, e9);
+ return pmt_t(t);
+}
+
+pmt_t
+to_tuple(const pmt_t &x)
+{
+ if (x->is_tuple()) // already one
+ return x;
+
+ size_t len = length(x);
+ pmt_tuple *t = new pmt_tuple(len);
+ pmt_t r = pmt_t(t);
+
+ if (x->is_vector()){
+ for (size_t i = 0; i < len; i++)
+ t->_set(i, _vector(x)->ref(i));
+ return r;
+ }
+
+ if (x->is_pair()){
+ pmt_t y = x;
+ for (size_t i = 0; i < len; i++){
+ t->_set(i, car(y));
+ y = cdr(y);
+ }
+ return r;
+ }
+
+ throw wrong_type("pmt_to_tuple", x);
+}
+
+
+
+////////////////////////////////////////////////////////////////////////////
+// Uniform Numeric Vectors
+////////////////////////////////////////////////////////////////////////////
+
+bool
+is_uniform_vector(pmt_t x)
+{
+ return x->is_uniform_vector();
+}
+
+const void *
+uniform_vector_elements(pmt_t vector, size_t &len)
+{
+ if (!vector->is_uniform_vector())
+ throw wrong_type("pmt_uniform_vector_elements", vector);
+ return _uniform_vector(vector)->uniform_elements(len);
+}
+
+void *
+uniform_vector_writable_elements(pmt_t vector, size_t &len)
+{
+ if (!vector->is_uniform_vector())
+ throw wrong_type("pmt_uniform_vector_writable_elements", vector);
+ return _uniform_vector(vector)->uniform_writable_elements(len);
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Dictionaries
+////////////////////////////////////////////////////////////////////////////
+
+/*
+ * This is an a-list implementation.
+ *
+ * When we need better performance for large dictionaries, consider implementing
+ * persistent Red-Black trees as described in "Purely Functional Data Structures",
+ * Chris Okasaki, 1998, section 3.3.
+ */
+
+bool
+is_dict(const pmt_t &obj)
+{
+ return is_null(obj) || is_pair(obj);
+}
+
+pmt_t
+make_dict()
+{
+ return PMT_NIL;
+}
+
+pmt_t
+dict_add(const pmt_t &dict, const pmt_t &key, const pmt_t &value)
+{
+ if (is_null(dict))
+ return acons(key, value, PMT_NIL);
+
+ if (dict_has_key(dict, key))
+ return acons(key, value, dict_delete(dict, key));
+
+ return acons(key, value, dict);
+}
+
+pmt_t
+dict_delete(const pmt_t &dict, const pmt_t &key)
+{
+ if (is_null(dict))
+ return dict;
+
+ if (eqv(caar(dict), key))
+ return cdr(dict);
+
+ return cons(car(dict), dict_delete(cdr(dict), key));
+}
+
+pmt_t
+dict_ref(const pmt_t &dict, const pmt_t &key, const pmt_t &not_found)
+{
+ pmt_t p = assv(key, dict); // look for (key . value) pair
+ if (is_pair(p))
+ return cdr(p);
+ else
+ return not_found;
+}
+
+bool
+dict_has_key(const pmt_t &dict, const pmt_t &key)
+{
+ return is_pair(assv(key, dict));
+}
+
+pmt_t
+dict_items(pmt_t dict)
+{
+ if (!is_dict(dict))
+ throw wrong_type("pmt_dict_values", dict);
+
+ return dict; // equivalent to dict in the a-list case
+}
+
+pmt_t
+dict_keys(pmt_t dict)
+{
+ if (!is_dict(dict))
+ throw wrong_type("pmt_dict_keys", dict);
+
+ return map(car, dict);
+}
+
+pmt_t
+dict_values(pmt_t dict)
+{
+ if (!is_dict(dict))
+ throw wrong_type("pmt_dict_keys", dict);
+
+ return map(cdr, dict);
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Any
+////////////////////////////////////////////////////////////////////////////
+
+pmt_any::pmt_any(const boost::any &any) : d_any(any) {}
+
+bool
+is_any(pmt_t obj)
+{
+ return obj->is_any();
+}
+
+pmt_t
+make_any(const boost::any &any)
+{
+ return pmt_t(new pmt_any(any));
+}
+
+boost::any
+any_ref(pmt_t obj)
+{
+ if (!obj->is_any())
+ throw wrong_type("pmt_any_ref", obj);
+ return _any(obj)->ref();
+}
+
+void
+any_set(pmt_t obj, const boost::any &any)
+{
+ if (!obj->is_any())
+ throw wrong_type("pmt_any_set", obj);
+ _any(obj)->set(any);
+}
+
+////////////////////////////////////////////////////////////////////////////
+// msg_accepter -- built from "any"
+////////////////////////////////////////////////////////////////////////////
+
+bool
+is_msg_accepter(const pmt_t &obj)
+{
+ if (!is_any(obj))
+ return false;
+
+ boost::any r = any_ref(obj);
+ return boost::any_cast<gr::messages::msg_accepter_sptr>(&r) != 0;
+}
+
+//! make a msg_accepter
+pmt_t
+make_msg_accepter(gr::messages::msg_accepter_sptr ma)
+{
+ return make_any(ma);
+}
+
+//! Return underlying msg_accepter
+gr::messages::msg_accepter_sptr
+msg_accepter_ref(const pmt_t &obj)
+{
+ try {
+ return boost::any_cast<gr::messages::msg_accepter_sptr>(any_ref(obj));
+ }
+ catch (boost::bad_any_cast &e){
+ throw wrong_type("pmt_msg_accepter_ref", obj);
+ }
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+// Binary Large Object -- currently a u8vector
+////////////////////////////////////////////////////////////////////////////
+
+bool
+is_blob(pmt_t x)
+{
+ // return is_u8vector(x);
+ return is_uniform_vector(x);
+}
+
+pmt_t
+make_blob(const void *buf, size_t len_in_bytes)
+{
+ return init_u8vector(len_in_bytes, (const uint8_t *) buf);
+}
+
+const void *
+blob_data(pmt_t blob)
+{
+ size_t len;
+ return uniform_vector_elements(blob, len);
+}
+
+size_t
+blob_length(pmt_t blob)
+{
+ size_t len;
+ uniform_vector_elements(blob, len);
+ return len;
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+// General Functions
+////////////////////////////////////////////////////////////////////////////
+
+bool
+eq(const pmt_t& x, const pmt_t& y)
+{
+ return x == y;
+}
+
+bool
+eqv(const pmt_t& x, const pmt_t& y)
+{
+ if (x == y)
+ return true;
+
+ if (x->is_integer() && y->is_integer())
+ return _integer(x)->value() == _integer(y)->value();
+
+ if (x->is_uint64() && y->is_uint64())
+ return _uint64(x)->value() == _uint64(y)->value();
+
+ if (x->is_real() && y->is_real())
+ return _real(x)->value() == _real(y)->value();
+
+ if (x->is_complex() && y->is_complex())
+ return _complex(x)->value() == _complex(y)->value();
+
+ return false;
+}
+
+bool
+eqv_raw(pmt_base *x, pmt_base *y)
+{
+ if (x == y)
+ return true;
+
+ if (x->is_integer() && y->is_integer())
+ return _integer(x)->value() == _integer(y)->value();
+
+ if (x->is_uint64() && y->is_uint64())
+ return _uint64(x)->value() == _uint64(y)->value();
+
+ if (x->is_real() && y->is_real())
+ return _real(x)->value() == _real(y)->value();
+
+ if (x->is_complex() && y->is_complex())
+ return _complex(x)->value() == _complex(y)->value();
+
+ return false;
+}
+
+bool
+equal(const pmt_t& x, const pmt_t& y)
+{
+ if (eqv(x, y))
+ return true;
+
+ if (x->is_pair() && y->is_pair())
+ return equal(car(x), car(y)) && equal(cdr(x), cdr(y));
+
+ if (x->is_vector() && y->is_vector()){
+ pmt_vector *xv = _vector(x);
+ pmt_vector *yv = _vector(y);
+ if (xv->length() != yv->length())
+ return false;
+
+ for (unsigned i = 0; i < xv->length(); i++)
+ if (!equal(xv->_ref(i), yv->_ref(i)))
+ return false;
+
+ return true;
+ }
+
+ if (x->is_tuple() && y->is_tuple()){
+ pmt_tuple *xv = _tuple(x);
+ pmt_tuple *yv = _tuple(y);
+ if (xv->length() != yv->length())
+ return false;
+
+ for (unsigned i = 0; i < xv->length(); i++)
+ if (!equal(xv->_ref(i), yv->_ref(i)))
+ return false;
+
+ return true;
+ }
+
+ if (x->is_uniform_vector() && y->is_uniform_vector()){
+ pmt_uniform_vector *xv = _uniform_vector(x);
+ pmt_uniform_vector *yv = _uniform_vector(y);
+ if (xv->length() != yv->length())
+ return false;
+
+ size_t len_x, len_y;
+ if (memcmp(xv->uniform_elements(len_x),
+ yv->uniform_elements(len_y),
+ len_x) == 0)
+ return true;
+
+ return true;
+ }
+
+ // FIXME add other cases here...
+
+ return false;
+}
+
+size_t
+length(const pmt_t& x)
+{
+ if (x->is_vector())
+ return _vector(x)->length();
+
+ if (x->is_uniform_vector())
+ return _uniform_vector(x)->length();
+
+ if (x->is_tuple())
+ return _tuple(x)->length();
+
+ if (x->is_null())
+ return 0;
+
+ if (x->is_pair()) {
+ size_t length=1;
+ pmt_t it = cdr(x);
+ while (is_pair(it)){
+ length++;
+ it = cdr(it);
+ }
+ if (is_null(it))
+ return length;
+
+ // not a proper list
+ throw wrong_type("pmt_length", x);
+ }
+
+ // FIXME dictionary length (number of entries)
+
+ throw wrong_type("pmt_length", x);
+}
+
+pmt_t
+assq(pmt_t obj, pmt_t alist)
+{
+ while (is_pair(alist)){
+ pmt_t p = car(alist);
+ if (!is_pair(p)) // malformed alist
+ return PMT_F;
+
+ if (eq(obj, car(p)))
+ return p;
+
+ alist = cdr(alist);
+ }
+ return PMT_F;
+}
+
+/*
+ * This avoids a bunch of shared_pointer reference count manipulation.
+ */
+pmt_t
+assv_raw(pmt_base *obj, pmt_base *alist)
+{
+ while (alist->is_pair()){
+ pmt_base *p = ((pmt_pair *)alist)->d_car.get();
+ if (!p->is_pair()) // malformed alist
+ return PMT_F;
+
+ if (eqv_raw(obj, ((pmt_pair *)p)->d_car.get()))
+ return ((pmt_pair *)alist)->d_car;
+
+ alist = (((pmt_pair *)alist)->d_cdr).get();
+ }
+ return PMT_F;
+}
+
+#if 1
+
+pmt_t
+assv(pmt_t obj, pmt_t alist)
+{
+ return assv_raw(obj.get(), alist.get());
+}
+
+#else
+
+pmt_t
+assv(pmt_t obj, pmt_t alist)
+{
+ while (is_pair(alist)){
+ pmt_t p = car(alist);
+ if (!is_pair(p)) // malformed alist
+ return PMT_F;
+
+ if (eqv(obj, car(p)))
+ return p;
+
+ alist = cdr(alist);
+ }
+ return PMT_F;
+}
+
+#endif
+
+
+pmt_t
+assoc(pmt_t obj, pmt_t alist)
+{
+ while (is_pair(alist)){
+ pmt_t p = car(alist);
+ if (!is_pair(p)) // malformed alist
+ return PMT_F;
+
+ if (equal(obj, car(p)))
+ return p;
+
+ alist = cdr(alist);
+ }
+ return PMT_F;
+}
+
+pmt_t
+map(pmt_t proc(const pmt_t&), pmt_t list)
+{
+ pmt_t r = PMT_NIL;
+
+ while(is_pair(list)){
+ r = cons(proc(car(list)), r);
+ list = cdr(list);
+ }
+
+ return reverse_x(r);
+}
+
+pmt_t
+reverse(pmt_t listx)
+{
+ pmt_t list = listx;
+ pmt_t r = PMT_NIL;
+
+ while(is_pair(list)){
+ r = cons(car(list), r);
+ list = cdr(list);
+ }
+ if (is_null(list))
+ return r;
+ else
+ throw wrong_type("pmt_reverse", listx);
+}
+
+pmt_t
+reverse_x(pmt_t list)
+{
+ // FIXME do it destructively
+ return reverse(list);
+}
+
+pmt_t
+nth(size_t n, pmt_t list)
+{
+ pmt_t t = nthcdr(n, list);
+ if (is_pair(t))
+ return car(t);
+ else
+ return PMT_NIL;
+}
+
+pmt_t
+nthcdr(size_t n, pmt_t list)
+{
+ if (!(is_pair(list) || is_null(list)))
+ throw wrong_type("pmt_nthcdr", list);
+
+ while (n > 0){
+ if (is_pair(list)){
+ list = cdr(list);
+ n--;
+ continue;
+ }
+ if (is_null(list))
+ return PMT_NIL;
+ else
+ throw wrong_type("pmt_nthcdr: not a LIST", list);
+ }
+ return list;
+}
+
+pmt_t
+memq(pmt_t obj, pmt_t list)
+{
+ while (is_pair(list)){
+ if (eq(obj, car(list)))
+ return list;
+ list = cdr(list);
+ }
+ return PMT_F;
+}
+
+pmt_t
+memv(pmt_t obj, pmt_t list)
+{
+ while (is_pair(list)){
+ if (eqv(obj, car(list)))
+ return list;
+ list = cdr(list);
+ }
+ return PMT_F;
+}
+
+pmt_t
+member(pmt_t obj, pmt_t list)
+{
+ while (is_pair(list)){
+ if (equal(obj, car(list)))
+ return list;
+ list = cdr(list);
+ }
+ return PMT_F;
+}
+
+bool
+subsetp(pmt_t list1, pmt_t list2)
+{
+ while (is_pair(list1)){
+ pmt_t p = car(list1);
+ if (is_false(memv(p, list2)))
+ return false;
+ list1 = cdr(list1);
+ }
+ return true;
+}
+
+pmt_t
+list1(const pmt_t& x1)
+{
+ return cons(x1, PMT_NIL);
+}
+
+pmt_t
+list2(const pmt_t& x1, const pmt_t& x2)
+{
+ return cons(x1, cons(x2, PMT_NIL));
+}
+
+pmt_t
+list3(const pmt_t& x1, const pmt_t& x2, const pmt_t& x3)
+{
+ return cons(x1, cons(x2, cons(x3, PMT_NIL)));
+}
+
+pmt_t
+list4(const pmt_t& x1, const pmt_t& x2, const pmt_t& x3, const pmt_t& x4)
+{
+ return cons(x1, cons(x2, cons(x3, cons(x4, PMT_NIL))));
+}
+
+pmt_t
+list5(const pmt_t& x1, const pmt_t& x2, const pmt_t& x3, const pmt_t& x4, const pmt_t& x5)
+{
+ return cons(x1, cons(x2, cons(x3, cons(x4, cons(x5, PMT_NIL)))));
+}
+
+pmt_t
+list6(const pmt_t& x1, const pmt_t& x2, const pmt_t& x3, const pmt_t& x4, const pmt_t& x5, const pmt_t& x6)
+{
+ return cons(x1, cons(x2, cons(x3, cons(x4, cons(x5, cons(x6, PMT_NIL))))));
+}
+
+pmt_t
+list_add(pmt_t list, const pmt_t& item)
+{
+ return reverse(cons(item, reverse(list)));
+}
+
+pmt_t
+list_rm(pmt_t list, const pmt_t& item)
+{
+ if(is_pair(list)){
+ pmt_t left = car(list);
+ pmt_t right = cdr(list);
+ if(!equal(left, item)){
+ return cons(left, list_rm(right, item));
+ } else {
+ return list_rm(right, item);
+ }
+ } else {
+ return list;
+ }
+}
+
+bool
+list_has(pmt_t list, const pmt_t& item)
+{
+ if(is_pair(list)){
+ pmt_t left = car(list);
+ pmt_t right = cdr(list);
+ if(equal(left,item))
+ return true;
+ return list_has(right, item);
+ } else {
+ if(is_null(list))
+ return false;
+ throw std::runtime_error("list contains invalid format!");
+ }
+}
+
+pmt_t
+caar(pmt_t pair)
+{
+ return (car(car(pair)));
+}
+
+pmt_t
+cadr(pmt_t pair)
+{
+ return car(cdr(pair));
+}
+
+pmt_t
+cdar(pmt_t pair)
+{
+ return cdr(car(pair));
+}
+
+pmt_t
+cddr(pmt_t pair)
+{
+ return cdr(cdr(pair));
+}
+
+pmt_t
+caddr(pmt_t pair)
+{
+ return car(cdr(cdr(pair)));
+}
+
+pmt_t
+cadddr(pmt_t pair)
+{
+ return car(cdr(cdr(cdr(pair))));
+}
+
+bool
+is_eof_object(pmt_t obj)
+{
+ return eq(obj, PMT_EOF);
+}
+
+void
+dump_sizeof()
+{
+ printf("sizeof(pmt_t) = %3zd\n", sizeof(pmt_t));
+ printf("sizeof(pmt_base) = %3zd\n", sizeof(pmt_base));
+ printf("sizeof(pmt_bool) = %3zd\n", sizeof(pmt_bool));
+ printf("sizeof(pmt_symbol) = %3zd\n", sizeof(pmt_symbol));
+ printf("sizeof(pmt_integer) = %3zd\n", sizeof(pmt_integer));
+ printf("sizeof(pmt_uint64) = %3zd\n", sizeof(pmt_uint64));
+ printf("sizeof(pmt_real) = %3zd\n", sizeof(pmt_real));
+ printf("sizeof(pmt_complex) = %3zd\n", sizeof(pmt_complex));
+ printf("sizeof(pmt_null) = %3zd\n", sizeof(pmt_null));
+ printf("sizeof(pmt_pair) = %3zd\n", sizeof(pmt_pair));
+ printf("sizeof(pmt_vector) = %3zd\n", sizeof(pmt_vector));
+ printf("sizeof(pmt_uniform_vector) = %3zd\n", sizeof(pmt_uniform_vector));
+}
+
+} /* namespace pmt */
diff --git a/gnuradio-runtime/lib/pmt/pmt_int.h b/gnuradio-runtime/lib/pmt/pmt_int.h
new file mode 100644
index 0000000000..aceb7b74d9
--- /dev/null
+++ b/gnuradio-runtime/lib/pmt/pmt_int.h
@@ -0,0 +1,247 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006,2009,2010 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef INCLUDED_PMT_INT_H
+#define INCLUDED_PMT_INT_H
+
+#include <pmt/pmt.h>
+#include <boost/utility.hpp>
+#include <boost/detail/atomic_count.hpp>
+
+/*
+ * EVERYTHING IN THIS FILE IS PRIVATE TO THE IMPLEMENTATION!
+ *
+ * See pmt.h for the public interface
+ */
+
+#define PMT_LOCAL_ALLOCATOR 0 // define to 0 or 1
+namespace pmt {
+
+class PMT_API pmt_base : boost::noncopyable {
+ mutable boost::detail::atomic_count count_;
+
+protected:
+ pmt_base() : count_(0) {};
+ virtual ~pmt_base();
+
+public:
+ virtual bool is_bool() const { return false; }
+ virtual bool is_symbol() const { return false; }
+ virtual bool is_number() const { return false; }
+ virtual bool is_integer() const { return false; }
+ virtual bool is_uint64() const { return false; }
+ virtual bool is_real() const { return false; }
+ virtual bool is_complex() const { return false; }
+ virtual bool is_null() const { return false; }
+ virtual bool is_pair() const { return false; }
+ virtual bool is_tuple() const { return false; }
+ virtual bool is_vector() const { return false; }
+ virtual bool is_dict() const { return false; }
+ virtual bool is_any() const { return false; }
+
+ virtual bool is_uniform_vector() const { return false; }
+ virtual bool is_u8vector() const { return false; }
+ virtual bool is_s8vector() const { return false; }
+ virtual bool is_u16vector() const { return false; }
+ virtual bool is_s16vector() const { return false; }
+ virtual bool is_u32vector() const { return false; }
+ virtual bool is_s32vector() const { return false; }
+ virtual bool is_u64vector() const { return false; }
+ virtual bool is_s64vector() const { return false; }
+ virtual bool is_f32vector() const { return false; }
+ virtual bool is_f64vector() const { return false; }
+ virtual bool is_c32vector() const { return false; }
+ virtual bool is_c64vector() const { return false; }
+
+ friend void intrusive_ptr_add_ref(pmt_base* p);
+ friend void intrusive_ptr_release(pmt_base* p);
+
+# if (PMT_LOCAL_ALLOCATOR)
+ void *operator new(size_t);
+ void operator delete(void *, size_t);
+#endif
+};
+
+class pmt_bool : public pmt_base
+{
+public:
+ pmt_bool();
+ //~pmt_bool(){}
+
+ bool is_bool() const { return true; }
+};
+
+
+class pmt_symbol : public pmt_base
+{
+ std::string d_name;
+ pmt_t d_next;
+
+public:
+ pmt_symbol(const std::string &name);
+ //~pmt_symbol(){}
+
+ bool is_symbol() const { return true; }
+ const std::string name() { return d_name; }
+
+ pmt_t next() { return d_next; } // symbol table link
+ void set_next(pmt_t next) { d_next = next; }
+};
+
+class pmt_integer : public pmt_base
+{
+public:
+ long d_value;
+
+ pmt_integer(long value);
+ //~pmt_integer(){}
+
+ bool is_number() const { return true; }
+ bool is_integer() const { return true; }
+ long value() const { return d_value; }
+};
+
+class pmt_uint64 : public pmt_base
+{
+public:
+ uint64_t d_value;
+
+ pmt_uint64(uint64_t value);
+ //~pmt_uint64(){}
+
+ bool is_number() const { return true; }
+ bool is_uint64() const { return true; }
+ uint64_t value() const { return d_value; }
+};
+
+class pmt_real : public pmt_base
+{
+public:
+ double d_value;
+
+ pmt_real(double value);
+ //~pmt_real(){}
+
+ bool is_number() const { return true; }
+ bool is_real() const { return true; }
+ double value() const { return d_value; }
+};
+
+class pmt_complex : public pmt_base
+{
+public:
+ std::complex<double> d_value;
+
+ pmt_complex(std::complex<double> value);
+ //~pmt_complex(){}
+
+ bool is_number() const { return true; }
+ bool is_complex() const { return true; }
+ std::complex<double> value() const { return d_value; }
+};
+
+class pmt_null : public pmt_base
+{
+public:
+ pmt_null();
+ //~pmt_null(){}
+
+ bool is_null() const { return true; }
+};
+
+class pmt_pair : public pmt_base
+{
+public:
+ pmt_t d_car;
+ pmt_t d_cdr;
+
+ pmt_pair(const pmt_t& car, const pmt_t& cdr);
+ //~pmt_pair(){};
+
+ bool is_pair() const { return true; }
+ pmt_t car() const { return d_car; }
+ pmt_t cdr() const { return d_cdr; }
+
+ void set_car(pmt_t car) { d_car = car; }
+ void set_cdr(pmt_t cdr) { d_cdr = cdr; }
+};
+
+class pmt_vector : public pmt_base
+{
+ std::vector<pmt_t> d_v;
+
+public:
+ pmt_vector(size_t len, pmt_t fill);
+ //~pmt_vector();
+
+ bool is_vector() const { return true; }
+ pmt_t ref(size_t k) const;
+ void set(size_t k, pmt_t obj);
+ void fill(pmt_t fill);
+ size_t length() const { return d_v.size(); }
+
+ pmt_t _ref(size_t k) const { return d_v[k]; }
+};
+
+class pmt_tuple : public pmt_base
+{
+ std::vector<pmt_t> d_v;
+
+public:
+ pmt_tuple(size_t len);
+ //~pmt_tuple();
+
+ bool is_tuple() const { return true; }
+ pmt_t ref(size_t k) const;
+ size_t length() const { return d_v.size(); }
+
+ pmt_t _ref(size_t k) const { return d_v[k]; }
+ void _set(size_t k, pmt_t v) { d_v[k] = v; }
+};
+
+class pmt_any : public pmt_base
+{
+ boost::any d_any;
+
+public:
+ pmt_any(const boost::any &any);
+ //~pmt_any();
+
+ bool is_any() const { return true; }
+ const boost::any &ref() const { return d_any; }
+ void set(const boost::any &any) { d_any = any; }
+};
+
+
+class pmt_uniform_vector : public pmt_base
+{
+public:
+ bool is_uniform_vector() const { return true; }
+ virtual const void *uniform_elements(size_t &len) = 0;
+ virtual void *uniform_writable_elements(size_t &len) = 0;
+ virtual size_t length() const = 0;
+};
+
+#include "pmt_unv_int.h"
+
+} /* namespace pmt */
+
+#endif /* INCLUDED_PMT_INT_H */
diff --git a/gnuradio-runtime/lib/pmt/pmt_io.cc b/gnuradio-runtime/lib/pmt/pmt_io.cc
new file mode 100644
index 0000000000..17bdee408f
--- /dev/null
+++ b/gnuradio-runtime/lib/pmt/pmt_io.cc
@@ -0,0 +1,169 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006,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 <sstream>
+#include <iostream>
+
+namespace pmt {
+
+static void
+write_list_tail(pmt_t obj, std::ostream &port)
+{
+ write(car(obj), port); // write the car
+ obj = cdr(obj); // step to cdr
+
+ if (is_null(obj)) // ()
+ port << ")";
+
+ else if (is_pair(obj)){ // normal list
+ port << " ";
+ write_list_tail(obj, port);
+ }
+ else { // dotted pair
+ port << " . ";
+ write(obj, port);
+ port << ")";
+ }
+}
+
+void
+write(pmt_t obj, std::ostream &port)
+{
+ if (is_bool(obj)){
+ if (is_true(obj))
+ port << "#t";
+ else
+ port << "#f";
+ }
+ else if (is_symbol(obj)){
+ port << symbol_to_string(obj);
+ }
+ else if (is_number(obj)){
+ if (is_integer(obj))
+ port << to_long(obj);
+ else if (is_uint64(obj))
+ port << to_uint64(obj);
+ else if (is_real(obj))
+ port << to_double(obj);
+ else if (is_complex(obj)){
+ std::complex<double> c = to_complex(obj);
+ port << c.real() << '+' << c.imag() << 'i';
+ }
+ else
+ goto error;
+ }
+ else if (is_null(obj)){
+ port << "()";
+ }
+ else if (is_pair(obj)){
+ port << "(";
+ write_list_tail(obj, port);
+ }
+ else if (is_tuple(obj)){
+ port << "{";
+ size_t len = length(obj);
+ if (len > 0){
+ port << tuple_ref(obj, 0);
+ for (size_t i = 1; i < len; i++)
+ port << " " << tuple_ref(obj, i);
+ }
+ port << "}";
+ }
+ else if (is_vector(obj)){
+ port << "#(";
+ size_t len = length(obj);
+ if (len > 0){
+ port << vector_ref(obj, 0);
+ for (size_t i = 1; i < len; i++)
+ port << " " << vector_ref(obj, i);
+ }
+ port << ")";
+ }
+ else if (is_dict(obj)){
+ // FIXME
+ // port << "#<dict " << obj << ">";
+ port << "#<dict>";
+ }
+ else if (is_uniform_vector(obj)){
+ // FIXME
+ // port << "#<uniform-vector " << obj << ">";
+ port << "#<uniform-vector>";
+ }
+ else {
+ error:
+ // FIXME
+ // port << "#<" << obj << ">";
+ port << "#<unknown>";
+ }
+}
+
+std::ostream& operator<<(std::ostream &os, pmt_t obj)
+{
+ write(obj, os);
+ return os;
+}
+
+std::string
+write_string(pmt_t obj)
+{
+ std::ostringstream s;
+ s << obj;
+ return s.str();
+}
+
+pmt_t
+read(std::istream &port)
+{
+ throw notimplemented("notimplemented: pmt::read", PMT_NIL);
+}
+
+void
+serialize(pmt_t obj, std::ostream &sink)
+{
+ throw notimplemented("notimplemented: pmt::serialize", obj);
+}
+
+/*!
+ * \brief Create obj from portable byte-serial representation
+ */
+pmt_t
+deserialize(std::istream &source)
+{
+ throw notimplemented("notimplemented: pmt::deserialize", PMT_NIL);
+}
+
+} /* namespace pmt */
+
+
+void
+pmt::print(pmt_t v)
+{
+ std::cout << write_string(v) << std::endl;
+}
+
+
diff --git a/gnuradio-runtime/lib/pmt/pmt_pool.cc b/gnuradio-runtime/lib/pmt/pmt_pool.cc
new file mode 100644
index 0000000000..8864f79dc2
--- /dev/null
+++ b/gnuradio-runtime/lib/pmt/pmt_pool.cc
@@ -0,0 +1,113 @@
+/* -*- 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 <pmt/pmt_pool.h>
+#include <algorithm>
+#include <stdint.h>
+
+namespace pmt {
+
+static inline size_t
+ROUNDUP(size_t x, size_t stride)
+{
+ return ((((x) + (stride) - 1)/(stride)) * (stride));
+}
+
+pmt_pool::pmt_pool(size_t itemsize, size_t alignment,
+ size_t allocation_size, size_t max_items)
+ : d_itemsize(ROUNDUP(itemsize, alignment)),
+ d_alignment(alignment),
+ d_allocation_size(std::max(allocation_size, 16 * itemsize)),
+ d_max_items(max_items), d_n_items(0),
+ d_freelist(0)
+{
+}
+
+pmt_pool::~pmt_pool()
+{
+ for (unsigned int i = 0; i < d_allocations.size(); i++){
+ delete [] d_allocations[i];
+ }
+}
+
+void *
+pmt_pool::malloc()
+{
+ scoped_lock guard(d_mutex);
+ item *p;
+
+ if (d_max_items != 0){
+ while (d_n_items >= d_max_items)
+ d_cond.wait(guard);
+ }
+
+ if (d_freelist){ // got something?
+ p = d_freelist;
+ d_freelist = p->d_next;
+ d_n_items++;
+ return p;
+ }
+
+ // allocate a new chunk
+ char *alloc = new char[d_allocation_size + d_alignment - 1];
+ d_allocations.push_back(alloc);
+
+ // get the alignment we require
+ char *start = (char *)(((uintptr_t)alloc + d_alignment-1) & -d_alignment);
+ char *end = alloc + d_allocation_size + d_alignment - 1;
+ size_t n = (end - start) / d_itemsize;
+
+ // link the new items onto the free list.
+ p = (item *) start;
+ for (size_t i = 0; i < n; i++){
+ p->d_next = d_freelist;
+ d_freelist = p;
+ p = (item *)((char *) p + d_itemsize);
+ }
+
+ // now return the first one
+ p = d_freelist;
+ d_freelist = p->d_next;
+ d_n_items++;
+ return p;
+}
+
+void
+pmt_pool::free(void *foo)
+{
+ if (!foo)
+ return;
+
+ scoped_lock guard(d_mutex);
+
+ item *p = (item *) foo;
+ p->d_next = d_freelist;
+ d_freelist = p;
+ d_n_items--;
+ if (d_max_items != 0)
+ d_cond.notify_one();
+}
+
+} /* namespace pmt */
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 */
diff --git a/gnuradio-runtime/lib/pmt/qa_pmt.cc b/gnuradio-runtime/lib/pmt/qa_pmt.cc
new file mode 100644
index 0000000000..27c617e747
--- /dev/null
+++ b/gnuradio-runtime/lib/pmt/qa_pmt.cc
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2006 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/*
+ * This class gathers together all the test cases for pmt into
+ * a single test suite. As you create new test cases, add them here.
+ */
+
+#include <qa_pmt.h>
+#include <qa_pmt_prims.h>
+#include <qa_pmt_unv.h>
+
+CppUnit::TestSuite *
+qa_pmt::suite ()
+{
+ CppUnit::TestSuite *s = new CppUnit::TestSuite ("pmt");
+
+ s->addTest (qa_pmt_prims::suite ());
+ s->addTest (qa_pmt_unv::suite ());
+
+ return s;
+}
diff --git a/gnuradio-runtime/lib/pmt/qa_pmt.h b/gnuradio-runtime/lib/pmt/qa_pmt.h
new file mode 100644
index 0000000000..3e0c91abac
--- /dev/null
+++ b/gnuradio-runtime/lib/pmt/qa_pmt.h
@@ -0,0 +1,37 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_QA_PMT_H
+#define INCLUDED_QA_PMT_H
+
+#include <attributes.h>
+#include <cppunit/TestSuite.h>
+
+//! collect all the tests for pmt
+
+class __GR_ATTR_EXPORT qa_pmt {
+ public:
+ //! return suite of tests for all of pmt
+ static CppUnit::TestSuite *suite ();
+};
+
+#endif /* INCLUDED_QA_PMT_H */
diff --git a/gnuradio-runtime/lib/pmt/qa_pmt_prims.cc b/gnuradio-runtime/lib/pmt/qa_pmt_prims.cc
new file mode 100644
index 0000000000..e9a897deac
--- /dev/null
+++ b/gnuradio-runtime/lib/pmt/qa_pmt_prims.cc
@@ -0,0 +1,603 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006,2009,2010 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <qa_pmt_prims.h>
+#include <cppunit/TestAssert.h>
+#include <messages/msg_passing.h>
+#include <boost/format.hpp>
+#include <cstdio>
+#include <cstring>
+#include <sstream>
+
+void
+qa_pmt_prims::test_symbols()
+{
+ CPPUNIT_ASSERT(!pmt::is_symbol(pmt::PMT_T));
+ CPPUNIT_ASSERT(!pmt::is_symbol(pmt::PMT_F));
+ CPPUNIT_ASSERT_THROW(pmt::symbol_to_string(pmt::PMT_F), pmt::wrong_type);
+
+ pmt::pmt_t sym1 = pmt::mp("test");
+ CPPUNIT_ASSERT(pmt::is_symbol(sym1));
+ CPPUNIT_ASSERT_EQUAL(std::string("test"), pmt::symbol_to_string(sym1));
+ CPPUNIT_ASSERT(pmt::is_true(sym1));
+ CPPUNIT_ASSERT(!pmt::is_false(sym1));
+
+ pmt::pmt_t sym2 = pmt::mp("foo");
+ pmt::pmt_t sym3 = pmt::mp("test");
+ CPPUNIT_ASSERT_EQUAL(sym1, sym3);
+ CPPUNIT_ASSERT(sym1 != sym2);
+ CPPUNIT_ASSERT(sym1 == sym3);
+
+ static const int N = 2048;
+ std::vector<pmt::pmt_t> v1(N);
+ std::vector<pmt::pmt_t> v2(N);
+
+ // generate a bunch of symbols
+ for (int i = 0; i < N; i++){
+ std::string buf = str(boost::format("test-%d") % i);
+ v1[i] = pmt::mp(buf.c_str());
+ }
+
+ // confirm that they are all unique
+ for (int i = 0; i < N; i++)
+ for (int j = i + 1; j < N; j++)
+ CPPUNIT_ASSERT(v1[i] != v1[j]);
+
+ // generate the same symbols again
+ for (int i = 0; i < N; i++){
+ std::string buf = str(boost::format("test-%d") % i);
+ v2[i] = pmt::mp(buf.c_str());
+ }
+
+ // confirm that we get the same ones back
+ for (int i = 0; i < N; i++)
+ CPPUNIT_ASSERT(v1[i] == v2[i]);
+}
+
+void
+qa_pmt_prims::test_booleans()
+{
+ pmt::pmt_t sym = pmt::mp("test");
+ CPPUNIT_ASSERT(pmt::is_bool(pmt::PMT_T));
+ CPPUNIT_ASSERT(pmt::is_bool(pmt::PMT_F));
+ CPPUNIT_ASSERT(!pmt::is_bool(sym));
+ CPPUNIT_ASSERT_EQUAL(pmt::from_bool(false), pmt::PMT_F);
+ CPPUNIT_ASSERT_EQUAL(pmt::from_bool(true), pmt::PMT_T);
+ CPPUNIT_ASSERT_EQUAL(false, pmt::to_bool(pmt::PMT_F));
+ CPPUNIT_ASSERT_EQUAL(true, pmt::to_bool(pmt::PMT_T));
+ CPPUNIT_ASSERT_THROW(pmt::to_bool(sym), pmt::wrong_type);
+}
+
+void
+qa_pmt_prims::test_integers()
+{
+ pmt::pmt_t p1 = pmt::from_long(1);
+ pmt::pmt_t m1 = pmt::from_long(-1);
+ CPPUNIT_ASSERT(!pmt::is_integer(pmt::PMT_T));
+ CPPUNIT_ASSERT(pmt::is_integer(p1));
+ CPPUNIT_ASSERT(pmt::is_integer(m1));
+ CPPUNIT_ASSERT_THROW(pmt::to_long(pmt::PMT_T), pmt::wrong_type);
+ CPPUNIT_ASSERT_EQUAL(-1L, pmt::to_long(m1));
+ CPPUNIT_ASSERT_EQUAL(1L, pmt::to_long(p1));
+}
+
+void
+qa_pmt_prims::test_uint64s()
+{
+ pmt::pmt_t p1 = pmt::from_uint64((uint64_t)1);
+ pmt::pmt_t m1 = pmt::from_uint64((uint64_t)8589934592ULL);
+ CPPUNIT_ASSERT(!pmt::is_uint64(pmt::PMT_T));
+ CPPUNIT_ASSERT(pmt::is_uint64(p1));
+ CPPUNIT_ASSERT(pmt::is_uint64(m1));
+ CPPUNIT_ASSERT_THROW(pmt::to_uint64(pmt::PMT_T), pmt::wrong_type);
+ CPPUNIT_ASSERT_EQUAL((uint64_t)8589934592ULL, (uint64_t)pmt::to_uint64(m1));
+ CPPUNIT_ASSERT_EQUAL((uint64_t)1ULL, (uint64_t)pmt::to_uint64(p1));
+}
+
+void
+qa_pmt_prims::test_reals()
+{
+ pmt::pmt_t p1 = pmt::from_double(1);
+ pmt::pmt_t m1 = pmt::from_double(-1);
+ CPPUNIT_ASSERT(!pmt::is_real(pmt::PMT_T));
+ CPPUNIT_ASSERT(pmt::is_real(p1));
+ CPPUNIT_ASSERT(pmt::is_real(m1));
+ CPPUNIT_ASSERT_THROW(pmt::to_double(pmt::PMT_T), pmt::wrong_type);
+ CPPUNIT_ASSERT_EQUAL(-1.0, pmt::to_double(m1));
+ CPPUNIT_ASSERT_EQUAL(1.0, pmt::to_double(p1));
+ CPPUNIT_ASSERT_EQUAL(1.0, pmt::to_double(pmt::from_long(1)));
+}
+
+void
+qa_pmt_prims::test_complexes()
+{
+ pmt::pmt_t p1 = pmt::make_rectangular(2, -3);
+ pmt::pmt_t m1 = pmt::make_rectangular(-3, 2);
+ pmt::pmt_t p2 = pmt::from_complex(2, -3);
+ pmt::pmt_t m2 = pmt::from_complex(-3, 2);
+ pmt::pmt_t p3 = pmt::from_complex(std::complex<double>(2, -3));
+ pmt::pmt_t m3 = pmt::from_complex(std::complex<double>(-3, 2));
+ CPPUNIT_ASSERT(!pmt::is_complex(pmt::PMT_T));
+ CPPUNIT_ASSERT(pmt::is_complex(p1));
+ CPPUNIT_ASSERT(pmt::is_complex(m1));
+ CPPUNIT_ASSERT(pmt::is_complex(p2));
+ CPPUNIT_ASSERT(pmt::is_complex(m2));
+ CPPUNIT_ASSERT(pmt::is_complex(p3));
+ CPPUNIT_ASSERT(pmt::is_complex(m3));
+ CPPUNIT_ASSERT_THROW(pmt::to_complex(pmt::PMT_T), pmt::wrong_type);
+ CPPUNIT_ASSERT_EQUAL(std::complex<double>(2, -3), pmt::to_complex(p1));
+ CPPUNIT_ASSERT_EQUAL(std::complex<double>(-3, 2), pmt::to_complex(m1));
+ CPPUNIT_ASSERT_EQUAL(std::complex<double>(2, -3), pmt::to_complex(p2));
+ CPPUNIT_ASSERT_EQUAL(std::complex<double>(-3, 2), pmt::to_complex(m2));
+ CPPUNIT_ASSERT_EQUAL(std::complex<double>(2, -3), pmt::to_complex(p3));
+ CPPUNIT_ASSERT_EQUAL(std::complex<double>(-3, 2), pmt::to_complex(m3));
+ CPPUNIT_ASSERT_EQUAL(std::complex<double>(1.0, 0), pmt::to_complex(pmt::from_long(1)));
+ CPPUNIT_ASSERT_EQUAL(std::complex<double>(1.0, 0), pmt::to_complex(pmt::from_double(1.0)));
+}
+
+void
+qa_pmt_prims::test_pairs()
+{
+ CPPUNIT_ASSERT(pmt::is_null(pmt::PMT_NIL));
+ CPPUNIT_ASSERT(!pmt::is_pair(pmt::PMT_NIL));
+ pmt::pmt_t s1 = pmt::mp("s1");
+ pmt::pmt_t s2 = pmt::mp("s2");
+ pmt::pmt_t s3 = pmt::mp("s3");
+
+
+ CPPUNIT_ASSERT_EQUAL((size_t)0, pmt::length(pmt::PMT_NIL));
+ CPPUNIT_ASSERT_THROW(pmt::length(s1), pmt::wrong_type);
+ CPPUNIT_ASSERT_THROW(pmt::length(pmt::from_double(42)), pmt::wrong_type);
+
+ pmt::pmt_t c1 = pmt::cons(s1, pmt::PMT_NIL);
+ CPPUNIT_ASSERT(pmt::is_pair(c1));
+ CPPUNIT_ASSERT(!pmt::is_pair(s1));
+ CPPUNIT_ASSERT_EQUAL(s1, pmt::car(c1));
+ CPPUNIT_ASSERT_EQUAL(pmt::PMT_NIL, pmt::cdr(c1));
+ CPPUNIT_ASSERT_EQUAL((size_t) 1, pmt::length(c1));
+
+ pmt::pmt_t c3 = pmt::cons(s3, pmt::PMT_NIL);
+ pmt::pmt_t c2 = pmt::cons(s2, c3);
+ pmt::set_cdr(c1, c2);
+ CPPUNIT_ASSERT_EQUAL(c2, pmt::cdr(c1));
+ pmt::set_car(c1, s3);
+ CPPUNIT_ASSERT_EQUAL(s3, pmt::car(c1));
+ CPPUNIT_ASSERT_EQUAL((size_t)1, pmt::length(c3));
+ CPPUNIT_ASSERT_EQUAL((size_t)2, pmt::length(c2));
+
+ CPPUNIT_ASSERT_THROW(pmt::cdr(pmt::PMT_NIL), pmt::wrong_type);
+ CPPUNIT_ASSERT_THROW(pmt::car(pmt::PMT_NIL), pmt::wrong_type);
+ CPPUNIT_ASSERT_THROW(pmt::set_car(s1, pmt::PMT_NIL), pmt::wrong_type);
+ CPPUNIT_ASSERT_THROW(pmt::set_cdr(s1, pmt::PMT_NIL), pmt::wrong_type);
+}
+
+void
+qa_pmt_prims::test_vectors()
+{
+ static const size_t N = 3;
+ pmt::pmt_t v1 = pmt::make_vector(N, pmt::PMT_NIL);
+ CPPUNIT_ASSERT_EQUAL(N, pmt::length(v1));
+ pmt::pmt_t s0 = pmt::mp("s0");
+ pmt::pmt_t s1 = pmt::mp("s1");
+ pmt::pmt_t s2 = pmt::mp("s2");
+
+ pmt::vector_set(v1, 0, s0);
+ pmt::vector_set(v1, 1, s1);
+ pmt::vector_set(v1, 2, s2);
+
+ CPPUNIT_ASSERT_EQUAL(s0, pmt::vector_ref(v1, 0));
+ CPPUNIT_ASSERT_EQUAL(s1, pmt::vector_ref(v1, 1));
+ CPPUNIT_ASSERT_EQUAL(s2, pmt::vector_ref(v1, 2));
+
+ CPPUNIT_ASSERT_THROW(pmt::vector_ref(v1, N), pmt::out_of_range);
+ CPPUNIT_ASSERT_THROW(pmt::vector_set(v1, N, pmt::PMT_NIL), pmt::out_of_range);
+
+ pmt::vector_fill(v1, s0);
+ for (size_t i = 0; i < N; i++)
+ CPPUNIT_ASSERT_EQUAL(s0, pmt::vector_ref(v1, i));
+}
+
+static void
+check_tuple(size_t len, const std::vector<pmt::pmt_t> &s, pmt::pmt_t t)
+{
+ CPPUNIT_ASSERT_EQUAL(true, pmt::is_tuple(t));
+ CPPUNIT_ASSERT_EQUAL(len, pmt::length(t));
+
+ for (size_t i = 0; i < len; i++)
+ CPPUNIT_ASSERT_EQUAL(s[i], pmt::tuple_ref(t, i));
+
+}
+
+void
+qa_pmt_prims::test_tuples()
+{
+ pmt::pmt_t v = pmt::make_vector(10, pmt::PMT_NIL);
+ std::vector<pmt::pmt_t> s(10);
+ for (size_t i = 0; i < 10; i++){
+ std::ostringstream os;
+ os << "s" << i;
+ s[i] = pmt::mp(os.str());
+ pmt::vector_set(v, i, s[i]);
+ }
+
+
+ pmt::pmt_t t;
+
+ t = pmt::make_tuple();
+ check_tuple(0, s, t);
+
+ t = pmt::make_tuple(s[0]);
+ check_tuple(1, s, t);
+
+ CPPUNIT_ASSERT(pmt::is_vector(v));
+ CPPUNIT_ASSERT(!pmt::is_tuple(v));
+ CPPUNIT_ASSERT(pmt::is_tuple(t));
+ CPPUNIT_ASSERT(!pmt::is_vector(t));
+
+ t = pmt::make_tuple(s[0], s[1]);
+ check_tuple(2, s, t);
+
+ t = pmt::make_tuple(s[0], s[1], s[2]);
+ check_tuple(3, s, t);
+
+ t = pmt::make_tuple(s[0], s[1], s[2], s[3]);
+ check_tuple(4, s, t);
+
+ t = pmt::make_tuple(s[0], s[1], s[2], s[3], s[4]);
+ check_tuple(5, s, t);
+
+ t = pmt::make_tuple(s[0], s[1], s[2], s[3], s[4], s[5]);
+ check_tuple(6, s, t);
+
+ t = pmt::make_tuple(s[0], s[1], s[2], s[3], s[4], s[5], s[6]);
+ check_tuple(7, s, t);
+
+ t = pmt::make_tuple(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7]);
+ check_tuple(8, s, t);
+
+ t = pmt::make_tuple(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[8]);
+ check_tuple(9, s, t);
+
+ t = pmt::make_tuple(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[8], s[9]);
+ check_tuple(10, s, t);
+
+ t = pmt::make_tuple(s[0], s[1], s[2]);
+ CPPUNIT_ASSERT_THROW(pmt::tuple_ref(t, 3), pmt::out_of_range);
+ CPPUNIT_ASSERT_THROW(pmt::vector_ref(t, 0), pmt::wrong_type);
+ CPPUNIT_ASSERT_THROW(pmt::tuple_ref(v, 0), pmt::wrong_type);
+
+ t = pmt::make_tuple(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[8], s[9]);
+ pmt::pmt_t t2 = pmt::to_tuple(v);
+ CPPUNIT_ASSERT_EQUAL(size_t(10), pmt::length(v));
+ CPPUNIT_ASSERT(pmt::equal(t, t2));
+ //std::cout << v << std::endl;
+ //std::cout << t2 << std::endl;
+
+
+ t = pmt::make_tuple(s[0], s[1], s[2]);
+ pmt::pmt_t list0 = pmt::list3(s[0], s[1], s[2]);
+ CPPUNIT_ASSERT_EQUAL(size_t(3), pmt::length(list0));
+ t2 = pmt::to_tuple(list0);
+ CPPUNIT_ASSERT_EQUAL(size_t(3), pmt::length(t2));
+ CPPUNIT_ASSERT(pmt::equal(t, t2));
+}
+
+void
+qa_pmt_prims::test_equivalence()
+{
+ pmt::pmt_t s0 = pmt::mp("s0");
+ pmt::pmt_t s1 = pmt::mp("s1");
+ pmt::pmt_t s2 = pmt::mp("s2");
+ pmt::pmt_t list0 = pmt::cons(s0, pmt::cons(s1, pmt::cons(s2, pmt::PMT_NIL)));
+ pmt::pmt_t list1 = pmt::cons(s0, pmt::cons(s1, pmt::cons(s2, pmt::PMT_NIL)));
+ pmt::pmt_t i0 = pmt::from_long(42);
+ pmt::pmt_t i1 = pmt::from_long(42);
+ pmt::pmt_t r0 = pmt::from_double(42);
+ pmt::pmt_t r1 = pmt::from_double(42);
+ pmt::pmt_t r2 = pmt::from_double(43);
+
+ CPPUNIT_ASSERT(pmt::eq(s0, s0));
+ CPPUNIT_ASSERT(!pmt::eq(s0, s1));
+ CPPUNIT_ASSERT(pmt::eqv(s0, s0));
+ CPPUNIT_ASSERT(!pmt::eqv(s0, s1));
+
+ CPPUNIT_ASSERT(pmt::eqv(i0, i1));
+ CPPUNIT_ASSERT(pmt::eqv(r0, r1));
+ CPPUNIT_ASSERT(!pmt::eqv(r0, r2));
+ CPPUNIT_ASSERT(!pmt::eqv(i0, r0));
+
+ CPPUNIT_ASSERT(!pmt::eq(list0, list1));
+ CPPUNIT_ASSERT(!pmt::eqv(list0, list1));
+ CPPUNIT_ASSERT(pmt::equal(list0, list1));
+
+ pmt::pmt_t v0 = pmt::make_vector(3, s0);
+ pmt::pmt_t v1 = pmt::make_vector(3, s0);
+ pmt::pmt_t v2 = pmt::make_vector(4, s0);
+ CPPUNIT_ASSERT(!pmt::eqv(v0, v1));
+ CPPUNIT_ASSERT(pmt::equal(v0, v1));
+ CPPUNIT_ASSERT(!pmt::equal(v0, v2));
+
+ pmt::vector_set(v0, 0, list0);
+ pmt::vector_set(v0, 1, list0);
+ pmt::vector_set(v1, 0, list1);
+ pmt::vector_set(v1, 1, list1);
+ CPPUNIT_ASSERT(pmt::equal(v0, v1));
+}
+
+void
+qa_pmt_prims::test_misc()
+{
+ pmt::pmt_t k0 = pmt::mp("k0");
+ pmt::pmt_t k1 = pmt::mp("k1");
+ pmt::pmt_t k2 = pmt::mp("k2");
+ pmt::pmt_t k3 = pmt::mp("k3");
+ pmt::pmt_t v0 = pmt::mp("v0");
+ pmt::pmt_t v1 = pmt::mp("v1");
+ pmt::pmt_t v2 = pmt::mp("v2");
+ pmt::pmt_t p0 = pmt::cons(k0, v0);
+ pmt::pmt_t p1 = pmt::cons(k1, v1);
+ pmt::pmt_t p2 = pmt::cons(k2, v2);
+
+ pmt::pmt_t alist = pmt::cons(p0, pmt::cons(p1, pmt::cons(p2, pmt::PMT_NIL)));
+ CPPUNIT_ASSERT(pmt::eq(p1, pmt::assv(k1, alist)));
+ CPPUNIT_ASSERT(pmt::eq(pmt::PMT_F, pmt::assv(k3, alist)));
+
+ pmt::pmt_t keys = pmt::cons(k0, pmt::cons(k1, pmt::cons(k2, pmt::PMT_NIL)));
+ pmt::pmt_t vals = pmt::cons(v0, pmt::cons(v1, pmt::cons(v2, pmt::PMT_NIL)));
+ CPPUNIT_ASSERT(pmt::equal(keys, pmt::map(pmt::car, alist)));
+ CPPUNIT_ASSERT(pmt::equal(vals, pmt::map(pmt::cdr, alist)));
+}
+
+void
+qa_pmt_prims::test_dict()
+{
+ pmt::pmt_t dict = pmt::make_dict();
+ CPPUNIT_ASSERT(pmt::is_dict(dict));
+
+ pmt::pmt_t k0 = pmt::mp("k0");
+ pmt::pmt_t k1 = pmt::mp("k1");
+ pmt::pmt_t k2 = pmt::mp("k2");
+ pmt::pmt_t k3 = pmt::mp("k3");
+ pmt::pmt_t v0 = pmt::mp("v0");
+ pmt::pmt_t v1 = pmt::mp("v1");
+ pmt::pmt_t v2 = pmt::mp("v2");
+ pmt::pmt_t v3 = pmt::mp("v3");
+ pmt::pmt_t not_found = pmt::cons(pmt::PMT_NIL, pmt::PMT_NIL);
+
+ CPPUNIT_ASSERT(!pmt::dict_has_key(dict, k0));
+ dict = pmt::dict_add(dict, k0, v0);
+ CPPUNIT_ASSERT(pmt::dict_has_key(dict, k0));
+ CPPUNIT_ASSERT(pmt::eqv(pmt::dict_ref(dict, k0, not_found), v0));
+ CPPUNIT_ASSERT(pmt::eqv(pmt::dict_ref(dict, k1, not_found), not_found));
+ dict = pmt::dict_add(dict, k1, v1);
+ dict = pmt::dict_add(dict, k2, v2);
+ CPPUNIT_ASSERT(pmt::eqv(pmt::dict_ref(dict, k1, not_found), v1));
+ dict = pmt::dict_add(dict, k1, v3);
+ CPPUNIT_ASSERT(pmt::eqv(pmt::dict_ref(dict, k1, not_found), v3));
+
+ pmt::pmt_t keys = pmt::list3(k1, k2, k0);
+ pmt::pmt_t vals = pmt::list3(v3, v2, v0);
+ //std::cout << "pmt::dict_keys: " << pmt::dict_keys(dict) << std::endl;
+ //std::cout << "pmt::dict_values: " << pmt::dict_values(dict) << std::endl;
+ CPPUNIT_ASSERT(pmt::equal(keys, pmt::dict_keys(dict)));
+ CPPUNIT_ASSERT(pmt::equal(vals, pmt::dict_values(dict)));
+}
+
+void
+qa_pmt_prims::test_io()
+{
+ pmt::pmt_t k0 = pmt::mp("k0");
+ pmt::pmt_t k1 = pmt::mp("k1");
+ pmt::pmt_t k2 = pmt::mp("k2");
+ pmt::pmt_t k3 = pmt::mp("k3");
+
+ CPPUNIT_ASSERT_EQUAL(std::string("k0"), pmt::write_string(k0));
+}
+
+void
+qa_pmt_prims::test_lists()
+{
+ pmt::pmt_t s0 = pmt::mp("s0");
+ pmt::pmt_t s1 = pmt::mp("s1");
+ pmt::pmt_t s2 = pmt::mp("s2");
+ pmt::pmt_t s3 = pmt::mp("s3");
+
+ pmt::pmt_t l1 = pmt::list4(s0, s1, s2, s3);
+ pmt::pmt_t l2 = pmt::list3(s0, s1, s2);
+ pmt::pmt_t l3 = pmt::list_add(l2, s3);
+ CPPUNIT_ASSERT(pmt::equal(l1, l3));
+}
+
+// ------------------------------------------------------------------------
+
+// class foo is used in test_any below.
+// It can't be declared in the scope of test_any because of template
+// namespace problems.
+
+class foo {
+public:
+ double d_double;
+ int d_int;
+ foo(double d=0, int i=0) : d_double(d), d_int(i) {}
+};
+
+bool operator==(const foo &a, const foo &b)
+{
+ return a.d_double == b.d_double && a.d_int == b.d_int;
+}
+
+std::ostream& operator<<(std::ostream &os, const foo obj)
+{
+ os << "<foo: " << obj.d_double << ", " << obj.d_int << ">";
+ return os;
+}
+
+void
+qa_pmt_prims::test_any()
+{
+ boost::any a0;
+ boost::any a1;
+ boost::any a2;
+
+ a0 = std::string("Hello!");
+ a1 = 42;
+ a2 = foo(3.250, 21);
+
+ pmt::pmt_t p0 = pmt::make_any(a0);
+ pmt::pmt_t p1 = pmt::make_any(a1);
+ pmt::pmt_t p2 = pmt::make_any(a2);
+
+ CPPUNIT_ASSERT_EQUAL(std::string("Hello!"),
+ boost::any_cast<std::string>(pmt::any_ref(p0)));
+
+ CPPUNIT_ASSERT_EQUAL(42,
+ boost::any_cast<int>(pmt::any_ref(p1)));
+
+ CPPUNIT_ASSERT_EQUAL(foo(3.250, 21),
+ boost::any_cast<foo>(pmt::any_ref(p2)));
+}
+
+// ------------------------------------------------------------------------
+
+class qa_pmt_msg_accepter_nop : public gr::messages::msg_accepter
+{
+public:
+ qa_pmt_msg_accepter_nop(){};
+ ~qa_pmt_msg_accepter_nop();
+ void post(pmt::pmt_t,pmt::pmt_t){};
+};
+
+qa_pmt_msg_accepter_nop::~qa_pmt_msg_accepter_nop(){}
+
+void
+qa_pmt_prims::test_msg_accepter()
+{
+ pmt::pmt_t sym = pmt::mp("my-symbol");
+
+ boost::any a0;
+ a0 = std::string("Hello!");
+ pmt::pmt_t p0 = pmt::make_any(a0);
+
+ gr::messages::msg_accepter_sptr ma0 = \
+ gr::messages::msg_accepter_sptr(new qa_pmt_msg_accepter_nop());
+ pmt::pmt_t p1 = pmt::make_msg_accepter(ma0);
+
+ CPPUNIT_ASSERT_EQUAL(ma0.get(), pmt::msg_accepter_ref(p1).get());
+
+ CPPUNIT_ASSERT_THROW(pmt::msg_accepter_ref(sym), pmt::wrong_type);
+ CPPUNIT_ASSERT_THROW(pmt::msg_accepter_ref(p0), pmt::wrong_type);
+
+ // just confirm interfaces on send are OK
+ pmt::pmt_t port(pmt::intern("port"));
+ gr::messages::send(ma0.get(), port, sym);
+ gr::messages::send(ma0, port, sym);
+ gr::messages::send(p1, port, sym);
+
+}
+
+// ------------------------------------------------------------------------
+
+void
+qa_pmt_prims::test_serialize()
+{
+ std::stringbuf sb; // fake channel
+ pmt::pmt_t a = pmt::mp("a");
+ pmt::pmt_t b = pmt::mp("b");
+ pmt::pmt_t c = pmt::mp("c");
+
+ sb.str(""); // reset channel to empty
+
+ // write stuff to channel
+
+ pmt::serialize(pmt::PMT_NIL, sb);
+ pmt::serialize(pmt::mp("foobarvia"), sb);
+ pmt::serialize(pmt::from_long(123456789), sb);
+ pmt::serialize(pmt::from_long(-123456789), sb);
+ pmt::serialize(pmt::cons(pmt::PMT_NIL, pmt::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::PMT_T, sb);
+ pmt::serialize(pmt::PMT_F, sb);
+
+ // read it back
+
+ CPPUNIT_ASSERT(pmt::equal(pmt::deserialize(sb), pmt::PMT_NIL));
+ CPPUNIT_ASSERT(pmt::equal(pmt::deserialize(sb), pmt::mp("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::PMT_NIL, pmt::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::PMT_T));
+ CPPUNIT_ASSERT(pmt::equal(pmt::deserialize(sb), pmt::PMT_F));
+
+ CPPUNIT_ASSERT(pmt::equal(pmt::deserialize(sb), pmt::PMT_EOF)); // last item
+
+
+ // FIXME add tests for real, complex, vector, uniform-vector, dict
+ // FIXME add tests for malformed input too.
+
+}
+
+void
+qa_pmt_prims::test_sets()
+{
+ pmt::pmt_t s1 = pmt::mp("s1");
+ pmt::pmt_t s2 = pmt::mp("s2");
+ pmt::pmt_t s3 = pmt::mp("s3");
+
+ pmt::pmt_t l1 = pmt::list1(s1);
+ pmt::pmt_t l2 = pmt::list2(s2,s3);
+ pmt::pmt_t l3 = pmt::list3(s1,s2,s3);
+
+ CPPUNIT_ASSERT(pmt::is_pair(pmt::memq(s1,l1)));
+ CPPUNIT_ASSERT(pmt::is_false(pmt::memq(s3,l1)));
+
+ CPPUNIT_ASSERT(pmt::subsetp(l1,l3));
+ CPPUNIT_ASSERT(pmt::subsetp(l2,l3));
+ CPPUNIT_ASSERT(!pmt::subsetp(l1,l2));
+ CPPUNIT_ASSERT(!pmt::subsetp(l2,l1));
+ CPPUNIT_ASSERT(!pmt::subsetp(l3,l2));
+}
+
+void
+qa_pmt_prims::test_sugar()
+{
+ CPPUNIT_ASSERT(pmt::is_symbol(pmt::mp("my-symbol")));
+ CPPUNIT_ASSERT_EQUAL((long) 10, pmt::to_long(pmt::mp(10)));
+ CPPUNIT_ASSERT_EQUAL((double) 1e6, pmt::to_double(pmt::mp(1e6)));
+ CPPUNIT_ASSERT_EQUAL(std::complex<double>(2, 3),
+ pmt::to_complex(pmt::mp(std::complex<double>(2, 3))));
+
+ int buf[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ pmt::pmt_t blob = pmt::mp(buf, sizeof(buf));
+ const void *data = pmt::blob_data(blob);
+ size_t nbytes = pmt::blob_length(blob);
+ CPPUNIT_ASSERT_EQUAL(sizeof(buf), nbytes);
+ CPPUNIT_ASSERT(memcmp(buf, data, nbytes) == 0);
+}
diff --git a/gnuradio-runtime/lib/pmt/qa_pmt_prims.h b/gnuradio-runtime/lib/pmt/qa_pmt_prims.h
new file mode 100644
index 0000000000..8c3f5c6220
--- /dev/null
+++ b/gnuradio-runtime/lib/pmt/qa_pmt_prims.h
@@ -0,0 +1,77 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef INCLUDED_QA_PMT_PRIMS_H
+#define INCLUDED_QA_PMT_PRIMS_H
+
+#include <attributes.h>
+#include <pmt/api.h> //reason: suppress warnings
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestCase.h>
+
+class __GR_ATTR_EXPORT qa_pmt_prims : public CppUnit::TestCase {
+
+ CPPUNIT_TEST_SUITE(qa_pmt_prims);
+ CPPUNIT_TEST(test_symbols);
+ CPPUNIT_TEST(test_booleans);
+ CPPUNIT_TEST(test_integers);
+ CPPUNIT_TEST(test_uint64s);
+ CPPUNIT_TEST(test_reals);
+ CPPUNIT_TEST(test_complexes);
+ CPPUNIT_TEST(test_pairs);
+ CPPUNIT_TEST(test_vectors);
+ CPPUNIT_TEST(test_tuples);
+ CPPUNIT_TEST(test_equivalence);
+ CPPUNIT_TEST(test_misc);
+ CPPUNIT_TEST(test_dict);
+ CPPUNIT_TEST(test_any);
+ CPPUNIT_TEST(test_msg_accepter);
+ CPPUNIT_TEST(test_io);
+ CPPUNIT_TEST(test_lists);
+ CPPUNIT_TEST(test_serialize);
+ CPPUNIT_TEST(test_sets);
+ CPPUNIT_TEST(test_sugar);
+ CPPUNIT_TEST_SUITE_END();
+
+ private:
+ void test_symbols();
+ void test_booleans();
+ void test_integers();
+ void test_uint64s();
+ void test_reals();
+ void test_complexes();
+ void test_pairs();
+ void test_vectors();
+ void test_tuples();
+ void test_equivalence();
+ void test_misc();
+ void test_dict();
+ void test_any();
+ void test_msg_accepter();
+ void test_io();
+ void test_lists();
+ void test_serialize();
+ void test_sets();
+ void test_sugar();
+};
+
+#endif /* INCLUDED_QA_PMT_PRIMS_H */
+
diff --git a/gnuradio-runtime/lib/pmt/unv_qa_template.cc.t b/gnuradio-runtime/lib/pmt/unv_qa_template.cc.t
new file mode 100644
index 0000000000..a04d532b4e
--- /dev/null
+++ b/gnuradio-runtime/lib/pmt/unv_qa_template.cc.t
@@ -0,0 +1,35 @@
+void
+qa_pmt_unv::test_@TAG@vector()
+{
+ static const size_t N = 3;
+ pmt_t v1 = pmt::make_@TAG@vector(N, 0);
+ CPPUNIT_ASSERT_EQUAL(N, pmt::length(v1));
+ @TYPE@ s0 = @TYPE@(10);
+ @TYPE@ s1 = @TYPE@(20);
+ @TYPE@ s2 = @TYPE@(30);
+
+ pmt::@TAG@vector_set(v1, 0, s0);
+ pmt::@TAG@vector_set(v1, 1, s1);
+ pmt::@TAG@vector_set(v1, 2, s2);
+
+ CPPUNIT_ASSERT_EQUAL(s0, pmt::@TAG@vector_ref(v1, 0));
+ CPPUNIT_ASSERT_EQUAL(s1, pmt::@TAG@vector_ref(v1, 1));
+ CPPUNIT_ASSERT_EQUAL(s2, pmt::@TAG@vector_ref(v1, 2));
+
+ CPPUNIT_ASSERT_THROW(pmt::@TAG@vector_ref(v1, N), pmt::out_of_range);
+ CPPUNIT_ASSERT_THROW(pmt::@TAG@vector_set(v1, N, @TYPE@(0)), pmt::out_of_range);
+
+ size_t len;
+ const @TYPE@ *rd = pmt::@TAG@vector_elements(v1, len);
+ CPPUNIT_ASSERT_EQUAL(len, N);
+ CPPUNIT_ASSERT_EQUAL(s0, rd[0]);
+ CPPUNIT_ASSERT_EQUAL(s1, rd[1]);
+ CPPUNIT_ASSERT_EQUAL(s2, rd[2]);
+
+ @TYPE@ *wr = pmt::@TAG@vector_writable_elements(v1, len);
+ CPPUNIT_ASSERT_EQUAL(len, N);
+ wr[0] = @TYPE@(0);
+ CPPUNIT_ASSERT_EQUAL(@TYPE@(0), wr[0]);
+ CPPUNIT_ASSERT_EQUAL(s1, wr[1]);
+ CPPUNIT_ASSERT_EQUAL(s2, wr[2]);
+}
diff --git a/gnuradio-runtime/lib/pmt/unv_template.cc.t b/gnuradio-runtime/lib/pmt/unv_template.cc.t
new file mode 100644
index 0000000000..8678894973
--- /dev/null
+++ b/gnuradio-runtime/lib/pmt/unv_template.cc.t
@@ -0,0 +1,141 @@
+////////////////////////////////////////////////////////////////////////////
+// pmt_@TAG@vector
+////////////////////////////////////////////////////////////////////////////
+
+namespace pmt {
+
+static pmt_@TAG@vector *
+_@TAG@vector(pmt_t x)
+{
+ return dynamic_cast<pmt_@TAG@vector*>(x.get());
+}
+
+
+pmt_@TAG@vector::pmt_@TAG@vector(size_t k, @TYPE@ fill)
+ : d_v(k)
+{
+ for (size_t i = 0; i < k; i++)
+ d_v[i] = fill;
+}
+
+pmt_@TAG@vector::pmt_@TAG@vector(size_t k, const @TYPE@ *data)
+ : d_v(k)
+{
+ for (size_t i = 0; i < k; i++)
+ d_v[i] = data[i];
+}
+
+@TYPE@
+pmt_@TAG@vector::ref(size_t k) const
+{
+ if (k >= length())
+ throw out_of_range("pmt_@TAG@vector_ref", from_long(k));
+ return d_v[k];
+}
+
+void
+pmt_@TAG@vector::set(size_t k, @TYPE@ x)
+{
+ if (k >= length())
+ throw out_of_range("pmt_@TAG@vector_set", from_long(k));
+ d_v[k] = x;
+}
+
+const @TYPE@ *
+pmt_@TAG@vector::elements(size_t &len)
+{
+ len = length();
+ return &d_v[0];
+}
+
+@TYPE@ *
+pmt_@TAG@vector::writable_elements(size_t &len)
+{
+ len = length();
+ return &d_v[0];
+}
+
+const void*
+pmt_@TAG@vector::uniform_elements(size_t &len)
+{
+ len = length() * sizeof(@TYPE@);
+ return &d_v[0];
+}
+
+void*
+pmt_@TAG@vector::uniform_writable_elements(size_t &len)
+{
+ len = length() * sizeof(@TYPE@);
+ return &d_v[0];
+}
+
+bool
+is_@TAG@vector(pmt_t obj)
+{
+ return obj->is_@TAG@vector();
+}
+
+pmt_t
+make_@TAG@vector(size_t k, @TYPE@ fill)
+{
+ return pmt_t(new pmt_@TAG@vector(k, fill));
+}
+
+pmt_t
+init_@TAG@vector(size_t k, const @TYPE@ *data)
+{
+ return pmt_t(new pmt_@TAG@vector(k, data));
+}
+
+pmt_t
+init_@TAG@vector(size_t k, const std::vector< @TYPE@ > &data)
+{
+
+ return pmt_t(new pmt_@TAG@vector(k, &data[0]));
+}
+
+@TYPE@
+@TAG@vector_ref(pmt_t vector, size_t k)
+{
+ if (!vector->is_@TAG@vector())
+ throw wrong_type("pmt_@TAG@vector_ref", vector);
+ return _@TAG@vector(vector)->ref(k);
+}
+
+void
+@TAG@vector_set(pmt_t vector, size_t k, @TYPE@ obj)
+{
+ if (!vector->is_@TAG@vector())
+ throw wrong_type("pmt_@TAG@vector_set", vector);
+ _@TAG@vector(vector)->set(k, obj);
+}
+
+const @TYPE@ *
+@TAG@vector_elements(pmt_t vector, size_t &len)
+{
+ if (!vector->is_@TAG@vector())
+ throw wrong_type("pmt_@TAG@vector_elements", vector);
+ return _@TAG@vector(vector)->elements(len);
+}
+
+const std::vector< @TYPE@ >
+@TAG@vector_elements(pmt_t vector)
+{
+ if (!vector->is_@TAG@vector())
+ throw wrong_type("pmt_@TAG@vector_elements", vector);
+ size_t len;
+ const @TYPE@ *array = _@TAG@vector(vector)->elements(len);
+ const std::vector< @TYPE@ > vec(array, array+len);
+ return vec;
+}
+
+
+@TYPE@ *
+@TAG@vector_writable_elements(pmt_t vector, size_t &len)
+{
+ if (!vector->is_@TAG@vector())
+ throw wrong_type("pmt_@TAG@vector_writable_elements", vector);
+ return _@TAG@vector(vector)->writable_elements(len);
+}
+
+} /* namespace pmt */
diff --git a/gnuradio-runtime/lib/pmt/unv_template.h.t b/gnuradio-runtime/lib/pmt/unv_template.h.t
new file mode 100644
index 0000000000..83ba0be0f4
--- /dev/null
+++ b/gnuradio-runtime/lib/pmt/unv_template.h.t
@@ -0,0 +1,23 @@
+
+////////////////////////////////////////////////////////////////////////////
+// pmt_@TAG@vector
+////////////////////////////////////////////////////////////////////////////
+
+class pmt_@TAG@vector : public pmt_uniform_vector
+{
+ std::vector< @TYPE@ > d_v;
+
+public:
+ pmt_@TAG@vector(size_t k, @TYPE@ fill);
+ pmt_@TAG@vector(size_t k, const @TYPE@ *data);
+ // ~pmt_@TAG@vector();
+
+ bool is_@TAG@vector() const { return true; }
+ size_t length() const { return d_v.size(); }
+ @TYPE@ ref(size_t k) const;
+ void set(size_t k, @TYPE@ x);
+ const @TYPE@ *elements(size_t &len);
+ @TYPE@ *writable_elements(size_t &len);
+ const void *uniform_elements(size_t &len);
+ void *uniform_writable_elements(size_t &len);
+};