changeset 4744:7dcb696159ac

[project @ 2004-02-06 05:46:22 by jwe]
author jwe
date Fri, 06 Feb 2004 05:46:22 +0000
parents 754e2855a32d
children 537509a45ba7
files src/ChangeLog src/oct-map.h src/ov-struct.cc
diffstat 3 files changed, 151 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Fri Feb 06 04:07:22 2004 +0000
+++ b/src/ChangeLog	Fri Feb 06 05:46:22 2004 +0000
@@ -1,3 +1,16 @@
+2004-02-05  John W. Eaton  <jwe@bevo.che.wisc.edu>
+
+	* ov-struct.cc (Fstruct): Use new Octave_map constructor to create
+	structures with specified sizes but no keys.
+
+	* ov-struct.cc (Fstruct): New function, from Paul Kienzle
+	<pkienzle@users.sf.net> and Petter Risholm  <risholm@stud.ntnu.no>.
+
+	* oct-map.h (Octave_map::Octave_map): Allow dimension to be
+	specified for map with no keys.
+
+	* ov-struct.cc (fieldnames): Return 0x1 cell array if no fieldnames.
+
 2004-02-05  Petter Risholm  <risholm@stud.ntnu.no>
 
 	* ov-base-mat.cc (octave_base_matrix<MT>::do_index_op):
--- a/src/oct-map.h	Fri Feb 06 04:07:22 2004 +0000
+++ b/src/oct-map.h	Fri Feb 06 05:46:22 2004 +0000
@@ -42,7 +42,10 @@
   typedef std::map<std::string, Cell>::iterator iterator;
   typedef std::map<std::string, Cell>::const_iterator const_iterator;
 
-  Octave_map (void) : map (), dimensions (0, 0) { }
+  // Warning!  You should always use at least two dimensions.
+
+  Octave_map (const dim_vector& dv = dim_vector (0, 0))
+    : map (), dimensions (dv) { }
 
   Octave_map (const std::string& k, const octave_value& value)
     : map (), dimensions (1, 1)
--- a/src/ov-struct.cc	Fri Feb 06 04:07:22 2004 +0000
+++ b/src/ov-struct.cc	Fri Feb 06 05:46:22 2004 +0000
@@ -453,6 +453,135 @@
   return retval;
 }
 
+static bool 
+scalar (const dim_vector& dims) 
+{
+  return dims.length () == 2 && dims (0) == 1 && dims (1) == 1;
+}
+
+// XXX FIXME XXX -- move these tests to the test directory?
+/*
+%!shared x
+%! x(1).a=1; x(2).a=2; x(1).b=3; x(2).b=3;
+%!assert(struct('a',1,'b',3),x(1))
+%!assert(struct('a',{},'b',{}),x([]))
+%!assert(struct('a',{1,2},'b',{3,3}),x)
+%!assert(struct('a',{1,2},'b',3),x)
+%!assert(struct('a',{1,2},'b',{3}),x)
+%!assert(struct('b',3,'a',{1,2}),x)
+%!assert(struct('b',{3},'a',{1,2}),x) 
+%!test x=struct([]);
+%!assert(size(x),[0,0]);
+%!assert(isstruct(x));
+%!assert(isempty(fieldnames(x)));
+%!fail("struct('a',{1,2},'b',{1,2,3})","dimensions of parameter 2 do not match those of parameter 4")
+%!fail("struct(1,2,3,4)","struct expects alternating 'field',value pairs");
+%!fail("struct('1',2,'3')","struct expects alternating 'field',value pairs");
+*/
+
+DEFUN (struct, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {} struct (\"field\", @var{value}, \"field\", @var{value}, @dots{})\n\
+\n\
+Create a structure and initialize its value.\n\
+\n\
+If the values are cell arrays, create a structure array and initialize\n\
+its values.  The dimensions of each cell array of values must match.\n\
+Singleton cells and non-cell values are repeated so that they fill\n\
+the entire array.  If the cells are empty, create an empty structure\n\
+array with the specified field names.")
+{
+  octave_value_list retval;
+
+  int nargin = args.length ();
+
+  // struct([]) returns an empty struct.
+  // XXX FIXME XXX should struct() also create an empty struct?
+
+  if (nargin == 1 && args(0).is_empty () && args(0).is_real_matrix ())
+    return octave_value (Octave_map ());
+    
+  // Check for "field", VALUE pairs.
+
+  for (int i = 0; i < nargin; i += 2) 
+    {
+      if (! args(i).is_string () || i + 1 >= nargin)
+	{
+	  error ("struct expects alternating \"field\", VALUE pairs");
+	  return retval;
+	}
+    }
+
+  // Check that the dimensions of the values correspond.
+
+  dim_vector dims (1, 1);
+
+  int first_dimensioned_value = 0;
+
+  for (int i = 1; i < nargin; i += 2) 
+    {
+      if (args(i).is_cell ()) 
+	{
+	  dim_vector argdims (args(i).dims ());
+
+	  if (! scalar (argdims))
+	    {
+	      if (! first_dimensioned_value)
+		{
+		  dims = argdims;
+		  first_dimensioned_value = i + 1;
+		}
+	      else if (dims != argdims)
+		{
+		  error ("struct: dimensions of parameter %d do not match those of parameter %d",
+			 first_dimensioned_value, i+1);
+		  return retval;
+		}
+	    }
+	}
+    }
+
+  // Create the return value.
+
+  Octave_map map (dims);
+
+  for (int i = 0; i < nargin; i+= 2) 
+    {
+      // Get key.
+
+      std::string key (args(i).string_value ());
+
+      if (error_state)
+	return retval;
+
+      // Value may be v, { v }, or { v1, v2, ... }
+      // In the first two cases, we need to create a cell array of
+      // the appropriate dimensions filled with v.  In the last case, 
+      // the cell array has already been determined to be of the
+      // correct dimensions.
+
+      if (args(i+1).is_cell ()) 
+	{
+	  const Cell c (args(i+1).cell_value ());
+
+	  if (error_state)
+	    return retval;
+
+	  if (scalar (c.dims ())) 
+	    map.assign (key, Cell (dims, c(0)));
+	  else 
+	    map.assign (key, c);
+	}
+      else 
+	map.assign (key, Cell (dims, args(i+1)));
+
+      if (error_state)
+	return retval;
+    }
+  
+  return octave_value (map);
+}
+
 DEFUN (isstruct, args, ,
   "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} isstruct (@var{expr})\n\
@@ -486,7 +615,11 @@
       if (args(0).is_map ())
 	{
 	  Octave_map m = args(0).map_value ();
-	  retval = Cell (m.keys ());
+	  string_vector keys = m.keys ();
+	  if (keys.length () == 0)
+	    retval = Cell (0, 1);
+	  else
+	    retval = Cell (m.keys ());
 	}
       else
 	gripe_wrong_type_arg ("fieldnames", args(0));