Added features that allow the reader to accept common non-standard JSON.

This is a version of patch #17, from Clay Wood:

    http://sourceforge.net/p/jsoncpp/patches/17/

git-svn-id: http://jsoncpp.svn.sourceforge.net/svnroot/jsoncpp/trunk/jsoncpp@280 1f120ed1-78a5-a849-adca-83f0a9e25bb6
diff --git a/include/json/features.h b/include/json/features.h
index 4353278..221d8ff 100644
--- a/include/json/features.h
+++ b/include/json/features.h
@@ -42,6 +42,12 @@
 
       /// \c true if root must be either an array or an object value. Default: \c false.
       bool strictRoot_;
+
+      /// \c true if dropped null placeholders are allowed. Default: \c false.
+      bool allowDroppedNullPlaceholders_;
+
+      /// \c true if numeric object key are allowed. Default: \c false.
+      bool allowNumericKeys_;
    };
 
 } // namespace Json
diff --git a/include/json/reader.h b/include/json/reader.h
index 3d8f628..0771342 100644
--- a/include/json/reader.h
+++ b/include/json/reader.h
@@ -146,9 +146,11 @@
       bool readObject( Token &token );
       bool readArray( Token &token );
       bool decodeNumber( Token &token );
+      bool decodeNumber( Token &token, Value &decoded );
       bool decodeString( Token &token );
       bool decodeString( Token &token, std::string &decoded );
       bool decodeDouble( Token &token );
+      bool decodeDouble( Token &token, Value &decoded );
       bool decodeUnicodeCodePoint( Token &token, 
                                    Location &current, 
                                    Location end, 
diff --git a/src/lib_json/json_reader.cpp b/src/lib_json/json_reader.cpp
index ed4f7a3..9ba4024 100644
--- a/src/lib_json/json_reader.cpp
+++ b/src/lib_json/json_reader.cpp
@@ -28,6 +28,8 @@
 Features::Features()
    : allowComments_( true )
    , strictRoot_( false )
+   , allowDroppedNullPlaceholders_ ( false )
+   , allowNumericKeys_ ( false )
 {
 }
 
@@ -45,6 +47,8 @@
    Features features;
    features.allowComments_ = false;
    features.strictRoot_ = true;
+   features.allowDroppedNullPlaceholders_ = false;
+   features.allowNumericKeys_ = false;
    return features;
 }
 
@@ -230,6 +234,16 @@
    case tokenNull:
       currentValue() = Value();
       break;
+   case tokenArraySeparator:
+      if ( features_.allowDroppedNullPlaceholders_ )
+      {
+         // "Un-read" the current token and mark the current value as a null
+         // token.
+         current_--;
+         currentValue() = Value();
+         break;
+      }
+      // Else, fall through...
    default:
       return addError( "Syntax error: value, object or array expected.", token );
    }
@@ -493,12 +507,24 @@
          break;
       if ( tokenName.type_ == tokenObjectEnd  &&  name.empty() )  // empty object
          return true;
-      if ( tokenName.type_ != tokenString )
-         break;
-      
       name = "";
-      if ( !decodeString( tokenName, name ) )
-         return recoverFromError( tokenObjectEnd );
+      if ( tokenName.type_ == tokenString )
+      {
+         if ( !decodeString( tokenName, name ) )
+            return recoverFromError( tokenObjectEnd );
+      }
+      else if ( tokenName.type_ == tokenNumber &&
+                features_.allowNumericKeys_ )
+      {
+         Value numberName;
+         if ( !decodeNumber( tokenName, numberName ) )
+            return recoverFromError( tokenObjectEnd );
+         name = numberName.asString();
+      }
+      else
+      {
+         break;
+      }
 
       Token colon;
       if ( !readToken( colon ) ||  colon.type_ != tokenMemberSeparator )
@@ -583,6 +609,17 @@
 bool 
 Reader::decodeNumber( Token &token )
 {
+  Value decoded;
+  if ( !decodeNumber( token, decoded ) )
+     return false;
+  currentValue() = decoded;
+  return true;
+}
+
+
+bool
+Reader::decodeNumber( Token &token, Value &decoded )
+{
    bool isDouble = false;
    for ( Location inspect = token.start_; inspect != token.end_; ++inspect )
    {
@@ -591,7 +628,7 @@
                  ||  ( *inspect == '-'  &&  inspect != token.start_ );
    }
    if ( isDouble )
-      return decodeDouble( token );
+      return decodeDouble( token, decoded );
    // Attempts to parse the number as an integer. If the number is
    // larger than the maximum supported value of an integer then
    // we decode the number as a double.
@@ -619,17 +656,17 @@
              current != token.end_ ||
              digit > maxIntegerValue % 10)
          {
-            return decodeDouble( token );
+            return decodeDouble( token, decoded );
          }
       }
       value = value * 10 + digit;
    }
    if ( isNegative )
-      currentValue() = -Value::LargestInt( value );
+      decoded = -Value::LargestInt( value );
    else if ( value <= Value::LargestUInt(Value::maxInt) )
-      currentValue() = Value::LargestInt( value );
+      decoded = Value::LargestInt( value );
    else
-      currentValue() = value;
+      decoded = value;
    return true;
 }
 
@@ -637,6 +674,17 @@
 bool 
 Reader::decodeDouble( Token &token )
 {
+  Value decoded;
+  if ( !decodeDouble( token, decoded ) )
+     return false;
+  currentValue() = decoded;
+  return true;
+}
+
+
+bool
+Reader::decodeDouble( Token &token, Value &decoded )
+{
    double value = 0;
    const int bufferSize = 32;
    int count;
@@ -669,7 +717,7 @@
 
    if ( count != 1 )
       return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token );
-   currentValue() = value;
+   decoded = value;
    return true;
 }