changeset 10638:e1559a8a60b4

general mechanism for string enum variables
author Jaroslav Hajek <highegg@gmail.com>
date Mon, 17 May 2010 14:41:56 +0200
parents 9cd5aa83fa62
children a52cc4f6ebfc
files src/ChangeLog src/DLD-FUNCTIONS/svd.cc src/variables.cc src/variables.h
diffstat 4 files changed, 72 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Mon May 17 13:46:57 2010 +0200
+++ b/src/ChangeLog	Mon May 17 14:41:56 2010 +0200
@@ -1,3 +1,11 @@
+2010-05-17  Jaroslav Hajek  <highegg@gmail.com>
+
+	* variables.cc (set_internal_variable (int&, ..., const char **, int)):
+	New overload.
+	* variables.h: Declare it.
+	(SET_INTERNAL_VARIABLE_CHOICES): New macro.
+	* DLD-FUNCTIONS/svd.cc (Fsvd_driver): Use it here.
+
 2010-05-17  Jaroslav Hajek  <highegg@gmail.com>
 
 	* ov-usr-fcn.h (octave_user_function::curr_unwind_protect_frame): New
--- a/src/DLD-FUNCTIONS/svd.cc	Mon May 17 13:46:57 2010 +0200
+++ b/src/DLD-FUNCTIONS/svd.cc	Mon May 17 14:41:56 2010 +0200
@@ -36,8 +36,9 @@
 #include "oct-obj.h"
 #include "pr-output.h"
 #include "utils.h"
+#include "variables.h"
 
-static SVD::driver driver = SVD::GESVD;
+static int Vsvd_driver = SVD::GESVD;
 
 DEFUN_DLD (svd, args, nargout,
   "-*- texinfo -*-\n\
@@ -148,6 +149,9 @@
                     ? SVD::sigma_only
                     : (nargin == 2) ? SVD::economy : SVD::std);
 
+  SVD::driver driver = static_cast<SVD::driver> (Vsvd_driver);
+  assert (driver == SVD::GESVD || driver == SVD::GESDD);
+
   if (nr == 0 || nc == 0)
     {
       if (isfloat)
@@ -399,7 +403,7 @@
 
 */
 
-DEFUN_DLD (svd_driver, args, ,
+DEFUN_DLD (svd_driver, args, nargout,
   "-*- texinfo -*-\n\
 @deftypefn {Loadable Function} {@var{old} =} svd_driver (@var{new})\n\
 Sets or queries the underlying LAPACK driver used by svd.\n\
@@ -407,34 +411,7 @@
 @seealso{svd}\n\
 @end deftypefn")
 {
-  octave_value retval;
-  int nargin = args.length ();
-
-  if (nargin == 0 || (nargin == 1 && args(0).is_string ()))
-    {
-      if (driver == SVD::GESVD)
-        retval = "gesvd";
-      else if (driver == SVD::GESDD)
-        retval = "gesdd";
-      else
-        panic_impossible ();
-
+  static const char *driver_names[] = { "gesvd", "gesdd" };
 
-      if (nargin == 1)
-        {
-          std::string opt = args(0).xtolower ().string_value ();
-          if (opt == "gesvd")
-            driver = SVD::GESVD;
-          else if (opt == "gesdd")
-            driver = SVD::GESDD;
-          else
-            error ("svd_driver: invalid driver spec: %s", opt.c_str ());
-        }
-    }
-  else
-    print_usage ();
-
-  return retval;
+  return SET_INTERNAL_VARIABLE_CHOICES (svd_driver, driver_names);
 }
-
-
--- a/src/variables.cc	Mon May 17 13:46:57 2010 +0200
+++ b/src/variables.cc	Mon May 17 14:41:56 2010 +0200
@@ -871,6 +871,52 @@
   return retval;
 }
 
+octave_value
+set_internal_variable (int& var, const octave_value_list& args,
+                       int nargout, const char *nm, const char **choices,
+                       int nchoices)
+{
+  octave_value retval;
+
+  int nargin = args.length ();
+  assert (var < nchoices);
+
+  if (nargout > 0 || nargin == 0)
+    retval = choices[var];
+
+  if (wants_local_change (args, nargin))
+    {
+      if (! try_local_protect (var))
+        warning ("\"local\" has no effect outside a function");
+    }
+
+  if (nargin == 1)
+    {
+      std::string sval = args(0).string_value ();
+
+      if (! error_state)
+        {
+          int i = 0;
+          for (; i < nchoices; i++)
+            {
+              if (sval == choices[i])
+                {
+                  var = i;
+                  break;
+                }
+            }
+          if (i == nchoices)
+            error ("%s: value not allowed (\"%s\")", nm, sval.c_str ());
+        }
+      else
+        error ("%s: expecting arg to be a character string", nm);
+    }
+  else if (nargin > 1)
+    print_usage ();
+
+  return retval;
+}
+
 struct
 whos_parameter
 {
--- a/src/variables.h	Mon May 17 13:46:57 2010 +0200
+++ b/src/variables.h	Mon May 17 14:41:56 2010 +0200
@@ -109,6 +109,11 @@
 set_internal_variable (std::string& var, const octave_value_list& args,
                        int nargout, const char *nm, bool empty_ok = true);
 
+extern OCTINTERP_API octave_value
+set_internal_variable (int& var, const octave_value_list& args,
+                       int nargout, const char *nm, const char **choices,
+                       int nchoices);
+
 #define SET_INTERNAL_VARIABLE(NM) \
   set_internal_variable (V ## NM, args, nargout, #NM)
 
@@ -118,6 +123,11 @@
 #define SET_INTERNAL_VARIABLE_WITH_LIMITS(NM, MINVAL, MAXVAL) \
   set_internal_variable (V ## NM, args, nargout, #NM, MINVAL, MAXVAL)
 
+// in the following, CHOICES must be a static C string array.
+#define SET_INTERNAL_VARIABLE_CHOICES(NM, CHOICES) \
+  set_internal_variable (V ## NM, args, nargout, #NM, CHOICES, \
+                         sizeof (CHOICES) / sizeof (const char *))
+
 extern OCTINTERP_API std::string builtin_string_variable (const std::string&);
 extern OCTINTERP_API int builtin_real_scalar_variable (const std::string&, double&);
 extern OCTINTERP_API octave_value builtin_any_variable (const std::string&);