]> git.tdb.fi Git - libs/datafile.git/commitdiff
Add reverse name lookup to Collection
authorMikko Rasa <tdb@tdb.fi>
Tue, 22 Jul 2008 15:34:59 +0000 (15:34 +0000)
committerMikko Rasa <tdb@tdb.fi>
Tue, 22 Jul 2008 15:34:59 +0000 (15:34 +0000)
Make the two-parameter global load function take a reference as the second parameter
Use numeric IDs for short strings in binary mode

source/binaryparser.cpp
source/binaryparser.h
source/binarywriter.cpp
source/binarywriter.h
source/collection.h
source/loader.h

index b55c7af3e1a8c76bc8f6c2c0855a4cea6fea7e17..214c35e70d3793437e786f90d0f99fd60a1fbd66 100644 (file)
@@ -19,8 +19,8 @@ BinaryParser::BinaryParser(Input &i, const string &s):
        ParserMode(i, s),
        first(true)
 {
-       dict[1]=DictEntry("__st", "iss");
-       dict[2]=DictEntry("__enum", "is");
+       dict[1]=DictEntry("__kwd", "iss");
+       dict[2]=DictEntry("__str", "is");
 }
 
 Statement BinaryParser::parse()
@@ -28,7 +28,7 @@ Statement BinaryParser::parse()
        while(1)
        {
                Statement st=parse_statement();
-               if(st.keyword=="__st")
+               if(st.keyword=="__kwd")
                {
                        if(st.args.size()!=3)
                                throw TypeError(src+": Keyword definition must have three arguments");
@@ -38,13 +38,13 @@ Statement BinaryParser::parse()
                        const string &args=st.args[2].get<const string &>();
                        dict[id]=DictEntry(kw, args);
                }
-               else if(st.keyword=="__enum")
+               else if(st.keyword=="__str")
                {
                        if(st.args.size()!=2)
-                               throw TypeError(src+": Enum definition must have three arguments");
+                               throw TypeError(src+": String definition must have two arguments");
 
                        const unsigned id=st.args[0].get<unsigned>();
-                       enums[id]=st.args[1].get<const std::string &>();
+                       strings[id]=st.args[1].get<const string &>();
                }
                else
                        return st;
@@ -117,7 +117,7 @@ long long BinaryParser::parse_int()
                        break;
        }
 
-       const long long mask=1<<(bits-1);
+       const long long mask=1LL<<(bits-1);
        result=(result^mask)-mask;
 
        return result;
@@ -149,20 +149,29 @@ bool BinaryParser::parse_bool()
 
 string BinaryParser::parse_string()
 {
-       unsigned len=parse_int();
-       string result;
-       result.reserve(len);
-       for(unsigned i=0; i<len; ++i)
-               result+=in.get();
-       return result;
+       int len=parse_int();
+       if(len>=0)
+       {
+               string result;
+               result.reserve(len);
+               for(int i=0; i<len; ++i)
+                       result+=in.get();
+               return result;
+       }
+       else
+               return lookup_string(-len);
 }
 
 string BinaryParser::parse_enum()
 {
-       unsigned id=parse_int();
-       EnumMap::iterator i=enums.find(id);
-       if(i==enums.end())
-               throw KeyError("Unknown enum", lexical_cast(id));
+       return lookup_string(parse_int());
+}
+
+const string &BinaryParser::lookup_string(unsigned id) const
+{
+       StringMap::const_iterator i=strings.find(id);
+       if(i==strings.end())
+               throw KeyError("Unknown string", lexical_cast(id));
        return i->second;
 }
 
index f1d51b236edc8b192c3644574905775c7cf9b9da..26fa380e4e290b67c4172449a009cc47991b5efc 100644 (file)
@@ -22,10 +22,10 @@ class BinaryParser: public ParserMode
 {
 private:
        typedef std::map<unsigned, DictEntry> Dictionary;
-       typedef std::map<unsigned, std::string> EnumMap;
+       typedef std::map<unsigned, std::string> StringMap;
 
        Dictionary dict;
-       EnumMap enums;
+       StringMap strings;
        bool first;
 
 public:
@@ -38,6 +38,7 @@ private:
        std::string parse_string();
        bool parse_bool();
        std::string parse_enum();
+       const std::string &lookup_string(unsigned) const;
 };
 
 } // namespace DataFile
index dd63d3dcefa03e32efd83af1f30b096e9ba54718..98dd2a9635317d56986ebff812867c263e25d5b9 100644 (file)
@@ -15,11 +15,11 @@ namespace DataFile {
 
 BinaryWriter::BinaryWriter(IO::Base &o):
        WriterMode(o),
-       next_st_id(3),
-       next_enum_id(1)
+       next_kwd_id(3),
+       next_str_id(1)
 {
-       dict[DictEntry("__st", "iss")]=1;
-       dict[DictEntry("__enum", "is")]=2;
+       dict[DictEntry("__kwd", "iss")]=1;
+       dict[DictEntry("__str", "is")]=2;
 }
 
 void BinaryWriter::write(const Statement &st)
@@ -72,26 +72,30 @@ void BinaryWriter::collect_keywords(const Statement &st)
        if(!dict.count(de))
        {
                Statement kst;
-               kst.keyword="__st";
-               kst.args.push_back(next_st_id);
+               kst.keyword="__kwd";
+               kst.args.push_back(next_kwd_id);
                kst.args.push_back(de.keyword);
                kst.args.push_back(de.args);
                write_(kst);
 
-               dict[de]=next_st_id++;
+               dict[de]=next_kwd_id++;
        }
 
        for(ValueArray::const_iterator i=st.args.begin(); i!=st.args.end(); ++i)
-               if(i->get_type()==ENUM && !enums.count(i->get_raw()))
+       {
+               const Type t=i->get_type();
+               const string &r=i->get_raw();
+               if((t==ENUM || (t==STRING && r.size()<32)) && !strings.count(r))
                {
-                       Statement est;
-                       est.keyword="__enum";
-                       est.args.push_back(next_enum_id);
-                       est.args.push_back(i->get_raw());
-                       write_(est);
+                       Statement sst;
+                       sst.keyword="__str";
+                       sst.args.push_back(next_str_id);
+                       sst.args.push_back(r);
+                       write_(sst);
 
-                       enums[i->get_raw()]=next_enum_id++;
+                       strings[r]=next_str_id++;
                }
+       }
 
        for(list<Statement>::const_iterator i=st.sub.begin(); i!=st.sub.end(); ++i)
                collect_keywords(*i);
@@ -112,8 +116,14 @@ void BinaryWriter::write_int(long long n)
 
 void BinaryWriter::write_string(const string &s)
 {
-       write_int(s.size());
-       out.write(s.data(), s.size());
+       StringMap::const_iterator i=strings.find(s);
+       if(i!=strings.end())
+               write_int(-static_cast<int>(i->second));
+       else
+       {
+               write_int(s.size());
+               out.write(s.data(), s.size());
+       }
 }
 
 void BinaryWriter::write_float(float f)
@@ -136,8 +146,8 @@ void BinaryWriter::write_float(float f)
 
 void BinaryWriter::write_enum(const string &e)
 {
-       EnumMap::const_iterator i=enums.find(e);
-       if(i==enums.end())
+       StringMap::const_iterator i=strings.find(e);
+       if(i==strings.end())
                throw InvalidParameterValue("Unknown enum");
        write_int(i->second);
 }
index 118f66b0d6cebdf75ea1d985a60e2ca66d9c6d50..c3a2b4c96d082b8ef42a642bc2866352a2307750 100644 (file)
@@ -22,12 +22,12 @@ class BinaryWriter: public WriterMode
 {
 private:
        typedef std::map<DictEntry, unsigned> Dictionary;
-       typedef std::map<std::string, unsigned> EnumMap;
+       typedef std::map<std::string, unsigned> StringMap;
 
        Dictionary dict;
-       unsigned next_st_id;
-       EnumMap enums;
-       unsigned next_enum_id;
+       unsigned next_kwd_id;
+       StringMap strings;
+       unsigned next_str_id;
 
 public:
        BinaryWriter(IO::Base &o);
index 303697a8c726f7c71e99c3a8d8e6582be998b87b..fa3a7de9dbe25441417f988fbe16a5235cbf638d 100644 (file)
@@ -284,6 +284,22 @@ public:
        */
        bool contains(const std::string &n) const;
 
+       /**
+       Returns the name of an item in the collection.
+       */
+       template<typename T>
+       const std::string &get_name(T *d) const
+       {
+               typedef typename RemoveConst<T>::Type NCT;
+
+               for(ItemMap::const_iterator i=items.begin(); i!=items.end(); ++i)
+                       if(Item<NCT> *item=dynamic_cast<Item<NCT> *>(i->second))
+                               if(item->data==d)
+                                       return i->first;
+       
+               throw KeyError("Item not found in collection");
+       }
+
 protected:
        /**
        Adds a type that can be loaded from datafiles.
index 5f4037c73dbedbe846cd13213b31784b1510df2d..5b39212e53c32beceda2cc3227109dc9eb4c9b6c 100644 (file)
@@ -361,7 +361,7 @@ void load(T &obj, const std::string &fn)
 }
 
 template<typename T, typename U>
-void load(T &obj, const std::string &fn, U arg)
+void load(T &obj, const std::string &fn, U &arg)
 {
        IO::File in(fn);
        IO::Buffered buf(in);