]> git.tdb.fi Git - libs/datafile.git/blobdiff - source/binaryparser.cpp
Cosmetic changes
[libs/datafile.git] / source / binaryparser.cpp
index 25edd63a15060d96bb5bcc95775cc3241dc9ce36..11e0badaaa5c148cd37e53659a8119114fae29d9 100644 (file)
@@ -1,56 +1,50 @@
 #include <limits>
-#include <sys/param.h>
 #include <msp/core/maputils.h>
 #include <msp/strings/format.h>
+#include "argumentstore.h"
 #include "binaryparser.h"
 #include "binfloat.h"
+#include "except.h"
 #include "input.h"
+#include "loaderaction.h"
 
 using namespace std;
 
 namespace Msp {
 namespace DataFile {
 
-class bad_definition: public runtime_error
-{
-public:
-       bad_definition(const std::string &w):
-               runtime_error(w)
-       { }
-
-       virtual ~bad_definition() throw() { }
-};
-
-
 BinaryParser::BinaryParser(Input &i, const string &s):
-       ParserMode(i, s),
-       first(true),
-       float_precision(32)
+       ParserMode(i, s)
 {
-       dict[-1] = StatementKey("__kwd", "iss");
-       dict[-2] = StatementKey("__str", "is");
-       dict[-3] = StatementKey("__flt", "i");
+       dict[-1] = StatementInfo("__kwd", "iss");
+       dict[-2] = StatementInfo("__str", "is");
+       dict[-3] = StatementInfo("__flt", "i");
 }
 
 Statement BinaryParser::parse()
 {
-       while(first && in.peek()=='\n')
-               in.get();
-       first = false;
-
-       int id = parse_int();
-       if(!in)
-               return Statement();
+       const StatementKey *key;
+       if(cur_info)
+       {
+               key = &cur_info->key;
+               cur_info = nullptr;
+       }
+       else
+       {
+               int id = parse_int();
+               if(!in)
+                       return Statement();
 
-       const StatementKey &key = get_item(dict, id);
+               key = &get_item(dict, id).key;
+       }
 
        Statement result;
-       result.keyword = key.keyword;
+       result.keyword = key->keyword;
        result.source = src;
 
-       for(unsigned j=0; j<key.signature.size(); ++j)
+       for(unsigned j=0; j<key->signature.size(); ++j)
        {
-               switch(key.signature[j])
+               switch(key->signature[j])
                {
                case IntType::signature:
                        result.args.push_back(parse_int());
@@ -65,15 +59,20 @@ Statement BinaryParser::parse()
                        result.args.push_back(parse_bool());
                        break;
                case SymbolType::signature:
-                       result.args.push_back(parse_symbol());
+                       result.args.push_back(Value(parse_symbol()));
                        break;
                }
        }
 
+       unsigned upper_nsub = (sub_remaining.empty() ? 0 : sub_remaining.back());
+
        unsigned nsub = parse_int();
        for(unsigned j = 0; j<nsub; ++j)
                result.sub.push_back(parse());
 
+       if(upper_nsub>0)
+               sub_remaining.back() = upper_nsub-1;
+
        result.valid = true;
 
        return result;
@@ -89,12 +88,12 @@ void BinaryParser::process_control_statement(const Statement &st)
 
                const string &kw = st.args[1].get<const string &>();
                const string &args = st.args[2].get<const string &>();
-               for(string::const_iterator i=args.begin(); i!=args.end(); ++i)
-                       for(unsigned j=0; valid_signatures[j]!=*i; ++j)
+               for(char c: args)
+                       for(unsigned j=0; valid_signatures[j]!=c; ++j)
                                if(!valid_signatures[j])
                                        throw bad_definition("__kwd");
 
-               dict[id] = StatementKey(kw, args);
+               dict[id] = StatementInfo(kw, args);
        }
        else if(st.keyword=="__str")
        {
@@ -108,6 +107,73 @@ void BinaryParser::process_control_statement(const Statement &st)
                float_precision = st.args[0].get<unsigned>();
 }
 
+const StatementKey *BinaryParser::peek(unsigned level)
+{
+       if(level>sub_remaining.size())
+               throw nesting_error("bad level");
+       while(level<sub_remaining.size())
+       {
+               // Discard any substatements that haven't been parsed yet
+               for(unsigned i=sub_remaining.back(); i-->0; )
+                       parse();
+               sub_remaining.pop_back();
+               cur_info = nullptr;
+       }
+
+       if(!sub_remaining.empty() && sub_remaining.back()==0)
+       {
+               // No more substatements on this level
+               cur_info = nullptr;
+               return nullptr;
+       }
+
+       if(cur_info)
+               return &cur_info->key;
+
+       int id = parse_int();
+       if(!in)
+               return nullptr;
+
+       cur_info = &get_item(dict, id);
+       return &cur_info->key;
+}
+
+bool BinaryParser::parse_and_load(unsigned level, Loader &ldr, const LoaderAction &act)
+{
+       if(!cur_info && !peek(level))
+               return false;
+
+       ArgumentStore args(*cur_info);
+       for(unsigned i=0; i<cur_info->key.signature.size(); ++i)
+               switch(cur_info->key.signature[i])
+               {
+               case IntType::signature:
+                       args.set(i, parse_int());
+                       break;
+               case FloatType::signature:
+                       args.set(i, parse_float());
+                       break;
+               case BoolType::signature:
+                       args.set(i, parse_bool());
+                       break;
+               case StringType::signature:
+                       args.set(i, parse_string());
+                       break;
+               case SymbolType::signature:
+                       args.set(i, parse_symbol());
+                       break;
+               }
+
+       if(!sub_remaining.empty())
+               --sub_remaining.back();
+       sub_remaining.push_back(parse_int());
+       cur_info = nullptr;
+
+       act.execute(ldr, args);
+
+       return true;
+}
+
 IntType::Store BinaryParser::parse_int()
 {
        IntType::Store result = 0;
@@ -132,7 +198,7 @@ IntType::Store BinaryParser::parse_int()
 
 FloatType::Store BinaryParser::parse_float()
 {
-       UInt64 encoded = 0;
+       uint64_t encoded = 0;
        for(unsigned i=0; i<float_precision; i+=8)
        {
                int c = in.get();