Updated MicroConf: support quoted strings; handle tokenizer errors.
authorStefan Westerfeld <stefan@space.twc.de>
Tue, 18 May 2010 15:56:03 +0000 (17:56 +0200)
committerStefan Westerfeld <stefan@space.twc.de>
Tue, 18 May 2010 15:56:03 +0000 (17:56 +0200)
src/microconf.cc
src/microconf.hh

index fe431a8..6dba61b 100644 (file)
@@ -51,7 +51,7 @@ MicroConf::next()
   while (!current_line.empty() && is_newline (current_line[current_line.size() - 1]))
     current_line.resize (current_line.size() - 1);
 
-  tokenize();
+  tokenizer_error = !tokenize();
 
   return true;
 }
@@ -83,10 +83,10 @@ white_space (char ch)
   return (ch == ' ' || ch == '\n' || ch == '\t' || ch == '\r');
 }
 
-void
+bool
 MicroConf::tokenize()
 {
-  enum { BLANK, STRING, COMMENT } state = BLANK;
+  enum { BLANK, STRING, QUOTED_STRING, QUOTED_STRING_ESCAPED, COMMENT } state = BLANK;
   string s;
 
   string xline = current_line + '\n';
@@ -98,21 +98,52 @@ MicroConf::tokenize()
           state = STRING;
           s += *i;
         }
+      else if (state == BLANK && *i == '"')
+        {
+          state = QUOTED_STRING;
+        }
+      else if (state == BLANK && white_space (*i))
+        {
+          // ignore more whitespaces if we've already seen one
+        }
       else if (state == STRING && string_chars (*i))
         {
           s += *i;
         }
-      else if (state == STRING && white_space (*i))
+      else if (state == STRING && white_space (*i)
+           ||  state == QUOTED_STRING && *i == '"')
         {
           tokens.push_back (s);
           s = "";
           state = BLANK;
         }
+      else if (state == QUOTED_STRING && *i == '\\')
+        {
+          state = QUOTED_STRING_ESCAPED;
+        }
+      else if (state == QUOTED_STRING)
+        {
+          s += *i;
+        }
+      else if (state == QUOTED_STRING_ESCAPED)
+        {
+          s += *i;
+          state = QUOTED_STRING;
+        }
       else if (*i == '#')
         {
           state = COMMENT;
         }
+      else if (state == COMMENT)
+        {
+          // ignore comments
+        }
+      else
+        {
+          return false;
+        }
     }
+  return state == BLANK;
 }
 
 bool
index 107c44c..a9dae05 100644 (file)
@@ -29,12 +29,13 @@ private:
   int                      current_no;
   std::string              current_file;
   std::vector<std::string> tokens;
+  bool                     tokenizer_error;
 
   bool convert (const std::string& token, int& arg);
   bool convert (const std::string& token, double& arg);
   bool convert (const std::string& token, std::string& arg);
 
-  void tokenize();
+  bool tokenize();
 public:
   MicroConf (const std::string& filename);
 
@@ -45,14 +46,14 @@ public:
   template<class T1>
   bool command (const std::string& cmd, T1& arg1)
   {
-    if (tokens.size() != 2 || cmd != tokens[0])
+    if (tokenizer_error || tokens.size() != 2 || cmd != tokens[0])
       return false;
     return convert (tokens[1], arg1);
   }
   template<class T1, class T2>
   bool command (const std::string& cmd, T1& arg1, T2& arg2)
   {
-    if (tokens.size() != 3 || cmd != tokens[0])
+    if (tokenizer_error || tokens.size() != 3 || cmd != tokens[0])
       return false;
     return convert (tokens[1], arg1) && convert (tokens[2], arg2);
   }