changeset 15050:abc858bc5165

Add functions to encode/decode double arrays to/from base64. * bootstrap.conf: add base64 to list of imported gnulib modules. * data.cc (base64_encode): new function. * data.cc (base64_decode): new function.
author Carlo de Falco <cdf@users.sourceforge.net>
date Sun, 29 Jul 2012 19:17:48 +0200
parents e499ebcd3b0f
children d43fec5684dd
files build-aux/bootstrap.conf src/data.cc
diffstat 2 files changed, 128 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/build-aux/bootstrap.conf
+++ b/build-aux/bootstrap.conf
@@ -18,6 +18,7 @@
 
 # gnulib modules used by this package.
 gnulib_modules="
+  base64
   c-strcase
   copysign
   copysignf
@@ -60,7 +61,6 @@
   signal
   sigprocmask
   sleep
-  sleep
   stat
   stdint
   stdio
--- a/src/data.cc
+++ b/src/data.cc
@@ -3,6 +3,7 @@
 Copyright (C) 1994-2012 John W. Eaton
 Copyright (C) 2009 Jaroslav Hajek
 Copyright (C) 2009-2010 VZLU Prague
+Copyright (C) 2012 Carlo de Falco
 
 This file is part of Octave.
 
@@ -37,6 +38,10 @@
 #include <ctime>
 
 #include <string>
+extern "C"
+{
+#include <base64.h>
+}
 
 #include "lo-ieee.h"
 #include "lo-math.h"
@@ -7227,3 +7232,125 @@
 
   return retval;
 }
+
+DEFUN (base64_encode, args, nargout, "-*- texinfo -*-\n\
+@deftypefn  {Loadable Function} {@var{s} =} base64_encode (@var{x})\n\
+Encode a double matrix or array @var{x} into the base64 format string @var{s}.\n\
+Encoding different numeric types is currently not supported, variables of such types \
+will be converted  to double before encoding.\n\
+@seealso{base64_decode}\n\
+@end deftypefn")
+{
+  octave_value_list retval;
+  
+  int nargin = args.length ();
+  if (nargin != 1)
+    print_usage ();
+  else 
+    {
+      const Array<double> in = args(0).array_value ();
+      if (! error_state)
+        {      
+          const char* inc = reinterpret_cast<const char*> (in.data ());
+          size_t inlen = in.numel () * sizeof (double) / sizeof (char);          
+          char* out;
+          
+          size_t outlen = base64_encode_alloc (inc, inlen, &out);
+          
+          if (! out && outlen == 0 && inlen != 0)
+            error ("base64_encode: input array too large");
+          else if (! out)
+            error ("base64_encode: memory allocation error");
+          else
+            retval(0) = octave_value (out);          
+        }
+    }
+     return retval;
+}
+
+/*
+  %!assert (base64_encode (single (pi)), base64_encode (double (single (pi))));
+  %!assert (base64_encode (uint8 (pi)), base64_encode (double (uint8 (pi))));
+
+  %!error (base64_encode ("A string"));
+*/
+
+DEFUN (base64_decode, args, nargout, "-*- texinfo -*-\n\
+@deftypefn  {Loadable Function} {@var{x} =} base64_decode (@var{s}, @var{dims})\n\
+Decode the double matrix or array @var{x} from the base64 format string @var{s}.\n\
+The optional input parameter @var{dims} should be a vector containing the dimensions \
+of the decoded array.\n\
+@seealso{base64_encode}\n\
+@end deftypefn")
+{
+  octave_value_list retval;
+  dim_vector new_dims;
+  Array<double> res;
+
+  int nargin = args.length ();
+  if (nargin < 1 || nargin > 2)
+    print_usage ();
+  else 
+    {
+      if (nargin > 1)
+        {
+          const Array<octave_idx_type> new_size = args(1).octave_idx_type_vector_value ();
+          if (! error_state)
+            {
+              new_dims = dim_vector::alloc (new_size.length ());
+              for (octave_idx_type i = 0; i < new_size.length (); i++)
+                new_dims(i) = new_size(i);              
+            }
+        } 
+
+      const std::string in = args(0).string_value ();
+
+      if (! error_state)
+        {      
+          const char *inc = &(in[0]);
+          char *out;
+          size_t inlen = in.length (), 
+            outlen;          
+
+          bool ok = base64_decode_alloc (inc, inlen, &out, &outlen);
+
+          if (! ok)
+            error ("base64_decode: input was not valid base64");
+          else if (! out)
+            error ("base64_decode: memory allocation error");
+          else
+            {
+              if ((outlen % (sizeof (double) / sizeof (char))) != 0)
+                error ("base64_decode: incorrect input size");
+              else
+                {
+                  octave_idx_type l = (outlen * sizeof (char)) / sizeof (double);
+                  res.resize1 (l);
+                  double *dout = reinterpret_cast<double*> (out);
+                  std::copy (dout, dout + l, res.fortran_vec ());
+
+                  if (nargin > 1)
+                    retval(0) = octave_value (res).reshape (new_dims);
+                  else
+                    retval(0) = octave_value (res);
+                }
+            }
+        }
+    }
+  return retval; 
+}
+
+/*
+  %!assert (base64_decode (base64_encode (pi)));
+  %!test 
+  %! in   = randn (10);
+  %! outv = base64_decode (base64_encode (in));
+  %! outm = base64_decode (base64_encode (in), size (in)); 
+  %! assert (outv, in(:).');
+  %! assert (outm, in);
+
+  %!error (base64_decode (1, "this is not a valid set of dimensions"))
+  %!error <not valid> (base64_decode (1))
+  %!error <not valid> (base64_decode ("AQ="))
+  %!error <incorrect input size> (base64_decode ("AQ=="))
+*/