]> git.tdb.fi Git - libs/datafile.git/commitdiff
Rewrite the type system
authorMikko Rasa <tdb@tdb.fi>
Thu, 4 Feb 2010 10:18:10 +0000 (10:18 +0000)
committerMikko Rasa <tdb@tdb.fi>
Thu, 4 Feb 2010 10:18:10 +0000 (10:18 +0000)
Values are now stored as native types instead of strings
Value stores its signature instead of an arbitary enum value
Statement can now report its signature directly

source/binaryparser.cpp
source/binarywriter.cpp
source/binarywriter.h
source/loaderaction.h
source/statement.cpp
source/statement.h
source/textparser.cpp
source/textwriter.cpp
source/type.h [new file with mode: 0644]
source/value.h
tool/compiler.cpp

index ed1d71c8b197db64366e5e858b35ff032bc9b8df..4d510c58c0347a85aa0c13cb9b5603ca6debcf1e 100644 (file)
@@ -74,20 +74,20 @@ Statement BinaryParser::parse_statement()
        {
                switch(de.args[j])
                {
-               case 'i':
+               case IntType::signature:
                        result.args.push_back(parse_int());
                        break;
-               case 'f':
+               case FloatType::signature:
                        result.args.push_back(parse_float());
                        break;
-               case 's':
+               case StringType::signature:
                        result.args.push_back(parse_string());
                        break;
-               case 'b':
+               case BoolType::signature:
                        result.args.push_back(parse_bool());
                        break;
-               case 'e':
-                       result.args.push_back(Value(ENUM, parse_enum()));
+               case SymbolType::signature:
+                       result.args.push_back(Symbol(parse_enum()));
                        break;
                }
        }
index 0e118c9eb0ceb4542eda97752633e8f95848f9ef..09e36c0085be33c8ad7c0ff0eb5c8a611ca33a95 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of libmspdatafile
-Copyright © 2006  Mikko Rasa, Mikkosoft Productions
+Copyright © 2007-2008, 2010  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
@@ -30,19 +30,19 @@ void BinaryWriter::write(const Statement &st)
 
 void BinaryWriter::write_(const Statement &st)
 {
-       Dictionary::iterator i = dict.find(create_entry(st));
+       Dictionary::iterator i = dict.find(DictEntry(st.keyword, st.get_signature()));
        if(i==dict.end())
                throw InvalidParameterValue("Unknown statement");
 
        write_int(i->second);
-       for(ValueArray::const_iterator j = st.args.begin(); j!=st.args.end(); ++j)
-               switch(j->get_type())
+       for(Statement::Arguments::const_iterator j = st.args.begin(); j!=st.args.end(); ++j)
+               switch(j->get_signature())
                {
-               case INTEGER: write_int   (j->get<long long>()); break;
-               case STRING:  write_string(j->get<const string &>()); break;
-               case BOOLEAN: write_int   (j->get<bool>()); break;
-               case FLOAT:   write_float (j->get<float>()); break;
-               case ENUM:    write_enum  (j->get_raw()); break;
+               case IntType::signature:    write_int   (j->get<IntType::Store>()); break;
+               case StringType::signature: write_string(j->get<StringType::Store>()); break;
+               case BoolType::signature:   write_int   (j->get<BoolType::Store>()); break;
+               case FloatType::signature:  write_float (j->get<FloatType::Store>()); break;
+               case SymbolType::signature: write_enum  (j->get<SymbolType::Store>()); break;
                }
 
        write_int(st.sub.size());
@@ -50,24 +50,9 @@ void BinaryWriter::write_(const Statement &st)
                write(*j);
 }
 
-DictEntry BinaryWriter::create_entry(const Statement &st)
-{
-       static const char types[] = "ifsbe";
-
-       string args;
-       for(ValueArray::const_iterator i = st.args.begin(); i!=st.args.end(); ++i)
-       {
-               if(i->get_type()>=5)
-                       throw InvalidParameterValue("Invalid argument type");
-               args += types[i->get_type()];
-       }
-
-       return DictEntry(st.keyword, args);
-}
-
 void BinaryWriter::collect_keywords(const Statement &st)
 {
-       DictEntry de = create_entry(st);
+       DictEntry de(st.keyword, st.get_signature());
 
        if(!dict.count(de))
        {
@@ -83,18 +68,29 @@ void BinaryWriter::collect_keywords(const Statement &st)
 
        for(ValueArray::const_iterator i = st.args.begin(); i!=st.args.end(); ++i)
        {
-               const Type t = i->get_type();
-               const string &r = i->get_raw();
-               if((t==ENUM || (t==STRING && r.size()<32)) && !strings.count(r))
+               char sig = i->get_signature();
+               string str;
+               if(sig==SymbolType::signature)
+                       str = i->get<Symbol>().name;
+               else if(sig==StringType::signature)
                {
-                       Statement sst;
-                       sst.keyword = "__str";
-                       sst.args.push_back(next_str_id);
-                       sst.args.push_back(r);
-                       write_(sst);
-
-                       strings[r] = next_str_id++;
+                       str = i->get<string>();
+                       if(str.size()>32)
+                               continue;
                }
+               else
+                       continue;
+
+               if(strings.count(str))
+                       continue;
+
+               Statement sst;
+               sst.keyword = "__str";
+               sst.args.push_back(next_str_id);
+               sst.args.push_back(str);
+               write_(sst);
+
+               strings[str] = next_str_id++;
        }
 
        for(list<Statement>::const_iterator i = st.sub.begin(); i!=st.sub.end(); ++i)
index c3a2b4c96d082b8ef42a642bc2866352a2307750..15a88a391da8f7e07b775f971300834e46378ad8 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of libmspdatafile
-Copyright © 2006  Mikko Rasa, Mikkosoft Productions
+Copyright © 2007-2008, 2010  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
@@ -34,7 +34,6 @@ public:
        void write(const Statement &st);
 private:
        void write_(const Statement &st);
-       DictEntry create_entry(const Statement &st);
        void collect_keywords(const Statement &st);
        void write_int(long long n);
        void write_string(const std::string &s);
index ff478ec2df7aa8ed651914922516781e3f519278..972757bd399fbc953cd65100567eca343cf99d7b 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of libmspdatafile
-Copyright © 2006-2008  Mikko Rasa, Mikkosoft Productions
+Copyright © 2008, 2010  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
@@ -86,7 +86,7 @@ public:
        {
                std::vector<A0> values;
                values.reserve(st.args.size());
-               for(ValueArray::const_iterator i=st.args.begin(); i!=st.args.end(); ++i)
+               for(Statement::Arguments::const_iterator i=st.args.begin(); i!=st.args.end(); ++i)
                        values.push_back(i->get<A0>());
                (dynamic_cast<L &>(l).*func)(values);
        }
index d485a20a80f27f1f082c1cc3e400fdb03c46023a..a1bd688bf38016b24e326ce2e863cc6f76f51fd8 100644 (file)
@@ -1,23 +1,44 @@
 /* $Id: statement.h 19 2007-08-21 14:11:23Z tdb $
 
 This file is part of libmspdatafile
-Copyright © 2006  Mikko Rasa, Mikkosoft Productions
+Copyright © 2007, 2010  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
 #include <msp/strings/formatter.h>
 #include "statement.h"
 
+using namespace std;
+
 namespace Msp {
 namespace DataFile {
 
-std::string Statement::get_location() const
+Statement::Statement():
+       valid(false),
+       line(0)
+{ }
+
+Statement::Statement(const string &kw):
+       keyword(kw),
+       valid(true),
+       line(0)
+{ }
+
+string Statement::get_location() const
 {
-       std::string result = source;
+       string result = source;
        if(line)
                result += format(":%d", line);
        return result;
 }
 
+string Statement::get_signature() const
+{
+       string result;
+       for(Arguments::const_iterator i = args.begin(); i!=args.end(); ++i)
+               result += i->get_signature();
+       return result;
+}
+
 } // namespace DataFile
 } // namespace Msp
index efc097bd7e11b4c100627fbd9dcf8a5776433cc0..e7e9861cf8f803509e6e28b199dcf3c80e3d632e 100644 (file)
@@ -1,9 +1,10 @@
 /* $Id$
 
 This file is part of libmspdatafile
-Copyright © 2006  Mikko Rasa, Mikkosoft Productions
+Copyright © 2006-2008, 2010  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
+
 #ifndef MSP_DATAFILE_STATEMENT_H_
 #define MSP_DATAFILE_STATEMENT_H_
 
@@ -16,21 +17,24 @@ namespace DataFile {
 class Statement
 {
 public:
+       typedef std::vector<Value> Arguments;
+
        std::string keyword;
-       ValueArray  args;
+       Arguments   args;
        bool        valid;
        std::string source;
        unsigned    line;
        std::list<Statement> sub;
 
-       Statement(): valid(false), line(0) { }
-       Statement(const std::string &kw): keyword(kw), valid(true), line(0) { }
+       Statement();
+       Statement(const std::string &);
        std::string get_location() const;
+       std::string get_signature() const;
        
        template<typename T>
        Statement &append(const T &v)
        {
-               args.push_back(Value(v));
+               args.push_back(v);
                return *this;
        }
 
index d8e422ee7ff4d4d710a764a62383955f377305f5..8bcde35802108ba2f16c32584e6ace17b1e33ee9 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of libmspdatafile
-Copyright © 2007-2008  Mikko Rasa, Mikkosoft Productions
+Copyright © 2007-2008, 2010  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
@@ -77,20 +77,19 @@ Statement TextParser::parse_statement(const Token *t)
                else if(token.str==";")
                        break;
                else if(token.type==Token::INTEGER)
-                       result.args.push_back(Value(INTEGER, token.str));
+                       result.append(lexical_cast<IntType::Store>(token.str));
                else if(token.type==Token::FLOAT)
-                       result.args.push_back(Value(FLOAT, token.str));
+                       result.append(lexical_cast<FloatType::Store>(token.str));
                else if(token.type==Token::STRING)
-                       result.args.push_back(Value(STRING, token.str));
+                       result.append(token.str);
                else if(token.type==Token::IDENTIFIER)
                {
                        if(token.str=="true")
-                               result.args.push_back(Value(BOOLEAN, "1"));
+                               result.append(true);
                        else if(token.str=="false")
-                               result.args.push_back(Value(BOOLEAN, "0"));
+                               result.append(false);
                        else
-                               result.args.push_back(Value(ENUM, token.str));
-                       //result.args.push_back(resolve_identifiertoken.str);
+                               result.append(Symbol(token.str));
                }
                else if(token.str=="")
                        throw_at(ParseError("Unexcepted end of input"), get_location());
index 2768462297e6fed397e31b8a7ae58e96b3110113..08909a1c6ed952b190754063d628f4e0e3dbe3dc 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of libmspdatafile
-Copyright © 2006  Mikko Rasa, Mikkosoft Productions
+Copyright © 2007-2008, 2010  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
@@ -32,12 +32,16 @@ void TextWriter::write_(const Statement &st, unsigned level)
        for(ValueArray::const_iterator i = st.args.begin(); i!=st.args.end(); ++i)
        {
                out.put(' ');
-               if(i->get_type()==STRING)
-                       IO::print(out, "\"%s\"", c_escape(i->get_raw(), false));
-               else if(i->get_type()==BOOLEAN)
-                       out.write(i->get<bool>() ? "true" : "false");
-               else
-                       out.write(i->get_raw());
+               if(i->get_signature()==StringType::signature)
+                       IO::print(out, "\"%s\"", c_escape(i->get<StringType::Store>(), false));
+               else if(i->get_signature()==BoolType::signature)
+                       out.write(i->get<BoolType::Store>() ? "true" : "false");
+               else if(i->get_signature()==IntType::signature)
+                       out.write(lexical_cast(i->get<IntType::Store>()));
+               else if(i->get_signature()==FloatType::signature)
+                       out.write(format("%15g", (i->get<FloatType::Store>())));
+               else if(i->get_signature()==SymbolType::signature)
+                       out.write(i->get<SymbolType::Store>().name);
        }
        if(!st.sub.empty())
        {
diff --git a/source/type.h b/source/type.h
new file mode 100644 (file)
index 0000000..5a87a10
--- /dev/null
@@ -0,0 +1,104 @@
+/* $Id$
+
+This file is part of libmspdatafile
+Copyright © 2010  Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef MSP_DATAFILE_TYPE_H_
+#define MSP_DATAFILE_TYPE_H_
+
+#include <msp/strings/lexicalcast.h>
+
+namespace Msp {
+namespace DataFile {
+
+struct Symbol
+{
+       std::string name;
+
+       Symbol(const std::string &n): name(n) { }
+
+       template<typename T> operator T() const { return lexical_cast<T>(name); }
+};
+
+struct IntType
+{
+       static const char signature = 'i';
+       typedef long long int Store;
+};
+
+struct FloatType
+{
+       static const char signature = 'f';
+       typedef double Store;
+};
+
+struct BoolType
+{
+       static const char signature = 'b';
+       typedef bool Store;
+};
+
+struct StringType
+{
+       static const char signature = 's';
+       typedef std::string Store;
+};
+
+struct SymbolType
+{
+       // For backward compatibility
+       static const char signature = 'e';
+       typedef Symbol Store;
+};
+
+template<typename T>
+struct TypeInfo: SymbolType { };
+
+template<>
+struct TypeInfo<short int>: IntType { };
+
+template<>
+struct TypeInfo<unsigned short int>: IntType { };
+
+template<>
+struct TypeInfo<int>: IntType { };
+
+template<>
+struct TypeInfo<unsigned int>: IntType { };
+
+template<>
+struct TypeInfo<long int>: IntType { };
+
+template<>
+struct TypeInfo<unsigned long int>: IntType { };
+
+template<>
+struct TypeInfo<long long int>: IntType { };
+
+template<>
+struct TypeInfo<unsigned long long int>: IntType { };
+
+template<>
+struct TypeInfo<float>: FloatType { };
+
+template<>
+struct TypeInfo<double>: FloatType { };
+
+template<>
+struct TypeInfo<bool>: BoolType { };
+
+template<>
+struct TypeInfo<std::string>: StringType { };
+
+template<typename T>
+struct TypeInfo<const T>: TypeInfo<T> { };
+
+template<typename T>
+struct TypeInfo<T &>: TypeInfo<T> { };
+
+} // namespace DataFile
+} // namespace Msp
+
+#endif
index ace18945cbc2ea39eb4bc395cc116c0016b8e7e0..1b12db9a22db5f40e77578199bdfd7817fff4093 100644 (file)
@@ -1,91 +1,67 @@
 /* $Id$
 
 This file is part of libmspdatafile
-Copyright © 2006  Mikko Rasa, Mikkosoft Productions
+Copyright © 2006-2008, 2010  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
+
 #ifndef MSP_DATAFILE_VALUE_H_
 #define MSP_DATAFILE_VALUE_H_
 
 #include <vector>
-#include <msp/strings/lexicalcast.h>
+#include <msp/core/meta.h>
+#include <msp/core/variant.h>
 #include "except.h"
+#include "type.h"
 
 namespace Msp {
 namespace DataFile {
 
-enum Type
-{
-       INTEGER,
-       FLOAT,
-       STRING,
-       BOOLEAN,
-       ENUM
-};
-
-template<typename T> struct TypeResolver       { static const Type type=ENUM; };
-template<> struct TypeResolver<short>          { static const Type type=INTEGER; };
-template<> struct TypeResolver<unsigned short> { static const Type type=INTEGER; };
-template<> struct TypeResolver<int>            { static const Type type=INTEGER; };
-template<> struct TypeResolver<unsigned>       { static const Type type=INTEGER; };
-template<> struct TypeResolver<long>           { static const Type type=INTEGER; };
-template<> struct TypeResolver<unsigned long>  { static const Type type=INTEGER; };
-template<> struct TypeResolver<long long>      { static const Type type=INTEGER; };
-template<> struct TypeResolver<unsigned long long> { static const Type type=INTEGER; };
-template<> struct TypeResolver<float>          { static const Type type=FLOAT; };
-template<> struct TypeResolver<double>         { static const Type type=FLOAT; };
-template<> struct TypeResolver<bool>           { static const Type type=BOOLEAN; };
-template<> struct TypeResolver<std::string>    { static const Type type=STRING; };
-template<typename T> struct TypeResolver<const T>   { static const Type type=TypeResolver<T>::type; };
-template<typename T> struct TypeResolver<T &>       { static const Type type=TypeResolver<T>::type; };
-template<typename T> struct TypeResolver<const T &> { static const Type type=TypeResolver<T>::type; };
-
 class Value
 {
-public:
-       Value(Type t, const std::string &d): type(t), data(d) { }
+private:
+       char sig;
+       Variant data;
 
+public:
        template<typename T>
-       Value(T d): type(TypeResolver<T>::type), data(lexical_cast(d)) { }
+       Value(T d):
+               sig(TypeInfo<T>::signature),
+               data(static_cast<typename TypeInfo<T>::Store>(d))
+       { }
+
+       Value(Symbol d): sig(TypeInfo<Symbol>::signature), data(d) { }
 
        template<typename T>
-       T get() const;
+       typename RemoveReference<T>::Type get() const
+       { return get_<typename TypeInfo<T>::Store>(); }
 
-       Type get_type() const { return type; }
-       const std::string &get_raw() const { return data; }
+       char get_signature() const { return sig; }
 private:
-       Type type;
-       std::string data;
+       template<typename T>
+       T get_() const;
 };
 
-typedef std::vector<Value> ValueArray;
-
-template<Type T> inline bool check_type(Type t)  { return t==T; }
-template<> inline bool check_type<FLOAT>(Type t) { return t==INTEGER || t==FLOAT; }
+typedef std::vector<Value> ValueArray __attribute__((deprecated));
 
 template<typename T>
-inline T Value::get() const
+inline T Value::get_() const
 {
-       if(!check_type<TypeResolver<T>::type>(type))
+       if(sig!=TypeInfo<T>::signature)
                throw TypeError("Type mismatch");
 
-       return lexical_cast<T>(data);
+       return data.value<typename TypeInfo<T>::Store>();
 }
 
 template<>
-inline std::string Value::get<std::string>() const
+inline FloatType::Store Value::get_<FloatType::Store>() const
 {
-       if(type!=STRING)
+       if(sig==IntType::signature)
+               return data.value<IntType::Store>();
+       else if(sig!=FloatType::signature)
                throw TypeError("Type mismatch");
-       return data;
-}
 
-template<>
-inline const std::string &Value::get<const std::string&>() const
-{
-       if(type!=STRING)
-               throw TypeError("Type mismatch");
-       return data;
+       return data.value<FloatType::Store>();
 }
 
 } // namespace DataFile
index 8c280c4a2ec2a3d0ec3ed07fd72235d15a8bc92c..03328e85ff369c6eed1981083a8c6415a15338fe 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of libmspdatafile
-Copyright © 2008  Mikko Rasa, Mikkosoft Productions
+Copyright © 2008, 2010  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
@@ -53,11 +53,12 @@ bool Compiler::process_statement(const FS::Path &fn, DataFile::Statement &st)
                return true;
 
        for(vector<DataFile::Value>::iterator i = st.args.begin(); i!=st.args.end(); ++i)
-               if(i->get_type()==DataFile::STRING)
+               if(i->get_signature()==DataFile::StringType::signature)
                {
-                       if(i->get_raw()=="$filename")
+                       string value = i->get<string>();
+                       if(value=="$filename")
                                *i = DataFile::Value(FS::basename(fn.str()));
-                       else if(i->get_raw()=="$content")
+                       else if(value=="$content")
                        {
                                IO::File in(fn.str());
                                string data;