JSON library for parser and serializer picojson is a header-file-only, JSON parser serializer in C . The original source code is available at https://github.com/kazuho/picojson

Dependents:   MotiV_ControlBox

Fork of picojson by mimil owns

Revision:
1:2bb500b021e2
Parent:
0:7bd1a48945f5
Child:
2:fa0776ec0f86
diff -r 7bd1a48945f5 -r 2bb500b021e2 picojson.h
--- a/picojson.h	Wed Aug 31 14:48:57 2011 +0000
+++ b/picojson.h	Tue Sep 06 16:49:40 2011 +0000
@@ -29,6 +29,7 @@
 #define picojson_h
 
 #include <cassert>
+#include <cmath>
 #include <cstdio>
 #include <cstdlib>
 #include <cstring>
@@ -164,9 +165,9 @@
     return *this;
   }
   
-#define IS(ctype, jtype)                 \
+#define IS(ctype, jtype)			     \
   template <> inline bool value::is<ctype>() const { \
-    return type_ == jtype##_type;             \
+    return type_ == jtype##_type;		     \
   }
   IS(null, null)
   IS(bool, boolean)
@@ -177,12 +178,12 @@
   IS(object, object)
 #undef IS
   
-#define GET(ctype, var)                          \
+#define GET(ctype, var)					      \
   template <> inline const ctype& value::get<ctype>() const { \
-    return var;                              \
-  }                                  \
-  template <> inline ctype& value::get<ctype>() {          \
-    return var;                              \
+    return var;						      \
+  }							      \
+  template <> inline ctype& value::get<ctype>() {	      \
+    return var;						      \
   }
   GET(bool, boolean_)
   GET(double, number_)
@@ -225,7 +226,8 @@
     case boolean_type:   return boolean_ ? "true" : "false";
     case number_type:    {
       char buf[256];
-      SNPRINTF(buf, sizeof(buf), "%f", number_);
+      double tmp;
+      SNPRINTF(buf, sizeof(buf), modf(number_, &tmp) == 0 ? "%.f" : "%f", number_);
       return buf;
     }
     case string_type:    return *string_;
@@ -247,24 +249,24 @@
     for (std::string::const_iterator i = s.begin(); i != s.end(); ++i) {
       switch (*i) {
 #define MAP(val, sym) case val: copy(sym, oi); break
-    MAP('"', "\\\"");
-    MAP('\\', "\\\\");
-    MAP('/', "\\/");
-    MAP('\b', "\\b");
-    MAP('\f', "\\f");
-    MAP('\n', "\\n");
-    MAP('\r', "\\r");
-    MAP('\t', "\\t");
+	MAP('"', "\\\"");
+	MAP('\\', "\\\\");
+	MAP('/', "\\/");
+	MAP('\b', "\\b");
+	MAP('\f', "\\f");
+	MAP('\n', "\\n");
+	MAP('\r', "\\r");
+	MAP('\t', "\\t");
 #undef MAP
       default:
-    if ((unsigned char)*i < 0x20 || *i == 0x7f) {
-      char buf[7];
-      SNPRINTF(buf, sizeof(buf), "\\u%04x", *i & 0xff);
-      copy(buf, buf + 6, oi);
-      } else {
-      *oi++ = *i;
-    }
-    break;
+	if ((unsigned char)*i < 0x20 || *i == 0x7f) {
+	  char buf[7];
+	  SNPRINTF(buf, sizeof(buf), "\\u%04x", *i & 0xff);
+	  copy(buf, buf + 6, oi);
+	  } else {
+	  *oi++ = *i;
+	}
+	break;
       }
     }
     *oi++ = '"';
@@ -278,10 +280,10 @@
     case array_type: {
       *oi++ = '[';
       for (array::const_iterator i = array_->begin(); i != array_->end(); ++i) {
-    if (i != array_->begin()) {
-      *oi++ = ',';
-    }
-    i->serialize(oi);
+	if (i != array_->begin()) {
+	  *oi++ = ',';
+	}
+	i->serialize(oi);
       }
       *oi++ = ']';
       break;
@@ -289,14 +291,14 @@
     case object_type: {
       *oi++ = '{';
       for (object::const_iterator i = object_->begin();
-       i != object_->end();
-       ++i) {
-    if (i != object_->begin()) {
-      *oi++ = ',';
-    }
-    serialize_str(i->first, oi);
-    *oi++ = ':';
-    i->second.serialize(oi);
+	   i != object_->end();
+	   ++i) {
+	if (i != object_->begin()) {
+	  *oi++ = ',';
+	}
+	serialize_str(i->first, oi);
+	*oi++ = ':';
+	i->second.serialize(oi);
       }
       *oi++ = '}';
       break;
@@ -323,52 +325,52 @@
     input(const Iter& first, const Iter& last) : cur_(first), end_(last), last_ch_(-1), ungot_(false), line_(1) {}
     int getc() {
       if (ungot_) {
-    ungot_ = false;
-    return last_ch_;
+	ungot_ = false;
+	return last_ch_;
       }
       if (cur_ == end_) {
-    last_ch_ = -1;
-    return -1;
+	last_ch_ = -1;
+	return -1;
       }
       if (last_ch_ == '\n') {
-    line_++;
+	line_++;
       }
       last_ch_ = *cur_++ & 0xff;
       return last_ch_;
     }
     void ungetc() {
       if (last_ch_ != -1) {
-    assert(! ungot_);
-    ungot_ = true;
+	assert(! ungot_);
+	ungot_ = true;
       }
     }
     Iter cur() const { return cur_; }
     int line() const { return line_; }
     void skip_ws() {
       while (1) {
-    int ch = getc();
-    if (! (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r')) {
-      ungetc();
-      break;
-    }
+	int ch = getc();
+	if (! (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r')) {
+	  ungetc();
+	  break;
+	}
       }
     }
     int expect(int expect) {
       skip_ws();
       if (getc() != expect) {
-    ungetc();
-    return false;
+	ungetc();
+	return false;
       }
       return true;
     }
     bool match(const std::string& pattern) {
       for (std::string::const_iterator pi(pattern.begin());
-       pi != pattern.end();
-       ++pi) {
-    if (getc() != *pi) {
-      ungetc();
-      return false;
-    }
+	   pi != pattern.end();
+	   ++pi) {
+	if (getc() != *pi) {
+	  ungetc();
+	  return false;
+	}
       }
       return true;
     }
@@ -378,17 +380,17 @@
     int uni_ch = 0, hex;
     for (int i = 0; i < 4; i++) {
       if ((hex = in.getc()) == -1) {
-    return -1;
+	return -1;
       }
       if ('0' <= hex && hex <= '9') {
-    hex -= '0';
+	hex -= '0';
       } else if ('A' <= hex && hex <= 'F') {
-    hex -= 'A' - 0xa;
+	hex -= 'A' - 0xa;
       } else if ('a' <= hex && hex <= 'f') {
-    hex -= 'a' - 0xa;
+	hex -= 'a' - 0xa;
       } else {
-    in.ungetc();
-    return -1;
+	in.ungetc();
+	return -1;
       }
       uni_ch = uni_ch * 16 + hex;
     }
@@ -402,17 +404,17 @@
     }
     if (0xd800 <= uni_ch && uni_ch <= 0xdfff) {
       if (0xdc00 <= uni_ch) {
-    // a second 16-bit of a surrogate pair appeared
-    return false;
+	// a second 16-bit of a surrogate pair appeared
+	return false;
       }
       // first 16-bit of surrogate pair, get the next one
       if (in.getc() != '\\' || in.getc() != 'u') {
-    in.ungetc();
-    return false;
+	in.ungetc();
+	return false;
       }
       int second = _parse_quadhex(in);
       if (! (0xdc00 <= second && second <= 0xdfff)) {
-    return false;
+	return false;
       }
       uni_ch = ((uni_ch - 0xd800) << 10) | ((second - 0xdc00) & 0x3ff);
       uni_ch += 0x10000;
@@ -421,15 +423,15 @@
       out.push_back(uni_ch);
     } else {
       if (uni_ch < 0x800) {
-    out.push_back(0xc0 | (uni_ch >> 6));
+	out.push_back(0xc0 | (uni_ch >> 6));
       } else {
-    if (uni_ch < 0x10000) {
-      out.push_back(0xe0 | (uni_ch >> 12));
-    } else {
-      out.push_back(0xf0 | (uni_ch >> 18));
-      out.push_back(0x80 | ((uni_ch >> 12) & 0x3f));
-    }
-    out.push_back(0x80 | ((uni_ch >> 6) & 0x3f));
+	if (uni_ch < 0x10000) {
+	  out.push_back(0xe0 | (uni_ch >> 12));
+	} else {
+	  out.push_back(0xf0 | (uni_ch >> 18));
+	  out.push_back(0x80 | ((uni_ch >> 12) & 0x3f));
+	}
+	out.push_back(0x80 | ((uni_ch >> 6) & 0x3f));
       }
       out.push_back(0x80 | (uni_ch & 0x3f));
     }
@@ -443,35 +445,35 @@
     while (1) {
       int ch = in.getc();
       if (ch < ' ') {
-    in.ungetc();
-    return false;
+	in.ungetc();
+	return false;
       } else if (ch == '"') {
-    return true;
+	return true;
       } else if (ch == '\\') {
-    if ((ch = in.getc()) == -1) {
-      return false;
-    }
-    switch (ch) {
+	if ((ch = in.getc()) == -1) {
+	  return false;
+	}
+	switch (ch) {
 #define MAP(sym, val) case sym: s.push_back(val); break
-      MAP('"', '\"');
-      MAP('\\', '\\');
-      MAP('/', '/');
-      MAP('b', '\b');
-      MAP('f', '\f');
-      MAP('n', '\n');
-      MAP('r', '\r');
-      MAP('t', '\t');
+	  MAP('"', '\"');
+	  MAP('\\', '\\');
+	  MAP('/', '/');
+	  MAP('b', '\b');
+	  MAP('f', '\f');
+	  MAP('n', '\n');
+	  MAP('r', '\r');
+	  MAP('t', '\t');
 #undef MAP
-    case 'u':
-      if (! _parse_codepoint(s, in)) {
-        return false;
-      }
-      break;
-    default:
-      return false;
-    }
+	case 'u':
+	  if (! _parse_codepoint(s, in)) {
+	    return false;
+	  }
+	  break;
+	default:
+	  return false;
+	}
       } else {
-    s.push_back(ch);
+	s.push_back(ch);
       }
     }
     return false;
@@ -486,7 +488,7 @@
     do {
       a.push_back(value());
       if (! _parse(a.back(), in)) {
-    return false;
+	return false;
       }
     } while (in.expect(','));
     return in.expect(']');
@@ -501,12 +503,12 @@
     do {
       value key, val;
       if (in.expect('"')
-      && _parse_string(key, in)
-      && in.expect(':')
-      && _parse(val, in)) {
-    o[key.to_str()] = val;
+	  && _parse_string(key, in)
+	  && in.expect(':')
+	  && _parse(val, in)) {
+	o[key.to_str()] = val;
       } else {
-    return false;
+	return false;
       }
     } while (in.expect(','));
     return in.expect('}');
@@ -517,11 +519,11 @@
     while (1) {
       int ch = in.getc();
       if (('0' <= ch && ch <= '9') || ch == '+' || ch == '-' || ch == '.'
-      || ch == 'e' || ch == 'E') {
-    num_str.push_back(ch);
+	  || ch == 'e' || ch == 'E') {
+	num_str.push_back(ch);
       } else {
-    in.ungetc();
-    break;
+	in.ungetc();
+	break;
       }
     }
     char* endp;
@@ -535,10 +537,10 @@
     switch (ch) {
 #define IS(ch, text, val) case ch: \
       if (in.match(text)) { \
-    out = val; \
-    return true; \
+	out = val; \
+	return true; \
       } else { \
-    return false; \
+	return false; \
       }
       IS('n', "ull", value());
       IS('f', "alse", value(false));
@@ -552,8 +554,8 @@
       return _parse_object(out, in);
     default:
       if (('0' <= ch && ch <= '9') || ch == '-') {
-    in.ungetc();
-    return _parse_number(out, in);
+	in.ungetc();
+	return _parse_number(out, in);
       }
       break;
     }
@@ -575,12 +577,12 @@
       SNPRINTF(buf, sizeof(buf), "syntax error at line %d near: ", in.line());
       *err = buf;
       while (1) {
-    int ch = in.getc();
-    if (ch == -1 || ch == '\n') {
-      break;
-    } else if (ch >= ' ') {
-      err->push_back(ch);
-    }
+	int ch = in.getc();
+	if (ch == -1 || ch == '\n') {
+	  break;
+	} else if (ch >= ' ') {
+	  err->push_back(ch);
+	}
       }
     }
     return in.cur();
@@ -589,7 +591,7 @@
   inline std::string parse(value& out, std::istream& is) {
     std::string err;
     parse(out, std::istreambuf_iterator<char>(is.rdbuf()),
-      std::istreambuf_iterator<char>(), &err);
+	  std::istreambuf_iterator<char>(), &err);
     return err;
   }
   
@@ -606,11 +608,11 @@
     return last_error_t<bool>::s;
   }
 
-  bool operator==(const value& x, const value& y) {
+  inline bool operator==(const value& x, const value& y) {
     if (x.is<null>())
       return y.is<null>();
-#define PICOJSON_CMP(type)                    \
-    if (x.is<type>())                        \
+#define PICOJSON_CMP(type)					\
+    if (x.is<type>())						\
       return y.is<type>() && x.get<type>() == y.get<type>()
     PICOJSON_CMP(bool);
     PICOJSON_CMP(double);
@@ -682,19 +684,19 @@
 
 int main(void)
 {
-  plan(61);
+  plan(62);
   
-#define TEST(in, type, cmp, serialize_test) {                \
-    picojson::value v;                            \
-    const char* s = in;                            \
-    string err = picojson::parse(v, s, s + strlen(s));            \
-    ok(err.empty(), in " no error");                    \
-    ok(v.is<type>(), in " check type");                    \
-    is(v.get<type>(), cmp, in " correct output");            \
-    is(*s, '\0', in " read to eof");                    \
-    if (serialize_test) {                        \
-      is(v.serialize(), string(in), in " serialize");            \
-    }                                    \
+#define TEST(in, type, cmp, serialize_test) {				\
+    picojson::value v;							\
+    const char* s = in;							\
+    string err = picojson::parse(v, s, s + strlen(s));			\
+    ok(err.empty(), in " no error");					\
+    ok(v.is<type>(), in " check type");					\
+    is(v.get<type>(), cmp, in " correct output");			\
+    is(*s, '\0', in " read to eof");					\
+    if (serialize_test) {						\
+      is(v.serialize(), string(in), in " serialize");			\
+    }									\
   }
   TEST("false", bool, false, true);
   TEST("true", bool, true, true);
@@ -707,12 +709,12 @@
   TEST("\"\\ud840\\udc0b\"", string, string("\xf0\xa0\x80\x8b"), false);
 #undef TEST
 
-#define TEST(type, expr) {                           \
-    picojson::value v;                               \
-    const char *s = expr;                           \
-    string err = picojson::parse(v, s, s + strlen(s));               \
-    ok(err.empty(), "empty " #type " no error");               \
-    ok(v.is<picojson::type>(), "empty " #type " check type");           \
+#define TEST(type, expr) {					       \
+    picojson::value v;						       \
+    const char *s = expr;					       \
+    string err = picojson::parse(v, s, s + strlen(s));		       \
+    ok(err.empty(), "empty " #type " no error");		       \
+    ok(v.is<picojson::type>(), "empty " #type " check type");	       \
     ok(v.get<picojson::type>().empty(), "check " #type " array size"); \
   }
   TEST(array, "[]");
@@ -747,11 +749,11 @@
     is(v.serialize(), string("{\"a\":true}"), "serialize object");
   }
 
-#define TEST(json, msg) do {                \
-    picojson::value v;                    \
-    const char *s = json;                \
-    string err = picojson::parse(v, s, s + strlen(s));    \
-    is(err, string("syntax error at line " msg), msg);    \
+#define TEST(json, msg) do {				\
+    picojson::value v;					\
+    const char *s = json;				\
+    string err = picojson::parse(v, s, s + strlen(s));	\
+    is(err, string("syntax error at line " msg), msg);	\
   } while (0)
   TEST("falsoa", "1 near: oa");
   TEST("{]", "1 near: ]");
@@ -809,7 +811,10 @@
     ok((v1 == v2), "check erase()");
   }
 
+  ok(picojson::value(3.0).serialize() == "3",
+     "integral number should be serialized as a integer");
+  
   return 0;
 }
 
-#endif
\ No newline at end of file
+#endif