From a582163d380833b1370ba067a1fd0ad5c2984723 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Thu, 4 Feb 2010 10:18:10 +0000 Subject: [PATCH] Rewrite the type system 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 | 12 ++--- source/binarywriter.cpp | 66 ++++++++++++------------- source/binarywriter.h | 3 +- source/loaderaction.h | 4 +- source/statement.cpp | 27 +++++++++-- source/statement.h | 14 ++++-- source/textparser.cpp | 15 +++--- source/textwriter.cpp | 18 ++++--- source/type.h | 104 ++++++++++++++++++++++++++++++++++++++++ source/value.h | 82 +++++++++++-------------------- tool/compiler.cpp | 9 ++-- 11 files changed, 229 insertions(+), 125 deletions(-) create mode 100644 source/type.h diff --git a/source/binaryparser.cpp b/source/binaryparser.cpp index ed1d71c..4d510c5 100644 --- a/source/binaryparser.cpp +++ b/source/binaryparser.cpp @@ -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; } } diff --git a/source/binarywriter.cpp b/source/binarywriter.cpp index 0e118c9..09e36c0 100644 --- a/source/binarywriter.cpp +++ b/source/binarywriter.cpp @@ -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()); break; - case STRING: write_string(j->get()); break; - case BOOLEAN: write_int (j->get()); break; - case FLOAT: write_float (j->get()); break; - case ENUM: write_enum (j->get_raw()); break; + case IntType::signature: write_int (j->get()); break; + case StringType::signature: write_string(j->get()); break; + case BoolType::signature: write_int (j->get()); break; + case FloatType::signature: write_float (j->get()); break; + case SymbolType::signature: write_enum (j->get()); 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().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(); + 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::const_iterator i = st.sub.begin(); i!=st.sub.end(); ++i) diff --git a/source/binarywriter.h b/source/binarywriter.h index c3a2b4c..15a88a3 100644 --- a/source/binarywriter.h +++ b/source/binarywriter.h @@ -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); diff --git a/source/loaderaction.h b/source/loaderaction.h index ff478ec..972757b 100644 --- a/source/loaderaction.h +++ b/source/loaderaction.h @@ -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 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()); (dynamic_cast(l).*func)(values); } diff --git a/source/statement.cpp b/source/statement.cpp index d485a20..a1bd688 100644 --- a/source/statement.cpp +++ b/source/statement.cpp @@ -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 #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 diff --git a/source/statement.h b/source/statement.h index efc097b..e7e9861 100644 --- a/source/statement.h +++ b/source/statement.h @@ -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 Arguments; + std::string keyword; - ValueArray args; + Arguments args; bool valid; std::string source; unsigned line; std::list 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 Statement &append(const T &v) { - args.push_back(Value(v)); + args.push_back(v); return *this; } diff --git a/source/textparser.cpp b/source/textparser.cpp index d8e422e..8bcde35 100644 --- a/source/textparser.cpp +++ b/source/textparser.cpp @@ -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(token.str)); else if(token.type==Token::FLOAT) - result.args.push_back(Value(FLOAT, token.str)); + result.append(lexical_cast(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()); diff --git a/source/textwriter.cpp b/source/textwriter.cpp index 2768462..08909a1 100644 --- a/source/textwriter.cpp +++ b/source/textwriter.cpp @@ -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() ? "true" : "false"); - else - out.write(i->get_raw()); + if(i->get_signature()==StringType::signature) + IO::print(out, "\"%s\"", c_escape(i->get(), false)); + else if(i->get_signature()==BoolType::signature) + out.write(i->get() ? "true" : "false"); + else if(i->get_signature()==IntType::signature) + out.write(lexical_cast(i->get())); + else if(i->get_signature()==FloatType::signature) + out.write(format("%15g", (i->get()))); + else if(i->get_signature()==SymbolType::signature) + out.write(i->get().name); } if(!st.sub.empty()) { diff --git a/source/type.h b/source/type.h new file mode 100644 index 0000000..5a87a10 --- /dev/null +++ b/source/type.h @@ -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 + +namespace Msp { +namespace DataFile { + +struct Symbol +{ + std::string name; + + Symbol(const std::string &n): name(n) { } + + template operator T() const { return lexical_cast(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 +struct TypeInfo: SymbolType { }; + +template<> +struct TypeInfo: IntType { }; + +template<> +struct TypeInfo: IntType { }; + +template<> +struct TypeInfo: IntType { }; + +template<> +struct TypeInfo: IntType { }; + +template<> +struct TypeInfo: IntType { }; + +template<> +struct TypeInfo: IntType { }; + +template<> +struct TypeInfo: IntType { }; + +template<> +struct TypeInfo: IntType { }; + +template<> +struct TypeInfo: FloatType { }; + +template<> +struct TypeInfo: FloatType { }; + +template<> +struct TypeInfo: BoolType { }; + +template<> +struct TypeInfo: StringType { }; + +template +struct TypeInfo: TypeInfo { }; + +template +struct TypeInfo: TypeInfo { }; + +} // namespace DataFile +} // namespace Msp + +#endif diff --git a/source/value.h b/source/value.h index ace1894..1b12db9 100644 --- a/source/value.h +++ b/source/value.h @@ -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 -#include +#include +#include #include "except.h" +#include "type.h" namespace Msp { namespace DataFile { -enum Type -{ - INTEGER, - FLOAT, - STRING, - BOOLEAN, - ENUM -}; - -template struct TypeResolver { static const Type type=ENUM; }; -template<> struct TypeResolver { static const Type type=INTEGER; }; -template<> struct TypeResolver { static const Type type=INTEGER; }; -template<> struct TypeResolver { static const Type type=INTEGER; }; -template<> struct TypeResolver { static const Type type=INTEGER; }; -template<> struct TypeResolver { static const Type type=INTEGER; }; -template<> struct TypeResolver { static const Type type=INTEGER; }; -template<> struct TypeResolver { static const Type type=INTEGER; }; -template<> struct TypeResolver { static const Type type=INTEGER; }; -template<> struct TypeResolver { static const Type type=FLOAT; }; -template<> struct TypeResolver { static const Type type=FLOAT; }; -template<> struct TypeResolver { static const Type type=BOOLEAN; }; -template<> struct TypeResolver { static const Type type=STRING; }; -template struct TypeResolver { static const Type type=TypeResolver::type; }; -template struct TypeResolver { static const Type type=TypeResolver::type; }; -template struct TypeResolver { static const Type type=TypeResolver::type; }; - class Value { -public: - Value(Type t, const std::string &d): type(t), data(d) { } +private: + char sig; + Variant data; +public: template - Value(T d): type(TypeResolver::type), data(lexical_cast(d)) { } + Value(T d): + sig(TypeInfo::signature), + data(static_cast::Store>(d)) + { } + + Value(Symbol d): sig(TypeInfo::signature), data(d) { } template - T get() const; + typename RemoveReference::Type get() const + { return get_::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 + T get_() const; }; -typedef std::vector ValueArray; - -template inline bool check_type(Type t) { return t==T; } -template<> inline bool check_type(Type t) { return t==INTEGER || t==FLOAT; } +typedef std::vector ValueArray __attribute__((deprecated)); template -inline T Value::get() const +inline T Value::get_() const { - if(!check_type::type>(type)) + if(sig!=TypeInfo::signature) throw TypeError("Type mismatch"); - return lexical_cast(data); + return data.value::Store>(); } template<> -inline std::string Value::get() const +inline FloatType::Store Value::get_() const { - if(type!=STRING) + if(sig==IntType::signature) + return data.value(); + else if(sig!=FloatType::signature) throw TypeError("Type mismatch"); - return data; -} -template<> -inline const std::string &Value::get() const -{ - if(type!=STRING) - throw TypeError("Type mismatch"); - return data; + return data.value(); } } // namespace DataFile diff --git a/tool/compiler.cpp b/tool/compiler.cpp index 8c280c4..03328e8 100644 --- a/tool/compiler.cpp +++ b/tool/compiler.cpp @@ -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::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(); + 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; -- 2.43.0