# HG changeset patch # User John W. Eaton # Date 1241723659 14400 # Node ID 1e5c11890f851d64e452791ac2af9ac46f127e7c # Parent 9861b3ec72a6ccef96da1c7e65a57b6298766c5a check for invalid property names when setting defaults diff --git a/src/ChangeLog b/src/ChangeLog --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,20 @@ +2009-05-07 John W. Eaton + + * 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 * ov-re-mat.cc (Fdouble): Fix order of branches. diff --git a/src/genprops.awk b/src/genprops.awk --- 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 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; } } diff --git a/src/graphics.cc b/src/graphics.cc --- 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 > 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& 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::iterator it = all_props.find (name); +base_properties::set_dynamic (const caseless_str& pname, + const std::string& cname, + const octave_value& val) +{ + std::map::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 diff --git a/src/graphics.h.in b/src/graphics.h.in --- 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 > 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"); }