summaryrefslogtreecommitdiff
path: root/gruel
diff options
context:
space:
mode:
Diffstat (limited to 'gruel')
-rw-r--r--gruel/CMakeLists.txt104
-rw-r--r--gruel/README29
-rw-r--r--gruel/gruel.pc.in11
-rw-r--r--gruel/src/include/gruel/CMakeLists.txt39
-rw-r--r--gruel/src/include/gruel/api.h33
-rw-r--r--gruel/src/include/gruel/attributes.h74
-rw-r--r--gruel/src/include/gruel/high_res_timer.h124
-rw-r--r--gruel/src/include/gruel/msg_accepter.h53
-rw-r--r--gruel/src/include/gruel/msg_accepter_msgq.h50
-rw-r--r--gruel/src/include/gruel/msg_passing.h116
-rw-r--r--gruel/src/include/gruel/msg_queue.h91
-rw-r--r--gruel/src/include/gruel/pmt.h864
-rw-r--r--gruel/src/include/gruel/pmt_pool.h73
-rw-r--r--gruel/src/include/gruel/pmt_sugar.h171
-rw-r--r--gruel/src/include/gruel/realtime.h96
-rw-r--r--gruel/src/include/gruel/sys_pri.h42
-rw-r--r--gruel/src/include/gruel/thread.h139
-rw-r--r--gruel/src/include/gruel/thread_body_wrapper.h69
-rw-r--r--gruel/src/include/gruel/thread_group.h45
-rw-r--r--gruel/src/lib/CMakeLists.txt110
-rw-r--r--gruel/src/lib/msg/CMakeLists.txt28
-rw-r--r--gruel/src/lib/msg/msg_accepter.cc36
-rw-r--r--gruel/src/lib/msg/msg_accepter_msgq.cc48
-rw-r--r--gruel/src/lib/msg/msg_queue.cc103
-rw-r--r--gruel/src/lib/pmt/CMakeLists.txt89
-rw-r--r--gruel/src/lib/pmt/gen-serial-tags.py53
-rwxr-xr-xgruel/src/lib/pmt/generate_unv.py190
-rw-r--r--gruel/src/lib/pmt/pmt-serial-tags.scm77
-rw-r--r--gruel/src/lib/pmt/pmt.cc1428
-rw-r--r--gruel/src/lib/pmt/pmt_int.h247
-rw-r--r--gruel/src/lib/pmt/pmt_io.cc168
-rw-r--r--gruel/src/lib/pmt/pmt_pool.cc112
-rw-r--r--gruel/src/lib/pmt/pmt_serialize.cc830
-rw-r--r--gruel/src/lib/pmt/qa_pmt.cc40
-rw-r--r--gruel/src/lib/pmt/qa_pmt.h37
-rw-r--r--gruel/src/lib/pmt/qa_pmt_prims.cc603
-rw-r--r--gruel/src/lib/pmt/qa_pmt_prims.h77
-rw-r--r--gruel/src/lib/pmt/unv_qa_template.cc.t35
-rw-r--r--gruel/src/lib/pmt/unv_template.cc.t141
-rw-r--r--gruel/src/lib/pmt/unv_template.h.t23
-rw-r--r--gruel/src/lib/realtime.cc178
-rw-r--r--gruel/src/lib/sys_pri.cc61
-rw-r--r--gruel/src/lib/test_gruel.cc52
-rw-r--r--gruel/src/lib/thread.cc226
-rw-r--r--gruel/src/lib/thread_body_wrapper.cc85
-rw-r--r--gruel/src/lib/thread_group.cc99
-rw-r--r--gruel/src/python/CMakeLists.txt53
-rw-r--r--gruel/src/python/__init__.py29
-rw-r--r--gruel/src/python/pmt/__init__.py31
-rw-r--r--gruel/src/python/pmt/pmt_to_python.py97
-rwxr-xr-xgruel/src/python/qa_pmt.py102
-rwxr-xr-xgruel/src/python/qa_pmt_to_python.py34
-rw-r--r--gruel/src/swig/CMakeLists.txt52
-rw-r--r--gruel/src/swig/__init__.py0
-rw-r--r--gruel/src/swig/gr_intrusive_ptr.i104
-rw-r--r--gruel/src/swig/gruel_common.i66
-rw-r--r--gruel/src/swig/pmt_swig.i792
57 files changed, 8759 insertions, 0 deletions
diff --git a/gruel/CMakeLists.txt b/gruel/CMakeLists.txt
new file mode 100644
index 000000000..3e8c5166e
--- /dev/null
+++ b/gruel/CMakeLists.txt
@@ -0,0 +1,104 @@
+# Copyright 2010-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.
+
+########################################################################
+# Setup dependencies
+########################################################################
+include(GrBoost)
+
+include(GrPython) #used for code generation
+
+########################################################################
+# Register component
+########################################################################
+include(GrComponent)
+GR_REGISTER_COMPONENT("gruel" ENABLE_GRUEL
+ Boost_FOUND
+ PYTHONINTERP_FOUND
+)
+
+include(GrMiscUtils)
+GR_SET_GLOBAL(GRUEL_INCLUDE_DIRS
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/include
+ ${CMAKE_CURRENT_BINARY_DIR}/src/include
+ ${Boost_INCLUDE_DIRS}
+)
+
+########################################################################
+# Begin conditional configuration
+########################################################################
+if(ENABLE_GRUEL)
+
+########################################################################
+# Setup CPack components
+########################################################################
+include(GrPackage)
+CPACK_SET(CPACK_COMPONENT_GROUP_GRUEL_DESCRIPTION "GNU Radio Utility Etcetera Library")
+
+CPACK_COMPONENT("gruel_runtime"
+ GROUP "Gruel"
+ DISPLAY_NAME "Runtime"
+ DESCRIPTION "Dynamic link libraries"
+)
+
+CPACK_COMPONENT("gruel_devel"
+ GROUP "Gruel"
+ DISPLAY_NAME "Development"
+ DESCRIPTION "C++ headers, package config, import libraries"
+)
+
+CPACK_COMPONENT("gruel_python"
+ GROUP "Gruel"
+ DISPLAY_NAME "Python"
+ DESCRIPTION "Python modules for runtime"
+ DEPENDS "gruel_runtime"
+)
+
+CPACK_COMPONENT("gruel_swig"
+ GROUP "Gruel"
+ DISPLAY_NAME "SWIG"
+ DESCRIPTION "SWIG development .i files"
+ DEPENDS "gruel_python;gruel_devel"
+)
+
+########################################################################
+# Add subdirectories
+########################################################################
+add_subdirectory(src/include/gruel)
+add_subdirectory(src/lib)
+if(ENABLE_PYTHON)
+ add_subdirectory(src/swig)
+ add_subdirectory(src/python)
+endif(ENABLE_PYTHON)
+
+########################################################################
+# Create Pkg Config File
+########################################################################
+configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/gruel.pc.in
+ ${CMAKE_CURRENT_BINARY_DIR}/gruel.pc
+@ONLY)
+
+install(
+ FILES ${CMAKE_CURRENT_BINARY_DIR}/gruel.pc
+ DESTINATION ${GR_LIBRARY_DIR}/pkgconfig
+ COMPONENT "gruel_devel"
+)
+
+endif(ENABLE_GRUEL)
diff --git a/gruel/README b/gruel/README
new file mode 100644
index 000000000..90dc4eeb4
--- /dev/null
+++ b/gruel/README
@@ -0,0 +1,29 @@
+#
+# Copyright 2008 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 GNU Radio Utility Etcetera Library, a collection of low-level routines
+to avoid dependencies on the full GNU Radio core or other libraries.
+
+Over time, some code from libgnuradio-core and libpmt will migrate
+here, to avoid duplication of code and simplify dependencies.
+
+By design, this library will not have dependencies on any other part
+of GNU Radio, but may have external dependencies such as Boost.
diff --git a/gruel/gruel.pc.in b/gruel/gruel.pc.in
new file mode 100644
index 000000000..7f3f821fe
--- /dev/null
+++ b/gruel/gruel.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: gruel
+Description: The GNU Radio Utility Etcetera Library
+Requires:
+Version: @LIBVER@
+Libs: -L${libdir} -lgruel
+Cflags: -I${includedir}
diff --git a/gruel/src/include/gruel/CMakeLists.txt b/gruel/src/include/gruel/CMakeLists.txt
new file mode 100644
index 000000000..d4c36eddb
--- /dev/null
+++ b/gruel/src/include/gruel/CMakeLists.txt
@@ -0,0 +1,39 @@
+# Copyright 2010-2012 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.
+
+########################################################################
+# Install the headers
+########################################################################
+install(FILES
+ api.h
+ attributes.h
+ high_res_timer.h
+ msg_accepter.h
+ msg_accepter_msgq.h
+ msg_queue.h
+ msg_passing.h
+ pmt.h
+ pmt_pool.h
+ pmt_sugar.h
+ realtime.h
+ sys_pri.h
+ thread_body_wrapper.h
+ thread_group.h
+ thread.h
+DESTINATION ${GR_INCLUDE_DIR}/gruel COMPONENT "gruel_devel")
diff --git a/gruel/src/include/gruel/api.h b/gruel/src/include/gruel/api.h
new file mode 100644
index 000000000..945814d43
--- /dev/null
+++ b/gruel/src/include/gruel/api.h
@@ -0,0 +1,33 @@
+/*
+ * 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_API_H
+#define INCLUDED_GRUEL_API_H
+
+#include <gruel/attributes.h>
+
+#ifdef gruel_EXPORTS
+# define GRUEL_API __GR_ATTR_EXPORT
+#else
+# define GRUEL_API __GR_ATTR_IMPORT
+#endif
+
+#endif /* INCLUDED_GRUEL_API_H */
diff --git a/gruel/src/include/gruel/attributes.h b/gruel/src/include/gruel/attributes.h
new file mode 100644
index 000000000..baa5521c8
--- /dev/null
+++ b/gruel/src/include/gruel/attributes.h
@@ -0,0 +1,74 @@
+/*
+ * 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
+
+////////////////////////////////////////////////////////////////////////
+// define inline when building C
+////////////////////////////////////////////////////////////////////////
+#if defined(_MSC_VER) && !defined(__cplusplus) && !defined(inline)
+# define inline __inline
+#endif
+
+////////////////////////////////////////////////////////////////////////
+// suppress warnings
+////////////////////////////////////////////////////////////////////////
+#ifdef _MSC_VER
+# pragma warning(disable: 4251) // class 'A<T>' needs to have dll-interface to be used by clients of class 'B'
+# pragma warning(disable: 4275) // non dll-interface class ... used as base for dll-interface class ...
+# pragma warning(disable: 4244) // conversion from 'double' to 'float', possible loss of data
+# pragma warning(disable: 4305) // 'initializing' : truncation from 'double' to 'float'
+# pragma warning(disable: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow)
+#endif
+
+#endif /* INCLUDED_GRUEL_ATTRIBUTES_H */
diff --git a/gruel/src/include/gruel/high_res_timer.h b/gruel/src/include/gruel/high_res_timer.h
new file mode 100644
index 000000000..a885520b6
--- /dev/null
+++ b/gruel/src/include/gruel/high_res_timer.h
@@ -0,0 +1,124 @@
+/*
+ * 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.
+ */
+
+#ifndef INCLUDED_GRUEL_HIGH_RES_TIMER_H
+#define INCLUDED_GRUEL_HIGH_RES_TIMER_H
+
+namespace gruel {
+ //! Typedef for the timer tick count
+ typedef signed long long high_res_timer_type;
+
+ //! Get the current time in ticks
+ high_res_timer_type high_res_timer_now(void);
+
+ //! Get the number of ticks per second
+ high_res_timer_type high_res_timer_tps(void);
+
+ //! Get the tick count at the epoch
+ high_res_timer_type high_res_timer_epoch(void);
+
+} /* namespace gruel */
+
+////////////////////////////////////////////////////////////////////////
+// Use architecture defines to determine the implementation
+////////////////////////////////////////////////////////////////////////
+#if defined(linux) || defined(__linux) || defined(__linux__)
+ #define GRUEL_HRT_USE_CLOCK_GETTIME
+#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
+ #define GRUEL_HRT_USE_QUERY_PERFORMANCE_COUNTER
+#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
+ #define GRUEL_HRT_USE_MACH_ABSOLUTE_TIME
+#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
+ #define GRUEL_HRT_USE_CLOCK_GETTIME
+#else
+ #define GRUEL_HRT_USE_MICROSEC_CLOCK
+#endif
+
+////////////////////////////////////////////////////////////////////////
+#ifdef GRUEL_HRT_USE_CLOCK_GETTIME
+ #include <ctime>
+
+ inline gruel::high_res_timer_type gruel::high_res_timer_now(void){
+ timespec ts;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ return ts.tv_sec*high_res_timer_tps() + ts.tv_nsec;
+ }
+
+ inline gruel::high_res_timer_type gruel::high_res_timer_tps(void){
+ return 1000000000UL;
+ }
+#endif /* GRUEL_HRT_USE_CLOCK_GETTIME */
+
+////////////////////////////////////////////////////////////////////////
+#ifdef GRUEL_HRT_USE_MACH_ABSOLUTE_TIME
+ #include <mach/mach_time.h>
+
+ inline gruel::high_res_timer_type gruel::high_res_timer_now(void){
+ return mach_absolute_time();
+ }
+
+ inline gruel::high_res_timer_type gruel::high_res_timer_tps(void){
+ mach_timebase_info_data_t info;
+ mach_timebase_info(&info);
+ return gruel::high_res_timer_type(info.numer*1000000000UL)/info.denom;
+ }
+#endif
+
+////////////////////////////////////////////////////////////////////////
+#ifdef GRUEL_HRT_USE_QUERY_PERFORMANCE_COUNTER
+ #include <Windows.h>
+
+ inline gruel::high_res_timer_type gruel::high_res_timer_now(void){
+ LARGE_INTEGER counts;
+ QueryPerformanceCounter(&counts);
+ return counts.QuadPart;
+ }
+
+ inline gruel::high_res_timer_type gruel::high_res_timer_tps(void){
+ LARGE_INTEGER freq;
+ QueryPerformanceFrequency(&freq);
+ return freq.QuadPart;
+ }
+#endif
+
+////////////////////////////////////////////////////////////////////////
+#ifdef GRUEL_HRT_USE_MICROSEC_CLOCK
+ #include <boost/date_time/posix_time/posix_time.hpp>
+
+ inline gruel::high_res_timer_type gruel::high_res_timer_now(void){
+ static const boost::posix_time::ptime epoch(boost::posix_time::from_time_t(0));
+ return (boost::posix_time::microsec_clock::universal_time() - epoch).ticks();
+ }
+
+ inline gruel::high_res_timer_type gruel::high_res_timer_tps(void){
+ return boost::posix_time::time_duration::ticks_per_second();
+ }
+#endif
+
+////////////////////////////////////////////////////////////////////////
+#include <boost/date_time/posix_time/posix_time.hpp>
+
+inline gruel::high_res_timer_type gruel::high_res_timer_epoch(void){
+ static const double hrt_ticks_per_utc_ticks = gruel::high_res_timer_tps()/double(boost::posix_time::time_duration::ticks_per_second());
+ boost::posix_time::time_duration utc = boost::posix_time::microsec_clock::universal_time() - boost::posix_time::from_time_t(0);
+ return gruel::high_res_timer_now() - utc.ticks()*hrt_ticks_per_utc_ticks;
+}
+
+#endif /* INCLUDED_GRUEL_HIGH_RES_TIMER_H */
diff --git a/gruel/src/include/gruel/msg_accepter.h b/gruel/src/include/gruel/msg_accepter.h
new file mode 100644
index 000000000..45acb3c78
--- /dev/null
+++ b/gruel/src/include/gruel/msg_accepter.h
@@ -0,0 +1,53 @@
+/* -*- c++ -*- */
+/*
+ * 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef INCLUDED_GRUEL_MSG_ACCEPTER_H
+#define INCLUDED_GRUEL_MSG_ACCEPTER_H
+
+#include <gruel/api.h>
+#include <gruel/pmt.h>
+#include <boost/shared_ptr.hpp>
+
+namespace gruel {
+
+ /*!
+ * \brief Virtual base class that accepts messages
+ */
+ class GRUEL_API msg_accepter
+ {
+ public:
+ msg_accepter() {};
+ virtual ~msg_accepter();
+
+ /*!
+ * \brief send \p msg to \p msg_accepter on port \p which_port
+ *
+ * Sending a message is an asynchronous operation. The \p post
+ * call will not wait for the message either to arrive at the
+ * destination or to be received.
+ */
+ virtual void post(pmt::pmt_t which_port, pmt::pmt_t msg) = 0;
+ };
+
+ typedef boost::shared_ptr<msg_accepter> msg_accepter_sptr;
+
+} /* namespace gruel */
+
+#endif /* INCLUDED_GRUEL_MSG_ACCEPTER_H */
diff --git a/gruel/src/include/gruel/msg_accepter_msgq.h b/gruel/src/include/gruel/msg_accepter_msgq.h
new file mode 100644
index 000000000..6b9bcf4db
--- /dev/null
+++ b/gruel/src/include/gruel/msg_accepter_msgq.h
@@ -0,0 +1,50 @@
+/* -*- c++ -*- */
+/*
+ * 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef INCLUDED_MSG_ACCEPTER_MSGQ_H
+#define INCLUDED_MSG_ACCEPTER_MSGQ_H
+
+#include <gruel/api.h>
+#include <gruel/msg_accepter.h>
+#include <gruel/msg_queue.h>
+
+namespace gruel {
+
+ /*!
+ * \brief Concrete class that accepts messages and inserts them into a message queue.
+ */
+ class GRUEL_API msg_accepter_msgq : public msg_accepter
+ {
+ protected:
+ msg_queue_sptr d_msg_queue;
+
+ public:
+ msg_accepter_msgq(msg_queue_sptr msgq);
+ ~msg_accepter_msgq();
+
+ virtual void post(pmt::pmt_t msg);
+
+ msg_queue_sptr msg_queue() const { return d_msg_queue; }
+ };
+
+} /* namespace gruel */
+
+#endif /* INCLUDED_MSG_ACCEPTER_MSGQ_H */
diff --git a/gruel/src/include/gruel/msg_passing.h b/gruel/src/include/gruel/msg_passing.h
new file mode 100644
index 000000000..25f30118f
--- /dev/null
+++ b/gruel/src/include/gruel/msg_passing.h
@@ -0,0 +1,116 @@
+/* -*- c++ -*- */
+/*
+ * 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef INCLUDED_GRUEL_MSG_PASSING_H
+#define INCLUDED_GRUEL_MSG_PASSING_H
+
+/*!
+ * \brief Include this header to use the message passing features
+ */
+
+#include <gruel/api.h>
+#include <gruel/pmt.h>
+#include <gruel/msg_accepter.h>
+
+
+namespace gruel {
+
+ /*!
+ * \brief send message to msg_accepter
+ *
+ * \param accepter is the target of the send.
+ * \param which_port A pmt symbol describing the port by name.
+ * \param msg is the message to send. It's usually a pmt tuple.
+ *
+ * Sending a message is an asynchronous operation. The \p send
+ * call will not wait for the message either to arrive at the
+ * destination or to be received.
+ *
+ * \returns msg
+ */
+ static inline pmt::pmt_t
+ send(msg_accepter_sptr accepter, const pmt::pmt_t &which_port, const pmt::pmt_t &msg)
+ {
+ accepter->post(which_port, msg);
+ return msg;
+ }
+
+ /*!
+ * \brief send message to msg_accepter
+ *
+ * \param accepter is the target of the send.
+ * \param which_port A pmt symbol describing the port by name.
+ * \param msg is the message to send. It's usually a pmt tuple.
+ *
+ * Sending a message is an asynchronous operation. The \p send
+ * call will not wait for the message either to arrive at the
+ * destination or to be received.
+ *
+ * \returns msg
+ */
+ static inline pmt::pmt_t
+ send(msg_accepter *accepter, const pmt::pmt_t &which_port, const pmt::pmt_t &msg)
+ {
+ accepter->post(which_port, msg);
+ return msg;
+ }
+
+ /*!
+ * \brief send message to msg_accepter
+ *
+ * \param accepter is the target of the send.
+ * \param which_port A pmt symbol describing the port by name.
+ * \param msg is the message to send. It's usually a pmt tuple.
+ *
+ * Sending a message is an asynchronous operation. The \p send
+ * call will not wait for the message either to arrive at the
+ * destination or to be received.
+ *
+ * \returns msg
+ */
+ static inline pmt::pmt_t
+ send(msg_accepter &accepter, const pmt::pmt_t &which_port, const pmt::pmt_t &msg)
+ {
+ accepter.post(which_port, msg);
+ return msg;
+ }
+
+ /*!
+ * \brief send message to msg_accepter
+ *
+ * \param accepter is the target of the send. precond: pmt_is_msg_accepter(accepter)
+ * \param which_port A pmt symbol describing the port by name.
+ * \param msg is the message to send. It's usually a pmt tuple.
+ *
+ * Sending a message is an asynchronous operation. The \p send
+ * call will not wait for the message either to arrive at the
+ * destination or to be received.
+ *
+ * \returns msg
+ */
+ static inline pmt::pmt_t
+ send(pmt::pmt_t accepter, const pmt::pmt_t &which_port, const pmt::pmt_t &msg)
+ {
+ return send(pmt_msg_accepter_ref(accepter), which_port, msg);
+ }
+
+} /* namespace gruel */
+
+#endif /* INCLUDED_GRUEL_MSG_PASSING_H */
diff --git a/gruel/src/include/gruel/msg_queue.h b/gruel/src/include/gruel/msg_queue.h
new file mode 100644
index 000000000..f038ca325
--- /dev/null
+++ b/gruel/src/include/gruel/msg_queue.h
@@ -0,0 +1,91 @@
+/* -*- c++ -*- */
+/*
+ * 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.
+ */
+#ifndef INCLUDED_MSG_QUEUE_H
+#define INCLUDED_MSG_QUEUE_H
+
+#include <gruel/api.h>
+#include <gruel/thread.h>
+#include <gruel/pmt.h>
+#include <deque>
+
+namespace gruel {
+
+ class msg_queue;
+ typedef boost::shared_ptr<msg_queue> msg_queue_sptr;
+
+ msg_queue_sptr make_msg_queue(unsigned int limit=0);
+
+ /*!
+ * \brief thread-safe message queue
+ */
+ class GRUEL_API msg_queue {
+
+ gruel::mutex d_mutex;
+ gruel::condition_variable d_not_empty;
+ gruel::condition_variable d_not_full;
+ unsigned int d_limit; // max # of messages in queue. 0 -> unbounded
+
+ std::deque<pmt::pmt_t> d_msgs;
+
+ public:
+ msg_queue(unsigned int limit);
+ ~msg_queue();
+
+ /*!
+ * \brief Insert message at tail of queue.
+ * \param msg message
+ *
+ * Block if queue if full.
+ */
+ void insert_tail(pmt::pmt_t msg);
+
+ /*!
+ * \brief Delete message from head of queue and return it.
+ * Block if no message is available.
+ */
+ pmt::pmt_t delete_head();
+
+ /*!
+ * \brief If there's a message in the q, delete it and return it.
+ * If no message is available, return pmt_t().
+ */
+ pmt::pmt_t delete_head_nowait();
+
+ //! Delete all messages from the queue
+ void flush();
+
+ //! is the queue empty?
+ bool empty_p() const { return d_msgs.empty(); }
+
+ //! is the queue full?
+ bool full_p() const { return d_limit != 0 && count() >= d_limit; }
+
+ //! return number of messages in queue
+ unsigned int count() const { return d_msgs.size(); }
+
+ //! return limit on number of message in queue. 0 -> unbounded
+ unsigned int limit() const { return d_limit; }
+ };
+
+} /* namespace gruel */
+
+#endif /* INCLUDED_MSG_QUEUE_H */
diff --git a/gruel/src/include/gruel/pmt.h b/gruel/src/include/gruel/pmt.h
new file mode 100644
index 000000000..383a1d44d
--- /dev/null
+++ b/gruel/src/include/gruel/pmt.h
@@ -0,0 +1,864 @@
+/* -*- 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_H
+#define INCLUDED_PMT_H
+
+#include <gruel/api.h>
+#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 <vector>
+
+namespace gruel {
+ class msg_accepter;
+};
+
+/*!
+ * This file defines a polymorphic type and the operations on it.
+ *
+ * It draws heavily on the idea of scheme and lisp data types.
+ * The interface parallels that in Guile 1.8, with the notable
+ * exception that these objects are transparently reference counted.
+ */
+
+namespace pmt {
+
+/*!
+ * \brief base class of all pmt types
+ */
+class pmt_base;
+
+/*!
+ * \brief typedef for shared pointer (transparent reference counting).
+ * See http://www.boost.org/libs/smart_ptr/smart_ptr.htm
+ */
+typedef boost::intrusive_ptr<pmt_base> pmt_t;
+
+extern GRUEL_API void intrusive_ptr_add_ref(pmt_base*);
+extern GRUEL_API void intrusive_ptr_release(pmt_base*);
+
+class GRUEL_API pmt_exception : public std::logic_error
+{
+public:
+ pmt_exception(const std::string &msg, pmt_t obj);
+};
+
+class GRUEL_API pmt_wrong_type : public pmt_exception
+{
+public:
+ pmt_wrong_type(const std::string &msg, pmt_t obj);
+};
+
+class GRUEL_API pmt_out_of_range : public pmt_exception
+{
+public:
+ pmt_out_of_range(const std::string &msg, pmt_t obj);
+};
+
+class GRUEL_API pmt_notimplemented : public pmt_exception
+{
+public:
+ pmt_notimplemented(const std::string &msg, pmt_t obj);
+};
+
+/*
+ * ------------------------------------------------------------------------
+ * 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 GRUEL_API const pmt_t PMT_T; //< \#t : boolean true constant
+extern GRUEL_API const pmt_t PMT_F; //< \#f : boolean false constant
+
+//! Return true if obj is \#t or \#f, else return false.
+GRUEL_API bool pmt_is_bool(pmt_t obj);
+
+//! Return false if obj is \#f, else return true.
+GRUEL_API bool pmt_is_true(pmt_t obj);
+
+//! Return true if obj is \#f, else return true.
+GRUEL_API bool pmt_is_false(pmt_t obj);
+
+//! Return \#f is val is false, else return \#t.
+GRUEL_API 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.
+GRUEL_API bool pmt_to_bool(pmt_t val);
+
+/*
+ * ------------------------------------------------------------------------
+ * Symbols
+ * ------------------------------------------------------------------------
+ */
+
+//! Return true if obj is a symbol, else false.
+GRUEL_API bool pmt_is_symbol(const pmt_t& obj);
+
+//! Return the symbol whose name is \p s.
+GRUEL_API pmt_t pmt_string_to_symbol(const std::string &s);
+
+//! Alias for pmt_string_to_symbol
+GRUEL_API 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.
+ */
+GRUEL_API 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.
+GRUEL_API bool pmt_is_number(pmt_t obj);
+
+/*
+ * ------------------------------------------------------------------------
+ * Integers
+ * ------------------------------------------------------------------------
+ */
+
+//! Return true if \p x is an integer number, else false
+GRUEL_API bool pmt_is_integer(pmt_t x);
+
+//! Return the pmt value that represents the integer \p x.
+GRUEL_API 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.
+ */
+GRUEL_API long pmt_to_long(pmt_t x);
+
+/*
+ * ------------------------------------------------------------------------
+ * uint64_t
+ * ------------------------------------------------------------------------
+ */
+
+//! Return true if \p x is an uint64 number, else false
+GRUEL_API bool pmt_is_uint64(pmt_t x);
+
+//! Return the pmt value that represents the uint64 \p x.
+GRUEL_API 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.
+ */
+GRUEL_API uint64_t pmt_to_uint64(pmt_t x);
+
+/*
+ * ------------------------------------------------------------------------
+ * Reals
+ * ------------------------------------------------------------------------
+ */
+
+/*
+ * \brief Return true if \p obj is a real number, else false.
+ */
+GRUEL_API bool pmt_is_real(pmt_t obj);
+
+//! Return the pmt value that represents double \p x.
+GRUEL_API 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.
+ */
+GRUEL_API double pmt_to_double(pmt_t x);
+
+/*
+ * ------------------------------------------------------------------------
+ * Complex
+ * ------------------------------------------------------------------------
+ */
+
+/*!
+ * \brief return true if \p obj is a complex number, false otherwise.
+ */
+GRUEL_API bool pmt_is_complex(pmt_t obj);
+
+//! Return a complex number constructed of the given real and imaginary parts.
+GRUEL_API pmt_t pmt_make_rectangular(double re, double im);
+
+//! Return a complex number constructed of the given real and imaginary parts.
+GRUEL_API pmt_t pmt_from_complex(double re, double im);
+
+//! Return a complex number constructed of the given a complex number.
+GRUEL_API pmt_t pmt_from_complex(const std::complex<double> &z);
+
+/*!
+ * If \p z is complex, real or integer, return the closest complex<double>.
+ * Otherwise, raise the wrong_type exception.
+ */
+GRUEL_API std::complex<double> pmt_to_complex(pmt_t z);
+
+/*
+ * ------------------------------------------------------------------------
+ * Pairs
+ * ------------------------------------------------------------------------
+ */
+
+extern GRUEL_API const pmt_t PMT_NIL; //< the empty list
+
+//! Return true if \p x is the empty list, otherwise return false.
+GRUEL_API bool pmt_is_null(const pmt_t& x);
+
+//! Return true if \p obj is a pair, else false.
+GRUEL_API bool pmt_is_pair(const pmt_t& obj);
+
+//! Return a newly allocated pair whose car is \p x and whose cdr is \p y.
+GRUEL_API 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.
+GRUEL_API 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.
+GRUEL_API pmt_t pmt_cdr(const pmt_t& pair);
+
+//! Stores \p value in the car field of \p pair.
+GRUEL_API void pmt_set_car(pmt_t pair, pmt_t value);
+
+//! Stores \p value in the cdr field of \p pair.
+GRUEL_API void pmt_set_cdr(pmt_t pair, pmt_t value);
+
+GRUEL_API pmt_t pmt_caar(pmt_t pair);
+GRUEL_API pmt_t pmt_cadr(pmt_t pair);
+GRUEL_API pmt_t pmt_cdar(pmt_t pair);
+GRUEL_API pmt_t pmt_cddr(pmt_t pair);
+GRUEL_API pmt_t pmt_caddr(pmt_t pair);
+GRUEL_API 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.
+GRUEL_API bool pmt_is_tuple(pmt_t x);
+
+GRUEL_API pmt_t pmt_make_tuple();
+GRUEL_API pmt_t pmt_make_tuple(const pmt_t &e0);
+GRUEL_API pmt_t pmt_make_tuple(const pmt_t &e0, const pmt_t &e1);
+GRUEL_API pmt_t pmt_make_tuple(const pmt_t &e0, const pmt_t &e1, const pmt_t &e2);
+GRUEL_API pmt_t pmt_make_tuple(const pmt_t &e0, const pmt_t &e1, const pmt_t &e2, const pmt_t &e3);
+GRUEL_API 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);
+GRUEL_API 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);
+GRUEL_API 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);
+GRUEL_API 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);
+GRUEL_API 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);
+GRUEL_API 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
+ */
+GRUEL_API 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.
+ */
+GRUEL_API 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.
+GRUEL_API bool pmt_is_vector(pmt_t x);
+
+//! Make a vector of length \p k, with initial values set to \p fill
+GRUEL_API 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.
+ */
+GRUEL_API pmt_t pmt_vector_ref(pmt_t vector, size_t k);
+
+//! Store \p obj in position \p k.
+GRUEL_API void pmt_vector_set(pmt_t vector, size_t k, pmt_t obj);
+
+//! Store \p fill in every position of \p vector
+GRUEL_API 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.
+GRUEL_API 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.
+ */
+GRUEL_API pmt_t pmt_make_blob(const void *buf, size_t len);
+
+//! Return a pointer to the blob's data
+GRUEL_API const void *pmt_blob_data(pmt_t blob);
+
+//! Return the blob's length in bytes
+GRUEL_API 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
+GRUEL_API bool pmt_is_uniform_vector(pmt_t x);
+
+GRUEL_API bool pmt_is_u8vector(pmt_t x);
+GRUEL_API bool pmt_is_s8vector(pmt_t x);
+GRUEL_API bool pmt_is_u16vector(pmt_t x);
+GRUEL_API bool pmt_is_s16vector(pmt_t x);
+GRUEL_API bool pmt_is_u32vector(pmt_t x);
+GRUEL_API bool pmt_is_s32vector(pmt_t x);
+GRUEL_API bool pmt_is_u64vector(pmt_t x);
+GRUEL_API bool pmt_is_s64vector(pmt_t x);
+GRUEL_API bool pmt_is_f32vector(pmt_t x);
+GRUEL_API bool pmt_is_f64vector(pmt_t x);
+GRUEL_API bool pmt_is_c32vector(pmt_t x);
+GRUEL_API bool pmt_is_c64vector(pmt_t x);
+
+GRUEL_API pmt_t pmt_make_u8vector(size_t k, uint8_t fill);
+GRUEL_API pmt_t pmt_make_s8vector(size_t k, int8_t fill);
+GRUEL_API pmt_t pmt_make_u16vector(size_t k, uint16_t fill);
+GRUEL_API pmt_t pmt_make_s16vector(size_t k, int16_t fill);
+GRUEL_API pmt_t pmt_make_u32vector(size_t k, uint32_t fill);
+GRUEL_API pmt_t pmt_make_s32vector(size_t k, int32_t fill);
+GRUEL_API pmt_t pmt_make_u64vector(size_t k, uint64_t fill);
+GRUEL_API pmt_t pmt_make_s64vector(size_t k, int64_t fill);
+GRUEL_API pmt_t pmt_make_f32vector(size_t k, float fill);
+GRUEL_API pmt_t pmt_make_f64vector(size_t k, double fill);
+GRUEL_API pmt_t pmt_make_c32vector(size_t k, std::complex<float> fill);
+GRUEL_API pmt_t pmt_make_c64vector(size_t k, std::complex<double> fill);
+
+GRUEL_API pmt_t pmt_init_u8vector(size_t k, const uint8_t *data);
+GRUEL_API pmt_t pmt_init_u8vector(size_t k, const std::vector<uint8_t> &data);
+GRUEL_API pmt_t pmt_init_s8vector(size_t k, const int8_t *data);
+GRUEL_API pmt_t pmt_init_s8vector(size_t k, const std::vector<int8_t> &data);
+GRUEL_API pmt_t pmt_init_u16vector(size_t k, const uint16_t *data);
+GRUEL_API pmt_t pmt_init_u16vector(size_t k, const std::vector<uint16_t> &data);
+GRUEL_API pmt_t pmt_init_s16vector(size_t k, const int16_t *data);
+GRUEL_API pmt_t pmt_init_s16vector(size_t k, const std::vector<int16_t> &data);
+GRUEL_API pmt_t pmt_init_u32vector(size_t k, const uint32_t *data);
+GRUEL_API pmt_t pmt_init_u32vector(size_t k, const std::vector<uint32_t> &data);
+GRUEL_API pmt_t pmt_init_s32vector(size_t k, const int32_t *data);
+GRUEL_API pmt_t pmt_init_s32vector(size_t k, const std::vector<int32_t> &data);
+GRUEL_API pmt_t pmt_init_u64vector(size_t k, const uint64_t *data);
+GRUEL_API pmt_t pmt_init_u64vector(size_t k, const std::vector<uint64_t> &data);
+GRUEL_API pmt_t pmt_init_s64vector(size_t k, const int64_t *data);
+GRUEL_API pmt_t pmt_init_s64vector(size_t k, const std::vector<int64_t> &data);
+GRUEL_API pmt_t pmt_init_f32vector(size_t k, const float *data);
+GRUEL_API pmt_t pmt_init_f32vector(size_t k, const std::vector<float> &data);
+GRUEL_API pmt_t pmt_init_f64vector(size_t k, const double *data);
+GRUEL_API pmt_t pmt_init_f64vector(size_t k, const std::vector<double> &data);
+GRUEL_API pmt_t pmt_init_c32vector(size_t k, const std::complex<float> *data);
+GRUEL_API pmt_t pmt_init_c32vector(size_t k, const std::vector<std::complex<float> > &data);
+GRUEL_API pmt_t pmt_init_c64vector(size_t k, const std::complex<double> *data);
+GRUEL_API pmt_t pmt_init_c64vector(size_t k, const std::vector<std::complex<double> > &data);
+
+GRUEL_API uint8_t pmt_u8vector_ref(pmt_t v, size_t k);
+GRUEL_API int8_t pmt_s8vector_ref(pmt_t v, size_t k);
+GRUEL_API uint16_t pmt_u16vector_ref(pmt_t v, size_t k);
+GRUEL_API int16_t pmt_s16vector_ref(pmt_t v, size_t k);
+GRUEL_API uint32_t pmt_u32vector_ref(pmt_t v, size_t k);
+GRUEL_API int32_t pmt_s32vector_ref(pmt_t v, size_t k);
+GRUEL_API uint64_t pmt_u64vector_ref(pmt_t v, size_t k);
+GRUEL_API int64_t pmt_s64vector_ref(pmt_t v, size_t k);
+GRUEL_API float pmt_f32vector_ref(pmt_t v, size_t k);
+GRUEL_API double pmt_f64vector_ref(pmt_t v, size_t k);
+GRUEL_API std::complex<float> pmt_c32vector_ref(pmt_t v, size_t k);
+GRUEL_API std::complex<double> pmt_c64vector_ref(pmt_t v, size_t k);
+
+GRUEL_API void pmt_u8vector_set(pmt_t v, size_t k, uint8_t x); //< v[k] = x
+GRUEL_API void pmt_s8vector_set(pmt_t v, size_t k, int8_t x);
+GRUEL_API void pmt_u16vector_set(pmt_t v, size_t k, uint16_t x);
+GRUEL_API void pmt_s16vector_set(pmt_t v, size_t k, int16_t x);
+GRUEL_API void pmt_u32vector_set(pmt_t v, size_t k, uint32_t x);
+GRUEL_API void pmt_s32vector_set(pmt_t v, size_t k, int32_t x);
+GRUEL_API void pmt_u64vector_set(pmt_t v, size_t k, uint64_t x);
+GRUEL_API void pmt_s64vector_set(pmt_t v, size_t k, int64_t x);
+GRUEL_API void pmt_f32vector_set(pmt_t v, size_t k, float x);
+GRUEL_API void pmt_f64vector_set(pmt_t v, size_t k, double x);
+GRUEL_API void pmt_c32vector_set(pmt_t v, size_t k, std::complex<float> x);
+GRUEL_API void pmt_c64vector_set(pmt_t v, size_t k, std::complex<double> x);
+
+// Return const pointers to the elements
+
+GRUEL_API const void *pmt_uniform_vector_elements(pmt_t v, size_t &len); //< works with any; len is in bytes
+
+GRUEL_API const uint8_t *pmt_u8vector_elements(pmt_t v, size_t &len); //< len is in elements
+GRUEL_API const int8_t *pmt_s8vector_elements(pmt_t v, size_t &len); //< len is in elements
+GRUEL_API const uint16_t *pmt_u16vector_elements(pmt_t v, size_t &len); //< len is in elements
+GRUEL_API const int16_t *pmt_s16vector_elements(pmt_t v, size_t &len); //< len is in elements
+GRUEL_API const uint32_t *pmt_u32vector_elements(pmt_t v, size_t &len); //< len is in elements
+GRUEL_API const int32_t *pmt_s32vector_elements(pmt_t v, size_t &len); //< len is in elements
+GRUEL_API const uint64_t *pmt_u64vector_elements(pmt_t v, size_t &len); //< len is in elements
+GRUEL_API const int64_t *pmt_s64vector_elements(pmt_t v, size_t &len); //< len is in elements
+GRUEL_API const float *pmt_f32vector_elements(pmt_t v, size_t &len); //< len is in elements
+GRUEL_API const double *pmt_f64vector_elements(pmt_t v, size_t &len); //< len is in elements
+GRUEL_API const std::complex<float> *pmt_c32vector_elements(pmt_t v, size_t &len); //< len is in elements
+GRUEL_API const std::complex<double> *pmt_c64vector_elements(pmt_t v, size_t &len); //< len is in elements
+
+// len is in elements
+GRUEL_API const std::vector<uint8_t> pmt_u8vector_elements(pmt_t v);
+GRUEL_API const std::vector<int8_t> pmt_s8vector_elements(pmt_t v);
+GRUEL_API const std::vector<uint16_t> pmt_u16vector_elements(pmt_t v);
+GRUEL_API const std::vector<int16_t> pmt_s16vector_elements(pmt_t v);
+GRUEL_API const std::vector<uint32_t> pmt_u32vector_elements(pmt_t v);
+GRUEL_API const std::vector<int32_t> pmt_s32vector_elements(pmt_t v);
+GRUEL_API const std::vector<uint64_t> pmt_u64vector_elements(pmt_t v);
+GRUEL_API const std::vector<int64_t> pmt_s64vector_elements(pmt_t v);
+GRUEL_API const std::vector<float> pmt_f32vector_elements(pmt_t v);
+GRUEL_API const std::vector<double> pmt_f64vector_elements(pmt_t v);
+GRUEL_API const std::vector<std::complex<float> > pmt_c32vector_elements(pmt_t v);
+GRUEL_API const std::vector<std::complex<double> > pmt_c64vector_elements(pmt_t v);
+
+// Return non-const pointers to the elements
+
+GRUEL_API void *pmt_uniform_vector_writable_elements(pmt_t v, size_t &len); //< works with any; len is in bytes
+
+GRUEL_API uint8_t *pmt_u8vector_writable_elements(pmt_t v, size_t &len); //< len is in elements
+GRUEL_API int8_t *pmt_s8vector_writable_elements(pmt_t v, size_t &len); //< len is in elements
+GRUEL_API uint16_t *pmt_u16vector_writable_elements(pmt_t v, size_t &len); //< len is in elements
+GRUEL_API int16_t *pmt_s16vector_writable_elements(pmt_t v, size_t &len); //< len is in elements
+GRUEL_API uint32_t *pmt_u32vector_writable_elements(pmt_t v, size_t &len); //< len is in elements
+GRUEL_API int32_t *pmt_s32vector_writable_elements(pmt_t v, size_t &len); //< len is in elements
+GRUEL_API uint64_t *pmt_u64vector_writable_elements(pmt_t v, size_t &len); //< len is in elements
+GRUEL_API int64_t *pmt_s64vector_writable_elements(pmt_t v, size_t &len); //< len is in elements
+GRUEL_API float *pmt_f32vector_writable_elements(pmt_t v, size_t &len); //< len is in elements
+GRUEL_API double *pmt_f64vector_writable_elements(pmt_t v, size_t &len); //< len is in elements
+GRUEL_API std::complex<float> *pmt_c32vector_writable_elements(pmt_t v, size_t &len); //< len is in elements
+GRUEL_API 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
+GRUEL_API bool pmt_is_dict(const pmt_t &obj);
+
+//! Make an empty dictionary
+GRUEL_API pmt_t pmt_make_dict();
+
+//! Return a new dictionary with \p key associated with \p value.
+GRUEL_API 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.
+GRUEL_API pmt_t pmt_dict_delete(const pmt_t &dict, const pmt_t &key);
+
+//! Return true if \p key exists in \p dict
+GRUEL_API 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.
+GRUEL_API pmt_t pmt_dict_ref(const pmt_t &dict, const pmt_t &key, const pmt_t &not_found);
+
+//! Return list of (key . value) pairs
+GRUEL_API pmt_t pmt_dict_items(pmt_t dict);
+
+//! Return list of keys
+GRUEL_API pmt_t pmt_dict_keys(pmt_t dict);
+
+//! Return list of values
+GRUEL_API 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
+GRUEL_API bool pmt_is_any(pmt_t obj);
+
+//! make an any
+GRUEL_API pmt_t pmt_make_any(const boost::any &any);
+
+//! Return underlying boost::any
+GRUEL_API boost::any pmt_any_ref(pmt_t obj);
+
+//! Store \p any in \p obj
+GRUEL_API 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
+GRUEL_API bool pmt_is_msg_accepter(const pmt_t &obj);
+
+//! make a msg_accepter
+GRUEL_API pmt_t pmt_make_msg_accepter(boost::shared_ptr<gruel::msg_accepter> ma);
+
+//! Return underlying msg_accepter
+GRUEL_API 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.
+GRUEL_API 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>
+ */
+GRUEL_API 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.
+ */
+GRUEL_API bool pmt_equal(const pmt_t& x, const pmt_t& y);
+
+
+//! Return the number of elements in v
+GRUEL_API 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.
+ */
+GRUEL_API 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.
+ */
+GRUEL_API 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.
+ */
+GRUEL_API 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.
+ */
+GRUEL_API pmt_t pmt_map(pmt_t proc(const pmt_t&), pmt_t list);
+
+/*!
+ * \brief reverse \p list.
+ *
+ * \p list must be a proper list.
+ */
+GRUEL_API pmt_t pmt_reverse(pmt_t list);
+
+/*!
+ * \brief destructively reverse \p list.
+ *
+ * \p list must be a proper list.
+ */
+GRUEL_API 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.
+ */
+GRUEL_API 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.
+ */
+GRUEL_API 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.
+ */
+GRUEL_API 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.
+ */
+GRUEL_API 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.
+ */
+GRUEL_API 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.
+ */
+GRUEL_API bool pmt_subsetp(pmt_t list1, pmt_t list2);
+
+/*!
+ * \brief Return a list of length 1 containing \p x1
+ */
+GRUEL_API pmt_t pmt_list1(const pmt_t& x1);
+
+/*!
+ * \brief Return a list of length 2 containing \p x1, \p x2
+ */
+GRUEL_API 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
+ */
+GRUEL_API 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
+ */
+GRUEL_API 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
+ */
+GRUEL_API 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
+ */
+GRUEL_API 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.
+ */
+GRUEL_API pmt_t pmt_list_add(pmt_t list, const pmt_t& item);
+
+/*!
+ * \brief Return \p list with \p item removed from it.
+ */
+GRUEL_API pmt_t pmt_list_rm(pmt_t list, const pmt_t& item);
+
+/*!
+ * \brief Return bool of \p list contains \p item
+ */
+GRUEL_API bool pmt_list_has(pmt_t list, const pmt_t& item);
+
+
+/*
+ * ------------------------------------------------------------------------
+ * read / write
+ * ------------------------------------------------------------------------
+ */
+extern GRUEL_API const pmt_t PMT_EOF; //< The end of file object
+
+//! return true if obj is the EOF object, otherwise return false.
+GRUEL_API 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.
+ */
+GRUEL_API pmt_t pmt_read(std::istream &port);
+
+/*!
+ * Write a written representation of \p obj to the given \p port.
+ */
+GRUEL_API 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.
+ */
+GRUEL_API std::string pmt_write_string(pmt_t obj);
+
+
+GRUEL_API std::ostream& operator<<(std::ostream &os, pmt_t obj);
+
+/*!
+ * \brief Write pmt string representation to stdout.
+ */
+GRUEL_API void pmt_print(pmt_t v);
+
+
+/*
+ * ------------------------------------------------------------------------
+ * portable byte stream representation
+ * ------------------------------------------------------------------------
+ */
+/*!
+ * \brief Write portable byte-serial representation of \p obj to \p sink
+ */
+GRUEL_API bool pmt_serialize(pmt_t obj, std::streambuf &sink);
+
+/*!
+ * \brief Create obj from portable byte-serial representation
+ */
+GRUEL_API pmt_t pmt_deserialize(std::streambuf &source);
+
+
+GRUEL_API void pmt_dump_sizeof(); // debugging
+
+/*!
+ * \brief Provide a simple string generating interface to pmt's serialize function
+ */
+GRUEL_API std::string pmt_serialize_str(pmt_t obj);
+
+/*!
+ * \brief Provide a simple string generating interface to pmt's deserialize function
+ */
+GRUEL_API pmt_t pmt_deserialize_str(std::string str);
+
+/*!
+ * \brief Provide a comparator function object to allow pmt use in stl types
+ */
+class pmt_comperator {
+ public:
+ bool operator()(pmt::pmt_t const& p1, pmt::pmt_t const& p2) const
+ { return pmt::pmt_eqv(p1,p2)?false:p1.get()>p2.get(); }
+ };
+
+} /* namespace pmt */
+
+#include <gruel/pmt_sugar.h>
+
+#endif /* INCLUDED_PMT_H */
diff --git a/gruel/src/include/gruel/pmt_pool.h b/gruel/src/include/gruel/pmt_pool.h
new file mode 100644
index 000000000..93c5290ad
--- /dev/null
+++ b/gruel/src/include/gruel/pmt_pool.h
@@ -0,0 +1,73 @@
+/* -*- 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.
+ */
+#ifndef INCLUDED_PMT_POOL_H
+#define INCLUDED_PMT_POOL_H
+
+#include <gruel/api.h>
+#include <cstddef>
+#include <vector>
+#include <boost/thread.hpp>
+
+namespace pmt {
+
+/*!
+ * \brief very simple thread-safe fixed-size allocation pool
+ *
+ * FIXME may want to go to global allocation with per-thread free list.
+ * This would eliminate virtually all lock contention.
+ */
+class GRUEL_API pmt_pool {
+
+ struct GRUEL_API item {
+ struct item *d_next;
+ };
+
+ typedef boost::unique_lock<boost::mutex> scoped_lock;
+ mutable boost::mutex d_mutex;
+ boost::condition_variable d_cond;
+
+ size_t d_itemsize;
+ size_t d_alignment;
+ size_t d_allocation_size;
+ size_t d_max_items;
+ size_t d_n_items;
+ item *d_freelist;
+ std::vector<char *> d_allocations;
+
+public:
+ /*!
+ * \param itemsize size in bytes of the items to be allocated.
+ * \param alignment alignment in bytes of all objects to be allocated (must be power-of-2).
+ * \param allocation_size number of bytes to allocate at a time from the underlying allocator.
+ * \param max_items is the maximum number of items to allocate. If this number is exceeded,
+ * the allocate blocks. 0 implies no limit.
+ */
+ pmt_pool(size_t itemsize, size_t alignment = 16,
+ size_t allocation_size = 4096, size_t max_items = 0);
+ ~pmt_pool();
+
+ void *malloc();
+ void free(void *p);
+};
+
+} /* namespace pmt */
+
+#endif /* INCLUDED_PMT_POOL_H */
diff --git a/gruel/src/include/gruel/pmt_sugar.h b/gruel/src/include/gruel/pmt_sugar.h
new file mode 100644
index 000000000..bde7f716d
--- /dev/null
+++ b/gruel/src/include/gruel/pmt_sugar.h
@@ -0,0 +1,171 @@
+/* -*- c++ -*- */
+/*
+ * 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef INCLUDED_GRUEL_PMT_SUGAR_H
+#define INCLUDED_GRUEL_PMT_SUGAR_H
+
+/*!
+ * This file is included by pmt.h and contains pseudo-constructor
+ * shorthand for making pmt objects
+ */
+
+namespace pmt {
+
+ //! Make pmt symbol
+ static inline pmt_t
+ mp(const std::string &s)
+ {
+ return pmt_string_to_symbol(s);
+ }
+
+ //! Make pmt symbol
+ static inline pmt_t
+ mp(const char *s)
+ {
+ return pmt_string_to_symbol(s);
+ }
+
+ //! Make pmt long
+ static inline pmt_t
+ mp(long x){
+ return pmt_from_long(x);
+ }
+
+ //! Make pmt long
+ static inline pmt_t
+ mp(long long unsigned x){
+ return pmt_from_long(x);
+ }
+
+ //! Make pmt long
+ static inline pmt_t
+ mp(int x){
+ return pmt_from_long(x);
+ }
+
+ //! Make pmt double
+ static inline pmt_t
+ mp(double x){
+ return pmt_from_double(x);
+ }
+
+ //! Make pmt complex
+ static inline pmt_t
+ mp(std::complex<double> z)
+ {
+ return pmt_make_rectangular(z.real(), z.imag());
+ }
+
+ //! Make pmt complex
+ static inline pmt_t
+ mp(std::complex<float> z)
+ {
+ return pmt_make_rectangular(z.real(), z.imag());
+ }
+
+ //! Make pmt msg_accepter
+ static inline pmt_t
+ mp(boost::shared_ptr<gruel::msg_accepter> ma)
+ {
+ return pmt_make_msg_accepter(ma);
+ }
+
+ //! Make pmt Binary Large Object (BLOB)
+ static inline pmt_t
+ mp(const void *data, size_t len_in_bytes)
+ {
+ return pmt_make_blob(data, len_in_bytes);
+ }
+
+ //! Make tuple
+ static inline pmt_t
+ mp(const pmt_t &e0)
+ {
+ return pmt_make_tuple(e0);
+ }
+
+ //! Make tuple
+ static inline pmt_t
+ mp(const pmt_t &e0, const pmt_t &e1)
+ {
+ return pmt_make_tuple(e0, e1);
+ }
+
+ //! Make tuple
+ static inline pmt_t
+ mp(const pmt_t &e0, const pmt_t &e1, const pmt_t &e2)
+ {
+ return pmt_make_tuple(e0, e1, e2);
+ }
+
+ //! Make tuple
+ static inline pmt_t
+ mp(const pmt_t &e0, const pmt_t &e1, const pmt_t &e2, const pmt_t &e3)
+ {
+ return pmt_make_tuple(e0, e1, e2, e3);
+ }
+
+ //! Make tuple
+ static inline pmt_t
+ mp(const pmt_t &e0, const pmt_t &e1, const pmt_t &e2, const pmt_t &e3, const pmt_t &e4)
+ {
+ return pmt_make_tuple(e0, e1, e2, e3, e4);
+ }
+
+ //! Make tuple
+ static inline pmt_t
+ mp(const pmt_t &e0, const pmt_t &e1, const pmt_t &e2, const pmt_t &e3, const pmt_t &e4, const pmt_t &e5)
+ {
+ return pmt_make_tuple(e0, e1, e2, e3, e4, e5);
+ }
+
+ //! Make tuple
+ static inline pmt_t
+ mp(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)
+ {
+ return pmt_make_tuple(e0, e1, e2, e3, e4, e5, e6);
+ }
+
+ //! Make tuple
+ static inline pmt_t
+ mp(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)
+ {
+ return pmt_make_tuple(e0, e1, e2, e3, e4, e5, e6, e7);
+ }
+
+ //! Make tuple
+ static inline pmt_t
+ mp(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)
+ {
+ return pmt_make_tuple(e0, e1, e2, e3, e4, e5, e6, e7, e8);
+ }
+
+ //! Make tuple
+ static inline pmt_t
+ mp(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)
+ {
+ return pmt_make_tuple(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9);
+ }
+
+
+} /* namespace pmt */
+
+
+#endif /* INCLUDED_GRUEL_PMT_SUGAR_H */
diff --git a/gruel/src/include/gruel/realtime.h b/gruel/src/include/gruel/realtime.h
new file mode 100644
index 000000000..13673ecb3
--- /dev/null
+++ b/gruel/src/include/gruel/realtime.h
@@ -0,0 +1,96 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006,2008 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_REALTIME_H
+#define INCLUDED_GRUEL_REALTIME_H
+
+#include <gruel/api.h>
+#include <stdexcept>
+
+/*!
+ * \brief System independent way to ask for realtime scheduling
+ *
+ * \sa sys_pri.h
+ */
+
+namespace gruel {
+
+ typedef enum {
+ RT_OK = 0,
+ RT_NOT_IMPLEMENTED,
+ RT_NO_PRIVS,
+ RT_OTHER_ERROR
+ } rt_status_t;
+
+
+ enum rt_sched_policy {
+ RT_SCHED_RR = 0, // round robin
+ RT_SCHED_FIFO = 1, // first in first out
+ };
+
+ /*
+ * Define the range for our virtual priorities (don't change these)
+ *
+ * Processes (or threads) with numerically higher priority values
+ * are scheduled before processes with numerically lower priority
+ * values. Thus, the value returned by rt_priority_max() will be
+ * greater than the value returned by rt_priority_min().
+ */
+ static inline int rt_priority_min() { return 0; }
+ static inline int rt_priority_max() { return 15; }
+ static inline int rt_priority_default() { return 1; }
+
+ struct GRUEL_API rt_sched_param {
+ int priority;
+ rt_sched_policy policy;
+
+ rt_sched_param()
+ : priority(rt_priority_default()), policy(RT_SCHED_RR){}
+
+ rt_sched_param(int priority_, rt_sched_policy policy_ = RT_SCHED_RR)
+ {
+ if (priority_ < rt_priority_min() || priority_ > rt_priority_max())
+ throw std::invalid_argument("rt_sched_param: priority out of range");
+
+ priority = priority_;
+ policy = policy_;
+ }
+ };
+
+ /*!
+ * \brief If possible, enable "realtime" scheduling.
+ * \ingroup misc
+ *
+ * In general, this means that the code will be scheduled before any
+ * non-realtime (normal) processes. Note that if your code contains
+ * an non-blocking infinite loop and you enable realtime scheduling,
+ * it's possible to hang the system.
+ */
+
+ // NOTE: If you change this, you need to change the code in
+ // gnuradio-core/src/lib/runtime/gr_realtime.i, see note there.
+ rt_status_t
+ GRUEL_API enable_realtime_scheduling(rt_sched_param = rt_sched_param());
+
+} // namespace gruel
+
+#endif /* INCLUDED_GRUEL_REALTIME_H */
diff --git a/gruel/src/include/gruel/sys_pri.h b/gruel/src/include/gruel/sys_pri.h
new file mode 100644
index 000000000..c0751e52c
--- /dev/null
+++ b/gruel/src/include/gruel/sys_pri.h
@@ -0,0 +1,42 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008 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.
+ */
+
+#ifndef INCLUDED_GRUEL_SYS_PRI_H
+#define INCLUDED_GRUEL_SYS_PRI_H
+
+#include <gruel/api.h>
+#include <gruel/realtime.h>
+
+/*
+ * A single place to define real-time priorities used by the system itself
+ */
+namespace gruel {
+
+ struct GRUEL_API sys_pri {
+ static rt_sched_param python(); // python code
+ static rt_sched_param normal(); // normal blocks
+ static rt_sched_param gcell_event_handler();
+ static rt_sched_param usrp2_backend(); // thread that services the ethernet
+ };
+
+}
+
+#endif /* INCLUDED_GRUEL_SYS_PRI_H */
diff --git a/gruel/src/include/gruel/thread.h b/gruel/src/include/gruel/thread.h
new file mode 100644
index 000000000..10c6c38cc
--- /dev/null
+++ b/gruel/src/include/gruel/thread.h
@@ -0,0 +1,139 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2009-2012 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.
+ */
+#ifndef INCLUDED_THREAD_H
+#define INCLUDED_THREAD_H
+
+#include <gruel/api.h>
+#include <boost/thread/thread.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/locks.hpp>
+#include <boost/thread/condition_variable.hpp>
+#include <vector>
+
+#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
+
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+
+#include <windows.h>
+
+#endif
+
+namespace gruel {
+
+ typedef boost::thread thread;
+ typedef boost::mutex mutex;
+ typedef boost::unique_lock<boost::mutex> scoped_lock;
+ typedef boost::condition_variable condition_variable;
+
+ /*! \brief a system-dependent typedef for the underlying thread type.
+ */
+#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
+ typedef HANDLE gr_thread_t;
+#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
+ typedef pthread_t gr_thread_t;
+#else
+ typedef pthread_t gr_thread_t;
+#endif
+
+ /*! \brief Get the current thread's ID as a gr_thread_t
+ *
+ * We use this when setting the thread affinity or any other
+ * low-level thread settings. Can be called withing a GNU Radio
+ * block to get a reference to its current thread ID.
+ */
+ GRUEL_API gr_thread_t get_current_thread_id();
+
+ /*! \brief Bind the current thread to a set of cores.
+ *
+ * Wrapper for system-dependent calls to set the affinity of the
+ * current thread to the processor mask. The mask is simply a
+ * 1-demensional vector containing the processor or core number from
+ * 0 to N-1 for N cores.
+ *
+ * Note: this does not work on OSX; it is a nop call since OSX does
+ * not support the concept of thread affinity (and what they do
+ * support in this way since 10.5 is not what we want or can use in
+ * this fashion).
+ */
+ GRUEL_API void thread_bind_to_processor(const std::vector<int> &mask);
+
+ /*! \brief Convineince function to bind the current thread to a single core.
+ *
+ * Wrapper for system-dependent calls to set the affinity of the
+ * current thread to a given core from 0 to N-1 for N cores.
+ *
+ * Note: this does not work on OSX; it is a nop call since OSX does
+ * not support the concept of thread affinity (and what they do
+ * support in this way since 10.5 is not what we want or can use in
+ * this fashion).
+ */
+ GRUEL_API void thread_bind_to_processor(int n);
+
+ /*! \brief Bind a thread to a set of cores.
+ *
+ * Wrapper for system-dependent calls to set the affinity of the
+ * given thread ID to the processor mask. The mask is simply a
+ * 1-demensional vector containing the processor or core number from
+ * 0 to N-1 for N cores.
+ *
+ * Note: this does not work on OSX; it is a nop call since OSX does
+ * not support the concept of thread affinity (and what they do
+ * support in this way since 10.5 is not what we want or can use in
+ * this fashion).
+ */
+ GRUEL_API void thread_bind_to_processor(gr_thread_t thread, const std::vector<int> &mask);
+
+
+ /*! \brief Convineince function to bind the a thread to a single core.
+ *
+ * Wrapper for system-dependent calls to set the affinity of the
+ * given thread ID to a given core from 0 to N-1 for N cores.
+ *
+ * Note: this does not work on OSX; it is a nop call since OSX does
+ * not support the concept of thread affinity (and what they do
+ * support in this way since 10.5 is not what we want or can use in
+ * this fashion).
+ */
+ GRUEL_API void thread_bind_to_processor(gr_thread_t thread, unsigned int n);
+
+ /*! \brief Remove any thread-processor affinity for the current thread.
+ *
+ * Note: this does not work on OSX; it is a nop call since OSX does
+ * not support the concept of thread affinity (and what they do
+ * support in this way since 10.5 is not what we want or can use in
+ * this fashion).
+ */
+ GRUEL_API void thread_unbind();
+
+ /*! \brief Remove any thread-processor affinity for a given thread ID.
+ *
+ * Note: this does not work on OSX; it is a nop call since OSX does
+ * not support the concept of thread affinity (and what they do
+ * support in this way since 10.5 is not what we want or can use in
+ * this fashion).
+ */
+ GRUEL_API void thread_unbind(gr_thread_t thread);
+
+} /* namespace gruel */
+
+#endif /* INCLUDED_THREAD_H */
diff --git a/gruel/src/include/gruel/thread_body_wrapper.h b/gruel/src/include/gruel/thread_body_wrapper.h
new file mode 100644
index 000000000..e09a43e68
--- /dev/null
+++ b/gruel/src/include/gruel/thread_body_wrapper.h
@@ -0,0 +1,69 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008,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.
+ */
+#ifndef INCLUDED_THREAD_BODY_WRAPPER_H
+#define INCLUDED_THREAD_BODY_WRAPPER_H
+
+#include <gruel/api.h>
+#include <gruel/thread.h>
+#include <exception>
+#include <iostream>
+
+namespace gruel
+{
+
+ GRUEL_API void mask_signals();
+
+ template <class F>
+ class thread_body_wrapper
+ {
+ F d_f;
+ std::string d_name;
+
+ public:
+
+ explicit thread_body_wrapper(F f, const std::string &name="")
+ : d_f(f), d_name(name) {}
+
+ void operator()()
+ {
+ mask_signals();
+
+ try {
+ d_f();
+ }
+ catch(boost::thread_interrupted const &)
+ {
+ }
+ catch(std::exception const &e)
+ {
+ std::cerr << "thread[" << d_name << "]: "
+ << e.what() << std::endl;
+ }
+ catch(...)
+ {
+ std::cerr << "thread[" << d_name << "]: "
+ << "caught unrecognized exception\n";
+ }
+ }
+ };
+}
+
+#endif /* INCLUDED_THREAD_BODY_WRAPPER_H */
diff --git a/gruel/src/include/gruel/thread_group.h b/gruel/src/include/gruel/thread_group.h
new file mode 100644
index 000000000..1b8a0a4bf
--- /dev/null
+++ b/gruel/src/include/gruel/thread_group.h
@@ -0,0 +1,45 @@
+/* -*- c++ -*- */
+/*
+ * Copyright (C) 2001-2003 William E. Kempf
+ * Copyright (C) 2007 Anthony Williams
+ * Copyright 2008,2009 Free Software Foundation, Inc.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+/*
+ * This was extracted from Boost 1.35.0 and fixed.
+ */
+
+#ifndef INCLUDED_GRUEL_THREAD_GROUP_H
+#define INCLUDED_GRUEL_THREAD_GROUP_H
+
+#include <gruel/api.h>
+#include <gruel/thread.h>
+#include <boost/utility.hpp>
+#include <boost/thread/shared_mutex.hpp>
+#include <boost/function.hpp>
+
+namespace gruel
+{
+ class GRUEL_API thread_group : public boost::noncopyable
+ {
+ public:
+ thread_group();
+ ~thread_group();
+
+ boost::thread* create_thread(const boost::function0<void>& threadfunc);
+ void add_thread(boost::thread* thrd);
+ void remove_thread(boost::thread* thrd);
+ void join_all();
+ void interrupt_all();
+ size_t size() const;
+
+ private:
+ std::list<boost::thread*> m_threads;
+ mutable boost::shared_mutex m_mutex;
+ };
+}
+
+#endif /* INCLUDED_GRUEL_THREAD_GROUP_H */
diff --git a/gruel/src/lib/CMakeLists.txt b/gruel/src/lib/CMakeLists.txt
new file mode 100644
index 000000000..717d56660
--- /dev/null
+++ b/gruel/src/lib/CMakeLists.txt
@@ -0,0 +1,110 @@
+# Copyright 2010-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 subdirs rather to populate to the sources lists.
+########################################################################
+include(GrMiscUtils)
+include(CheckCXXSourceCompiles)
+
+GR_CHECK_HDR_N_DEF(signal.h HAVE_SIGNAL_H)
+GR_CHECK_HDR_N_DEF(sched.h HAVE_SCHED_H)
+
+set(CMAKE_REQUIRED_LIBRARIES -lpthread)
+CHECK_CXX_SOURCE_COMPILES("
+ #include <signal.h>
+ int main(){pthread_sigmask(0, 0, 0); return 0;}
+ " HAVE_PTHREAD_SIGMASK
+)
+GR_ADD_COND_DEF(HAVE_PTHREAD_SIGMASK)
+
+set(CMAKE_REQUIRED_LIBRARIES -lpthread)
+CHECK_CXX_SOURCE_COMPILES("
+ #include <pthread.h>
+ int main(){
+ pthread_t pthread;
+ pthread_setschedparam(pthread, 0, 0);
+ return 0;
+ } " HAVE_PTHREAD_SETSCHEDPARAM
+)
+GR_ADD_COND_DEF(HAVE_PTHREAD_SETSCHEDPARAM)
+
+CHECK_CXX_SOURCE_COMPILES("
+ #include <sched.h>
+ int main(){
+ pid_t pid;
+ sched_setscheduler(pid, 0, 0);
+ return 0;
+ } " HAVE_SCHED_SETSCHEDULER
+)
+GR_ADD_COND_DEF(HAVE_SCHED_SETSCHEDULER)
+
+########################################################################
+# Include subdirs rather to populate to the sources lists.
+########################################################################
+GR_INCLUDE_SUBDIRECTORY(msg)
+GR_INCLUDE_SUBDIRECTORY(pmt)
+
+########################################################################
+# Setup the include and linker paths
+########################################################################
+include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+include_directories(${GRUEL_INCLUDE_DIRS})
+
+include_directories(${Boost_INCLUDE_DIRS})
+link_directories(${Boost_LIBRARY_DIRS})
+
+########################################################################
+# Setup library
+########################################################################
+list(APPEND gruel_sources
+ realtime.cc
+ sys_pri.cc
+ thread.cc
+ thread_body_wrapper.cc
+ thread_group.cc
+)
+
+list(APPEND gruel_libs ${Boost_LIBRARIES})
+
+if(HAVE_PTHREAD_SETSCHEDPARAM)
+ list(APPEND gruel_libs pthread)
+endif()
+
+add_library(gruel SHARED ${gruel_sources})
+target_link_libraries(gruel ${gruel_libs})
+GR_LIBRARY_FOO(gruel RUNTIME_COMPONENT "gruel_runtime" DEVEL_COMPONENT "gruel_devel")
+
+########################################################################
+# Setup tests
+# Set the test environment so the build libs will be found under MSVC.
+########################################################################
+if(ENABLE_TESTING)
+
+include_directories(${CPPUNIT_INCLUDE_DIRS})
+link_directories(${CPPUNIT_LIBRARY_DIRS})
+
+include(GrTest)
+set(GR_TEST_TARGET_DEPS gruel)
+list(APPEND test_gruel_sources test_gruel.cc)
+add_executable(test_gruel ${test_gruel_sources})
+target_link_libraries(test_gruel gruel ${CPPUNIT_LIBRARIES})
+GR_ADD_TEST(gruel-test test_gruel)
+
+endif(ENABLE_TESTING)
diff --git a/gruel/src/lib/msg/CMakeLists.txt b/gruel/src/lib/msg/CMakeLists.txt
new file mode 100644
index 000000000..74010af7e
--- /dev/null
+++ b/gruel/src/lib/msg/CMakeLists.txt
@@ -0,0 +1,28 @@
+# 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.
+
+########################################################################
+# This file included, use CMake directory variables
+########################################################################
+
+list(APPEND gruel_sources
+ ${CMAKE_CURRENT_SOURCE_DIR}/msg_accepter.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/msg_accepter_msgq.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/msg_queue.cc
+)
diff --git a/gruel/src/lib/msg/msg_accepter.cc b/gruel/src/lib/msg/msg_accepter.cc
new file mode 100644
index 000000000..5acd98aa2
--- /dev/null
+++ b/gruel/src/lib/msg/msg_accepter.cc
@@ -0,0 +1,36 @@
+/* -*- c++ -*- */
+/*
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gruel/msg_accepter.h>
+
+namespace gruel {
+
+ msg_accepter::~msg_accepter()
+ {
+ // NOP, required as virtual destructor
+ }
+
+} /* namespace gruel */
diff --git a/gruel/src/lib/msg/msg_accepter_msgq.cc b/gruel/src/lib/msg/msg_accepter_msgq.cc
new file mode 100644
index 000000000..2ae3537b8
--- /dev/null
+++ b/gruel/src/lib/msg/msg_accepter_msgq.cc
@@ -0,0 +1,48 @@
+/* -*- c++ -*- */
+/*
+ * 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gruel/msg_accepter_msgq.h>
+
+using namespace pmt;
+
+namespace gruel {
+
+ msg_accepter_msgq::msg_accepter_msgq(msg_queue_sptr msgq)
+ : d_msg_queue(msgq)
+ {
+ }
+
+ msg_accepter_msgq::~msg_accepter_msgq()
+ {
+ // NOP, required as virtual destructor
+ }
+
+ void
+ msg_accepter_msgq::post(pmt_t msg)
+ {
+ d_msg_queue->insert_tail(msg);
+ }
+
+} /* namespace gruel */
diff --git a/gruel/src/lib/msg/msg_queue.cc b/gruel/src/lib/msg/msg_queue.cc
new file mode 100644
index 000000000..a0b120e40
--- /dev/null
+++ b/gruel/src/lib/msg/msg_queue.cc
@@ -0,0 +1,103 @@
+/* -*- c++ -*- */
+/*
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gruel/msg_queue.h>
+#include <stdexcept>
+
+using namespace pmt;
+
+namespace gruel {
+
+ msg_queue_sptr
+ make_msg_queue(unsigned int limit)
+ {
+ return msg_queue_sptr(new msg_queue(limit));
+ }
+
+ msg_queue::msg_queue(unsigned int limit)
+ : d_limit(limit)
+ {
+ }
+
+ msg_queue::~msg_queue()
+ {
+ flush();
+ }
+
+ void
+ msg_queue::insert_tail(pmt_t msg)
+ {
+ gruel::scoped_lock guard(d_mutex);
+
+ while (full_p())
+ d_not_full.wait(guard);
+
+ d_msgs.push_back(msg);
+ d_not_empty.notify_one();
+ }
+
+ pmt_t
+ msg_queue::delete_head()
+ {
+ gruel::scoped_lock guard(d_mutex);
+
+ while (empty_p())
+ d_not_empty.wait(guard);
+
+ pmt_t m(d_msgs.front());
+ d_msgs.pop_front();
+
+ if (d_limit > 0) // Unlimited length queues never block on write
+ d_not_full.notify_one();
+
+ return m;
+ }
+
+ pmt_t
+ msg_queue::delete_head_nowait()
+ {
+ gruel::scoped_lock guard(d_mutex);
+
+ if (empty_p())
+ return pmt_t();
+
+ pmt_t m(d_msgs.front());
+ d_msgs.pop_front();
+
+ if (d_limit > 0) // Unlimited length queues never block on write
+ d_not_full.notify_one();
+
+ return m;
+ }
+
+ void
+ msg_queue::flush()
+ {
+ while (delete_head_nowait() != pmt_t())
+ ;
+ }
+
+} /* namespace gruel */
diff --git a/gruel/src/lib/pmt/CMakeLists.txt b/gruel/src/lib/pmt/CMakeLists.txt
new file mode 100644
index 000000000..6ea616e10
--- /dev/null
+++ b/gruel/src/lib/pmt/CMakeLists.txt
@@ -0,0 +1,89 @@
+# Copyright 2010-2012 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/gruel/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}/gruel
+ COMPONENT "gruel_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 gruel_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
+)
+
+list(APPEND test_gruel_sources
+ ${CMAKE_CURRENT_BINARY_DIR}/qa_pmt_unv.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/qa_pmt_prims.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/qa_pmt.cc
+)
diff --git a/gruel/src/lib/pmt/gen-serial-tags.py b/gruel/src/lib/pmt/gen-serial-tags.py
new file mode 100644
index 000000000..18e927beb
--- /dev/null
+++ b/gruel/src/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/gruel/src/lib/pmt/generate_unv.py b/gruel/src/lib/pmt/generate_unv.py
new file mode 100755
index 000000000..42b57e245
--- /dev/null
+++ b/gruel/src/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 <gruel/pmt.h>
+#include "pmt_int.h"
+"""
+
+qa_includes = """
+#include <qa_pmt_unv.h>
+#include <cppunit/TestAssert.h>
+#include <gruel/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/gruel/src/lib/pmt/pmt-serial-tags.scm b/gruel/src/lib/pmt/pmt-serial-tags.scm
new file mode 100644
index 000000000..4f06bf75f
--- /dev/null
+++ b/gruel/src/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/gruel/src/lib/pmt/pmt.cc b/gruel/src/lib/pmt/pmt.cc
new file mode 100644
index 000000000..1d1e9ba7c
--- /dev/null
+++ b/gruel/src/lib/pmt/pmt.cc
@@ -0,0 +1,1428 @@
+/* -*- 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 <gruel/pmt.h>
+#include "pmt_int.h"
+#include <gruel/msg_accepter.h>
+#include <gruel/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
+////////////////////////////////////////////////////////////////////////////
+
+pmt_exception::pmt_exception(const std::string &msg, pmt_t obj)
+ : logic_error(msg + ": " + pmt_write_string(obj))
+{
+}
+
+pmt_wrong_type::pmt_wrong_type(const std::string &msg, pmt_t obj)
+ : pmt_exception(msg + ": wrong_type ", obj)
+{
+}
+
+pmt_out_of_range::pmt_out_of_range(const std::string &msg, pmt_t obj)
+ : pmt_exception(msg + ": out of range ", obj)
+{
+}
+
+pmt_notimplemented::pmt_notimplemented(const std::string &msg, pmt_t obj)
+ : pmt_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 = pmt_cons(PMT_NIL, PMT_NIL); // singleton
+
+////////////////////////////////////////////////////////////////////////////
+// Booleans
+////////////////////////////////////////////////////////////////////////////
+
+pmt_bool::pmt_bool(){}
+
+bool
+pmt_is_true(pmt_t obj)
+{
+ return obj != PMT_F;
+}
+
+bool
+pmt_is_false(pmt_t obj)
+{
+ return obj == PMT_F;
+}
+
+bool
+pmt_is_bool(pmt_t obj)
+{
+ return obj->is_bool();
+}
+
+pmt_t
+pmt_from_bool(bool val)
+{
+ return val ? PMT_T : PMT_F;
+}
+
+bool
+pmt_to_bool(pmt_t val)
+{
+ if (val == PMT_T)
+ return true;
+ if (val == PMT_F)
+ return false;
+ throw pmt_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
+pmt_is_symbol(const pmt_t& obj)
+{
+ return obj->is_symbol();
+}
+
+pmt_t
+pmt_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
+pmt_intern(const std::string &name)
+{
+ return pmt_string_to_symbol(name);
+}
+
+const std::string
+pmt_symbol_to_string(const pmt_t& sym)
+{
+ if (!sym->is_symbol())
+ throw pmt_wrong_type("pmt_symbol_to_string", sym);
+
+ return _symbol(sym)->name();
+}
+
+
+
+////////////////////////////////////////////////////////////////////////////
+// Number
+////////////////////////////////////////////////////////////////////////////
+
+bool
+pmt_is_number(pmt_t x)
+{
+ return x->is_number();
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Integer
+////////////////////////////////////////////////////////////////////////////
+
+pmt_integer::pmt_integer(long value) : d_value(value) {}
+
+bool
+pmt_is_integer(pmt_t x)
+{
+ return x->is_integer();
+}
+
+
+pmt_t
+pmt_from_long(long x)
+{
+ return pmt_t(new pmt_integer(x));
+}
+
+long
+pmt_to_long(pmt_t x)
+{
+ pmt_integer* i = dynamic_cast<pmt_integer*>(x.get());
+ if ( i )
+ return i->value();
+
+ throw pmt_wrong_type("pmt_to_long", x);
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Uint64
+////////////////////////////////////////////////////////////////////////////
+
+pmt_uint64::pmt_uint64(uint64_t value) : d_value(value) {}
+
+bool
+pmt_is_uint64(pmt_t x)
+{
+ return x->is_uint64();
+}
+
+
+pmt_t
+pmt_from_uint64(uint64_t x)
+{
+ return pmt_t(new pmt_uint64(x));
+}
+
+uint64_t
+pmt_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 pmt_wrong_type("pmt_to_uint64", x);
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Real
+////////////////////////////////////////////////////////////////////////////
+
+pmt_real::pmt_real(double value) : d_value(value) {}
+
+bool
+pmt_is_real(pmt_t x)
+{
+ return x->is_real();
+}
+
+pmt_t
+pmt_from_double(double x)
+{
+ return pmt_t(new pmt_real(x));
+}
+
+double
+pmt_to_double(pmt_t x)
+{
+ if (x->is_real())
+ return _real(x)->value();
+ if (x->is_integer())
+ return _integer(x)->value();
+
+ throw pmt_wrong_type("pmt_to_double", x);
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Complex
+////////////////////////////////////////////////////////////////////////////
+
+pmt_complex::pmt_complex(std::complex<double> value) : d_value(value) {}
+
+bool
+pmt_is_complex(pmt_t x)
+{
+ return x->is_complex();
+}
+
+pmt_t
+pmt_make_rectangular(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 pmt_from_complex(const std::complex<double> &z)
+{
+ return pmt_t(new pmt_complex(z));
+}
+
+std::complex<double>
+pmt_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 pmt_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
+pmt_is_null(const pmt_t& x)
+{
+ return x == PMT_NIL;
+}
+
+bool
+pmt_is_pair(const pmt_t& obj)
+{
+ return obj->is_pair();
+}
+
+pmt_t
+pmt_cons(const pmt_t& x, const pmt_t& y)
+{
+ return pmt_t(new pmt_pair(x, y));
+}
+
+pmt_t
+pmt_car(const pmt_t& pair)
+{
+ pmt_pair* p = dynamic_cast<pmt_pair*>(pair.get());
+ if ( p )
+ return p->car();
+
+ throw pmt_wrong_type("pmt_car", pair);
+}
+
+pmt_t
+pmt_cdr(const pmt_t& pair)
+{
+ pmt_pair* p = dynamic_cast<pmt_pair*>(pair.get());
+ if ( p )
+ return p->cdr();
+
+ throw pmt_wrong_type("pmt_cdr", pair);
+}
+
+void
+pmt_set_car(pmt_t pair, pmt_t obj)
+{
+ if (pair->is_pair())
+ _pair(pair)->set_car(obj);
+ else
+ throw pmt_wrong_type("pmt_set_car", pair);
+}
+
+void
+pmt_set_cdr(pmt_t pair, pmt_t obj)
+{
+ if (pair->is_pair())
+ _pair(pair)->set_cdr(obj);
+ else
+ throw pmt_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 pmt_out_of_range("pmt_vector_ref", pmt_from_long(k));
+ return d_v[k];
+}
+
+void
+pmt_vector::set(size_t k, pmt_t obj)
+{
+ if (k >= length())
+ throw pmt_out_of_range("pmt_vector_set", pmt_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
+pmt_is_vector(pmt_t obj)
+{
+ return obj->is_vector();
+}
+
+pmt_t
+pmt_make_vector(size_t k, pmt_t fill)
+{
+ return pmt_t(new pmt_vector(k, fill));
+}
+
+pmt_t
+pmt_vector_ref(pmt_t vector, size_t k)
+{
+ if (!vector->is_vector())
+ throw pmt_wrong_type("pmt_vector_ref", vector);
+ return _vector(vector)->ref(k);
+}
+
+void
+pmt_vector_set(pmt_t vector, size_t k, pmt_t obj)
+{
+ if (!vector->is_vector())
+ throw pmt_wrong_type("pmt_vector_set", vector);
+ _vector(vector)->set(k, obj);
+}
+
+void
+pmt_vector_fill(pmt_t vector, pmt_t obj)
+{
+ if (!vector->is_vector())
+ throw pmt_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 pmt_out_of_range("pmt_tuple_ref", pmt_from_long(k));
+ return d_v[k];
+}
+
+bool
+pmt_is_tuple(pmt_t obj)
+{
+ return obj->is_tuple();
+}
+
+pmt_t
+pmt_tuple_ref(const pmt_t &tuple, size_t k)
+{
+ if (!tuple->is_tuple())
+ throw pmt_wrong_type("pmt_tuple_ref", tuple);
+ return _tuple(tuple)->ref(k);
+}
+
+// for (i=0; i < 10; i++)
+// make_constructor()
+
+pmt_t
+pmt_make_tuple()
+{
+ return pmt_t(new pmt_tuple(0));
+}
+
+pmt_t
+pmt_make_tuple(const pmt_t &e0)
+{
+ pmt_tuple *t = new pmt_tuple(1);
+ t->_set(0, e0);
+ return pmt_t(t);
+}
+
+pmt_t
+pmt_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
+pmt_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
+pmt_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
+pmt_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
+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_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
+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_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
+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_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
+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_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
+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)
+{
+ 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
+pmt_to_tuple(const pmt_t &x)
+{
+ if (x->is_tuple()) // already one
+ return x;
+
+ size_t len = pmt_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, pmt_car(y));
+ y = pmt_cdr(y);
+ }
+ return r;
+ }
+
+ throw pmt_wrong_type("pmt_to_tuple", x);
+}
+
+
+
+////////////////////////////////////////////////////////////////////////////
+// Uniform Numeric Vectors
+////////////////////////////////////////////////////////////////////////////
+
+bool
+pmt_is_uniform_vector(pmt_t x)
+{
+ return x->is_uniform_vector();
+}
+
+const void *
+pmt_uniform_vector_elements(pmt_t vector, size_t &len)
+{
+ if (!vector->is_uniform_vector())
+ throw pmt_wrong_type("pmt_uniform_vector_elements", vector);
+ return _uniform_vector(vector)->uniform_elements(len);
+}
+
+void *
+pmt_uniform_vector_writable_elements(pmt_t vector, size_t &len)
+{
+ if (!vector->is_uniform_vector())
+ throw pmt_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
+pmt_is_dict(const pmt_t &obj)
+{
+ return pmt_is_null(obj) || pmt_is_pair(obj);
+}
+
+pmt_t
+pmt_make_dict()
+{
+ return PMT_NIL;
+}
+
+pmt_t
+pmt_dict_add(const pmt_t &dict, const pmt_t &key, const pmt_t &value)
+{
+ if (pmt_is_null(dict))
+ return pmt_acons(key, value, PMT_NIL);
+
+ if (pmt_dict_has_key(dict, key))
+ return pmt_acons(key, value, pmt_dict_delete(dict, key));
+
+ return pmt_acons(key, value, dict);
+}
+
+pmt_t
+pmt_dict_delete(const pmt_t &dict, const pmt_t &key)
+{
+ if (pmt_is_null(dict))
+ return dict;
+
+ if (pmt_eqv(pmt_caar(dict), key))
+ return pmt_cdr(dict);
+
+ return pmt_cons(pmt_car(dict), pmt_dict_delete(pmt_cdr(dict), key));
+}
+
+pmt_t
+pmt_dict_ref(const pmt_t &dict, const pmt_t &key, const pmt_t &not_found)
+{
+ pmt_t p = pmt_assv(key, dict); // look for (key . value) pair
+ if (pmt_is_pair(p))
+ return pmt_cdr(p);
+ else
+ return not_found;
+}
+
+bool
+pmt_dict_has_key(const pmt_t &dict, const pmt_t &key)
+{
+ return pmt_is_pair(pmt_assv(key, dict));
+}
+
+pmt_t
+pmt_dict_items(pmt_t dict)
+{
+ if (!pmt_is_dict(dict))
+ throw pmt_wrong_type("pmt_dict_values", dict);
+
+ return dict; // equivalent to dict in the a-list case
+}
+
+pmt_t
+pmt_dict_keys(pmt_t dict)
+{
+ if (!pmt_is_dict(dict))
+ throw pmt_wrong_type("pmt_dict_keys", dict);
+
+ return pmt_map(pmt_car, dict);
+}
+
+pmt_t
+pmt_dict_values(pmt_t dict)
+{
+ if (!pmt_is_dict(dict))
+ throw pmt_wrong_type("pmt_dict_keys", dict);
+
+ return pmt_map(pmt_cdr, dict);
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Any
+////////////////////////////////////////////////////////////////////////////
+
+pmt_any::pmt_any(const boost::any &any) : d_any(any) {}
+
+bool
+pmt_is_any(pmt_t obj)
+{
+ return obj->is_any();
+}
+
+pmt_t
+pmt_make_any(const boost::any &any)
+{
+ return pmt_t(new pmt_any(any));
+}
+
+boost::any
+pmt_any_ref(pmt_t obj)
+{
+ if (!obj->is_any())
+ throw pmt_wrong_type("pmt_any_ref", obj);
+ return _any(obj)->ref();
+}
+
+void
+pmt_any_set(pmt_t obj, const boost::any &any)
+{
+ if (!obj->is_any())
+ throw pmt_wrong_type("pmt_any_set", obj);
+ _any(obj)->set(any);
+}
+
+////////////////////////////////////////////////////////////////////////////
+// msg_accepter -- built from "any"
+////////////////////////////////////////////////////////////////////////////
+
+bool
+pmt_is_msg_accepter(const pmt_t &obj)
+{
+ if (!pmt_is_any(obj))
+ return false;
+
+ boost::any r = pmt_any_ref(obj);
+ return boost::any_cast<gruel::msg_accepter_sptr>(&r) != 0;
+}
+
+//! make a msg_accepter
+pmt_t
+pmt_make_msg_accepter(gruel::msg_accepter_sptr ma)
+{
+ return pmt_make_any(ma);
+}
+
+//! Return underlying msg_accepter
+gruel::msg_accepter_sptr
+pmt_msg_accepter_ref(const pmt_t &obj)
+{
+ try {
+ return boost::any_cast<gruel::msg_accepter_sptr>(pmt_any_ref(obj));
+ }
+ catch (boost::bad_any_cast &e){
+ throw pmt_wrong_type("pmt_msg_accepter_ref", obj);
+ }
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+// Binary Large Object -- currently a u8vector
+////////////////////////////////////////////////////////////////////////////
+
+bool
+pmt_is_blob(pmt_t x)
+{
+ // return pmt_is_u8vector(x);
+ return pmt_is_uniform_vector(x);
+}
+
+pmt_t
+pmt_make_blob(const void *buf, size_t len_in_bytes)
+{
+ return pmt_init_u8vector(len_in_bytes, (const uint8_t *) buf);
+}
+
+const void *
+pmt_blob_data(pmt_t blob)
+{
+ size_t len;
+ return pmt_uniform_vector_elements(blob, len);
+}
+
+size_t
+pmt_blob_length(pmt_t blob)
+{
+ size_t len;
+ pmt_uniform_vector_elements(blob, len);
+ return len;
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+// General Functions
+////////////////////////////////////////////////////////////////////////////
+
+bool
+pmt_eq(const pmt_t& x, const pmt_t& y)
+{
+ return x == y;
+}
+
+bool
+pmt_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
+pmt_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
+pmt_equal(const pmt_t& x, const pmt_t& y)
+{
+ if (pmt_eqv(x, y))
+ return true;
+
+ if (x->is_pair() && y->is_pair())
+ return pmt_equal(pmt_car(x), pmt_car(y)) && pmt_equal(pmt_cdr(x), pmt_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 (!pmt_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 (!pmt_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
+pmt_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 = pmt_cdr(x);
+ while (pmt_is_pair(it)){
+ length++;
+ it = pmt_cdr(it);
+ }
+ if (pmt_is_null(it))
+ return length;
+
+ // not a proper list
+ throw pmt_wrong_type("pmt_length", x);
+ }
+
+ // FIXME dictionary length (number of entries)
+
+ throw pmt_wrong_type("pmt_length", x);
+}
+
+pmt_t
+pmt_assq(pmt_t obj, pmt_t alist)
+{
+ while (pmt_is_pair(alist)){
+ pmt_t p = pmt_car(alist);
+ if (!pmt_is_pair(p)) // malformed alist
+ return PMT_F;
+
+ if (pmt_eq(obj, pmt_car(p)))
+ return p;
+
+ alist = pmt_cdr(alist);
+ }
+ return PMT_F;
+}
+
+/*
+ * This avoids a bunch of shared_pointer reference count manipulation.
+ */
+pmt_t
+pmt_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 (pmt_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
+pmt_assv(pmt_t obj, pmt_t alist)
+{
+ return pmt_assv_raw(obj.get(), alist.get());
+}
+
+#else
+
+pmt_t
+pmt_assv(pmt_t obj, pmt_t alist)
+{
+ while (pmt_is_pair(alist)){
+ pmt_t p = pmt_car(alist);
+ if (!pmt_is_pair(p)) // malformed alist
+ return PMT_F;
+
+ if (pmt_eqv(obj, pmt_car(p)))
+ return p;
+
+ alist = pmt_cdr(alist);
+ }
+ return PMT_F;
+}
+
+#endif
+
+
+pmt_t
+pmt_assoc(pmt_t obj, pmt_t alist)
+{
+ while (pmt_is_pair(alist)){
+ pmt_t p = pmt_car(alist);
+ if (!pmt_is_pair(p)) // malformed alist
+ return PMT_F;
+
+ if (pmt_equal(obj, pmt_car(p)))
+ return p;
+
+ alist = pmt_cdr(alist);
+ }
+ return PMT_F;
+}
+
+pmt_t
+pmt_map(pmt_t proc(const pmt_t&), pmt_t list)
+{
+ pmt_t r = PMT_NIL;
+
+ while(pmt_is_pair(list)){
+ r = pmt_cons(proc(pmt_car(list)), r);
+ list = pmt_cdr(list);
+ }
+
+ return pmt_reverse_x(r);
+}
+
+pmt_t
+pmt_reverse(pmt_t listx)
+{
+ pmt_t list = listx;
+ pmt_t r = PMT_NIL;
+
+ while(pmt_is_pair(list)){
+ r = pmt_cons(pmt_car(list), r);
+ list = pmt_cdr(list);
+ }
+ if (pmt_is_null(list))
+ return r;
+ else
+ throw pmt_wrong_type("pmt_reverse", listx);
+}
+
+pmt_t
+pmt_reverse_x(pmt_t list)
+{
+ // FIXME do it destructively
+ return pmt_reverse(list);
+}
+
+pmt_t
+pmt_nth(size_t n, pmt_t list)
+{
+ pmt_t t = pmt_nthcdr(n, list);
+ if (pmt_is_pair(t))
+ return pmt_car(t);
+ else
+ return PMT_NIL;
+}
+
+pmt_t
+pmt_nthcdr(size_t n, pmt_t list)
+{
+ if (!(pmt_is_pair(list) || pmt_is_null(list)))
+ throw pmt_wrong_type("pmt_nthcdr", list);
+
+ while (n > 0){
+ if (pmt_is_pair(list)){
+ list = pmt_cdr(list);
+ n--;
+ continue;
+ }
+ if (pmt_is_null(list))
+ return PMT_NIL;
+ else
+ throw pmt_wrong_type("pmt_nthcdr: not a LIST", list);
+ }
+ return list;
+}
+
+pmt_t
+pmt_memq(pmt_t obj, pmt_t list)
+{
+ while (pmt_is_pair(list)){
+ if (pmt_eq(obj, pmt_car(list)))
+ return list;
+ list = pmt_cdr(list);
+ }
+ return PMT_F;
+}
+
+pmt_t
+pmt_memv(pmt_t obj, pmt_t list)
+{
+ while (pmt_is_pair(list)){
+ if (pmt_eqv(obj, pmt_car(list)))
+ return list;
+ list = pmt_cdr(list);
+ }
+ return PMT_F;
+}
+
+pmt_t
+pmt_member(pmt_t obj, pmt_t list)
+{
+ while (pmt_is_pair(list)){
+ if (pmt_equal(obj, pmt_car(list)))
+ return list;
+ list = pmt_cdr(list);
+ }
+ return PMT_F;
+}
+
+bool
+pmt_subsetp(pmt_t list1, pmt_t list2)
+{
+ while (pmt_is_pair(list1)){
+ pmt_t p = pmt_car(list1);
+ if (pmt_is_false(pmt_memv(p, list2)))
+ return false;
+ list1 = pmt_cdr(list1);
+ }
+ return true;
+}
+
+pmt_t
+pmt_list1(const pmt_t& x1)
+{
+ return pmt_cons(x1, PMT_NIL);
+}
+
+pmt_t
+pmt_list2(const pmt_t& x1, const pmt_t& x2)
+{
+ return pmt_cons(x1, pmt_cons(x2, PMT_NIL));
+}
+
+pmt_t
+pmt_list3(const pmt_t& x1, const pmt_t& x2, const pmt_t& x3)
+{
+ return pmt_cons(x1, pmt_cons(x2, pmt_cons(x3, PMT_NIL)));
+}
+
+pmt_t
+pmt_list4(const pmt_t& x1, const pmt_t& x2, const pmt_t& x3, const pmt_t& x4)
+{
+ return pmt_cons(x1, pmt_cons(x2, pmt_cons(x3, pmt_cons(x4, PMT_NIL))));
+}
+
+pmt_t
+pmt_list5(const pmt_t& x1, const pmt_t& x2, const pmt_t& x3, const pmt_t& x4, const pmt_t& x5)
+{
+ return pmt_cons(x1, pmt_cons(x2, pmt_cons(x3, pmt_cons(x4, pmt_cons(x5, PMT_NIL)))));
+}
+
+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)
+{
+ return pmt_cons(x1, pmt_cons(x2, pmt_cons(x3, pmt_cons(x4, pmt_cons(x5, pmt_cons(x6, PMT_NIL))))));
+}
+
+pmt_t
+pmt_list_add(pmt_t list, const pmt_t& item)
+{
+ return pmt_reverse(pmt_cons(item, pmt_reverse(list)));
+}
+
+pmt_t
+pmt_list_rm(pmt_t list, const pmt_t& item)
+{
+ if(pmt_is_pair(list)){
+ pmt_t left = pmt_car(list);
+ pmt_t right = pmt_cdr(list);
+ if(!pmt_equal(left, item)){
+ return pmt_cons(left, pmt_list_rm(right, item));
+ } else {
+ return pmt_list_rm(right, item);
+ }
+ } else {
+ return list;
+ }
+}
+
+bool
+pmt_list_has(pmt_t list, const pmt_t& item)
+{
+ if(pmt_is_pair(list)){
+ pmt_t left = pmt_car(list);
+ pmt_t right = pmt_cdr(list);
+ if(pmt_equal(left,item))
+ return true;
+ return pmt_list_has(right, item);
+ } else {
+ if(pmt_is_null(list))
+ return false;
+ throw std::runtime_error("list contains invalid format!");
+ }
+}
+
+pmt_t
+pmt_caar(pmt_t pair)
+{
+ return (pmt_car(pmt_car(pair)));
+}
+
+pmt_t
+pmt_cadr(pmt_t pair)
+{
+ return pmt_car(pmt_cdr(pair));
+}
+
+pmt_t
+pmt_cdar(pmt_t pair)
+{
+ return pmt_cdr(pmt_car(pair));
+}
+
+pmt_t
+pmt_cddr(pmt_t pair)
+{
+ return pmt_cdr(pmt_cdr(pair));
+}
+
+pmt_t
+pmt_caddr(pmt_t pair)
+{
+ return pmt_car(pmt_cdr(pmt_cdr(pair)));
+}
+
+pmt_t
+pmt_cadddr(pmt_t pair)
+{
+ return pmt_car(pmt_cdr(pmt_cdr(pmt_cdr(pair))));
+}
+
+bool
+pmt_is_eof_object(pmt_t obj)
+{
+ return pmt_eq(obj, PMT_EOF);
+}
+
+void
+pmt_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/gruel/src/lib/pmt/pmt_int.h b/gruel/src/lib/pmt/pmt_int.h
new file mode 100644
index 000000000..d669e1049
--- /dev/null
+++ b/gruel/src/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 <gruel/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 GRUEL_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/gruel/src/lib/pmt/pmt_io.cc b/gruel/src/lib/pmt/pmt_io.cc
new file mode 100644
index 000000000..4bac4a0ec
--- /dev/null
+++ b/gruel/src/lib/pmt/pmt_io.cc
@@ -0,0 +1,168 @@
+/* -*- 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 <gruel/pmt.h>
+#include "pmt_int.h"
+#include <sstream>
+#include <iostream>
+
+namespace pmt {
+
+static void
+pmt_write_list_tail(pmt_t obj, std::ostream &port)
+{
+ pmt_write(pmt_car(obj), port); // write the car
+ obj = pmt_cdr(obj); // step to cdr
+
+ if (pmt_is_null(obj)) // ()
+ port << ")";
+
+ else if (pmt_is_pair(obj)){ // normal list
+ port << " ";
+ pmt_write_list_tail(obj, port);
+ }
+ else { // dotted pair
+ port << " . ";
+ pmt_write(obj, port);
+ port << ")";
+ }
+}
+
+void
+pmt_write(pmt_t obj, std::ostream &port)
+{
+ if (pmt_is_bool(obj)){
+ if (pmt_is_true(obj))
+ port << "#t";
+ else
+ port << "#f";
+ }
+ else if (pmt_is_symbol(obj)){
+ port << pmt_symbol_to_string(obj);
+ }
+ else if (pmt_is_number(obj)){
+ if (pmt_is_integer(obj))
+ port << pmt_to_long(obj);
+ else if (pmt_is_uint64(obj))
+ port << pmt_to_uint64(obj);
+ else if (pmt_is_real(obj))
+ port << pmt_to_double(obj);
+ else if (pmt_is_complex(obj)){
+ std::complex<double> c = pmt_to_complex(obj);
+ port << c.real() << '+' << c.imag() << 'i';
+ }
+ else
+ goto error;
+ }
+ else if (pmt_is_null(obj)){
+ port << "()";
+ }
+ else if (pmt_is_pair(obj)){
+ port << "(";
+ pmt_write_list_tail(obj, port);
+ }
+ else if (pmt_is_tuple(obj)){
+ port << "{";
+ size_t len = pmt_length(obj);
+ if (len > 0){
+ port << pmt_tuple_ref(obj, 0);
+ for (size_t i = 1; i < len; i++)
+ port << " " << pmt_tuple_ref(obj, i);
+ }
+ port << "}";
+ }
+ else if (pmt_is_vector(obj)){
+ port << "#(";
+ size_t len = pmt_length(obj);
+ if (len > 0){
+ port << pmt_vector_ref(obj, 0);
+ for (size_t i = 1; i < len; i++)
+ port << " " << pmt_vector_ref(obj, i);
+ }
+ port << ")";
+ }
+ else if (pmt_is_dict(obj)){
+ // FIXME
+ // port << "#<dict " << obj << ">";
+ port << "#<dict>";
+ }
+ else if (pmt_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)
+{
+ pmt_write(obj, os);
+ return os;
+}
+
+std::string
+pmt_write_string(pmt_t obj)
+{
+ std::ostringstream s;
+ s << obj;
+ return s.str();
+}
+
+pmt_t
+pmt_read(std::istream &port)
+{
+ throw pmt_notimplemented("notimplemented: pmt_read", PMT_NIL);
+}
+
+void
+pmt_serialize(pmt_t obj, std::ostream &sink)
+{
+ throw pmt_notimplemented("notimplemented: pmt_serialize", obj);
+}
+
+/*!
+ * \brief Create obj from portable byte-serial representation
+ */
+pmt_t
+pmt_deserialize(std::istream &source)
+{
+ throw pmt_notimplemented("notimplemented: pmt_deserialize", PMT_NIL);
+}
+
+} /* 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_pool.cc b/gruel/src/lib/pmt/pmt_pool.cc
new file mode 100644
index 000000000..63a681abf
--- /dev/null
+++ b/gruel/src/lib/pmt/pmt_pool.cc
@@ -0,0 +1,112 @@
+/* -*- 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 <gruel/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/gruel/src/lib/pmt/pmt_serialize.cc b/gruel/src/lib/pmt/pmt_serialize.cc
new file mode 100644
index 000000000..24be6b772
--- /dev/null
+++ b/gruel/src/lib/pmt/pmt_serialize.cc
@@ -0,0 +1,830 @@
+/* -*- 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 <gruel/pmt.h>
+#include "pmt_int.h"
+#include "gruel/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 = pmt_deserialize( sb );
+ if(pmt_eq(list, PMT_NIL)){
+ list = pmt_list1(item);
+ } else {
+ list = pmt_list_add(list, item);
+ }
+ }
+ (*tuple) = pmt_to_tuple(list);
+ return ok;
+}
+
+
+/*
+ * Write portable byte-serial representation of \p obj to \p sb
+ *
+ * N.B., Circular structures cause infinite recursion.
+ */
+bool
+pmt_serialize(pmt_t obj, std::streambuf &sb)
+{
+ bool ok = true;
+
+ tail_recursion:
+
+ if (pmt_is_bool(obj)){
+ if (pmt_eq(obj, PMT_T))
+ return serialize_untagged_u8(PST_TRUE, sb);
+ else
+ return serialize_untagged_u8(PST_FALSE, sb);
+ }
+
+ if (pmt_is_null(obj))
+ return serialize_untagged_u8(PST_NULL, sb);
+
+ if (pmt_is_symbol(obj)){
+ const std::string s = pmt_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 (pmt_is_pair(obj)){
+ ok = serialize_untagged_u8(PST_PAIR, sb);
+ ok &= pmt_serialize(pmt_car(obj), sb);
+ if (!ok)
+ return false;
+ obj = pmt_cdr(obj);
+ goto tail_recursion;
+ }
+
+ if (pmt_is_number(obj)){
+
+ if (pmt_is_uint64(obj)){
+ uint64_t i = pmt_to_uint64(obj);
+ ok = serialize_untagged_u8(PST_UINT64, sb);
+ ok &= serialize_untagged_u64(i, sb);
+ return ok;
+ } else
+ if (pmt_is_integer(obj)){
+ long i = pmt_to_long(obj);
+ if (sizeof(long) > 4){
+ if (i < -2147483647 || i > 2147483647)
+ throw pmt_notimplemented("pmt_serialize (64-bit integers)", obj);
+ }
+ ok = serialize_untagged_u8(PST_INT32, sb);
+ ok &= serialize_untagged_u32(i, sb);
+ return ok;
+ }
+
+ 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_vector(obj)) {
+ size_t vec_len = pmt::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 &= pmt_serialize(pmt_vector_ref(obj, i), sb);
+ }
+ return ok;
+ }
+
+ if (pmt_is_uniform_vector(obj)) {
+ size_t npad = 1;
+ size_t vec_len = pmt::pmt_length(obj);
+
+ if(pmt_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(pmt_u8vector_ref(obj, i), sb);
+ }
+ return ok;
+ }
+
+ if(pmt_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(pmt_s8vector_ref(obj, i), sb);
+ }
+ return ok;
+ }
+
+ if(pmt_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(pmt_u16vector_ref(obj, i), sb);
+ }
+ return ok;
+ }
+
+ if(pmt_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(pmt_s16vector_ref(obj, i), sb);
+ }
+ return ok;
+ }
+
+ if(pmt_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(pmt_u32vector_ref(obj, i), sb);
+ }
+ return ok;
+ }
+
+ if(pmt_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(pmt_s32vector_ref(obj, i), sb);
+ }
+ return ok;
+ }
+
+ if(pmt_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(pmt_u64vector_ref(obj, i), sb);
+ }
+ return ok;
+ }
+
+ if(pmt_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(pmt_s64vector_ref(obj, i), sb);
+ }
+ return ok;
+ }
+
+ if(pmt_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(pmt_f32vector_ref(obj, i), sb);
+ }
+ return ok;
+ }
+
+ if(pmt_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(pmt_f64vector_ref(obj, i), sb);
+ }
+ return ok;
+ }
+
+ if(pmt_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 = pmt_c32vector_ref(obj, i);
+ ok &= serialize_untagged_f64(c.real(), sb);
+ ok &= serialize_untagged_f64(c.imag(), sb);
+ }
+ return ok;
+ }
+
+ if(pmt_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 = pmt_c64vector_ref(obj, i);
+ ok &= serialize_untagged_f64(c.real(), sb);
+ ok &= serialize_untagged_f64(c.imag(), sb);
+ }
+ return ok;
+ }
+ }
+
+ if (pmt_is_dict(obj))
+ throw pmt_notimplemented("pmt_serialize (dict)", obj);
+
+ if (pmt_is_tuple(obj)){
+ size_t tuple_len = pmt::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 &= pmt_serialize(pmt_tuple_ref(obj, i), sb);
+ }
+ return ok;
+ }
+ //throw pmt_notimplemented("pmt_serialize (tuple)", obj);
+
+ throw pmt_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
+pmt_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 pmt_notimplemented("pmt_deserialize: very long symbol",
+ PMT_F);
+ if (sb.sgetn(tmpbuf, u16) != u16)
+ goto error;
+ return pmt_intern(std::string(tmpbuf, u16));
+
+ case PST_INT32:
+ if (!deserialize_untagged_u32(&u32, sb))
+ goto error;
+ return pmt_from_long((int32_t) u32);
+
+ case PST_UINT64:
+ if(!deserialize_untagged_u64(&u64, sb))
+ goto error;
+ return pmt_from_uint64(u64);
+
+ case PST_PAIR:
+ 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_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 = pmt_make_vector(nitems, PMT_NIL);
+ for(uint32_t i=0; i<nitems; i++) {
+ pmt_t item = pmt_deserialize(sb);
+ pmt_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 = pmt_make_u8vector(nitems, 0);
+ for(uint32_t i=0; i<nitems; i++) {
+ deserialize_untagged_u8(&u8, sb);
+ pmt_u8vector_set(vec, i, u8);
+ }
+ return vec;
+ }
+ case(UVI_S8):
+ {
+ pmt_t vec = pmt_make_s8vector(nitems, 0);
+ for(uint32_t i=0; i<nitems; i++) {
+ deserialize_untagged_u8(&u8, sb);
+ pmt_s8vector_set(vec, i, u8);
+ }
+ return vec;
+ }
+ case(UVI_U16):
+ {
+ pmt_t vec = pmt_make_u16vector(nitems, 0);
+ for(uint32_t i=0; i<nitems; i++) {
+ deserialize_untagged_u16(&u16, sb);
+ pmt_u16vector_set(vec, i, u16);
+ }
+ return vec;
+ }
+ case(UVI_S16):
+ {
+ pmt_t vec = pmt_make_s16vector(nitems, 0);
+ for(uint32_t i=0; i<nitems; i++) {
+ deserialize_untagged_u16(&u16, sb);
+ pmt_s16vector_set(vec, i, u16);
+ }
+ return vec;
+ }
+ case(UVI_U32):
+ {
+ pmt_t vec = pmt_make_u32vector(nitems, 0);
+ for(uint32_t i=0; i<nitems; i++) {
+ deserialize_untagged_u32(&u32, sb);
+ pmt_u32vector_set(vec, i, u32);
+ }
+ return vec;
+ }
+ case(UVI_S32):
+ {
+ pmt_t vec = pmt_make_s32vector(nitems, 0);
+ for(uint32_t i=0; i<nitems; i++) {
+ deserialize_untagged_u32(&u32, sb);
+ pmt_s32vector_set(vec, i, u32);
+ }
+ return vec;
+ }
+ case(UVI_U64):
+ {
+ pmt_t vec = pmt_make_u64vector(nitems, 0);
+ for(uint32_t i=0; i<nitems; i++) {
+ deserialize_untagged_u64(&u64, sb);
+ pmt_u64vector_set(vec, i, u64);
+ }
+ return vec;
+ }
+ case(UVI_S64):
+ {
+ pmt_t vec = pmt_make_s64vector(nitems, 0);
+ for(uint32_t i=0; i<nitems; i++) {
+ deserialize_untagged_u64(&u64, sb);
+ pmt_s64vector_set(vec, i, u64);
+ }
+ return vec;
+ }
+ case(UVI_F32):
+ {
+ pmt_t vec = pmt_make_f32vector(nitems, 0);
+ for(uint32_t i=0; i<nitems; i++) {
+ deserialize_untagged_f64(&f64, sb);
+ pmt_f32vector_set(vec, i, static_cast<float>(f64));
+ }
+ return vec;
+ }
+ case(UVI_F64):
+ {
+ pmt_t vec = pmt_make_f64vector(nitems, 0);
+ for(uint32_t i=0; i<nitems; i++) {
+ deserialize_untagged_f64(&f64, sb);
+ pmt_f64vector_set(vec, i, f64);
+ }
+ return vec;
+ }
+ case(UVI_C32):
+ {
+ pmt_t vec = pmt_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);
+ pmt_c32vector_set(vec, i, std::complex<float>(re, im));
+ }
+ return vec;
+ }
+
+ case(UVI_C64):
+ {
+ pmt_t vec = pmt_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;
+ pmt_c64vector_set(vec, i, std::complex<double>(re, im));
+ }
+ return vec;
+ }
+
+ default:
+ throw pmt_exception("pmt_deserialize: malformed input stream, tag value = ",
+ pmt_from_long(tag));
+ }
+ }
+
+ case PST_DICT:
+ case PST_COMMENT:
+ throw pmt_notimplemented("pmt_deserialize: tag value = ",
+ pmt_from_long(tag));
+
+ default:
+ throw pmt_exception("pmt_deserialize: malformed input stream, tag value = ",
+ pmt_from_long(tag));
+ }
+
+ error:
+ 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.
+ *
+ * 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 = pmt_deserialize(sb); // read the car
+
+ nptr = pmt_cons(expr, PMT_NIL); // build new cell
+ if (pmt_is_null(lastnptr))
+ val = nptr;
+ else
+ pmt_set_cdr(lastnptr, nptr);
+ lastnptr = nptr;
+
+ if (!deserialize_untagged_u8(&tag, sb)) // get tag of cdr
+ throw pmt_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 = pmt_deserialize(sb);
+ break;
+ }
+
+ //
+ // At this point, expr contains the value of the final cdr in the list.
+ //
+ pmt_set_cdr(lastnptr, expr);
+ return val;
+}
+
+} /* namespace pmt */
diff --git a/gruel/src/lib/pmt/qa_pmt.cc b/gruel/src/lib/pmt/qa_pmt.cc
new file mode 100644
index 000000000..27c617e74
--- /dev/null
+++ b/gruel/src/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/gruel/src/lib/pmt/qa_pmt.h b/gruel/src/lib/pmt/qa_pmt.h
new file mode 100644
index 000000000..3de5872c7
--- /dev/null
+++ b/gruel/src/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 <gruel/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/gruel/src/lib/pmt/qa_pmt_prims.cc b/gruel/src/lib/pmt/qa_pmt_prims.cc
new file mode 100644
index 000000000..3ae4d70b6
--- /dev/null
+++ b/gruel/src/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 <gruel/msg_passing.h>
+#include <boost/format.hpp>
+#include <cstdio>
+#include <cstring>
+#include <sstream>
+
+using namespace pmt;
+
+void
+qa_pmt_prims::test_symbols()
+{
+ CPPUNIT_ASSERT(!pmt_is_symbol(PMT_T));
+ CPPUNIT_ASSERT(!pmt_is_symbol(PMT_F));
+ CPPUNIT_ASSERT_THROW(pmt_symbol_to_string(PMT_F), pmt_wrong_type);
+
+ pmt_t sym1 = 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_t sym2 = mp("foo");
+ pmt_t sym3 = mp("test");
+ CPPUNIT_ASSERT_EQUAL(sym1, sym3);
+ CPPUNIT_ASSERT(sym1 != sym2);
+ CPPUNIT_ASSERT(sym1 == sym3);
+
+ static const int N = 2048;
+ std::vector<pmt_t> v1(N);
+ std::vector<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] = 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] = 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_t sym = mp("test");
+ CPPUNIT_ASSERT(pmt_is_bool(PMT_T));
+ CPPUNIT_ASSERT(pmt_is_bool(PMT_F));
+ CPPUNIT_ASSERT(!pmt_is_bool(sym));
+ CPPUNIT_ASSERT_EQUAL(pmt_from_bool(false), PMT_F);
+ CPPUNIT_ASSERT_EQUAL(pmt_from_bool(true), PMT_T);
+ CPPUNIT_ASSERT_EQUAL(false, pmt_to_bool(PMT_F));
+ CPPUNIT_ASSERT_EQUAL(true, pmt_to_bool(PMT_T));
+ CPPUNIT_ASSERT_THROW(pmt_to_bool(sym), pmt_wrong_type);
+}
+
+void
+qa_pmt_prims::test_integers()
+{
+ pmt_t p1 = pmt_from_long(1);
+ pmt_t m1 = pmt_from_long(-1);
+ CPPUNIT_ASSERT(!pmt_is_integer(PMT_T));
+ CPPUNIT_ASSERT(pmt_is_integer(p1));
+ CPPUNIT_ASSERT(pmt_is_integer(m1));
+ CPPUNIT_ASSERT_THROW(pmt_to_long(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_t p1 = pmt_from_uint64((uint64_t)1);
+ pmt_t m1 = pmt_from_uint64((uint64_t)8589934592ULL);
+ CPPUNIT_ASSERT(!pmt_is_uint64(PMT_T));
+ CPPUNIT_ASSERT(pmt_is_uint64(p1));
+ CPPUNIT_ASSERT(pmt_is_uint64(m1));
+ CPPUNIT_ASSERT_THROW(pmt_to_uint64(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_t p1 = pmt_from_double(1);
+ pmt_t m1 = pmt_from_double(-1);
+ CPPUNIT_ASSERT(!pmt_is_real(PMT_T));
+ CPPUNIT_ASSERT(pmt_is_real(p1));
+ CPPUNIT_ASSERT(pmt_is_real(m1));
+ CPPUNIT_ASSERT_THROW(pmt_to_double(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_t p1 = pmt_make_rectangular(2, -3);
+ pmt_t m1 = pmt_make_rectangular(-3, 2);
+ pmt_t p2 = pmt_from_complex(2, -3);
+ pmt_t m2 = pmt_from_complex(-3, 2);
+ pmt_t p3 = pmt_from_complex(std::complex<double>(2, -3));
+ pmt_t m3 = pmt_from_complex(std::complex<double>(-3, 2));
+ CPPUNIT_ASSERT(!pmt_is_complex(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_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_NIL));
+ CPPUNIT_ASSERT(!pmt_is_pair(PMT_NIL));
+ pmt_t s1 = mp("s1");
+ pmt_t s2 = mp("s2");
+ pmt_t s3 = mp("s3");
+
+
+ CPPUNIT_ASSERT_EQUAL((size_t)0, pmt_length(PMT_NIL));
+ CPPUNIT_ASSERT_THROW(pmt_length(s1), pmt_wrong_type);
+ CPPUNIT_ASSERT_THROW(pmt_length(pmt_from_double(42)), pmt_wrong_type);
+
+ pmt_t c1 = pmt_cons(s1, 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_NIL, pmt_cdr(c1));
+ CPPUNIT_ASSERT_EQUAL((size_t) 1, pmt_length(c1));
+
+ pmt_t c3 = pmt_cons(s3, PMT_NIL);
+ 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_NIL), pmt_wrong_type);
+ CPPUNIT_ASSERT_THROW(pmt_car(PMT_NIL), pmt_wrong_type);
+ CPPUNIT_ASSERT_THROW(pmt_set_car(s1, PMT_NIL), pmt_wrong_type);
+ CPPUNIT_ASSERT_THROW(pmt_set_cdr(s1, PMT_NIL), pmt_wrong_type);
+}
+
+void
+qa_pmt_prims::test_vectors()
+{
+ static const size_t N = 3;
+ pmt_t v1 = pmt_make_vector(N, PMT_NIL);
+ CPPUNIT_ASSERT_EQUAL(N, pmt_length(v1));
+ pmt_t s0 = mp("s0");
+ pmt_t s1 = mp("s1");
+ pmt_t s2 = 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_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_t> &s, 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_t v = pmt_make_vector(10, PMT_NIL);
+ std::vector<pmt_t> s(10);
+ for (size_t i = 0; i < 10; i++){
+ std::ostringstream os;
+ os << "s" << i;
+ s[i] = mp(os.str());
+ pmt_vector_set(v, i, s[i]);
+ }
+
+
+ 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_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_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_t s0 = mp("s0");
+ pmt_t s1 = mp("s1");
+ pmt_t s2 = mp("s2");
+ pmt_t list0 = pmt_cons(s0, pmt_cons(s1, pmt_cons(s2, PMT_NIL)));
+ pmt_t list1 = pmt_cons(s0, pmt_cons(s1, pmt_cons(s2, PMT_NIL)));
+ pmt_t i0 = pmt_from_long(42);
+ pmt_t i1 = pmt_from_long(42);
+ pmt_t r0 = pmt_from_double(42);
+ pmt_t r1 = pmt_from_double(42);
+ 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_t v0 = pmt_make_vector(3, s0);
+ pmt_t v1 = pmt_make_vector(3, s0);
+ 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_t k0 = mp("k0");
+ pmt_t k1 = mp("k1");
+ pmt_t k2 = mp("k2");
+ pmt_t k3 = mp("k3");
+ pmt_t v0 = mp("v0");
+ pmt_t v1 = mp("v1");
+ pmt_t v2 = mp("v2");
+ pmt_t p0 = pmt_cons(k0, v0);
+ pmt_t p1 = pmt_cons(k1, v1);
+ pmt_t p2 = pmt_cons(k2, v2);
+
+ pmt_t alist = pmt_cons(p0, pmt_cons(p1, pmt_cons(p2, PMT_NIL)));
+ CPPUNIT_ASSERT(pmt_eq(p1, pmt_assv(k1, alist)));
+ CPPUNIT_ASSERT(pmt_eq(PMT_F, pmt_assv(k3, alist)));
+
+ pmt_t keys = pmt_cons(k0, pmt_cons(k1, pmt_cons(k2, PMT_NIL)));
+ pmt_t vals = pmt_cons(v0, pmt_cons(v1, pmt_cons(v2, 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_t dict = pmt_make_dict();
+ CPPUNIT_ASSERT(pmt_is_dict(dict));
+
+ pmt_t k0 = mp("k0");
+ pmt_t k1 = mp("k1");
+ pmt_t k2 = mp("k2");
+ pmt_t k3 = mp("k3");
+ pmt_t v0 = mp("v0");
+ pmt_t v1 = mp("v1");
+ pmt_t v2 = mp("v2");
+ pmt_t v3 = mp("v3");
+ pmt_t not_found = pmt_cons(PMT_NIL, 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_t keys = pmt_list3(k1, k2, k0);
+ 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_t k0 = mp("k0");
+ pmt_t k1 = mp("k1");
+ pmt_t k2 = mp("k2");
+ pmt_t k3 = mp("k3");
+
+ CPPUNIT_ASSERT_EQUAL(std::string("k0"), pmt_write_string(k0));
+}
+
+void
+qa_pmt_prims::test_lists()
+{
+ pmt_t s0 = mp("s0");
+ pmt_t s1 = mp("s1");
+ pmt_t s2 = mp("s2");
+ pmt_t s3 = mp("s3");
+
+ pmt_t l1 = pmt_list4(s0, s1, s2, s3);
+ pmt_t l2 = pmt_list3(s0, s1, s2);
+ 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_t p0 = pmt_make_any(a0);
+ pmt_t p1 = pmt_make_any(a1);
+ 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 gruel::msg_accepter {
+public:
+ qa_pmt_msg_accepter_nop(){};
+ ~qa_pmt_msg_accepter_nop();
+ void post(pmt_t,pmt_t){};
+};
+
+qa_pmt_msg_accepter_nop::~qa_pmt_msg_accepter_nop(){}
+
+void
+qa_pmt_prims::test_msg_accepter()
+{
+ pmt_t sym = mp("my-symbol");
+
+ boost::any a0;
+ a0 = std::string("Hello!");
+ pmt_t p0 = pmt_make_any(a0);
+
+ gruel::msg_accepter_sptr ma0 = gruel::msg_accepter_sptr(new qa_pmt_msg_accepter_nop());
+ 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_t port(pmt_intern("port"));
+ gruel::send(ma0.get(), port, sym);
+ gruel::send(ma0, port, sym);
+ gruel::send(p1, port, sym);
+
+}
+
+// ------------------------------------------------------------------------
+
+void
+qa_pmt_prims::test_serialize()
+{
+ std::stringbuf sb; // fake channel
+ pmt_t a = mp("a");
+ pmt_t b = mp("b");
+ pmt_t c = mp("c");
+
+ sb.str(""); // reset channel to empty
+
+ // write stuff to channel
+
+ pmt_serialize(PMT_NIL, sb);
+ pmt_serialize(mp("foobarvia"), sb);
+ pmt_serialize(pmt_from_long(123456789), sb);
+ pmt_serialize(pmt_from_long(-123456789), sb);
+ pmt_serialize(pmt_cons(PMT_NIL, 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_T, sb);
+ pmt_serialize(PMT_F, sb);
+
+ // read it back
+
+ CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), PMT_NIL));
+ CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), 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_NIL, 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_T));
+ CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), PMT_F));
+
+ CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), 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_t s1 = mp("s1");
+ pmt_t s2 = mp("s2");
+ pmt_t s3 = mp("s3");
+
+ pmt_t l1 = pmt_list1(s1);
+ pmt_t l2 = pmt_list2(s2,s3);
+ 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(mp("my-symbol")));
+ CPPUNIT_ASSERT_EQUAL((long) 10, pmt_to_long(mp(10)));
+ CPPUNIT_ASSERT_EQUAL((double) 1e6, pmt_to_double(mp(1e6)));
+ CPPUNIT_ASSERT_EQUAL(std::complex<double>(2, 3),
+ pmt_to_complex(mp(std::complex<double>(2, 3))));
+
+ int buf[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ pmt_t blob = 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/gruel/src/lib/pmt/qa_pmt_prims.h b/gruel/src/lib/pmt/qa_pmt_prims.h
new file mode 100644
index 000000000..a407509b2
--- /dev/null
+++ b/gruel/src/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 <gruel/attributes.h>
+#include <gruel/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/gruel/src/lib/pmt/unv_qa_template.cc.t b/gruel/src/lib/pmt/unv_qa_template.cc.t
new file mode 100644
index 000000000..1e2c8e8eb
--- /dev/null
+++ b/gruel/src/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/gruel/src/lib/pmt/unv_template.cc.t b/gruel/src/lib/pmt/unv_template.cc.t
new file mode 100644
index 000000000..1ed505e29
--- /dev/null
+++ b/gruel/src/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 pmt_out_of_range("pmt_@TAG@vector_ref", pmt_from_long(k));
+ return d_v[k];
+}
+
+void
+pmt_@TAG@vector::set(size_t k, @TYPE@ x)
+{
+ if (k >= length())
+ throw pmt_out_of_range("pmt_@TAG@vector_set", pmt_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
+pmt_is_@TAG@vector(pmt_t obj)
+{
+ return obj->is_@TAG@vector();
+}
+
+pmt_t
+pmt_make_@TAG@vector(size_t k, @TYPE@ fill)
+{
+ return pmt_t(new pmt_@TAG@vector(k, fill));
+}
+
+pmt_t
+pmt_init_@TAG@vector(size_t k, const @TYPE@ *data)
+{
+ return pmt_t(new pmt_@TAG@vector(k, data));
+}
+
+pmt_t
+pmt_init_@TAG@vector(size_t k, const std::vector< @TYPE@ > &data)
+{
+
+ return pmt_t(new pmt_@TAG@vector(k, &data[0]));
+}
+
+@TYPE@
+pmt_@TAG@vector_ref(pmt_t vector, size_t k)
+{
+ if (!vector->is_@TAG@vector())
+ throw pmt_wrong_type("pmt_@TAG@vector_ref", vector);
+ return _@TAG@vector(vector)->ref(k);
+}
+
+void
+pmt_@TAG@vector_set(pmt_t vector, size_t k, @TYPE@ obj)
+{
+ if (!vector->is_@TAG@vector())
+ throw pmt_wrong_type("pmt_@TAG@vector_set", vector);
+ _@TAG@vector(vector)->set(k, obj);
+}
+
+const @TYPE@ *
+pmt_@TAG@vector_elements(pmt_t vector, size_t &len)
+{
+ if (!vector->is_@TAG@vector())
+ throw pmt_wrong_type("pmt_@TAG@vector_elements", vector);
+ return _@TAG@vector(vector)->elements(len);
+}
+
+const std::vector< @TYPE@ >
+pmt_@TAG@vector_elements(pmt_t vector)
+{
+ if (!vector->is_@TAG@vector())
+ throw pmt_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@ *
+pmt_@TAG@vector_writable_elements(pmt_t vector, size_t &len)
+{
+ if (!vector->is_@TAG@vector())
+ throw pmt_wrong_type("pmt_@TAG@vector_writable_elements", vector);
+ return _@TAG@vector(vector)->writable_elements(len);
+}
+
+} /* namespace pmt */
diff --git a/gruel/src/lib/pmt/unv_template.h.t b/gruel/src/lib/pmt/unv_template.h.t
new file mode 100644
index 000000000..83ba0be0f
--- /dev/null
+++ b/gruel/src/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);
+};
diff --git a/gruel/src/lib/realtime.cc b/gruel/src/lib/realtime.cc
new file mode 100644
index 000000000..e01c6c53d
--- /dev/null
+++ b/gruel/src/lib/realtime.cc
@@ -0,0 +1,178 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006,2007,2008 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 <gruel/realtime.h>
+
+#ifdef HAVE_SCHED_H
+#include <sched.h>
+#endif
+
+#include <algorithm>
+#include <math.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+
+#if defined(HAVE_PTHREAD_SETSCHEDPARAM) || defined(HAVE_SCHED_SETSCHEDULER)
+#include <pthread.h>
+
+namespace gruel {
+
+ /*!
+ * Rescale our virtual priority so that it maps to the middle 1/2 of
+ * the priorities given by min_real_pri and max_real_pri.
+ */
+ static int
+ rescale_virtual_pri(int virtual_pri, int min_real_pri, int max_real_pri)
+ {
+ float rmin = min_real_pri + (0.25 * (max_real_pri - min_real_pri));
+ float rmax = min_real_pri + (0.75 * (max_real_pri - min_real_pri));
+ float m = (rmax - rmin) / (rt_priority_max() - rt_priority_min());
+ float y = m * (virtual_pri - rt_priority_min()) + rmin;
+ int y_int = static_cast<int>(rint(y));
+ return std::max(min_real_pri, std::min(max_real_pri, y_int));
+ }
+
+} // namespace gruel
+
+#endif
+
+
+#if defined(HAVE_PTHREAD_SETSCHEDPARAM)
+
+namespace gruel {
+
+ rt_status_t
+ enable_realtime_scheduling(rt_sched_param p)
+ {
+ int policy = p.policy == RT_SCHED_FIFO ? SCHED_FIFO : SCHED_RR;
+ int min_real_pri = sched_get_priority_min(policy);
+ int max_real_pri = sched_get_priority_max(policy);
+ int pri = rescale_virtual_pri(p.priority, min_real_pri, max_real_pri);
+
+ // FIXME check hard and soft limits with getrlimit, and limit the value we ask for.
+ // fprintf(stderr, "pthread_setschedparam: policy = %d, pri = %d\n", policy, pri);
+
+ struct sched_param param;
+ memset (&param, 0, sizeof (param));
+ param.sched_priority = pri;
+ int result = pthread_setschedparam (pthread_self(), policy, &param);
+ if (result != 0) {
+ if (result == EPERM) // N.B., return value, not errno
+ return RT_NO_PRIVS;
+ else {
+ fprintf(stderr,
+ "pthread_setschedparam: failed to set real time priority: %s\n",
+ strerror(result));
+ return RT_OTHER_ERROR;
+ }
+ }
+
+ //printf("SCHED_FIFO enabled with priority = %d\n", pri);
+ return RT_OK;
+ }
+} // namespace gruel
+
+
+#elif defined(HAVE_SCHED_SETSCHEDULER)
+
+namespace gruel {
+
+ rt_status_t
+ enable_realtime_scheduling(rt_sched_param p)
+ {
+ int policy = p.policy == RT_SCHED_FIFO ? SCHED_FIFO : SCHED_RR;
+ int min_real_pri = sched_get_priority_min(policy);
+ int max_real_pri = sched_get_priority_max(policy);
+ int pri = rescale_virtual_pri(p.priority, min_real_pri, max_real_pri);
+
+ // FIXME check hard and soft limits with getrlimit, and limit the value we ask for.
+ // fprintf(stderr, "sched_setscheduler: policy = %d, pri = %d\n", policy, pri);
+
+ int pid = 0; // this process
+ struct sched_param param;
+ memset(&param, 0, sizeof(param));
+ param.sched_priority = pri;
+ int result = sched_setscheduler(pid, policy, &param);
+ if (result != 0){
+ if (errno == EPERM)
+ return RT_NO_PRIVS;
+ else {
+ perror ("sched_setscheduler: failed to set real time priority");
+ return RT_OTHER_ERROR;
+ }
+ }
+
+ //printf("SCHED_FIFO enabled with priority = %d\n", pri);
+ return RT_OK;
+ }
+
+} // namespace gruel
+
+#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
+
+#include <windows.h>
+
+namespace gruel {
+
+ rt_status_t enable_realtime_scheduling(rt_sched_param p){
+
+ //set the priority class on the process
+ int pri_class = (true)? REALTIME_PRIORITY_CLASS : NORMAL_PRIORITY_CLASS;
+ if (SetPriorityClass(GetCurrentProcess(), pri_class) == 0)
+ return RT_OTHER_ERROR;
+
+ //scale the priority value to the constants
+ int priorities[] = {
+ THREAD_PRIORITY_IDLE, THREAD_PRIORITY_LOWEST, THREAD_PRIORITY_BELOW_NORMAL, THREAD_PRIORITY_NORMAL,
+ THREAD_PRIORITY_ABOVE_NORMAL, THREAD_PRIORITY_HIGHEST, THREAD_PRIORITY_TIME_CRITICAL
+ };
+ const double priority = double(p.priority)/(rt_priority_max() - rt_priority_min());
+ size_t pri_index = size_t((priority+1.0)*6/2.0); // -1 -> 0, +1 -> 6
+ pri_index %= sizeof(priorities)/sizeof(*priorities); //range check
+
+ //set the thread priority on the thread
+ if (SetThreadPriority(GetCurrentThread(), priorities[pri_index]) == 0)
+ return RT_OTHER_ERROR;
+
+ //printf("SetPriorityClass + SetThreadPriority\n");
+ return RT_OK;
+ }
+
+} // namespace gruel
+
+#else
+
+namespace gruel {
+
+ rt_status_t
+ enable_realtime_scheduling(rt_sched_param p)
+ {
+ return RT_NOT_IMPLEMENTED;
+ }
+} // namespace gruel
+
+#endif
diff --git a/gruel/src/lib/sys_pri.cc b/gruel/src/lib/sys_pri.cc
new file mode 100644
index 000000000..c8a505341
--- /dev/null
+++ b/gruel/src/lib/sys_pri.cc
@@ -0,0 +1,61 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008 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/sys_pri.h>
+
+namespace gruel {
+
+ /*
+ * These may need per-OS tweaking.
+ *
+ * Under linux virtual_pri -> system_pri
+ * 0 -> 0
+ * 1 -> 5
+ * 2 -> 10
+ * 3 -> 15
+ * 4 -> 20 // typically used by jack and pulse audio
+ * 5 -> 25
+ * 6 -> 30
+ * 7 -> 35
+ * 8 -> 40
+ * 9 -> 45
+ * 10 -> 50
+ * 11 -> 54
+ * 12 -> 59
+ * 13 -> 64
+ * 14 -> 69
+ * 15 -> 74
+ */
+ rt_sched_param
+ sys_pri::python() { return rt_sched_param(0, RT_SCHED_RR); }
+
+ rt_sched_param
+ sys_pri::normal() { return rt_sched_param(2, RT_SCHED_RR); }
+
+ rt_sched_param
+ sys_pri::gcell_event_handler(){ return rt_sched_param(5, RT_SCHED_FIFO); }
+
+ rt_sched_param
+ sys_pri::usrp2_backend() { return rt_sched_param(6, RT_SCHED_FIFO); }
+}
diff --git a/gruel/src/lib/test_gruel.cc b/gruel/src/lib/test_gruel.cc
new file mode 100644
index 000000000..f32e3f341
--- /dev/null
+++ b/gruel/src/lib/test_gruel.cc
@@ -0,0 +1,52 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006,2009,2010,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 <cppunit/TextTestRunner.h>
+#include <cppunit/XmlOutputter.h>
+
+#include <stdlib.h>
+#include <sys/stat.h>
+
+#include "pmt/qa_pmt.h"
+
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/path.hpp>
+namespace fs = boost::filesystem;
+
+int
+main(int argc, char **argv)
+{
+ 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.string().c_str());
+ CppUnit::XmlOutputter *xmlout = new CppUnit::XmlOutputter(&runner.result(), xmlfile);
+
+ runner.addTest(qa_pmt::suite ());
+ runner.setOutputter(xmlout);
+
+ bool was_successful = runner.run("", false);
+
+ return was_successful ? 0 : 1;
+}
diff --git a/gruel/src/lib/thread.cc b/gruel/src/lib/thread.cc
new file mode 100644
index 000000000..a5116b687
--- /dev/null
+++ b/gruel/src/lib/thread.cc
@@ -0,0 +1,226 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 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>
+
+#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
+
+#include <Windows.h>
+
+namespace gruel {
+
+ gr_thread_t
+ get_current_thread_id()
+ {
+ return GetCurrentThread();
+ }
+
+ void
+ thread_bind_to_processor(int n)
+ {
+ std::vector<int> mask(1, n);
+ thread_bind_to_processor(get_current_thread_id(), mask);
+ }
+
+ void
+ thread_bind_to_processor(const std::vector<int> &mask)
+ {
+ thread_bind_to_processor(get_current_thread_id(), mask);
+ }
+
+ void
+ thread_bind_to_processor(gr_thread_t thread, int n)
+ {
+ std::vector<int> mask(1, n);
+ thread_bind_to_processor(thread, mask);
+ }
+
+ void
+ thread_bind_to_processor(gr_thread_t thread, const std::vector<int> &mask)
+ {
+ //DWORD_PTR mask = (1 << n);
+ DWORD_PTR dword_mask = 0;
+
+ std::vector<int> _mask = mask;
+ std::vector<int>::iterator itr;
+ for(itr = _mask.begin(); itr != _mask.end(); itr++)
+ dword_mask |= (1 << (*itr));
+
+ DWORD_PTR ret = SetThreadAffinityMask(thread, dword_mask);
+ if(ret == 0) {
+ std::stringstream s;
+ s << "thread_bind_to_processor failed with error: " << GetLastError() << std::endl;
+ throw std::runtime_error(s.str());
+ }
+ }
+
+ void
+ thread_unbind()
+ {
+ thread_unbind(get_current_thread_id());
+ }
+
+ void
+ thread_unbind(gr_thread_t thread)
+ {
+ DWORD_PTR dword_mask = sizeof(DWORD_PTR) - 1;
+ DWORD_PTR ret = SetThreadAffinityMask(thread, dword_mask);
+ if(ret == 0) {
+ std::stringstream s;
+ s << "thread_unbind failed with error: " << GetLastError() << std::endl;
+ throw std::runtime_error(s.str());
+ }
+ }
+} /* namespace gruel */
+
+#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
+
+namespace gruel {
+
+ gr_thread_t
+ get_current_thread_id()
+ {
+ // Not implemented on OSX
+ }
+
+ void
+ thread_bind_to_processor(int n)
+ {
+ // Not implemented on OSX
+ }
+
+ void
+ thread_bind_to_processor(gr_thread_t thread, int n)
+ {
+ // Not implemented on OSX
+ }
+
+ void
+ thread_bind_to_processor(const std::vector<int> &mask)
+ {
+ // Not implemented on OSX
+ }
+
+ void
+ thread_bind_to_processor(gr_thread_t thread, const std::vector<int> &mask)
+ {
+ // Not implemented on OSX
+ }
+
+ void
+ thread_unbind()
+ {
+ // Not implemented on OSX
+ }
+
+ void
+ thread_unbind(gr_thread_t thread)
+ {
+ // Not implemented on OSX
+ }
+} /* namespace gruel */
+
+#else
+
+#include <sstream>
+#include <stdexcept>
+#include <pthread.h>
+
+namespace gruel {
+
+ gr_thread_t
+ get_current_thread_id()
+ {
+ return pthread_self();
+ }
+
+ void
+ thread_bind_to_processor(int n)
+ {
+ std::vector<int> mask(1, n);
+ thread_bind_to_processor(get_current_thread_id(), mask);
+ }
+
+ void
+ thread_bind_to_processor(const std::vector<int> &mask)
+ {
+ thread_bind_to_processor(get_current_thread_id(), mask);
+ }
+
+ void
+ thread_bind_to_processor(gr_thread_t thread, int n)
+ {
+ std::vector<int> mask(1, n);
+ thread_bind_to_processor(thread, mask);
+ }
+
+ void
+ thread_bind_to_processor(gr_thread_t thread, const std::vector<int> &mask)
+ {
+ cpu_set_t set;
+ size_t len = sizeof(cpu_set_t);
+ std::vector<int> _mask = mask;
+ std::vector<int>::iterator itr;
+
+ CPU_ZERO(&set);
+ for(itr = _mask.begin(); itr != _mask.end(); itr++)
+ CPU_SET(*itr, &set);
+
+ int ret = pthread_setaffinity_np(thread, len, &set);
+ if(ret != 0) {
+ std::stringstream s;
+ s << "thread_bind_to_processor failed with error: " << ret << std::endl;
+ throw std::runtime_error(s.str());
+ }
+ }
+
+ void
+ thread_unbind()
+ {
+ thread_unbind(get_current_thread_id());
+ }
+
+ void
+ thread_unbind(gr_thread_t thread)
+ {
+ cpu_set_t set;
+ size_t len = sizeof(cpu_set_t);
+
+ CPU_ZERO(&set);
+ long ncpus = sysconf(_SC_NPROCESSORS_ONLN);
+ for(long n = 0; n < ncpus; n++) {
+ CPU_SET(n, &set);
+ }
+
+ int ret = pthread_setaffinity_np(thread, len, &set);
+ if(ret != 0) {
+ std::stringstream s;
+ s << "thread_unbind failed with error: " << ret << std::endl;
+ throw std::runtime_error(s.str());
+ }
+ }
+} /* namespace gruel */
+
+#endif
diff --git a/gruel/src/lib/thread_body_wrapper.cc b/gruel/src/lib/thread_body_wrapper.cc
new file mode 100644
index 000000000..019eaa342
--- /dev/null
+++ b/gruel/src/lib/thread_body_wrapper.cc
@@ -0,0 +1,85 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008 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_body_wrapper.h>
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+#include <stdio.h>
+
+namespace gruel {
+
+#if defined(HAVE_PTHREAD_SIGMASK) && defined(HAVE_SIGNAL_H)
+
+ void mask_signals()
+ {
+ sigset_t new_set;
+ int r;
+
+ sigemptyset(&new_set);
+ sigaddset(&new_set, SIGHUP); // block these...
+ sigaddset(&new_set, SIGINT);
+ sigaddset(&new_set, SIGPIPE);
+ sigaddset(&new_set, SIGALRM);
+ sigaddset(&new_set, SIGTERM);
+ sigaddset(&new_set, SIGUSR1);
+ sigaddset(&new_set, SIGCHLD);
+#ifdef SIGPOLL
+ sigaddset(&new_set, SIGPOLL);
+#endif
+#ifdef SIGPROF
+ sigaddset(&new_set, SIGPROF);
+#endif
+#ifdef SIGSYS
+ sigaddset(&new_set, SIGSYS);
+#endif
+#ifdef SIGTRAP
+ sigaddset(&new_set, SIGTRAP);
+#endif
+#ifdef SIGURG
+ sigaddset(&new_set, SIGURG);
+#endif
+#ifdef SIGVTALRM
+ sigaddset(&new_set, SIGVTALRM);
+#endif
+#ifdef SIGXCPU
+ sigaddset(&new_set, SIGXCPU);
+#endif
+#ifdef SIGXFSZ
+ sigaddset(&new_set, SIGXFSZ);
+#endif
+ r = pthread_sigmask(SIG_BLOCK, &new_set, 0);
+ if (r != 0)
+ perror("pthread_sigmask");
+ }
+
+#else
+
+ void mask_signals()
+ {
+ }
+
+#endif
+
+};
diff --git a/gruel/src/lib/thread_group.cc b/gruel/src/lib/thread_group.cc
new file mode 100644
index 000000000..9e8ded4df
--- /dev/null
+++ b/gruel/src/lib/thread_group.cc
@@ -0,0 +1,99 @@
+/* -*- c++ -*- */
+/*
+ * Copyright (C) 2001-2003 William E. Kempf
+ * Copyright (C) 2007 Anthony Williams
+ * Copyright 2008 Free Software Foundation, Inc.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+/*
+ * This was extracted from Boost 1.35.0 and fixed.
+ */
+
+#include <gruel/thread_group.h>
+
+namespace gruel
+{
+ thread_group::thread_group()
+ {
+ }
+
+ thread_group::~thread_group()
+ {
+ // We shouldn't have to scoped_lock here, since referencing this object
+ // from another thread while we're deleting it in the current thread is
+ // going to lead to undefined behavior any way.
+ for (std::list<boost::thread*>::iterator it = m_threads.begin();
+ it != m_threads.end(); ++it)
+ {
+ delete (*it);
+ }
+ }
+
+ boost::thread* thread_group::create_thread(const boost::function0<void>& threadfunc)
+ {
+ // No scoped_lock required here since the only "shared data" that's
+ // modified here occurs inside add_thread which does scoped_lock.
+ std::auto_ptr<boost::thread> thrd(new boost::thread(threadfunc));
+ add_thread(thrd.get());
+ return thrd.release();
+ }
+
+ void thread_group::add_thread(boost::thread* thrd)
+ {
+ boost::lock_guard<boost::shared_mutex> guard(m_mutex);
+
+ // For now we'll simply ignore requests to add a thread object multiple
+ // times. Should we consider this an error and either throw or return an
+ // error value?
+ std::list<boost::thread*>::iterator it = std::find(m_threads.begin(),
+ m_threads.end(), thrd);
+ BOOST_ASSERT(it == m_threads.end());
+ if (it == m_threads.end())
+ m_threads.push_back(thrd);
+ }
+
+ void thread_group::remove_thread(boost::thread* thrd)
+ {
+ boost::lock_guard<boost::shared_mutex> guard(m_mutex);
+
+ // For now we'll simply ignore requests to remove a thread object that's
+ // not in the group. Should we consider this an error and either throw or
+ // return an error value?
+ std::list<boost::thread*>::iterator it = std::find(m_threads.begin(),
+ m_threads.end(), thrd);
+ BOOST_ASSERT(it != m_threads.end());
+ if (it != m_threads.end())
+ m_threads.erase(it);
+ }
+
+ void thread_group::join_all()
+ {
+ boost::shared_lock<boost::shared_mutex> guard(m_mutex);
+ for (std::list<boost::thread*>::iterator it = m_threads.begin();
+ it != m_threads.end(); ++it)
+ {
+ (*it)->join();
+ }
+ }
+
+ void thread_group::interrupt_all()
+ {
+ boost::shared_lock<boost::shared_mutex> guard(m_mutex);
+ for(std::list<boost::thread*>::iterator it=m_threads.begin(),end=m_threads.end();
+ it!=end;
+ ++it)
+ {
+ (*it)->interrupt();
+ }
+ }
+
+ size_t thread_group::size() const
+ {
+ boost::shared_lock<boost::shared_mutex> guard(m_mutex);
+ return m_threads.size();
+ }
+
+} // namespace gruel
diff --git a/gruel/src/python/CMakeLists.txt b/gruel/src/python/CMakeLists.txt
new file mode 100644
index 000000000..f5c4ac47a
--- /dev/null
+++ b/gruel/src/python/CMakeLists.txt
@@ -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 GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+include(GrPython)
+
+########################################################################
+# Install python files
+########################################################################
+GR_PYTHON_INSTALL(
+ FILES __init__.py
+ DESTINATION ${GR_PYTHON_DIR}/gruel
+ COMPONENT "gruel_python"
+)
+
+GR_PYTHON_INSTALL(FILES
+ pmt/__init__.py
+ pmt/pmt_to_python.py
+ DESTINATION ${GR_PYTHON_DIR}/gruel/pmt
+ COMPONENT "gruel_python"
+)
+
+########################################################################
+# Setup unit tests
+########################################################################
+if(ENABLE_TESTING)
+include(GrTest)
+file(GLOB py_qa_test_files "qa_*.py")
+foreach(py_qa_test_file ${py_qa_test_files})
+ get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE)
+ set(GR_TEST_PYTHON_DIRS
+ ${CMAKE_BINARY_DIR}/gruel/src/python
+ ${CMAKE_BINARY_DIR}/gruel/src/swig
+ )
+ set(GR_TEST_TARGET_DEPS gruel gnuradio-core)
+ GR_ADD_TEST(${py_qa_test_name} ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
+endforeach(py_qa_test_file)
+endif(ENABLE_TESTING)
diff --git a/gruel/src/python/__init__.py b/gruel/src/python/__init__.py
new file mode 100644
index 000000000..976b2ed1e
--- /dev/null
+++ b/gruel/src/python/__init__.py
@@ -0,0 +1,29 @@
+#
+# 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
+
+'''
+The GNU Radio Utility Etcetera Library.
+'''
+
+import pmt;
+
diff --git a/gruel/src/python/pmt/__init__.py b/gruel/src/python/pmt/__init__.py
new file mode 100644
index 000000000..bc933e80a
--- /dev/null
+++ b/gruel/src/python/pmt/__init__.py
@@ -0,0 +1,31 @@
+#
+# 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
+
+'''
+The GNU Radio Utility Etcetera Library's Polymorphic Types for Python.
+'''
+
+from pmt_swig import *
+from pmt_to_python import pmt_to_python as to_python
+from pmt_to_python import python_to_pmt as to_pmt
+
diff --git a/gruel/src/python/pmt/pmt_to_python.py b/gruel/src/python/pmt/pmt_to_python.py
new file mode 100644
index 000000000..030c1c11d
--- /dev/null
+++ b/gruel/src/python/pmt/pmt_to_python.py
@@ -0,0 +1,97 @@
+# Copyright 2012,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.
+
+try: import pmt_swig as pmt
+except: import pmt
+import numpy
+
+#define missing
+def pmt_to_tuple(p):
+ elems = list()
+ for i in range(pmt.pmt_length(p)):
+ elem = pmt.pmt_tuple_ref(p, i)
+ elems.append(pmt_to_python(elem))
+ return tuple(elems)
+
+def pmt_from_tuple(p):
+ args = map(python_to_pmt, p)
+ return pmt.pmt_make_tuple(*args)
+
+def pmt_to_vector(p):
+ v = list()
+ for i in range(pmt.pmt_length(p)):
+ elem = pmt.pmt_vector_ref(p, i)
+ v.append(pmt_to_python(elem))
+ return v
+
+def pmt_from_vector(p):
+ v = pmt.pmt_make_vector(len(p), pmt.PMT_NIL)
+ for i, elem in enumerate(p):
+ pmt.pmt_vector_set(v, i, python_to_pmt(elem))
+ return v
+
+def pmt_to_dict(p):
+ d = dict()
+ items = pmt.pmt_dict_items(p)
+ for i in range(pmt.pmt_length(items)):
+ pair = pmt.pmt_nth(i, items)
+ k = pmt.pmt_car(pair)
+ v = pmt.pmt_cdr(pair)
+ d[pmt_to_python(k)] = pmt_to_python(v)
+ return d
+
+def pmt_from_dict(p):
+ d = pmt.pmt_make_dict()
+ for k, v in p.iteritems():
+ #dict is immutable -> therefore pmt_dict_add returns the new dict
+ d = pmt.pmt_dict_add(d, python_to_pmt(k), python_to_pmt(v))
+ return d
+
+def numpy_to_blob(p):
+ p = p.view(numpy.uint8)
+ b = pmt.pmt_make_blob(len(p))
+ pmt.pmt_blob_data(b)[:] = p
+ return b
+
+THE_TABLE = ( #python type, check pmt type, to python, from python
+ (None, pmt.pmt_is_null, lambda x: None, lambda x: pmt.PMT_NIL),
+ (bool, pmt.pmt_is_bool, pmt.pmt_to_bool, pmt.pmt_from_bool),
+ (str, pmt.pmt_is_symbol, pmt.pmt_symbol_to_string, pmt.pmt_string_to_symbol),
+ (int, pmt.pmt_is_integer, pmt.pmt_to_long, pmt.pmt_from_long),
+ (long, pmt.pmt_is_uint64, lambda x: long(pmt.pmt_to_uint64(x)), pmt.pmt_from_uint64),
+ (float, pmt.pmt_is_real, pmt.pmt_to_double, pmt.pmt_from_double),
+ (complex, pmt.pmt_is_complex, pmt.pmt_to_complex, pmt.pmt_from_complex),
+ (tuple, pmt.pmt_is_tuple, pmt_to_tuple, pmt_from_tuple),
+ (list, pmt.pmt_is_vector, pmt_to_vector, pmt_from_vector),
+ (dict, pmt.pmt_is_dict, pmt_to_dict, pmt_from_dict),
+ (numpy.ndarray, pmt.pmt_is_blob, pmt.pmt_blob_data, numpy_to_blob),
+)
+
+def pmt_to_python(p):
+ for python_type, pmt_check, to_python, from_python in THE_TABLE:
+ if pmt_check(p): return to_python(p)
+ return p #give up, we return the same
+
+def python_to_pmt(p):
+ for python_type, pmt_check, to_python, from_python in THE_TABLE:
+ if python_type is None:
+ if p == None: return from_python(p)
+ elif isinstance(p, python_type): return from_python(p)
+ return p #give up, we return the same
+
diff --git a/gruel/src/python/qa_pmt.py b/gruel/src/python/qa_pmt.py
new file mode 100755
index 000000000..59a5725fc
--- /dev/null
+++ b/gruel/src/python/qa_pmt.py
@@ -0,0 +1,102 @@
+#!/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 as pmt
+
+class test_gruel_pmt(unittest.TestCase):
+
+ def test01 (self):
+ a = pmt.pmt_intern("a")
+ b = pmt.pmt_from_double(123765)
+ d1 = pmt.pmt_make_dict()
+ d2 = pmt.pmt_dict_add(d1, a, b)
+ pmt.pmt_print(d2)
+
+ def test02 (self):
+ const = 123765
+ x_pmt = pmt.pmt_from_double(const)
+ x_int = pmt.pmt_to_double(x_pmt)
+ self.assertEqual(x_int, const)
+
+ def test03(self):
+ v = pmt.pmt_init_f32vector(3, [11, -22, 33])
+ s = pmt.pmt_serialize_str(v)
+ d = pmt.pmt_deserialize_str(s)
+ self.assertTrue(pmt.pmt_equal(v, d))
+
+ def test04(self):
+ v = pmt.pmt_init_f64vector(3, [11, -22, 33])
+ s = pmt.pmt_serialize_str(v)
+ d = pmt.pmt_deserialize_str(s)
+ self.assertTrue(pmt.pmt_equal(v, d))
+
+ def test05(self):
+ v = pmt.pmt_init_u8vector(3, [11, 22, 33])
+ s = pmt.pmt_serialize_str(v)
+ d = pmt.pmt_deserialize_str(s)
+ self.assertTrue(pmt.pmt_equal(v, d))
+
+ def test06(self):
+ v = pmt.pmt_init_s8vector(3, [11, -22, 33])
+ s = pmt.pmt_serialize_str(v)
+ d = pmt.pmt_deserialize_str(s)
+ self.assertTrue(pmt.pmt_equal(v, d))
+
+ def test07(self):
+ v = pmt.pmt_init_u16vector(3, [11, 22, 33])
+ s = pmt.pmt_serialize_str(v)
+ d = pmt.pmt_deserialize_str(s)
+ self.assertTrue(pmt.pmt_equal(v, d))
+
+ def test08(self):
+ v = pmt.pmt_init_s16vector(3, [11, -22, 33])
+ s = pmt.pmt_serialize_str(v)
+ d = pmt.pmt_deserialize_str(s)
+ self.assertTrue(pmt.pmt_equal(v, d))
+
+ def test09(self):
+ v = pmt.pmt_init_u32vector(3, [11, 22, 33])
+ s = pmt.pmt_serialize_str(v)
+ d = pmt.pmt_deserialize_str(s)
+ self.assertTrue(pmt.pmt_equal(v, d))
+
+ def test10(self):
+ v = pmt.pmt_init_s32vector(3, [11, -22, 33])
+ s = pmt.pmt_serialize_str(v)
+ d = pmt.pmt_deserialize_str(s)
+ self.assertTrue(pmt.pmt_equal(v, d))
+
+ def test11(self):
+ v = pmt.pmt_init_c32vector(3, [11 + -101j, -22 + 202j, 33 + -303j])
+ s = pmt.pmt_serialize_str(v)
+ d = pmt.pmt_deserialize_str(s)
+ self.assertTrue(pmt.pmt_equal(v, d))
+
+ def test12(self):
+ v = pmt.pmt_init_c64vector(3, [11 + -101j, -22 + 202j, 33 + -303j])
+ s = pmt.pmt_serialize_str(v)
+ d = pmt.pmt_deserialize_str(s)
+ self.assertTrue(pmt.pmt_equal(v, d))
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/gruel/src/python/qa_pmt_to_python.py b/gruel/src/python/qa_pmt_to_python.py
new file mode 100755
index 000000000..c63403a52
--- /dev/null
+++ b/gruel/src/python/qa_pmt_to_python.py
@@ -0,0 +1,34 @@
+#!/usr/bin/env python
+#
+# Copyright 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.
+#
+
+import unittest
+import pmt
+
+class test_gruel_pmt_to_python(unittest.TestCase):
+
+ def test01 (self):
+ b = pmt.pmt_from_double(123765)
+ self.assertEqual(pmt.to_python(b), 123765)
+ t = pmt.to_pmt(range(5))
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/gruel/src/swig/CMakeLists.txt b/gruel/src/swig/CMakeLists.txt
new file mode 100644
index 000000000..aeceaa605
--- /dev/null
+++ b/gruel/src/swig/CMakeLists.txt
@@ -0,0 +1,52 @@
+# Copyright 2011-2012 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.
+
+########################################################################
+# Setup swig generation
+########################################################################
+include(GrPython)
+include(GrSwig)
+
+set(GR_SWIG_TARGET_DEPS pmt_generated)
+set(GR_SWIG_INCLUDE_DIRS
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${GRUEL_INCLUDE_DIRS}
+ ${Boost_INCLUDE_DIRS}
+)
+set(GR_SWIG_LIBRARIES gruel)
+
+set(GR_SWIG_DOC_FILE ${CMAKE_CURRENT_BINARY_DIR}/pmt_swig_doc.i)
+set(GR_SWIG_DOC_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../include/gruel ${CMAKE_CURRENT_BINARY_DIR}/../include/gruel)
+
+GR_SWIG_MAKE(pmt_swig pmt_swig.i)
+
+GR_SWIG_INSTALL(
+ TARGETS pmt_swig
+ DESTINATION ${GR_PYTHON_DIR}/gruel/pmt
+ COMPONENT "gruel_python"
+)
+
+install(
+ FILES gr_intrusive_ptr.i pmt_swig.i gruel_common.i
+ ${CMAKE_CURRENT_BINARY_DIR}/pmt_swig_doc.i
+ DESTINATION ${GR_INCLUDE_DIR}/gruel/swig
+ COMPONENT "gruel_swig"
+)
+
+add_custom_target(pmt_swig DEPENDS ${SWIG_MODULE_pmt_swig_REAL_NAME})
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/gr_intrusive_ptr.i b/gruel/src/swig/gr_intrusive_ptr.i
new file mode 100644
index 000000000..dc6004f44
--- /dev/null
+++ b/gruel/src/swig/gr_intrusive_ptr.i
@@ -0,0 +1,104 @@
+#ifndef SWIG_INTRUSIVE_PTR_NAMESPACE
+
+// This file was borrowed from the SWIG project to allow use to
+// wrap PMTs that use intrusive pointers. This is only necessary
+// to support backwards compatability with older distributions of
+// Linux that do not natively support a new enough version of SWIG.
+// We do this to prevent having to update our dependency on a new
+// SWIG. Eventually, the need for this should go away.
+
+// Allow for different namespaces for shared_ptr / intrusive_ptr - they could be boost or std or std::tr1
+// For example for std::tr1, use:
+// #define SWIG_SHARED_PTR_NAMESPACE std
+// #define SWIG_SHARED_PTR_SUBNAMESPACE tr1
+// #define SWIG_INTRUSIVE_PTR_NAMESPACE boost
+// #define SWIG_INTRUSIVE_PTR_SUBNAMESPACE
+
+#if !defined(SWIG_INTRUSIVE_PTR_NAMESPACE)
+# define SWIG_INTRUSIVE_PTR_NAMESPACE boost
+#endif
+
+#if defined(SWIG_INTRUSIVE_PTR_SUBNAMESPACE)
+# define SWIG_INTRUSIVE_PTR_QNAMESPACE SWIG_INTRUSIVE_PTR_NAMESPACE::SWIG_INTRUSIVE_PTR_SUBNAMESPACE
+#else
+# define SWIG_INTRUSIVE_PTR_QNAMESPACE SWIG_INTRUSIVE_PTR_NAMESPACE
+#endif
+
+namespace SWIG_INTRUSIVE_PTR_NAMESPACE {
+#if defined(SWIG_INTRUSIVE_PTR_SUBNAMESPACE)
+ namespace SWIG_INTRUSIVE_PTR_SUBNAMESPACE {
+#endif
+ template <class T> class intrusive_ptr {
+ };
+#if defined(SWIG_INTRUSIVE_PTR_SUBNAMESPACE)
+ }
+#endif
+}
+
+%fragment("SWIG_intrusive_deleter", "header") {
+template<class T> struct SWIG_intrusive_deleter {
+ void operator()(T *p) {
+ if (p)
+ intrusive_ptr_release(p);
+ }
+};
+}
+
+%fragment("SWIG_null_deleter", "header") {
+struct SWIG_null_deleter {
+ void operator() (void const *) const {
+ }
+};
+%#define SWIG_NO_NULL_DELETER_0 , SWIG_null_deleter()
+%#define SWIG_NO_NULL_DELETER_1
+}
+
+// Main user macro for defining intrusive_ptr typemaps for both const and non-const pointer types
+// For plain classes, do not use for derived classes
+%define SWIG_INTRUSIVE_PTR(PROXYCLASS, TYPE...)
+SWIG_INTRUSIVE_PTR_TYPEMAPS(PROXYCLASS, , TYPE)
+SWIG_INTRUSIVE_PTR_TYPEMAPS(PROXYCLASS, const, TYPE)
+%enddef
+
+// Main user macro for defining intrusive_ptr typemaps for both const and non-const pointer types
+// For derived classes
+%define SWIG_INTRUSIVE_PTR_DERIVED(PROXYCLASS, BASECLASSTYPE, TYPE...)
+SWIG_INTRUSIVE_PTR_TYPEMAPS(PROXYCLASS, , TYPE)
+SWIG_INTRUSIVE_PTR_TYPEMAPS(PROXYCLASS, const, TYPE)
+%types(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > = SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< BASECLASSTYPE >) %{
+ *newmemory = SWIG_CAST_NEW_MEMORY;
+ return (void *) new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< BASECLASSTYPE >(*(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *)$from);
+ %}
+%extend TYPE {
+ static SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< BASECLASSTYPE > SWIGSharedPtrUpcast(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > swigSharedPtrUpcast) {
+ return swigSharedPtrUpcast;
+ }
+}
+%enddef
+
+// Extra user macro for including classes in intrusive_ptr typemaps for both const and non-const pointer types
+// This caters for classes which cannot be wrapped by intrusive_ptrs but are still part of the class hierarchy
+// For plain classes, do not use for derived classes
+%define SWIG_INTRUSIVE_PTR_NO_WRAP(PROXYCLASS, TYPE...)
+SWIG_INTRUSIVE_PTR_TYPEMAPS_NO_WRAP(PROXYCLASS, , TYPE)
+SWIG_INTRUSIVE_PTR_TYPEMAPS_NO_WRAP(PROXYCLASS, const, TYPE)
+%enddef
+
+// Extra user macro for including classes in intrusive_ptr typemaps for both const and non-const pointer types
+// This caters for classes which cannot be wrapped by intrusive_ptrs but are still part of the class hierarchy
+// For derived classes
+%define SWIG_INTRUSIVE_PTR_DERIVED_NO_WRAP(PROXYCLASS, BASECLASSTYPE, TYPE...)
+SWIG_INTRUSIVE_PTR_TYPEMAPS_NO_WRAP(PROXYCLASS, , TYPE)
+SWIG_INTRUSIVE_PTR_TYPEMAPS_NO_WRAP(PROXYCLASS, const, TYPE)
+%types(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > = SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< BASECLASSTYPE >) %{
+ *newmemory = SWIG_CAST_NEW_MEMORY;
+ return (void *) new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< BASECLASSTYPE >(*(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *)$from);
+%}
+%extend TYPE {
+ static SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< BASECLASSTYPE > SWIGSharedPtrUpcast(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > swigSharedPtrUpcast) {
+ return swigSharedPtrUpcast;
+ }
+}
+%enddef
+
+#endif //SWIG_INTRUSIVE_PTR_NAMESPACE
diff --git a/gruel/src/swig/gruel_common.i b/gruel/src/swig/gruel_common.i
new file mode 100644
index 000000000..3a4d841d6
--- /dev/null
+++ b/gruel/src/swig/gruel_common.i
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+#ifndef GRUEL_COMMON_I
+#define GRUEL_COMMON_I
+
+////////////////////////////////////////////////////////////////////////
+// Language independent exception handler
+////////////////////////////////////////////////////////////////////////
+%include exception.i
+
+%exception {
+ try {
+ $action
+ }
+ catch(std::exception &e) {
+ SWIG_exception(SWIG_RuntimeError, e.what());
+ }
+ catch(...) {
+ SWIG_exception(SWIG_RuntimeError, "Unknown exception");
+ }
+
+}
+
+////////////////////////////////////////////////////////////////////////
+// Wrapper for python calls that may block
+////////////////////////////////////////////////////////////////////////
+
+/*!
+ * Use GR_PYTHON_BLOCKING_CODE when calling code that blocks.
+ *
+ * The try/catch is to save us from boost::thread::interrupt:
+ * If a thread from the scheduler (or any other boost thread)
+ * is blocking the routine and throws an interrupt exception.
+ */
+%{
+
+#define GR_PYTHON_BLOCKING_CODE(code) { \
+ PyThreadState *_save; \
+ _save = PyEval_SaveThread(); \
+ try{code} \
+ catch(...){PyEval_RestoreThread(_save); throw;} \
+ PyEval_RestoreThread(_save); \
+}
+
+%}
+
+#endif /*GRUEL_COMMON_I*/
diff --git a/gruel/src/swig/pmt_swig.i b/gruel/src/swig/pmt_swig.i
new file mode 100644
index 000000000..84f48b099
--- /dev/null
+++ b/gruel/src/swig/pmt_swig.i
@@ -0,0 +1,792 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2011-2012 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 "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>
+%}
+
+%include "gruel_common.i"
+//load generated python docstrings
+%include "pmt_swig_doc.i"
+
+%include <std_complex.i>
+%include <std_vector.i>
+%include <stl.i>
+
+namespace std {
+ %template() vector<unsigned char>;
+ %template() vector<uint8_t>;
+ %template() vector<char>;
+ %template() vector<int8_t>;
+ %template() vector<short>;
+ %template() vector<uint16_t>;
+ %template() vector<int16_t>;
+ %template() vector<int>;
+ %template() vector<int32_t>;
+ %template() vector<uint32_t>;
+ %template() vector<float>;
+ %template() vector<double>;
+ %template() vector< std::complex<float> >;
+ %template() vector< std::complex<double> >;
+};
+
+////////////////////////////////////////////////////////////////////////
+// Language independent exception handler
+////////////////////////////////////////////////////////////////////////
+
+// Template intrusive_ptr for Swig to avoid dereferencing issues
+namespace pmt{
+ class pmt_base;
+}
+//%import <intrusive_ptr.i>
+%import <gr_intrusive_ptr.i>
+%template(swig_int_ptr) boost::intrusive_ptr<pmt::pmt_base>;
+
+namespace pmt{
+
+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);
+
+pmt_t pmt_from_complex(const std::complex<double> &z);
+
+/*!
+ * 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 std::vector<uint8_t> &data);
+pmt_t pmt_init_s8vector(size_t k, const std::vector<int8_t> &data);
+pmt_t pmt_init_u16vector(size_t k, const std::vector<uint16_t> &data);
+pmt_t pmt_init_s16vector(size_t k, const std::vector<int16_t> &data);
+pmt_t pmt_init_u32vector(size_t k, const std::vector<uint32_t> &data);
+pmt_t pmt_init_s32vector(size_t k, const std::vector<int32_t> &data);
+pmt_t pmt_init_f32vector(size_t k, const std::vector<float> &data);
+pmt_t pmt_init_f64vector(size_t k, const std::vector<double> &data);
+pmt_t pmt_init_c32vector(size_t k, const std::vector<std::complex<float> > &data);
+pmt_t pmt_init_c64vector(size_t k, const std::vector<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
+
+%apply size_t & INOUT { size_t &len };
+
+// works with any; len is in bytes
+// Returns an opaque Python type
+const void *pmt_uniform_vector_elements(pmt_t v, size_t &len);
+
+// Returns a Python tuple
+const std::vector<uint8_t> pmt_u8vector_elements(pmt_t v);
+const std::vector<int8_t> pmt_s8vector_elements(pmt_t v);
+const std::vector<uint16_t> pmt_u16vector_elements(pmt_t v);
+const std::vector<int16_t> pmt_s16vector_elements(pmt_t v);
+const std::vector<uint32_t> pmt_u32vector_elements(pmt_t v);
+const std::vector<int32_t> pmt_s32vector_elements(pmt_t v);
+const std::vector<float> pmt_f32vector_elements(pmt_t v);
+const std::vector<double> pmt_f64vector_elements(pmt_t v);
+const std::vector<std::complex<float> > pmt_c32vector_elements(pmt_t v);
+const std::vector<std::complex<double> > pmt_c64vector_elements(pmt_t v);
+
+/*
+ * ------------------------------------------------------------------------
+ * 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 &not_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);
+
+/*!
+ * \brief Return \p list with \p item removed
+ */
+pmt_t pmt_list_rm(pmt_t list, const pmt_t& item);
+
+/*!
+ * \brief Return bool of \p list contains \p item
+ */
+bool pmt_list_has(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);
+
+} //namespace pmt