Beispiel #1
0
 public override IValue DeepCopy()
 {
     ListValue result = new ListValue();
     foreach(IValue value in list_) {
         result.Append(value.DeepCopy());
     }
     return result;
 }
Beispiel #2
0
    /// <summary>
    /// Recursively build <see cref="Value"/>.
    /// </summary>
    /// <param name="is_root">true to verify if the root is either an object or an array; otherwise, false.</param>
    /// <returns>An IDictionary&alt;string, string&gt; containing the parsed JSON string or a null reference
    /// if we don't have a valid JSON string.</returns>
    /// <exception cref="ArgumentException">Too much nesting.</exception>
    IValue BuildValue(bool is_root) {
      ++stack_depth_;
      if (stack_depth_ > kStackLimit) {
        throw new InvalidOperationException(
          Resources.Resources.InvalidOperation_TooMuchNesting);
      }

      Token token = ParseToken();
      // The root token must be an array or an object.
      if (is_root && token.type != Token.TokenType.OBJECT_BEGIN && token.type != Token.TokenType.ARRAY_BEGIN)
        return null;

      IValue node;

      switch (token.type) {
        case Token.TokenType.END_OF_INPUT:
        case Token.TokenType.INVALID_TOKEN:
          return null;

        case Token.TokenType.NULL_TOKEN:
          node = Value.CreateNullValue();
          break;

        case Token.TokenType.BOOL_TRUE:
          node = Value.CreateBooleanValue(true);
          break;

        case Token.TokenType.BOOL_FALSE:
          node = Value.CreateBooleanValue(false);
          break;

        case Token.TokenType.NUMBER:
          node = DecodeNumber(token);
          break;

        case Token.TokenType.STRING:
          node = DecodeString(token);
          break;

        case Token.TokenType.ARRAY_BEGIN: {
            json_pos_ += token.length;
            token = ParseToken();

            node = new ListValue();
            while (token.type != Token.TokenType.ARRAY_END) {
              IValue array_node = BuildValue(false);
              if (array_node == null)
                return null;
              ((ListValue)node).Append(array_node);

              // After a list value, we expect a comma ot the end of the list.
              token = ParseToken();
              if (token.type == Token.TokenType.LIST_SEPARATOR) {
                json_pos_ += token.length;
                token = ParseToken();

                // Trailing commas are invalid according to the JSON RFC, but some
                // consumers need the parsing leniency, so handle accordingly.
                if (token.type == Token.TokenType.ARRAY_END) {
                  if (!allow_trailing_comma_) {
                    throw new InvalidOperationException(string.Format(
                      Resources.Resources.InvalidOperation_json_TrailingComma,
                      json_pos_));
                  }
                  // Trailing comma OK, stop parsing the Array.
                  break;
                }
              } else if (token.type != Token.TokenType.ARRAY_END) {
                // Unexpected value after list value. Bail out.
                return null;
              }
            }
            if (token.type != Token.TokenType.ARRAY_END) {
              return null;
            }
            break;
          }

        case Token.TokenType.OBJECT_BEGIN: {
            json_pos_ += token.length;
            token = ParseToken();

            node = new DictionaryValue();
            while (token.type != Token.TokenType.OBJECT_END) {
              if (token.type != Token.TokenType.STRING) {
                throw new InvalidOperationException(string.Format(
                  Resources.Resources.InvalidOperation_json_UnquotedDictionaryKey,
                  json_pos_));
              }

              IValue dict_key_value = DecodeString(token);
              if (dict_key_value == null)
                return null;

              // Converts the key into a string.
              string dict_key;
              bool success = dict_key_value.GetAsString(out dict_key);

              json_pos_ += token.length;
              token = ParseToken();
              if (token.type != Token.TokenType.OBJECT_PAIR_SEPARATOR)
                return null;

              json_pos_ += token.length;
              //token = ParseToken();

              IValue dict_value = BuildValue(false);
              if (dict_value == null)
                return null;

              (node as DictionaryValue)[dict_key] = dict_value;

              // After a key value pair, we expect a comma or the end of the object
              token = ParseToken();
              if (token.type == Token.TokenType.LIST_SEPARATOR) {
                json_pos_ += token.length;
                token = ParseToken();
                // Trailing commas are invalid according to the JSON RFC, but some
                // consumers need the parsing leniency, so handle accordingly.
                if (token.type == Token.TokenType.OBJECT_END) {
                  if (!allow_trailing_comma_) {
                    throw new InvalidOperationException(string.Format(
                      Resources.Resources.InvalidOperation_json_TrailingComma,
                      json_pos_));
                  }
                  // Trailing comma OK, stop parsing the object.
                  break;
                }
              } else if (token.type != Token.TokenType.OBJECT_END) {
                // Unexpected value after last object value. Bail out.
                return null;
              }
            }
            if (token.type != Token.TokenType.OBJECT_END)
              return null;

            break;
          }

        default:
          // We got a token that's not a value.
          return null;
      }
      json_pos_ += token.length;

      --stack_depth_;

      return node;
    }
Beispiel #3
0
        /// <summary>
        /// Convenience form of Get().
        /// </summary>
        /// <param name="index">The zero-based index of the element to get.</param>
        /// <param name="out_value">When this method returns, contains the <see cref="Value"/> associated
        /// with the specified index if the index falls within the current list range; otherwise null</param>
        /// <returns>true if the index falls within the current list range; otherwise false.</returns>
        public bool GetList(int index, out ListValue out_value)
        {
            IValue value;

            out_value = null;
            if (!Get(index, out value) || value.IsType(ValueType.List))
                return false;

            out_value = value as ListValue;
            return true;
        }