diff options
Diffstat (limited to 'gruel')
25 files changed, 1335 insertions, 231 deletions
diff --git a/gruel/Makefile.am b/gruel/Makefile.am index 93f56a7db..c43e461f2 100644 --- a/gruel/Makefile.am +++ b/gruel/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright 2008 Free Software Foundation, Inc. +# Copyright 2008,2010 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -21,7 +21,7 @@ include $(top_srcdir)/Makefile.common -EXTRA_DIST = \ +EXTRA_DIST += \ gruel.pc.in SUBDIRS = src diff --git a/gruel/src/Makefile.am b/gruel/src/Makefile.am index 71bdd8573..93b17d6db 100644 --- a/gruel/src/Makefile.am +++ b/gruel/src/Makefile.am @@ -19,5 +19,11 @@ # Boston, MA 02110-1301, USA. # -SUBDIRS = lib include scheme +SUBDIRS = lib include scheme + +if PYTHON + +SUBDIRS += . swig python + +endif diff --git a/gruel/src/include/gruel/Makefile.am b/gruel/src/include/gruel/Makefile.am index 67dd12995..89a9da7f0 100644 --- a/gruel/src/include/gruel/Makefile.am +++ b/gruel/src/include/gruel/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright 2008,2009 Free Software Foundation, Inc. +# Copyright 2008-2011 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -21,13 +21,13 @@ include $(top_srcdir)/Makefile.common -BUILT_SOURCES = \ - inet.h +EXTRA_DIST += inet.h.in gruelincludedir = $(prefix)/include/gruel gruelinclude_HEADERS = \ - $(BUILT_SOURCES) \ + attributes.h \ + inet.h \ msg_accepter.h \ msg_accepter_msgq.h \ msg_queue.h \ diff --git a/gruel/src/include/gruel/attributes.h b/gruel/src/include/gruel/attributes.h new file mode 100644 index 000000000..fdf48c977 --- /dev/null +++ b/gruel/src/include/gruel/attributes.h @@ -0,0 +1,56 @@ +/* + * Copyright 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_GRUEL_ATTRIBUTES_H +#define INCLUDED_GRUEL_ATTRIBUTES_H + +//////////////////////////////////////////////////////////////////////// +// Cross-platform attribute macros +//////////////////////////////////////////////////////////////////////// +#if defined __GNUC__ +# define __GR_ATTR_ALIGNED(x) __attribute__((aligned(x))) +# define __GR_ATTR_UNUSED __attribute__((unused)) +# define __GR_ATTR_INLINE __attribute__((always_inline)) +# define __GR_ATTR_DEPRECATED __attribute__((deprecated)) +# if __GNUC__ >= 4 +# define __GR_ATTR_EXPORT __attribute__((visibility("default"))) +# define __GR_ATTR_IMPORT __attribute__((visibility("default"))) +# else +# define __GR_ATTR_EXPORT +# define __GR_ATTR_IMPORT +# endif +#elif _MSC_VER +# define __GR_ATTR_ALIGNED(x) __declspec(align(x)) +# define __GR_ATTR_UNUSED +# define __GR_ATTR_INLINE __forceinline +# define __GR_ATTR_DEPRECATED __declspec(deprecated) +# define __GR_ATTR_EXPORT __declspec(dllexport) +# define __GR_ATTR_IMPORT __declspec(dllimport) +#else +# define __GR_ATTR_ALIGNED(x) +# define __GR_ATTR_UNUSED +# define __GR_ATTR_INLINE +# define __GR_ATTR_DEPRECATED +# define __GR_ATTR_EXPORT +# define __GR_ATTR_IMPORT +#endif + +#endif /* INCLUDED_GRUEL_ATTRIBUTES_H */ diff --git a/gruel/src/include/gruel/pmt.h b/gruel/src/include/gruel/pmt.h index 514b24d8b..2948abb39 100644 --- a/gruel/src/include/gruel/pmt.h +++ b/gruel/src/include/gruel/pmt.h @@ -770,6 +770,11 @@ std::string pmt_write_string(pmt_t obj); std::ostream& operator<<(std::ostream &os, pmt_t obj); +/*! + * \brief Write pmt string representation to stdout. + */ +void pmt_print(pmt_t v); + /* * ------------------------------------------------------------------------ @@ -789,8 +794,17 @@ pmt_t pmt_deserialize(std::streambuf &source); void pmt_dump_sizeof(); // debugging -} /* namespace pmt */ +/*! + * \brief Provide a simple string generating interface to pmt's serialize function + */ +std::string pmt_serialize_str(pmt_t obj); +/*! + * \brief Provide a simple string generating interface to pmt's deserialize function + */ +pmt_t pmt_deserialize_str(std::string str); + +} /* namespace pmt */ #include <gruel/pmt_sugar.h> diff --git a/gruel/src/include/gruel/thread.h b/gruel/src/include/gruel/thread.h index d72e5520c..5a8ab1876 100644 --- a/gruel/src/include/gruel/thread.h +++ b/gruel/src/include/gruel/thread.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2009,2010 Free Software Foundation, Inc. + * Copyright 2009,2010,2011 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -21,21 +21,17 @@ #ifndef INCLUDED_THREAD_H #define INCLUDED_THREAD_H -#include <boost/thread.hpp> -#include <boost/date_time/posix_time/posix_time.hpp> +#include <boost/thread/thread.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/locks.hpp> +#include <boost/thread/condition_variable.hpp> namespace gruel { typedef boost::thread thread; typedef boost::mutex mutex; - typedef boost::unique_lock<boost::mutex> scoped_lock; + typedef boost::mutex::scoped_lock scoped_lock; typedef boost::condition_variable condition_variable; - typedef boost::posix_time::time_duration duration; - - /*! - * Returns absolute time 'secs' into the future - */ - boost::system_time get_new_timeout(double secs); } /* namespace gruel */ diff --git a/gruel/src/lib/Makefile.am b/gruel/src/lib/Makefile.am index 5c3302f19..f37ab27a1 100644 --- a/gruel/src/lib/Makefile.am +++ b/gruel/src/lib/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright 2008,2009,2010 Free Software Foundation, Inc. +# Copyright 2008,2009,2010,2011 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -45,12 +45,13 @@ MSG_LIB = msg/libmsg.la libgruel_la_SOURCES = \ realtime.cc \ sys_pri.cc \ - thread.cc \ thread_body_wrapper.cc \ thread_group.cc libgruel_la_LIBADD = \ $(BOOST_THREAD_LIB) \ + $(BOOST_SYSTEM_LIB) \ + $(BOOST_FILESYSTEM_LIB) \ $(PMT_LIB) \ $(MSG_LIB) \ -lstdc++ diff --git a/gruel/src/lib/pmt/Makefile.am b/gruel/src/lib/pmt/Makefile.am index d3efc1afa..0c8e12dc3 100644 --- a/gruel/src/lib/pmt/Makefile.am +++ b/gruel/src/lib/pmt/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright 2008,2009,2010 Free Software Foundation, Inc. +# Copyright 2008,2009,2010,2011 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -48,7 +48,7 @@ python_built_sources = $(GENERATED_H) $(GENERATED_CC) PMT_SERIAL_TAGS_H = $(abs_top_builddir)/gruel/src/include/gruel/pmt_serial_tags.h BUILT_SOURCES = $(python_built_sources) $(PMT_SERIAL_TAGS_H) -EXTRA_DIST = $(code_generator) +EXTRA_DIST += $(code_generator) # ---------------------------------------------------------------- @@ -99,7 +99,7 @@ gen_sources_deps = $(core_generator) par_gen_command = PYTHONPATH=$(top_srcdir)/gruel/src/lib/pmt srcdir=$(srcdir) $(PYTHON) $(srcdir)/generate_unv.py include $(top_srcdir)/Makefile.par.gen -# Rule to create the build header file using GUILE +# Rule to create the build header file using python # Doesn't need parallel protections because there is a single target -$(PMT_SERIAL_TAGS_H): $(srcdir)/../../scheme/gnuradio/gen-serial-tags.scm $(srcdir)/../../scheme/gnuradio/pmt-serial-tags.scm - $(RUN_GUILE) $(srcdir)/../../scheme/gnuradio/gen-serial-tags.scm $(srcdir)/../../scheme/gnuradio/pmt-serial-tags.scm $(PMT_SERIAL_TAGS_H) +$(PMT_SERIAL_TAGS_H): $(top_srcdir)/gruel/src/scheme/gnuradio/gen-serial-tags.py $(top_srcdir)/gruel/src/scheme/gnuradio/pmt-serial-tags.scm + $(PYTHON) $^ $@ diff --git a/gruel/src/lib/pmt/pmt_io.cc b/gruel/src/lib/pmt/pmt_io.cc index b909c1b64..1214ff588 100644 --- a/gruel/src/lib/pmt/pmt_io.cc +++ b/gruel/src/lib/pmt/pmt_io.cc @@ -26,6 +26,7 @@ #include <gruel/pmt.h> #include "pmt_int.h" #include <sstream> +#include <iostream> namespace pmt { @@ -156,3 +157,12 @@ pmt_deserialize(std::istream &source) } } /* namespace pmt */ + + +void +pmt::pmt_print(pmt_t v) +{ + std::cout << pmt_write_string(v) << std::endl; +} + + diff --git a/gruel/src/lib/pmt/pmt_serialize.cc b/gruel/src/lib/pmt/pmt_serialize.cc index 937423a93..184a31e6b 100644 --- a/gruel/src/lib/pmt/pmt_serialize.cc +++ b/gruel/src/lib/pmt/pmt_serialize.cc @@ -59,6 +59,26 @@ serialize_untagged_u32(unsigned int i, std::streambuf &sb) 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(); +} + + #if 0 // always writes big-endian static bool @@ -163,6 +183,41 @@ deserialize_untagged_u64(uint64_t *ip, std::streambuf &sb) } #endif +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(); +} + + /* * Write portable byte-serial representation of \p obj to \p sb * @@ -172,7 +227,7 @@ bool pmt_serialize(pmt_t obj, std::streambuf &sb) { bool ok = true; - + tail_recursion: if (pmt_is_bool(obj)){ @@ -217,11 +272,21 @@ pmt_serialize(pmt_t obj, std::streambuf &sb) return ok; } - if (pmt_is_real(obj)) - throw pmt_notimplemented("pmt_serialize (real)", obj); + if (pmt_is_real(obj)){ + float i = pmt_to_double(obj); + ok = serialize_untagged_u8(PST_DOUBLE, sb); + ok &= serialize_untagged_f64(i, sb); + return ok; + } + + if (pmt_is_complex(obj)){ + std::complex<double> i = pmt_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 (pmt_is_complex(obj)) - throw pmt_notimplemented("pmt_serialize (complex)", obj); } if (pmt_is_vector(obj)) @@ -251,6 +316,7 @@ pmt_deserialize(std::streambuf &sb) uint16_t u16; uint32_t u32; //uint32_t u64; + double f64; static char tmpbuf[1024]; if (!deserialize_untagged_u8(&tag, sb)) @@ -285,7 +351,18 @@ pmt_deserialize(std::streambuf &sb) return parse_pair(sb); case PST_DOUBLE: + if(!deserialize_untagged_f64(&f64, sb)) + goto error; + return pmt_from_double( f64 ); + case PST_COMPLEX: + { + double r,i; + if(!deserialize_untagged_f64(&r, sb) && !deserialize_untagged_f64(&i, sb)) + goto error; + return pmt_make_rectangular( r,i ); + } + case PST_VECTOR: case PST_DICT: case PST_UNIFORM_VECTOR: @@ -302,6 +379,26 @@ pmt_deserialize(std::streambuf &sb) throw pmt_exception("pmt_deserialize: malformed input stream", PMT_F); } + +/* + * provide a simple string accessor to the serialized pmt form + */ +std::string pmt_serialize_str(pmt_t obj){ + std::stringbuf sb; + pmt_serialize(obj, sb); + return sb.str(); +} + + +/* + * provide a simple string accessor to the deserialized pmt form + */ +pmt_t pmt_deserialize_str(std::string s){ + std::stringbuf sb(s); + return pmt_deserialize(sb); +} + + /* * This is a mostly non-recursive implementation that allows us to * deserialize very long lists w/o exhausting the evaluation stack. diff --git a/gruel/src/lib/test_gruel.cc b/gruel/src/lib/test_gruel.cc index 2c9528b0a..7ef3520e6 100644 --- a/gruel/src/lib/test_gruel.cc +++ b/gruel/src/lib/test_gruel.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2006,2009,2010 Free Software Foundation, Inc. + * Copyright 2006,2009,2010,2011 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -28,16 +28,19 @@ #include "pmt/qa_pmt.h" -static void get_unittest_path (const char *filename, char *fullpath, size_t pathsize); +#include <boost/filesystem/operations.hpp> +#include <boost/filesystem/path.hpp> +namespace fs = boost::filesystem; int main(int argc, char **argv) { - char path[200]; - get_unittest_path ("gruel.xml", path, 200); - + fs::path path = fs::current_path() / ".unittests"; + if (!fs::is_directory(path)) fs::create_directory(path); + path = path / "gruel.xml"; + CppUnit::TextTestRunner runner; - std::ofstream xmlfile(path); + std::ofstream xmlfile(path.string().c_str()); CppUnit::XmlOutputter *xmlout = new CppUnit::XmlOutputter(&runner.result(), xmlfile); runner.addTest(qa_pmt::suite ()); @@ -47,41 +50,3 @@ main(int argc, char **argv) return was_successful ? 0 : 1; } - - -// NOTE: These are defined in gr_unittest.h for the rest of the project; -// rewriting here since we don't depend on gnuradio-core in gruel - -#ifdef MKDIR_TAKES_ONE_ARG -#define gr_mkdir(pathname, mode) mkdir(pathname) -#else -#define gr_mkdir(pathname, mode) mkdir((pathname), (mode)) -#endif - -/* - * Mostly taken from gr_preferences.cc/h - * The simplest thing that could possibly work: - * the key is the filename; the value is the file contents. - */ - -static void -ensure_unittest_path (const char *path) -{ - struct stat statbuf; - if (stat (path, &statbuf) == 0 && S_ISDIR (statbuf.st_mode)) - return; - - // blindly try to make it // FIXME make this robust. C++ SUCKS! - gr_mkdir (path, 0750); -} - -static void -get_unittest_path (const char *filename, char *fullpath, size_t pathsize) -{ - char path[200]; - snprintf (path, sizeof(path), "./.unittests"); - snprintf (fullpath, pathsize, "%s/%s", path, filename); - - ensure_unittest_path(path); -} - diff --git a/gruel/src/lib/thread.cc b/gruel/src/lib/thread.cc deleted file mode 100644 index d8f77b506..000000000 --- a/gruel/src/lib/thread.cc +++ /dev/null @@ -1,35 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 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 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 <gruel/thread.h> - -namespace gruel { - - boost::system_time - get_new_timeout(double secs) - { - return boost::get_system_time() + boost::posix_time::milliseconds(long(secs*1e3)); - } - -} diff --git a/gruel/src/python/.gitignore b/gruel/src/python/.gitignore new file mode 100644 index 000000000..b336cc7ce --- /dev/null +++ b/gruel/src/python/.gitignore @@ -0,0 +1,2 @@ +/Makefile +/Makefile.in diff --git a/gruel/src/python/Makefile.am b/gruel/src/python/Makefile.am new file mode 100644 index 000000000..5a45510d5 --- /dev/null +++ b/gruel/src/python/Makefile.am @@ -0,0 +1,39 @@ +# +# 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 GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +include $(top_srcdir)/Makefile.common + +TESTS = +EXTRA_DIST += run_tests.in + +if PYTHON +TESTS += run_tests + +grueldir = $(pythondir)/gruel + +noinst_PYTHON = \ + qa_pmt.py + +gruel_PYTHON = \ + __init__.py + +endif + diff --git a/gruel/src/python/__init__.py b/gruel/src/python/__init__.py new file mode 100644 index 000000000..421a9aaa8 --- /dev/null +++ b/gruel/src/python/__init__.py @@ -0,0 +1,25 @@ +# +# 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 GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +# The presence of this file turns this directory into a Python package + +from pmt_swig import * + diff --git a/gruel/src/python/qa_pmt.py b/gruel/src/python/qa_pmt.py new file mode 100755 index 000000000..00cdb064e --- /dev/null +++ b/gruel/src/python/qa_pmt.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python +# +# 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 GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +import unittest +import pmt_swig + +class test_gruel_pmt(unittest.TestCase): + + def test01 (self): + a = pmt_swig.pmt_intern("a") + b = pmt_swig.pmt_from_double(123765) + d1 = pmt_swig.pmt_make_dict() + d2 = pmt_swig.pmt_dict_add(d1, a, b) + pmt_swig.pmt_print(d2) + + def test02 (self): + const = 123765 + x_pmt = pmt_swig.pmt_from_double(const) + x_int = pmt_swig.pmt_to_double(x_pmt) + self.assertEqual(x_int, const) + +if __name__ == '__main__': + unittest.main() diff --git a/gruel/src/python/run_tests.in b/gruel/src/python/run_tests.in new file mode 100644 index 000000000..ff399bcc6 --- /dev/null +++ b/gruel/src/python/run_tests.in @@ -0,0 +1,17 @@ +#!/bin/sh + +# 1st parameter is absolute path to component source directory +# 2nd parameter is absolute path to component build directory +# 3rd parameter is path to Python QA directory + +# For OS/X +DYLD_LIBRARY_PATH=@abs_top_builddir@/gruel/src/lib/:@abs_top_builddir@/gruel/src/swig/.libs:$DYLD_LIBRARY_PATH +export DYLD_LIBRARY_PATH + +# For Win32 +PATH=@abs_top_builddir@/gruel/:@abs_top_builddir@/gruel/.libs:$PATH + +@top_builddir@/run_tests.sh \ + @abs_top_srcdir@/gruel/src \ + @abs_top_builddir@/gruel/src \ + @srcdir@ diff --git a/gruel/src/scheme/gnuradio/Makefile.am b/gruel/src/scheme/gnuradio/Makefile.am index 0ce01f6f8..e7b6bf744 100644 --- a/gruel/src/scheme/gnuradio/Makefile.am +++ b/gruel/src/scheme/gnuradio/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright 2007,2009 Free Software Foundation, Inc. +# Copyright 2007,2009,2010,2011 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -18,12 +18,14 @@ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # +include $(top_srcdir)/Makefile.common + #pkgdatadir = $(datadir)/gnuradio -EXTRA_DIST = \ - gen-serial-tags.scm +EXTRA_DIST += \ + gen-serial-tags.py -# really scheme source files +# really scheme source files FIXME wrong location dist_pkgdata_DATA = \ pmt-serial-tags.scm \ pmt-serialize.scm \ diff --git a/gruel/src/scheme/gnuradio/gen-serial-tags.py b/gruel/src/scheme/gnuradio/gen-serial-tags.py new file mode 100644 index 000000000..18e927beb --- /dev/null +++ b/gruel/src/scheme/gnuradio/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/gruel/src/scheme/gnuradio/gen-serial-tags.scm b/gruel/src/scheme/gnuradio/gen-serial-tags.scm deleted file mode 100755 index 7b9087228..000000000 --- a/gruel/src/scheme/gnuradio/gen-serial-tags.scm +++ /dev/null @@ -1,118 +0,0 @@ -#!/usr/bin/guile \ --e main -s -!# -;;; -*-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 (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. -;;; - -(use-modules (ice-9 format)) - -(defmacro when (pred . body) - `(if ,pred (begin ,@body) #f)) - -;; ---------------------------------------------------------------- - -(define (main args) - - (define (usage) - (format 0 - "usage: ~a <pmt-serial-tags.scm> <pmt_serial_tags.h>~%" - (car args))) - - (when (not (= (length args) 3)) - (usage) - (format 0 "args: ~s~%" args) - (exit 1)) - - (let ((i-file (open-input-file (cadr args))) - (h-file (open-output-file (caddr args)))) - - (write-header-comment h-file "// ") - (display "#ifndef INCLUDED_PMT_SERIAL_TAGS_H\n" h-file) - (display "#define INCLUDED_PMT_SERIAL_TAGS_H\n" h-file) - (newline h-file) - (display "enum pst_tags {\n" h-file) - - (for-each-in-file i-file - (lambda (form) - (let* ((name (cadr form)) - (c-name (string-upcase (c-ify name))) - (value (caddr form))) - ;;(format h-file "static const int ~a\t= 0x~x;~%" c-name value) - (format h-file " ~a\t= 0x~x,~%" c-name value)))) - - (display "};\n" h-file) - (display "#endif\n" h-file))) - -(define (c-ify name) - (list->string (map (lambda (c) - (if (eqv? c #\-) #\_ c)) - (string->list (symbol->string name))))) - - -(define (write-header-comment o-port prefix) - (for-each (lambda (comment) - (format o-port "~a~a~%" prefix comment)) - header-comment)) - -(define header-comment - '( - "" - "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 (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 pmt-serial-tags.scm. DO NOT EDIT BY HAND." - "See pmt-serial-tags.scm for additional commentary." - "")) - - - -(define (for-each-in-file file f) - (let ((port (if (port? file) - file - (open-input-file file)))) - (letrec - ((loop - (lambda (port form) - (cond ((eof-object? form) - (when (not (eq? port file)) - (close-input-port port)) - #t) - (else - (f form) - (set! form #f) ; for GC - (loop port (read port))))))) - (loop port (read port))))) diff --git a/gruel/src/swig/.gitignore b/gruel/src/swig/.gitignore new file mode 100644 index 000000000..b336cc7ce --- /dev/null +++ b/gruel/src/swig/.gitignore @@ -0,0 +1,2 @@ +/Makefile +/Makefile.in diff --git a/gruel/src/swig/Makefile.am b/gruel/src/swig/Makefile.am new file mode 100644 index 000000000..294045567 --- /dev/null +++ b/gruel/src/swig/Makefile.am @@ -0,0 +1,55 @@ +# +# 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 GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +include $(top_srcdir)/Makefile.common +include $(top_srcdir)/Makefile.swig + +TESTS = + +AM_CPPFLAGS = \ + -I$(top_srcdir)/gruel/src/lib \ + $(STD_DEFINES_AND_INCLUDES) \ + $(PYTHON_CPPFLAGS) \ + $(WITH_INCLUDES) + +TOP_SWIG_IFILES = \ + pmt_swig.i + +############################## +# SWIG interface and library +TOP_SWIG_IFILES = \ + pmt_swig.i + +# Install so that they end up available as: +# import gruel.pmt +# This ends up at: +# ${prefix}/lib/python${python_version}/site-packages/gruel/pmt +pmt_swig_pythondir_category = \ + gruel/pmt + +# additional libraries for linking with the SWIG-generated library +pmt_swig_la_swig_libadd = \ + $(abs_top_builddir)/gruel/src/lib/pmt/libpmt.la + +# additional SWIG files to be installed +pmt_swig_swiginclude_headers = + + diff --git a/gruel/src/swig/Makefile.swig.gen b/gruel/src/swig/Makefile.swig.gen new file mode 100644 index 000000000..c6a2fb956 --- /dev/null +++ b/gruel/src/swig/Makefile.swig.gen @@ -0,0 +1,115 @@ +# -*- Makefile -*- +# +# Copyright 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. +# + +# Makefile.swig.gen for gnuradio_core_runtime.i + +## Default install locations for these files: +## +## Default location for the Python directory is: +## ${prefix}/lib/python${python_version}/site-packages/[category]/gnuradio_core_runtime +## Default location for the Python exec directory is: +## ${exec_prefix}/lib/python${python_version}/site-packages/[category]/gnuradio_core_runtime +## +## The following can be overloaded to change the install location, but +## this has to be done in the including Makefile.am -before- +## Makefile.swig is included. + +pmt_swig_pythondir_category ?= gruel/pmt_swig +pmt_swig_pylibdir_category ?= $(pmt_swig_pythondir_category) +pmt_swig_pythondir = $(pythondir)/$(pmt_swig_pythondir_category) +pmt_swig_pylibdir = $(pyexecdir)/$(pmt_swig_pylibdir_category) + +# The .so libraries for the guile modules get installed whereever guile +# is installed, usually /usr/lib/guile/gnuradio/ +# FIXME: determince whether these should be installed with gnuradio. +pmt_swig_scmlibdir = $(libdir) + +# The scm files for the guile modules get installed where ever guile +# is installed, usually /usr/share/guile/site/gnuradio_core_runtime +# FIXME: determince whether these should be installed with gnuradio. +pmt_swig_scmdir = $(guiledir) + +## SWIG headers are always installed into the same directory. + +pmt_swig_swigincludedir = $(swigincludedir) + +## This is a template file for a "generated" Makefile addition (in +## this case, "Makefile.swig.gen"). By including the top-level +## Makefile.swig, this file will be used to generate the SWIG +## dependencies. Assign the variable TOP_SWIG_FILES to be the list of +## SWIG .i files to generated wrappings for; there can be more than 1 +## so long as the names are unique (no sorting is done on the +## TOP_SWIG_FILES list). This file explicitly assumes that a SWIG .i +## file will generate .cc, .py, and possibly .h files -- meaning that +## all of these files will have the same base name (that provided for +## the SWIG .i file). +## +## This code is setup to ensure parallel MAKE ("-j" or "-jN") does the +## right thing. For more info, see < +## http://sources.redhat.com/automake/automake.html#Multiple-Outputs > + +## Other cleaned files: dependency files generated by SWIG or this Makefile + +MOSTLYCLEANFILES += $(DEPDIR)/*.S* + +## Various SWIG variables. These can be overloaded in the including +## Makefile.am by setting the variable value there, then including +## Makefile.swig . + +pmt_swig_swiginclude_HEADERS = \ + pmt_swig.i \ + $(pmt_swig_swiginclude_headers) + +if PYTHON +pmt_swig_pylib_LTLIBRARIES = \ + _pmt_swig.la + +_pmt_swig_la_SOURCES = \ + python/pmt_swig.cc \ + $(pmt_swig_la_swig_sources) + +pmt_swig_python_PYTHON = \ + pmt_swig.py \ + $(pmt_swig_python) + +_pmt_swig_la_LIBADD = \ + $(STD_SWIG_LA_LIB_ADD) \ + $(pmt_swig_la_swig_libadd) + +_pmt_swig_la_LDFLAGS = \ + $(STD_SWIG_LA_LD_FLAGS) \ + $(pmt_swig_la_swig_ldflags) + +_pmt_swig_la_CXXFLAGS = \ + $(STD_SWIG_CXX_FLAGS) \ + -I$(top_builddir) \ + $(pmt_swig_la_swig_cxxflags) + +python/pmt_swig.cc: pmt_swig.py +pmt_swig.py: pmt_swig.i + +# Include the python dependencies for this file +-include python/pmt_swig.d + +endif # end of if python + + diff --git a/gruel/src/swig/__init__.py b/gruel/src/swig/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/gruel/src/swig/__init__.py diff --git a/gruel/src/swig/pmt_swig.i b/gruel/src/swig/pmt_swig.i new file mode 100644 index 000000000..6435e03cc --- /dev/null +++ b/gruel/src/swig/pmt_swig.i @@ -0,0 +1,760 @@ +/* -*- c++ -*- */ +/* + * 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +%module pmt +%include "std_string.i" +%include "stdint.i" +%{ +#include <boost/intrusive_ptr.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/any.hpp> +#include <complex> +#include <string> +#include <stdint.h> +#include <iosfwd> +#include <stdexcept> +#include <gruel/pmt.h> +using namespace pmt; +%} + +// Template intrusive_ptr for Swig to avoid dereferencing issues +class pmt_base; +%import <intrusive_ptr.i> +%template(swig_int_ptr) boost::intrusive_ptr<pmt_base>; + +typedef boost::intrusive_ptr<pmt_base> pmt_t; + +/* + * ------------------------------------------------------------------------ + * Booleans. Two constants, #t and #f. + * + * In predicates, anything that is not #f is considered true. + * I.e., there is a single false value, #f. + * ------------------------------------------------------------------------ + */ +extern const pmt_t PMT_T; +extern const pmt_t PMT_F; + +//! Return true if obj is \#t or \#f, else return false. +bool pmt_is_bool(pmt_t obj); + +//! Return false if obj is \#f, else return true. +bool pmt_is_true(pmt_t obj); + +//! Return true if obj is \#f, else return true. +bool pmt_is_false(pmt_t obj); + +//! Return \#f is val is false, else return \#t. +pmt_t pmt_from_bool(bool val); + +//! Return true if val is PMT_T, return false when val is PMT_F, +// else raise wrong_type exception. +bool pmt_to_bool(pmt_t val); + +/* + * ------------------------------------------------------------------------ + * Symbols + * ------------------------------------------------------------------------ + */ + +//! Return true if obj is a symbol, else false. +bool pmt_is_symbol(const pmt_t& obj); + +//! Return the symbol whose name is \p s. +pmt_t pmt_string_to_symbol(const std::string &s); + +//! Alias for pmt_string_to_symbol +pmt_t pmt_intern(const std::string &s); + + +/*! + * If \p is a symbol, return the name of the symbol as a string. + * Otherwise, raise the wrong_type exception. + */ +const std::string pmt_symbol_to_string(const pmt_t& sym); + +/* + * ------------------------------------------------------------------------ + * Numbers: we support integer, real and complex + * ------------------------------------------------------------------------ + */ + +//! Return true if obj is any kind of number, else false. +bool pmt_is_number(pmt_t obj); + +/* + * ------------------------------------------------------------------------ + * Integers + * ------------------------------------------------------------------------ + */ + +//! Return true if \p x is an integer number, else false +bool pmt_is_integer(pmt_t x); + +//! Return the pmt value that represents the integer \p x. +pmt_t pmt_from_long(long x); + +/*! + * \brief Convert pmt to long if possible. + * + * When \p x represents an exact integer that fits in a long, + * return that integer. Else raise an exception, either wrong_type + * when x is not an exact integer, or out_of_range when it doesn't fit. + */ +long pmt_to_long(pmt_t x); + +/* + * ------------------------------------------------------------------------ + * uint64_t + * ------------------------------------------------------------------------ + */ + +//! Return true if \p x is an uint64 number, else false +bool pmt_is_uint64(pmt_t x); + +//! Return the pmt value that represents the uint64 \p x. +pmt_t pmt_from_uint64(uint64_t x); + +/*! + * \brief Convert pmt to uint64 if possible. + * + * When \p x represents an exact integer that fits in a uint64, + * return that uint64. Else raise an exception, either wrong_type + * when x is not an exact uint64, or out_of_range when it doesn't fit. + */ +uint64_t pmt_to_uint64(pmt_t x); + +/* + * ------------------------------------------------------------------------ + * Reals + * ------------------------------------------------------------------------ + */ + +/* + * \brief Return true if \p obj is a real number, else false. + */ +bool pmt_is_real(pmt_t obj); + +//! Return the pmt value that represents double \p x. +pmt_t pmt_from_double(double x); + +/*! + * \brief Convert pmt to double if possible. + * + * Returns the number closest to \p val that is representable + * as a double. The argument \p val must be a real or integer, otherwise + * a wrong_type exception is raised. + */ +double pmt_to_double(pmt_t x); + +/* + * ------------------------------------------------------------------------ + * Complex + * ------------------------------------------------------------------------ + */ + +/*! + * \brief return true if \p obj is a complex number, false otherwise. + */ +bool pmt_is_complex(pmt_t obj); + +//! Return a complex number constructed of the given real and imaginary parts. +pmt_t pmt_make_rectangular(double re, double im); + +/*! + * If \p z is complex, real or integer, return the closest complex<double>. + * Otherwise, raise the wrong_type exception. + */ +std::complex<double> pmt_to_complex(pmt_t z); + +/* + * ------------------------------------------------------------------------ + * Pairs + * ------------------------------------------------------------------------ + */ + +extern const pmt_t PMT_NIL; //< the empty list + +//! Return true if \p x is the empty list, otherwise return false. +bool pmt_is_null(const pmt_t& x); + +//! Return true if \p obj is a pair, else false. +bool pmt_is_pair(const pmt_t& obj); + +//! Return a newly allocated pair whose car is \p x and whose cdr is \p y. +pmt_t pmt_cons(const pmt_t& x, const pmt_t& y); + +//! If \p pair is a pair, return the car of the \p pair, otherwise raise wrong_type. +pmt_t pmt_car(const pmt_t& pair); + +//! If \p pair is a pair, return the cdr of the \p pair, otherwise raise wrong_type. +pmt_t pmt_cdr(const pmt_t& pair); + +//! Stores \p value in the car field of \p pair. +void pmt_set_car(pmt_t pair, pmt_t value); + +//! Stores \p value in the cdr field of \p pair. +void pmt_set_cdr(pmt_t pair, pmt_t value); + +pmt_t pmt_caar(pmt_t pair); +pmt_t pmt_cadr(pmt_t pair); +pmt_t pmt_cdar(pmt_t pair); +pmt_t pmt_cddr(pmt_t pair); +pmt_t pmt_caddr(pmt_t pair); +pmt_t pmt_cadddr(pmt_t pair); + +/* + * ------------------------------------------------------------------------ + * Tuples + * + * Store a fixed number of objects. Tuples are not modifiable, and thus + * are excellent for use as messages. Indexing is zero based. + * Access time to an element is O(1). + * ------------------------------------------------------------------------ + */ + +//! Return true if \p x is a tuple, othewise false. +bool pmt_is_tuple(pmt_t x); + +pmt_t pmt_make_tuple(); +pmt_t pmt_make_tuple(const pmt_t &e0); +pmt_t pmt_make_tuple(const pmt_t &e0, const pmt_t &e1); +pmt_t pmt_make_tuple(const pmt_t &e0, const pmt_t &e1, const pmt_t &e2); +pmt_t pmt_make_tuple(const pmt_t &e0, const pmt_t &e1, const pmt_t &e2, const pmt_t &e3); +pmt_t pmt_make_tuple(const pmt_t &e0, const pmt_t &e1, const pmt_t &e2, const pmt_t &e3, const pmt_t &e4); +pmt_t pmt_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_t pmt_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_t pmt_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_t pmt_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_t pmt_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); + +/*! + * If \p x is a vector or proper list, return a tuple containing the elements of x + */ +pmt_t pmt_to_tuple(const pmt_t &x); + +/*! + * Return the contents of position \p k of \p tuple. + * \p k must be a valid index of \p tuple. + */ +pmt_t pmt_tuple_ref(const pmt_t &tuple, size_t k); + +/* + * ------------------------------------------------------------------------ + * Vectors + * + * These vectors can hold any kind of objects. Indexing is zero based. + * ------------------------------------------------------------------------ + */ + +//! Return true if \p x is a vector, othewise false. +bool pmt_is_vector(pmt_t x); + +//! Make a vector of length \p k, with initial values set to \p fill +pmt_t pmt_make_vector(size_t k, pmt_t fill); + +/*! + * Return the contents of position \p k of \p vector. + * \p k must be a valid index of \p vector. + */ +pmt_t pmt_vector_ref(pmt_t vector, size_t k); + +//! Store \p obj in position \p k. +void pmt_vector_set(pmt_t vector, size_t k, pmt_t obj); + +//! Store \p fill in every position of \p vector +void pmt_vector_fill(pmt_t vector, pmt_t fill); + +/* + * ------------------------------------------------------------------------ + * Binary Large Objects (BLOBs) + * + * Handy for passing around uninterpreted chunks of memory. + * ------------------------------------------------------------------------ + */ + +//! Return true if \p x is a blob, othewise false. +bool pmt_is_blob(pmt_t x); + +/*! + * \brief Make a blob given a pointer and length in bytes + * + * \param buf is the pointer to data to use to create blob + * \param len is the size of the data in bytes. + * + * The data is copied into the blob. + */ +pmt_t pmt_make_blob(const void *buf, size_t len); + +//! Return a pointer to the blob's data +const void *pmt_blob_data(pmt_t blob); + +//! Return the blob's length in bytes +size_t pmt_blob_length(pmt_t blob); + +/*! + * <pre> + * ------------------------------------------------------------------------ + * Uniform Numeric Vectors + * + * A uniform numeric vector is a vector whose elements are all of single + * numeric type. pmt offers uniform numeric vectors for signed and + * unsigned 8-bit, 16-bit, 32-bit, and 64-bit integers, two sizes of + * floating point values, and complex floating-point numbers of these + * two sizes. Indexing is zero based. + * + * The names of the functions include these tags in their names: + * + * u8 unsigned 8-bit integers + * s8 signed 8-bit integers + * u16 unsigned 16-bit integers + * s16 signed 16-bit integers + * u32 unsigned 32-bit integers + * s32 signed 32-bit integers + * u64 unsigned 64-bit integers + * s64 signed 64-bit integers + * f32 the C++ type float + * f64 the C++ type double + * c32 the C++ type complex<float> + * c64 the C++ type complex<double> + * ------------------------------------------------------------------------ + * </pre> + */ + +//! true if \p x is any kind of uniform numeric vector +bool pmt_is_uniform_vector(pmt_t x); + +bool pmt_is_u8vector(pmt_t x); +bool pmt_is_s8vector(pmt_t x); +bool pmt_is_u16vector(pmt_t x); +bool pmt_is_s16vector(pmt_t x); +bool pmt_is_u32vector(pmt_t x); +bool pmt_is_s32vector(pmt_t x); +bool pmt_is_u64vector(pmt_t x); +bool pmt_is_s64vector(pmt_t x); +bool pmt_is_f32vector(pmt_t x); +bool pmt_is_f64vector(pmt_t x); +bool pmt_is_c32vector(pmt_t x); +bool pmt_is_c64vector(pmt_t x); + +pmt_t pmt_make_u8vector(size_t k, uint8_t fill); +pmt_t pmt_make_s8vector(size_t k, int8_t fill); +pmt_t pmt_make_u16vector(size_t k, uint16_t fill); +pmt_t pmt_make_s16vector(size_t k, int16_t fill); +pmt_t pmt_make_u32vector(size_t k, uint32_t fill); +pmt_t pmt_make_s32vector(size_t k, int32_t fill); +pmt_t pmt_make_u64vector(size_t k, uint64_t fill); +pmt_t pmt_make_s64vector(size_t k, int64_t fill); +pmt_t pmt_make_f32vector(size_t k, float fill); +pmt_t pmt_make_f64vector(size_t k, double fill); +pmt_t pmt_make_c32vector(size_t k, std::complex<float> fill); +pmt_t pmt_make_c64vector(size_t k, std::complex<double> fill); + +pmt_t pmt_init_u8vector(size_t k, const uint8_t *data); +pmt_t pmt_init_s8vector(size_t k, const int8_t *data); +pmt_t pmt_init_u16vector(size_t k, const uint16_t *data); +pmt_t pmt_init_s16vector(size_t k, const int16_t *data); +pmt_t pmt_init_u32vector(size_t k, const uint32_t *data); +pmt_t pmt_init_s32vector(size_t k, const int32_t *data); +pmt_t pmt_init_f32vector(size_t k, const float *data); +pmt_t pmt_init_f64vector(size_t k, const double *data); +pmt_t pmt_init_c32vector(size_t k, const std::complex<float> *data); +pmt_t pmt_init_c64vector(size_t k, const std::complex<double> *data); + +uint8_t pmt_u8vector_ref(pmt_t v, size_t k); +int8_t pmt_s8vector_ref(pmt_t v, size_t k); +uint16_t pmt_u16vector_ref(pmt_t v, size_t k); +int16_t pmt_s16vector_ref(pmt_t v, size_t k); +uint32_t pmt_u32vector_ref(pmt_t v, size_t k); +int32_t pmt_s32vector_ref(pmt_t v, size_t k); +uint64_t pmt_u64vector_ref(pmt_t v, size_t k); +int64_t pmt_s64vector_ref(pmt_t v, size_t k); +float pmt_f32vector_ref(pmt_t v, size_t k); +double pmt_f64vector_ref(pmt_t v, size_t k); +std::complex<float> pmt_c32vector_ref(pmt_t v, size_t k); +std::complex<double> pmt_c64vector_ref(pmt_t v, size_t k); + +void pmt_u8vector_set(pmt_t v, size_t k, uint8_t x); //< v[k] = x +void pmt_s8vector_set(pmt_t v, size_t k, int8_t x); +void pmt_u16vector_set(pmt_t v, size_t k, uint16_t x); +void pmt_s16vector_set(pmt_t v, size_t k, int16_t x); +void pmt_u32vector_set(pmt_t v, size_t k, uint32_t x); +void pmt_s32vector_set(pmt_t v, size_t k, int32_t x); +void pmt_u64vector_set(pmt_t v, size_t k, uint64_t x); +void pmt_s64vector_set(pmt_t v, size_t k, int64_t x); +void pmt_f32vector_set(pmt_t v, size_t k, float x); +void pmt_f64vector_set(pmt_t v, size_t k, double x); +void pmt_c32vector_set(pmt_t v, size_t k, std::complex<float> x); +void pmt_c64vector_set(pmt_t v, size_t k, std::complex<double> x); + +// Return const pointers to the elements + +const void *pmt_uniform_vector_elements(pmt_t v, size_t &len); //< works with any; len is in bytes + +const uint8_t *pmt_u8vector_elements(pmt_t v, size_t &len); //< len is in elements +const int8_t *pmt_s8vector_elements(pmt_t v, size_t &len); //< len is in elements +const uint16_t *pmt_u16vector_elements(pmt_t v, size_t &len); //< len is in elements +const int16_t *pmt_s16vector_elements(pmt_t v, size_t &len); //< len is in elements +const uint32_t *pmt_u32vector_elements(pmt_t v, size_t &len); //< len is in elements +const int32_t *pmt_s32vector_elements(pmt_t v, size_t &len); //< len is in elements +const uint64_t *pmt_u64vector_elements(pmt_t v, size_t &len); //< len is in elements +const int64_t *pmt_s64vector_elements(pmt_t v, size_t &len); //< len is in elements +const float *pmt_f32vector_elements(pmt_t v, size_t &len); //< len is in elements +const double *pmt_f64vector_elements(pmt_t v, size_t &len); //< len is in elements +const std::complex<float> *pmt_c32vector_elements(pmt_t v, size_t &len); //< len is in elements +const std::complex<double> *pmt_c64vector_elements(pmt_t v, size_t &len); //< len is in elements + +// Return non-const pointers to the elements + +void *pmt_uniform_vector_writable_elements(pmt_t v, size_t &len); //< works with any; len is in bytes + +uint8_t *pmt_u8vector_writable_elements(pmt_t v, size_t &len); //< len is in elements +int8_t *pmt_s8vector_writable_elements(pmt_t v, size_t &len); //< len is in elements +uint16_t *pmt_u16vector_writable_elements(pmt_t v, size_t &len); //< len is in elements +int16_t *pmt_s16vector_writable_elements(pmt_t v, size_t &len); //< len is in elements +uint32_t *pmt_u32vector_writable_elements(pmt_t v, size_t &len); //< len is in elements +int32_t *pmt_s32vector_writable_elements(pmt_t v, size_t &len); //< len is in elements +uint64_t *pmt_u64vector_writable_elements(pmt_t v, size_t &len); //< len is in elements +int64_t *pmt_s64vector_writable_elements(pmt_t v, size_t &len); //< len is in elements +float *pmt_f32vector_writable_elements(pmt_t v, size_t &len); //< len is in elements +double *pmt_f64vector_writable_elements(pmt_t v, size_t &len); //< len is in elements +std::complex<float> *pmt_c32vector_writable_elements(pmt_t v, size_t &len); //< len is in elements +std::complex<double> *pmt_c64vector_writable_elements(pmt_t v, size_t &len); //< len is in elements + +/* + * ------------------------------------------------------------------------ + * Dictionary (a.k.a associative array, hash, map) + * + * This is a functional data structure that is persistent. Updating a + * functional data structure does not destroy the existing version, but + * rather creates a new version that coexists with the old. + * ------------------------------------------------------------------------ + */ + +//! Return true if \p obj is a dictionary +bool pmt_is_dict(const pmt_t &obj); + +//! Make an empty dictionary +pmt_t pmt_make_dict(); + +//! Return a new dictionary with \p key associated with \p value. +pmt_t pmt_dict_add(const pmt_t &dict, const pmt_t &key, const pmt_t &value); + +//! Return a new dictionary with \p key removed. +pmt_t pmt_dict_delete(const pmt_t &dict, const pmt_t &key); + +//! Return true if \p key exists in \p dict +bool pmt_dict_has_key(const pmt_t &dict, const pmt_t &key); + +//! If \p key exists in \p dict, return associated value; otherwise return \p not_found. +pmt_t pmt_dict_ref(const pmt_t &dict, const pmt_t &key, const pmt_t ¬_found); + +//! Return list of (key . value) pairs +pmt_t pmt_dict_items(pmt_t dict); + +//! Return list of keys +pmt_t pmt_dict_keys(pmt_t dict); + +//! Return list of values +pmt_t pmt_dict_values(pmt_t dict); + +/* + * ------------------------------------------------------------------------ + * Any (wraps boost::any -- can be used to wrap pretty much anything) + * + * Cannot be serialized or used across process boundaries. + * See http://www.boost.org/doc/html/any.html + * ------------------------------------------------------------------------ + */ + +//! Return true if \p obj is an any +bool pmt_is_any(pmt_t obj); + +//! make an any +pmt_t pmt_make_any(const boost::any &any); + +//! Return underlying boost::any +boost::any pmt_any_ref(pmt_t obj); + +//! Store \p any in \p obj +void pmt_any_set(pmt_t obj, const boost::any &any); + + +/* + * ------------------------------------------------------------------------ + * msg_accepter -- pmt representation of gruel::msg_accepter + * ------------------------------------------------------------------------ + */ +//! Return true if \p obj is a msg_accepter +bool pmt_is_msg_accepter(const pmt_t &obj); + +//! make a msg_accepter +pmt_t pmt_make_msg_accepter(boost::shared_ptr<gruel::msg_accepter> ma); + +//! Return underlying msg_accepter +boost::shared_ptr<gruel::msg_accepter> pmt_msg_accepter_ref(const pmt_t &obj); + +/* + * ------------------------------------------------------------------------ + * General functions + * ------------------------------------------------------------------------ + */ + +//! Return true if x and y are the same object; otherwise return false. +bool pmt_eq(const pmt_t& x, const pmt_t& y); + +/*! + * \brief Return true if x and y should normally be regarded as the same object, else false. + * + * <pre> + * eqv returns true if: + * x and y are the same object. + * x and y are both \#t or both \#f. + * x and y are both symbols and their names are the same. + * x and y are both numbers, and are numerically equal. + * x and y are both the empty list (nil). + * x and y are pairs or vectors that denote same location in store. + * </pre> + */ +bool pmt_eqv(const pmt_t& x, const pmt_t& y); + +/*! + * pmt_equal recursively compares the contents of pairs and vectors, + * applying pmt_eqv on other objects such as numbers and symbols. + * pmt_equal may fail to terminate if its arguments are circular data + * structures. + */ +bool pmt_equal(const pmt_t& x, const pmt_t& y); + + +//! Return the number of elements in v +size_t pmt_length(const pmt_t& v); + +/*! + * \brief Find the first pair in \p alist whose car field is \p obj + * and return that pair. + * + * \p alist (for "association list") must be a list of pairs. If no pair + * in \p alist has \p obj as its car then \#f is returned. + * Uses pmt_eq to compare \p obj with car fields of the pairs in \p alist. + */ +pmt_t pmt_assq(pmt_t obj, pmt_t alist); + +/*! + * \brief Find the first pair in \p alist whose car field is \p obj + * and return that pair. + * + * \p alist (for "association list") must be a list of pairs. If no pair + * in \p alist has \p obj as its car then \#f is returned. + * Uses pmt_eqv to compare \p obj with car fields of the pairs in \p alist. + */ +pmt_t pmt_assv(pmt_t obj, pmt_t alist); + +/*! + * \brief Find the first pair in \p alist whose car field is \p obj + * and return that pair. + * + * \p alist (for "association list") must be a list of pairs. If no pair + * in \p alist has \p obj as its car then \#f is returned. + * Uses pmt_equal to compare \p obj with car fields of the pairs in \p alist. + */ +pmt_t pmt_assoc(pmt_t obj, pmt_t alist); + +/*! + * \brief Apply \p proc element-wise to the elements of list and returns + * a list of the results, in order. + * + * \p list must be a list. The dynamic order in which \p proc is + * applied to the elements of \p list is unspecified. + */ +pmt_t pmt_map(pmt_t proc(const pmt_t&), pmt_t list); + +/*! + * \brief reverse \p list. + * + * \p list must be a proper list. + */ +pmt_t pmt_reverse(pmt_t list); + +/*! + * \brief destructively reverse \p list. + * + * \p list must be a proper list. + */ +pmt_t pmt_reverse_x(pmt_t list); + +/*! + * \brief (acons x y a) == (cons (cons x y) a) + */ +inline static pmt_t +pmt_acons(pmt_t x, pmt_t y, pmt_t a) +{ + return pmt_cons(pmt_cons(x, y), a); +} + +/*! + * \brief locates \p nth element of \n list where the car is the 'zeroth' element. + */ +pmt_t pmt_nth(size_t n, pmt_t list); + +/*! + * \brief returns the tail of \p list that would be obtained by calling + * cdr \p n times in succession. + */ +pmt_t pmt_nthcdr(size_t n, pmt_t list); + +/*! + * \brief Return the first sublist of \p list whose car is \p obj. + * If \p obj does not occur in \p list, then \#f is returned. + * pmt_memq use pmt_eq to compare \p obj with the elements of \p list. + */ +pmt_t pmt_memq(pmt_t obj, pmt_t list); + +/*! + * \brief Return the first sublist of \p list whose car is \p obj. + * If \p obj does not occur in \p list, then \#f is returned. + * pmt_memv use pmt_eqv to compare \p obj with the elements of \p list. + */ +pmt_t pmt_memv(pmt_t obj, pmt_t list); + +/*! + * \brief Return the first sublist of \p list whose car is \p obj. + * If \p obj does not occur in \p list, then \#f is returned. + * pmt_member use pmt_equal to compare \p obj with the elements of \p list. + */ +pmt_t pmt_member(pmt_t obj, pmt_t list); + +/*! + * \brief Return true if every element of \p list1 appears in \p list2, and false otherwise. + * Comparisons are done with pmt_eqv. + */ +bool pmt_subsetp(pmt_t list1, pmt_t list2); + +/*! + * \brief Return a list of length 1 containing \p x1 + */ +pmt_t pmt_list1(const pmt_t& x1); + +/*! + * \brief Return a list of length 2 containing \p x1, \p x2 + */ +pmt_t pmt_list2(const pmt_t& x1, const pmt_t& x2); + +/*! + * \brief Return a list of length 3 containing \p x1, \p x2, \p x3 + */ +pmt_t pmt_list3(const pmt_t& x1, const pmt_t& x2, const pmt_t& x3); + +/*! + * \brief Return a list of length 4 containing \p x1, \p x2, \p x3, \p x4 + */ +pmt_t pmt_list4(const pmt_t& x1, const pmt_t& x2, const pmt_t& x3, const pmt_t& x4); + +/*! + * \brief Return a list of length 5 containing \p x1, \p x2, \p x3, \p x4, \p x5 + */ +pmt_t pmt_list5(const pmt_t& x1, const pmt_t& x2, const pmt_t& x3, const pmt_t& x4, const pmt_t& x5); + +/*! + * \brief Return a list of length 6 containing \p x1, \p x2, \p x3, \p x4, \p + * x5, \p x6 + */ +pmt_t pmt_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); + +/*! + * \brief Return \p list with \p item added to it. + */ +pmt_t pmt_list_add(pmt_t list, const pmt_t& item); + + +/* + * ------------------------------------------------------------------------ + * read / write + * ------------------------------------------------------------------------ + */ +extern const pmt_t PMT_EOF; //< The end of file object + +//! return true if obj is the EOF object, otherwise return false. +bool pmt_is_eof_object(pmt_t obj); + +/*! + * read converts external representations of pmt objects into the + * objects themselves. Read returns the next object parsable from + * the given input port, updating port to point to the first + * character past the end of the external representation of the + * object. + * + * If an end of file is encountered in the input before any + * characters are found that can begin an object, then an end of file + * object is returned. The port remains open, and further attempts + * to read will also return an end of file object. If an end of file + * is encountered after the beginning of an object's external + * representation, but the external representation is incomplete and + * therefore not parsable, an error is signaled. + */ +pmt_t pmt_read(std::istream &port); + +/*! + * Write a written representation of \p obj to the given \p port. + */ +void pmt_write(pmt_t obj, std::ostream &port); + +/*! + * Return a string representation of \p obj. + * This is the same output as would be generated by pmt_write. + */ +std::string pmt_write_string(pmt_t obj); + + +/*! + * \brief Write pmt string representation to stdout. + */ +void pmt_print(pmt_t v); + + +/* + * ------------------------------------------------------------------------ + * portable byte stream representation + * ------------------------------------------------------------------------ + */ +/*! + * \brief Write portable byte-serial representation of \p obj to \p sink + */ +bool pmt_serialize(pmt_t obj, std::streambuf &sink); + +/*! + * \brief Create obj from portable byte-serial representation + */ +pmt_t pmt_deserialize(std::streambuf &source); + + +void pmt_dump_sizeof(); // debugging + +/*! + * \brief Provide a simple string generating interface to pmt's serialize function + */ +std::string pmt_serialize_str(pmt_t obj); + +/*! + * \brief Provide a simple string generating interface to pmt's deserialize function + */ +pmt_t pmt_deserialize_str(std::string str); |