From 66899f063d6c82701bba9a501cb46c4915d9a40b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaakko=20Ker=C3=A4nen?= Date: Fri, 28 Mar 2014 18:08:37 +0200 Subject: [PATCH] libdeng2|Info: Retain letter case in identifiers While block types are still forced to lower case, all element names now retain their case. They are indexed case insensitively, though, and looking up elements by name is also case insensitive. This improves use of Info for scripting, as one can use mixed-case identifiers without restrictions. --- doomsday/libdeng2/include/de/data/info.h | 31 ++++++++++++++++++------ doomsday/libdeng2/src/data/info.cpp | 4 +-- doomsday/tests/test_info/test_info.dei | 11 ++++++--- 3 files changed, 32 insertions(+), 14 deletions(-) diff --git a/doomsday/libdeng2/include/de/data/info.h b/doomsday/libdeng2/include/de/data/info.h index e96dff87dd..0a1fa28e06 100644 --- a/doomsday/libdeng2/include/de/data/info.h +++ b/doomsday/libdeng2/include/de/data/info.h @@ -29,12 +29,15 @@ namespace de { /** * Key/value tree. The tree is parsed from the "Snowberry" Info file format. - * @ingroup data + * + * All element names (key identifiers, block names, etc.) are case insensitive, although + * their case is preserved when parsing the tree. * * See the Doomsday Wiki for an example of the syntax: * http://dengine.net/dew/index.php?title=Info * * This implementation is based on a C++ port of cfparser.py from Snowberry. + * @ingroup data * * @todo Should use de::Lex internally. */ @@ -97,7 +100,12 @@ class DENG2_PUBLIC Info DENG2_AS_IS_METHODS() - void setName(String const &name) { _name = name.toLower(); } + void setName(String const &name) { _name = name; } + + /// Convenience for case-insensitively checking if the name matches @a name. + bool isName(String const &name) const { + return !_name.compareWithoutCase(name); + } virtual ValueList values() const = 0; @@ -151,9 +159,9 @@ class DENG2_PUBLIC Info }; /** - * Contains other Elements, including other block elements. In addition to - * a name, each block may have a "block type", which is a case insensitive - * identifier. + * Contains other Elements, including other block elements. In addition to a name, + * each block may have a "block type", which is a lower case identifier (always + * forced to lower case). */ class DENG2_PUBLIC BlockElement : public Element { public: @@ -189,7 +197,7 @@ class DENG2_PUBLIC Info int size() const { return _contents.size(); } - bool contains(String const &name) { return _contents.contains(name); } + bool contains(String const &name) { return _contents.contains(name.toLower()); } void setBlockType(String const &bType) { _blockType = bType.toLower(); } @@ -226,7 +234,7 @@ class DENG2_PUBLIC Info private: Info &_info; String _blockType; - Contents _contents; + Contents _contents; // indexed in lower case ContentsInOrder _contentsInOrder; }; @@ -272,12 +280,19 @@ class DENG2_PUBLIC Info BlockElement const &root() const; + /** + * Finds an element by its path. Info paths use a colon ':' as separator. + * + * @param path Path of element (case insensitive). + * + * @return Element, or @c NULL. + */ Element const *findByPath(String const &path) const; /** * Finds the value of a key. * - * @param key Key to find. + * @param key Key to find (case insensitive). * @param value The value is returned here. * * @return @c true, if the key was found and @a value is valid. If @c diff --git a/doomsday/libdeng2/src/data/info.cpp b/doomsday/libdeng2/src/data/info.cpp index 55111ff0a9..1bf6b6db7d 100644 --- a/doomsday/libdeng2/src/data/info.cpp +++ b/doomsday/libdeng2/src/data/info.cpp @@ -599,13 +599,13 @@ void Info::BlockElement::add(Info::Element *elem) _contentsInOrder.append(elem); // owned if(!elem->name().isEmpty()) { - _contents.insert(elem->name(), elem); // not owned (name may be empty) + _contents.insert(elem->name().toLower(), elem); // not owned (name may be empty) } } Info::Element *Info::BlockElement::find(String const &name) const { - Contents::const_iterator found = _contents.find(name); + Contents::const_iterator found = _contents.find(name.toLower()); if(found == _contents.end()) return 0; return found.value(); } diff --git a/doomsday/tests/test_info/test_info.dei b/doomsday/tests/test_info/test_info.dei index 5a83ab9fc6..d7881a0a4c 100644 --- a/doomsday/tests/test_info/test_info.dei +++ b/doomsday/tests/test_info/test_info.dei @@ -71,9 +71,12 @@ group font { } } - # Identifiers are all case insensitive. - Font "Title" inherits font.default { - Size: 24pt - Weight $: if __this__.weight == "normal": "bold"; else: "normal" + # Identifiers retain case in script namespaces (and are case + # sensitive), however group types are forced lower case (FoNt==font). + FoNt "Title" inherits font.Default { + SIZE: 24pt + weight $: if __this__.weight == "normal": "bold"; else: "normal" } } + +script { print "Title font:\n", font.Title }