/// <summary> /// オブジェクトをストリームから読み込む。 /// </summary> /// <param name="reader">読み込み元</param> /// <param name="parent">親オブジェクト(無い場合にはnull)</param> /// <param name="paramName">パラメータ名(無い場合にはnull)</param> /// <returns>オブジェクト</returns> private object ReadObject(LocalReader reader, object parent, string paramName) { while (!reader.EndOfStream) { char c = (char)(reader.Peek()); if (IsSpace(c)) { reader.Consume(); } if (c == '{') { return(ReadDictionary(reader, parent, paramName)); } else if (c == '[') { return(ReadArray(reader, parent, paramName)); } else if (!Char.IsControl((char)(c))) { return(ReadPrimitive(reader)); } else { // 読み捨て。 reader.Consume(); } } return(null); }
/// <summary> /// 数字データを読み込む。 /// </summary> /// <param name="reader">読み込み元</param> /// <returns>数字</returns> private static string ReadNumberString(LocalReader reader) { // 数値プリミティブ char c = reader.Read(); StringBuilder sb = new StringBuilder(); if (c != '+') { sb.Append(c); } // 数字か.が出る限り追加。 string pattern = "0123456789."; while (!reader.EndOfStream) { c = reader.Peek(); if (pattern.IndexOf(c) >= 0) { reader.Consume(); sb.Append(c); if (c == '.') { pattern = "0123456789"; } } else { break; } } return(sb.ToString()); }
/// <summary> /// オブジェクトをストリームから読み込む。 /// </summary> /// <param name="reader">読み込み元</param> /// <returns>オブジェクト</returns> private static JObject ReadObject(LocalReader reader) { while (!reader.EndOfStream) { char c = (char)(reader.Peek()); if (IsSpace(c)) { reader.Consume(); } if (c == '{') { return(ReadDictionary(reader)); } else if (c == '[') { return(ReadArray(reader)); } else if (!Char.IsControl((char)(c))) { return(ReadPrimitive(reader)); } else { reader.Consume(); } } return(null); }
/// <summary> /// ダブルクォーテーションまたはシングルクォーテーションでくくられた文字を読み出す。 /// 返す文字列はダブルクォーテーション(またはシングルクォーテーション)を外した状態で返す。 /// </summary> /// <param name="reader">読み込み元</param> /// <param name="quoatChar">くくり文字</param> /// <returns>読み込んだ文字列</returns> private static string ReadQuoatedString(LocalReader reader, char quoatChar) { reader.Read(); // 文字列型 次の'\"'が出てくるまで読む。 StringBuilder sb = new StringBuilder(); while (!reader.EndOfStream) { char c = (char)(reader.Read()); if (c == quoatChar) { break; } else if (c == '\\') { sb.Append(c); sb.Append((char)(reader.Read())); } else { sb.Append(c); } } return(sb.ToString()); }
private static JObject ReadPrimitive(LocalReader reader) { char firstChar = (char)(reader.Peek()); if ((firstChar == '\"') || (firstChar == '\'')) { string strValue = ReadQuoatedString(reader, firstChar); return(new JPrimitive(strValue)); } else if (char.IsDigit(firstChar) || (firstChar == '-') || (firstChar == '+')) { string numValue = ReadNumberString(reader); return(new JPrimitive(numValue)); } else { // ここに来ること基本的にないよね。変数指定のときだけじゃ。 string s = ReadString(reader); if (s.Equals("null")) { return(null); } else if (s.Length > 0) { return(new JPrimitive(s)); } else { throw new Exception("Parse error. [" + s + "]"); } } }
/// <summary> /// 連想配列のデータを読み込む。 /// </summary> /// <param name="reader">読み込み元</param> /// <param name="parent">親オブジェクト(無い場合はnull)</param> /// <param name="paramName">パラメータ名(無い場合はnull)</param> /// <returns>連想配列</returns> private object ReadDictionary(LocalReader reader, object parent, string paramName) { // 最初の1文字読み捨て。'{' reader.Consume(); object dictionary = DataConstructor.CreateDictionary(parent, paramName); string key = null; object obj = null; while (!reader.EndOfStream) { char c = reader.Peek(); if (IsSpace(c)) { reader.Consume(); // Consume. } else if (c == ',') { reader.Consume(); // Consume if (!string.IsNullOrEmpty(key)) { DataConstructor.SetDictionaryData(dictionary, key, obj); } key = null; obj = null; } else if (c == '}') { reader.Consume(); // Consume. if (!string.IsNullOrEmpty(key)) { DataConstructor.SetDictionaryData(dictionary, key, obj); } break; } else if (c == ':') { if (string.IsNullOrEmpty(key)) { throw new Exception("key not specified."); } reader.Consume(); } else { if (key == null) { key = ReadKeyString(reader); } else { obj = ReadObject(reader, dictionary, key); } } } return(dictionary); }
/// <summary> /// 連想配列のデータを読み込む。 /// </summary> /// <param name="reader">読み込み元</param> /// <returns>連想配列</returns> private static JDictionary ReadDictionary(LocalReader reader) { // 最初の1文字読み捨て。'{' reader.Consume(); JDictionary dictionary = new JDictionary(); string key = null; JObject obj = null; while (!reader.EndOfStream) { char c = reader.Peek(); if (IsSpace(c)) { reader.Consume(); // Consume. } else if (c == ',') { reader.Consume(); // Consume if (!string.IsNullOrEmpty(key)) { dictionary[key] = obj; } key = null; obj = null; } else if (c == '}') { reader.Consume(); // Consume. if (!string.IsNullOrEmpty(key)) { dictionary[key] = obj; } break; } else if (c == ':') { if (string.IsNullOrEmpty(key)) { throw new Exception("key not specified."); } reader.Consume(); } else { if (key == null) { key = ReadKeyString(reader); } else { obj = ReadObject(reader); } } } return(dictionary); }
/// <summary> /// くくられている/くくられていないにかかわらず、続く文字列を読み出す。 /// </summary> /// <param name="reader">読み込み元</param> /// <returns>読み込んだ文字列</returns> private string ReadKeyString(LocalReader reader) { char firstChar = (char)(reader.Peek()); if ((firstChar == '\"') || (firstChar == '\'')) { return(ReadQuoatedString(reader, firstChar)); } else { return(ReadKeyString(reader)); } }
/// <summary> /// 文字列を読み出す。 /// </summary> /// <param name="reader">読み込み元</param> /// <returns>文字列</returns> private string ReadString(LocalReader reader) { StringBuilder sb = new StringBuilder(); while (!reader.EndOfStream) { char c = (char)(reader.Peek()); if (char.IsControl(c) || (":,[]{} ".IndexOf(c) >= 0)) { break; } else { reader.Consume(); sb.Append(c); } } return(sb.ToString()); }
/// <summary> /// プリミティブデータを読み出す。 /// </summary> /// <param name="reader">読み込み元</param> /// <returns>プリミティブデータ</returns> private object ReadPrimitive(LocalReader reader) { char firstChar = (char)(reader.Peek()); if ((firstChar == '\"') || (firstChar == '\'')) { string strValue = ReadQuoatedString(reader, firstChar); return(DataConstructor.CreatePrimitive(strValue, true)); } else if (char.IsDigit(firstChar) || (firstChar == '-') || (firstChar == '+')) { string numValue = ReadNumberString(reader); return(DataConstructor.CreatePrimitive(numValue, false)); } else { // ここに来ること基本的にないよね。変数指定のときだけじゃ。 string s = ReadString(reader); return(DataConstructor.CreatePrimitive(s, false)); } }
/// <summary> /// 配列を読み込む。 /// </summary> /// <param name="reader">読み出しに使用するStreamReaderオブジェクト</param> /// <param name="parent">親オブジェクト</param> /// <param name="paramName">パラメータ名</param> /// <returns>配列を表すobjectが返る</returns> private object ReadArray(LocalReader reader, object parent, string paramName) { // 最初の1文字読み捨て。'[' reader.Consume(); object array = DataConstructor.CreateArray(parent, paramName); object obj = null; while (!reader.EndOfStream) { char c = (char)(reader.Peek()); if (IsSpace(c)) { reader.Consume(); } else if (c == ',') { reader.Consume(); DataConstructor.AddArrayData(array, obj); obj = null; } else if (c == ']') { reader.Consume(); if (obj != null) { DataConstructor.AddArrayData(array, obj); } break; } else { obj = ReadObject(reader, array, null); } } return(array); }
/// <summary> /// 配列を読み込む。 /// </summary> /// <param name="reader">読み出しに使用するStreamReaderオブジェクト</param> /// <returns>JArrayが返る</returns> private static JArray ReadArray(LocalReader reader) { // 最初の1文字読み捨て。'[' reader.Consume(); JArray array = new JArray(); JObject obj = null; while (!reader.EndOfStream) { char c = (char)(reader.Peek()); if (IsSpace(c)) { reader.Consume(); } else if (c == ',') { reader.Consume(); array.Add(obj); obj = null; } else if (c == ']') { reader.Consume(); if (obj != null) { array.Add(obj); } break; } else { obj = ReadObject(reader); } } return(array); }
/// <summary> /// ストリームからデータを読み込んで解析する。 /// </summary> /// <param name="stream">読み込み元</param> /// <returns>読み込んだデータ</returns> public object Read(System.IO.Stream stream) { LocalReader reader = new LocalReader(stream); return(ReadObject(reader, null, null)); }
/// <summary> /// ダブルクォーテーションまたはシングルクォーテーションでくくられた文字を読み出す。 /// 返す文字列はダブルクォーテーション(またはシングルクォーテーション)を外した状態で返す。 /// </summary> /// <param name="reader">読み込み元</param> /// <param name="quoatChar">くくり文字</param> /// <returns>読み込んだ文字列</returns> private string ReadQuoatedString(LocalReader reader, char quoatChar) { reader.Read(); // 文字列型 次の'\"'が出てくるまで読む。 StringBuilder sb = new StringBuilder(); while (!reader.EndOfStream) { char c = (char)(reader.Read()); if (c == quoatChar) { break; } else if (c == '\\') { // エスケープシーケンス // 一応次の文字次第で処理を変更する。 char nextChar = reader.Peek(); switch (nextChar) { case '\'': // \' シングルクォーテーション reader.Consume(); sb.Append('\''); break; case '\"': // \" ダブルクォーテーション reader.Consume(); sb.Append('\"'); break; case 'r': // \r 改行 reader.Consume(); sb.Append('\r'); break; case 'n': // \n 改行 reader.Consume(); sb.Append('\n'); break; case 't': // \t タブ reader.Consume(); sb.Append('\t'); break; case '\\': // エスケープコード reader.Consume(); sb.Append('\\'); break; default: sb.Append(c); break; } } else { sb.Append(c); } } return(sb.ToString()); }
/// <summary> /// ストリームからデータを読み込んで解析する。 /// </summary> /// <param name="stream">読み込み元</param> /// <returns>読み込んだデータ</returns> public JObject Parse(System.IO.Stream stream) { LocalReader reader = new LocalReader(stream); return(ReadObject(reader)); }