changeset 9185:1e5c11890f85

check for invalid property names when setting defaults
author John W. Eaton <jwe@octave.org>
date Thu, 07 May 2009 15:14:19 -0400
parents 9861b3ec72a6
children 49a0c58a7dcf
files src/ChangeLog src/genprops.awk src/graphics.cc src/graphics.h.in
diffstat 4 files changed, 125 insertions(+), 36 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,20 @@
+2009-05-07  John W. Eaton  <jwe@octave.org>
+
+	* genprops.awk (emit_declarations): Emit decls for static
+	has_property functions.
+	(emit_source): Add class name argument to base_properties::set
+	function.  Pass class name to set_dynamic and
+	base_properties::set.  Emit definitions for has_property
+	functions.
+	* graphics.h.in, graphics.cc
+	(base_properties::set, base_properties::set_dynamic):
+	New argument CNAME.
+	(base_properties::all_dynamic_properties): New static data member.
+	(base_properties::has_dynamic_property): New static function.
+	(base_graphics_object::set): Pass class name to
+	base_properties::set function.
+	(property_list::set): Check for invalid property names.
+
 2009-05-06  Jaroslav Hajek  <highegg@gmail.com>
 
 	* ov-re-mat.cc (Fdouble): Fix order of branches.
--- a/src/genprops.awk
+++ b/src/genprops.awk
@@ -257,6 +257,12 @@
   if (class_name && ! base)
     emit_common_declarations();
 
+  printf ("public:\n\n");
+  if (base)
+    printf ("\n  static bool has_property (const std::string& pname, const std::string& cname);\n\n");
+  else
+    printf ("\n  static bool has_property (const std::string& pname);\n\n");
+
   if (idx > 0)
     print (base ? "protected:\n" : "private:\n");
 
@@ -422,7 +428,7 @@
     ## set method
 
     if (base)
-      printf ("void\nbase_properties::set (const caseless_str& pname, const octave_value& val)\n{\n") >> filename;
+      printf ("void\nbase_properties::set (const caseless_str& pname, const std::string& cname, const octave_value& val)\n{\n") >> filename;
     else
       printf ("void\n%s::properties::set (const caseless_str& pname, const octave_value& val)\n{\n",
               class_name) >> filename;
@@ -440,9 +446,9 @@
     }
 
     if (base)
-      printf ("  else\n    set_dynamic (pname, val);\n}\n\n") >> filename;
+      printf ("  else\n    set_dynamic (pname, cname, val);\n}\n\n") >> filename;
     else
-      printf ("  else\n    base_properties::set (pname, val);\n}\n\n") >> filename;
+      printf ("  else\n    base_properties::set (pname, \"%s\", val);\n}\n\n", class_name) >> filename;
 
     ## get "all" method
 
@@ -559,6 +565,19 @@
     if (! base)
       printf ("std::string %s::properties::go_name (\"%s\");\n\n",
               class_name, object_name) >> filename;
+
+    if (base)
+      printf ("bool base_properties::has_property (const std::string& pname, const std::string& cname") >> filename;
+    else
+    printf ("bool %s::properties::has_property (const std::string& pname", class_name) >> filename;
+    printf (")\n{\n  static std::set<std::string> all_properties;\n\n  static bool initialized = false;\n\n  if (! initialized)\n    {\n") >> filename;
+    for (i = 1; i <= idx; i++)
+      printf ("      all_properties.insert (\"%s\");\n", name[i]) >> filename;
+    printf ("\n      initialized = true;\n    }\n\n") >> filename;
+    if (base)
+	printf ("  return all_properties.find (pname) != all_properties.end () || has_dynamic_property (pname, cname);\n}\n\n") >> filename;
+    else
+      printf ("  return all_properties.find (pname) != all_properties.end () || base_properties::has_property (pname, \"%s\");\n}\n\n", class_name) >> filename;
   }
 }
 
--- a/src/graphics.cc
+++ b/src/graphics.cc
@@ -1170,29 +1170,52 @@
 	  std::transform (pfx.begin (), pfx.end (), pfx.begin (), tolower);
 	  std::transform (pname.begin (), pname.end (), pname.begin (), tolower);
 
-	  bool remove = false;
-	  if (val.is_string ())
+	  bool has_property = false;
+	  if (pfx == "axes")
+	    has_property = axes::properties::has_property (pname);
+	  else if (pfx == "line")
+	    has_property = line::properties::has_property (pname);
+	  else if (pfx == "text")
+	    has_property = text::properties::has_property (pname);
+	  else if (pfx == "image")
+	    has_property = image::properties::has_property (pname);
+	  else if (pfx == "patch")
+	    has_property = patch::properties::has_property (pname);
+	  else if (pfx == "figure")
+	    has_property = figure::properties::has_property (pname);
+	  else if (pfx == "surface")
+	    has_property = surface::properties::has_property (pname);
+	  else if (pfx == "hggroup")
+	    has_property = hggroup::properties::has_property (pname);
+
+	  if (has_property)
 	    {
-	      caseless_str tval = val.string_value ();
-
-	      remove = tval.compare ("remove");
-	    }
-
-	  pval_map_type& pval_map = plist_map[pfx];
-
-	  if (remove)
-	    {
-	      pval_map_iterator p = pval_map.find (pname);
-
-	      if (p != pval_map.end ())
-		pval_map.erase (p);
+	      bool remove = false;
+	      if (val.is_string ())
+		{
+		  caseless_str tval = val.string_value ();
+
+		  remove = tval.compare ("remove");
+		}
+
+	      pval_map_type& pval_map = plist_map[pfx];
+
+	      if (remove)
+		{
+		  pval_map_iterator p = pval_map.find (pname);
+
+		  if (p != pval_map.end ())
+		    pval_map.erase (p);
+		}
+	      else
+		pval_map[pname] = val;
 	    }
 	  else
-	    pval_map[pname] = val;
+	    error ("invalid %s property `%s'", pfx.c_str (), pname.c_str ());
 	}
     }
 
-  if (offset == 0)
+  if (! error_state && offset == 0)
     error ("invalid default property specification");
 }
 
@@ -1703,18 +1726,41 @@
   return m;
 }
 
+std::map<std::string, std::set<std::string> > base_properties::all_dynamic_properties;
+
+bool
+base_properties::has_dynamic_property (const std::string& pname,
+				       const std::string& cname)
+{
+  // FIXME -- we need to maintain a static map of class names to sets
+  // of dynamic property names, then look up the set for the given
+  // cname, then see if the set contains the given pname.  Doing that
+  // implies changes to set_dynamic, I think.  Where is set_dynamic
+  // ever used?
+
+  std::set<std::string>& dynprops = all_dynamic_properties[cname];
+
+  return dynprops.find (pname) != dynprops.end ();
+}
+
 void
-base_properties::set_dynamic (const caseless_str& name, const octave_value& val)
-{
-  std::map<caseless_str, property, cmp_caseless_str>::iterator it = all_props.find (name);
+base_properties::set_dynamic (const caseless_str& pname,
+			      const std::string& cname,
+			      const octave_value& val)
+{
+  std::map<caseless_str, property, cmp_caseless_str>::iterator it = all_props.find (pname);
 
   if (it != all_props.end ())
     it->second.set (val);
   else
-    error ("set: unknown property \"%s\"", name.c_str ());
+    error ("set: unknown property \"%s\"", pname.c_str ());
 
   if (! error_state)
-    mark_modified ();
+    {
+      all_dynamic_properties[cname].insert (pname);
+
+      mark_modified ();
+    }
 }
 
 property
--- a/src/graphics.h.in
+++ b/src/graphics.h.in
@@ -1642,15 +1642,16 @@
       all_props[name] = p;
     }
 
-  virtual void set (const caseless_str&, const octave_value&);
-
-  virtual octave_value get (const caseless_str&) const;
+  virtual void set (const caseless_str& pname, const std::string& cname,
+		    const octave_value& val);
+
+  virtual octave_value get (const caseless_str& pname) const;
 
   virtual octave_value get (bool all = false) const;
 
-  virtual property get_property (const caseless_str&);
-
-  bool has_property (const caseless_str&);
+  virtual property get_property (const caseless_str& pname);
+
+  bool has_property (const caseless_str& pname);
 
   bool is_modified (void) const { return is___modified__ (); }
  
@@ -1723,15 +1724,21 @@
   {
     return ! handlevisibility.is ("off");
   }
+
+  static std::map<std::string, std::set<std::string> > all_dynamic_properties;
  
+  static bool has_dynamic_property (const std::string& pname,
+				    const std::string& cname);
+
 protected:
-  void set_dynamic (const caseless_str&, const octave_value&);
-
-  octave_value get_dynamic (const caseless_str&) const;
+  void set_dynamic (const caseless_str& pname, const std::string& cname,
+		    const octave_value& val);
+
+  octave_value get_dynamic (const caseless_str& pname) const;
 
   octave_value get_dynamic (bool all = false) const;
 
-  property get_property_dynamic (const caseless_str&);
+  property get_property_dynamic (const caseless_str& pname);
 
   BEGIN_BASE_PROPERTIES
     // properties common to all objects
@@ -1821,7 +1828,7 @@
   virtual void set (const caseless_str& pname, const octave_value& pval)
   {
     if (valid_object ())
-      get_properties ().set (pname, pval);
+      get_properties ().set (pname, type (), pval);
     else
       error ("base_graphics_object::set: invalid graphics object");
   }