Pruned empty files, moved JSON files to a new dir, updated MSVC solution files
git-svn-id: http://libopenmetaverse.googlecode.com/svn/trunk@103 52acb1d6-8a22-11de-b505-999d5b087335
This commit is contained in:
172
libsecondlife-cs/JSON/JSONArray.cs
Normal file
172
libsecondlife-cs/JSON/JSONArray.cs
Normal file
@@ -0,0 +1,172 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Text;
|
||||
|
||||
namespace Nii.JSON
|
||||
{
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// A JSONArray is an ordered sequence of values. Its external form is a string
|
||||
/// wrapped in square brackets with commas between the values. The internal form
|
||||
/// is an object having get() and opt() methods for accessing the values by
|
||||
/// index, and put() methods for adding or replacing values. The values can be
|
||||
/// any of these types: Boolean, JSONArray, JSONObject, Number, String, or the
|
||||
/// JSONObject.NULL object.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The constructor can convert a JSON external form string into an
|
||||
/// internal form Java object. The toString() method creates an external
|
||||
/// form string.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// A get() method returns a value if one can be found, and throws an exception
|
||||
/// if one cannot be found. An opt() method returns a default value instead of
|
||||
/// throwing an exception, and so is useful for obtaining optional values.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The generic get() and opt() methods return an object which you can cast or
|
||||
/// query for type. There are also typed get() and opt() methods that do typing
|
||||
/// checking and type coersion for you.
|
||||
///</para>
|
||||
/// <para>
|
||||
/// The texts produced by the toString() methods are very strict.
|
||||
/// The constructors are more forgiving in the texts they will accept.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// <list type="bullet">
|
||||
/// <item><description>An extra comma may appear just before the closing bracket.</description></item>
|
||||
/// <item><description>Strings may be quoted with single quotes.</description></item>
|
||||
/// <item><description>Strings do not need to be quoted at all if they do not contain leading
|
||||
/// or trailing spaces, and if they do not contain any of these characters:
|
||||
/// { } [ ] / \ : , </description></item>
|
||||
/// <item><description>Numbers may have the 0- (octal) or 0x- (hex) prefix.</description></item>
|
||||
/// </list>
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Public Domain 2002 JSON.org
|
||||
/// @author JSON.org
|
||||
/// @version 0.1
|
||||
///</para>
|
||||
/// Ported to C# by Are Bjolseth, teleplan.no
|
||||
/// TODO:
|
||||
/// 1. Implement Custom exceptions
|
||||
/// 2. Add indexer JSONObject[i] = object, and object = JSONObject[i];
|
||||
/// 3. Add indexer JSONObject["key"] = object, and object = JSONObject["key"]
|
||||
/// 4. Add unit testing
|
||||
/// 5. Add log4net
|
||||
/// 6. Make get/put methods private, to force use of indexer instead?
|
||||
/// </summary>
|
||||
public class JSONArray
|
||||
{
|
||||
/// <summary>The ArrayList where the JSONArray's properties are kept.</summary>
|
||||
private ArrayList myArrayList;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Construct an empty JSONArray
|
||||
/// </summary>
|
||||
public JSONArray()
|
||||
{
|
||||
myArrayList = new ArrayList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a JSONArray from a JSONTokener.
|
||||
/// </summary>
|
||||
/// <param name="x">A JSONTokener</param>
|
||||
public JSONArray(JSONTokener x) : this()
|
||||
{
|
||||
if (x.nextClean() != '[')
|
||||
{
|
||||
throw new Exception("A JSONArray must start with '['");
|
||||
}
|
||||
if (x.nextClean() == ']')
|
||||
{
|
||||
return;
|
||||
}
|
||||
x.back();
|
||||
while (true)
|
||||
{
|
||||
myArrayList.Add(x.nextObject());
|
||||
switch (x.nextClean())
|
||||
{
|
||||
case ',':
|
||||
if (x.nextClean() == ']')
|
||||
{
|
||||
return;
|
||||
}
|
||||
x.back();
|
||||
break;
|
||||
case ']':
|
||||
return;
|
||||
default:
|
||||
throw new Exception("Expected a ',' or ']'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Alternate to Java get/put method, by using indexer
|
||||
/// </summary>
|
||||
public object this[int i]
|
||||
{
|
||||
get
|
||||
{
|
||||
return opt(i);
|
||||
}
|
||||
set
|
||||
{
|
||||
//myArrayList[i] = value;
|
||||
put(i, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the optional object value associated with an index.
|
||||
/// </summary>
|
||||
/// <param name="i">index subscript</param>
|
||||
/// <returns>object at that index.</returns>
|
||||
public object opt(int i)
|
||||
{
|
||||
if (i < 0 || i >= myArrayList.Count)
|
||||
throw new ArgumentOutOfRangeException("int i", i, "Index out of bounds!");
|
||||
|
||||
return myArrayList[i];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Put or replace a boolean value in the JSONArray.
|
||||
/// </summary>
|
||||
/// <param name="i">
|
||||
/// The subscript. If the index is greater than the length of
|
||||
/// the JSONArray, then null elements will be added as necessary to pad it out.
|
||||
/// </param>
|
||||
/// <param name="val">An object value.</param>
|
||||
/// <returns>this (JSONArray)</returns>
|
||||
public JSONArray put(int i, object val)
|
||||
{
|
||||
if (i < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("i", i, "Negative indexes illegal");
|
||||
}
|
||||
else if (val == null)
|
||||
{
|
||||
throw new ArgumentNullException("val", "Object cannt be null");
|
||||
}
|
||||
else if (i < myArrayList.Count)
|
||||
{
|
||||
myArrayList.Insert(i, val);
|
||||
}
|
||||
// NOTE! Since i is >= Count, fill null vals before index i, then append new object at i
|
||||
else
|
||||
{
|
||||
while (i != myArrayList.Count)
|
||||
{
|
||||
myArrayList.Add(null);
|
||||
}
|
||||
myArrayList.Add(val);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
26
libsecondlife-cs/JSON/JSONFacade.cs
Normal file
26
libsecondlife-cs/JSON/JSONFacade.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Specialized;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace Nii.JSON
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for JsonFacade.
|
||||
/// </summary>
|
||||
public sealed class JsonFacade
|
||||
{
|
||||
/// <summary>
|
||||
/// Parse JSON formatted string and return a Hashtable
|
||||
/// </summary>
|
||||
/// <param name="sJSON"></param>
|
||||
/// <returns></returns>
|
||||
public static IDictionary fromJSON(string sJSON)
|
||||
{
|
||||
JSONObject jsob = new JSONObject(sJSON);
|
||||
IDictionary idict = jsob.getDictionary();
|
||||
return idict;
|
||||
}
|
||||
}
|
||||
}
|
||||
293
libsecondlife-cs/JSON/JSONObject.cs
Normal file
293
libsecondlife-cs/JSON/JSONObject.cs
Normal file
@@ -0,0 +1,293 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Specialized;
|
||||
using System.Text;
|
||||
using System.Globalization;
|
||||
|
||||
/*
|
||||
* A JSONObject is an unordered collection of name/value pairs. Its
|
||||
* external form is a string wrapped in curly braces with colons between the
|
||||
* names and values, and commas between the values and names. The internal form
|
||||
* is an object having get() and opt() methods for accessing the values by name,
|
||||
* and put() methods for adding or replacing values by name. The values can be
|
||||
* any of these types: Boolean, JSONArray, JSONObject, Number, String, or the
|
||||
* JSONObject.NULL object.
|
||||
* <p>
|
||||
* The constructor can convert an external form string into an internal form
|
||||
* Java object. The toString() method creates an external form string.
|
||||
* <p>
|
||||
* A get() method returns a value if one can be found, and throws an exception
|
||||
* if one cannot be found. An opt() method returns a default value instead of
|
||||
* throwing an exception, and so is useful for obtaining optional values.
|
||||
* <p>
|
||||
* The generic get() and opt() methods return an object, which you can cast or
|
||||
* query for type. There are also typed get() and opt() methods that do typing
|
||||
* checking and type coersion for you.
|
||||
* <p>
|
||||
* The texts produced by the toString() methods are very strict.
|
||||
* The constructors are more forgiving in the texts they will accept.
|
||||
* <ul>
|
||||
* <li>An extra comma may appear just before the closing brace.</li>
|
||||
* <li>Strings may be quoted with single quotes.</li>
|
||||
* <li>Strings do not need to be quoted at all if they do not contain leading
|
||||
* or trailing spaces, and if they do not contain any of these characters:
|
||||
* { } [ ] / \ : , </li>
|
||||
* <li>Numbers may have the 0- (octal) or 0x- (hex) prefix.</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* Public Domain 2002 JSON.org
|
||||
* @author JSON.org
|
||||
* @version 0.1
|
||||
* <p>
|
||||
* Ported to C# by Are Bjolseth, teleplan.no
|
||||
* TODO:
|
||||
* 1. Implement Custom exceptions
|
||||
* 2. Add indexer JSONObject[i] = object, and object = JSONObject[i];
|
||||
* 3. Add indexer JSONObject["key"] = object, and object = JSONObject["key"]
|
||||
* 4. Add unit testing
|
||||
* 5. Add log4net
|
||||
*/
|
||||
namespace Nii.JSON
|
||||
{
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// A JSONArray is an ordered sequence of values. Its external form is a string
|
||||
/// wrapped in square brackets with commas between the values. The internal form
|
||||
/// is an object having get() and opt() methods for accessing the values by
|
||||
/// index, and put() methods for adding or replacing values. The values can be
|
||||
/// any of these types: Boolean, JSONArray, JSONObject, Number, String, or the
|
||||
/// JSONObject.NULL object.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The constructor can convert a JSON external form string into an
|
||||
/// internal form Java object. The toString() method creates an external
|
||||
/// form string.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// A get() method returns a value if one can be found, and throws an exception
|
||||
/// if one cannot be found. An opt() method returns a default value instead of
|
||||
/// throwing an exception, and so is useful for obtaining optional values.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The generic get() and opt() methods return an object which you can cast or
|
||||
/// query for type. There are also typed get() and opt() methods that do typing
|
||||
/// checking and type coersion for you.
|
||||
///</para>
|
||||
/// <para>
|
||||
/// The texts produced by the toString() methods are very strict.
|
||||
/// The constructors are more forgiving in the texts they will accept.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// <list type="bullet">
|
||||
/// <item><description>An extra comma may appear just before the closing bracket.</description></item>
|
||||
/// <item><description>Strings may be quoted with single quotes.</description></item>
|
||||
/// <item><description>Strings do not need to be quoted at all if they do not contain leading
|
||||
/// or trailing spaces, and if they do not contain any of these characters:
|
||||
/// { } [ ] / \ : , </description></item>
|
||||
/// <item><description>Numbers may have the 0- (octal) or 0x- (hex) prefix.</description></item>
|
||||
/// </list>
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Public Domain 2002 JSON.org
|
||||
/// @author JSON.org
|
||||
/// @version 0.1
|
||||
///</para>
|
||||
/// Ported to C# by Are Bjolseth, teleplan.no
|
||||
/// TODO:
|
||||
/// 1. Implement Custom exceptions
|
||||
/// 2. Add indexer JSONObject[i] = object, and object = JSONObject[i];
|
||||
/// 3. Add indexer JSONObject["key"] = object, and object = JSONObject["key"]
|
||||
/// 4. Add unit testing
|
||||
/// 5. Add log4net
|
||||
/// 6. Make get/put methods private, to force use of indexer instead?
|
||||
/// </summary>
|
||||
public class JSONObject
|
||||
{
|
||||
/// <summary>
|
||||
/// Make a Null object
|
||||
/// JSONObject.NULL is equivalent to the value that JavaScript calls null,
|
||||
/// whilst C#'s null is equivalent to the value that JavaScript calls undefined.
|
||||
/// </summary>
|
||||
public struct JSONNull
|
||||
{
|
||||
/*
|
||||
public object clone()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
*/
|
||||
/*
|
||||
public bool equals(object obj)
|
||||
{
|
||||
return (obj == null) || (obj == this);
|
||||
}
|
||||
*/
|
||||
/// <summary>
|
||||
/// Overriden to return "null"
|
||||
/// </summary>
|
||||
/// <returns>null</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
//return base.ToString ();
|
||||
return "null";
|
||||
}
|
||||
}
|
||||
|
||||
///<summary>The hash map where the JSONObject's properties are kept.</summary>
|
||||
private Hashtable myHashMap;
|
||||
|
||||
///<summary>A shadow list of keys to enable access by sequence of insertion</summary>
|
||||
private ArrayList myKeyIndexList;
|
||||
|
||||
/// <summary>
|
||||
/// It is sometimes more convenient and less ambiguous to have a NULL
|
||||
/// object than to use C#'s null value.
|
||||
/// JSONObject.NULL.toString() returns "null".
|
||||
/// </summary>
|
||||
public static readonly JSONNull NULL = new JSONNull();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Construct an empty JSONObject.
|
||||
/// </summary>
|
||||
public JSONObject()
|
||||
{
|
||||
myHashMap = new Hashtable();
|
||||
myKeyIndexList = new ArrayList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a JSONObject from a JSONTokener.
|
||||
/// </summary>
|
||||
/// <param name="x">A JSONTokener object containing the source string.</param>
|
||||
public JSONObject(JSONTokener x) : this()
|
||||
{
|
||||
char c;
|
||||
string key;
|
||||
if (x.next() == '%')
|
||||
{
|
||||
x.unescape();
|
||||
}
|
||||
x.back();
|
||||
if (x.nextClean() != '{')
|
||||
{
|
||||
throw new Exception("A JSONObject must begin with '{'");
|
||||
}
|
||||
while (true)
|
||||
{
|
||||
c = x.nextClean();
|
||||
switch (c)
|
||||
{
|
||||
case (char)0:
|
||||
throw new Exception("A JSONObject must end with '}'");
|
||||
case '}':
|
||||
return;
|
||||
default:
|
||||
x.back();
|
||||
key = x.nextObject().ToString();
|
||||
break;
|
||||
}
|
||||
if (x.nextClean() != ':')
|
||||
{
|
||||
throw new Exception("Expected a ':' after a key");
|
||||
}
|
||||
object obj = x.nextObject();
|
||||
myHashMap.Add(key, obj);
|
||||
myKeyIndexList.Add(key);
|
||||
switch (x.nextClean())
|
||||
{
|
||||
case ',':
|
||||
if (x.nextClean() == '}')
|
||||
{
|
||||
return;
|
||||
}
|
||||
x.back();
|
||||
break;
|
||||
case '}':
|
||||
return;
|
||||
default:
|
||||
throw new Exception("Expected a ',' or '}'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Construct a JSONObject from a string.
|
||||
/// </summary>
|
||||
/// <param name="sJSON">A string beginning with '{' and ending with '}'.</param>
|
||||
public JSONObject(string sJSON) : this(new JSONTokener(sJSON))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// C# convenience method
|
||||
/// </summary>
|
||||
/// <returns>The Hashtable</returns>
|
||||
public IDictionary getDictionary()
|
||||
{
|
||||
return myHashMap;
|
||||
}
|
||||
|
||||
// OMITTED - all put methods can be replaced by a indexer in C#
|
||||
// - ===================================================
|
||||
// public JSONObject put(String key, boolean value)
|
||||
// public JSONObject put(String key, double value)
|
||||
// public JSONObject put(String key, int value)
|
||||
|
||||
/// <summary>
|
||||
/// Put a key/value pair in the JSONObject. If the value is null,
|
||||
/// then the key will be removed from the JSONObject if it is present.
|
||||
/// </summary>
|
||||
/// <param name="key"> A key string.</param>
|
||||
/// <param name="val">
|
||||
/// An object which is the value. It should be of one of these
|
||||
/// types: Boolean, Double, Integer, JSONArray, JSONObject, String, or the
|
||||
/// JSONObject.NULL object.
|
||||
/// </param>
|
||||
/// <returns>JSONObject</returns>
|
||||
public JSONObject put(string key, object val)
|
||||
{
|
||||
if (key == null)
|
||||
{
|
||||
throw new ArgumentNullException("key", "key cannot be null");
|
||||
}
|
||||
if (val != null)
|
||||
{
|
||||
if (!myHashMap.ContainsKey(key))
|
||||
{
|
||||
myHashMap.Add(key,val);
|
||||
myKeyIndexList.Add(key);
|
||||
}
|
||||
else
|
||||
{
|
||||
myHashMap[key]=val;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
remove(key);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove a object assosiateted with the given key
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
public object remove(string key)
|
||||
{
|
||||
if (myHashMap.ContainsKey(key))
|
||||
{
|
||||
// TODO - does it really work ???
|
||||
object obj = myHashMap[key];
|
||||
myHashMap.Remove(key);
|
||||
myKeyIndexList.Remove(key);
|
||||
return obj;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
340
libsecondlife-cs/JSON/JSONTokener.cs
Normal file
340
libsecondlife-cs/JSON/JSONTokener.cs
Normal file
@@ -0,0 +1,340 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Nii.JSON
|
||||
{
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// A JSONTokener takes a source string and extracts characters and tokens from
|
||||
/// it. It is used by the JSONObject and JSONArray constructors to parse
|
||||
/// JSON source strings.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Public Domain 2002 JSON.org
|
||||
/// @author JSON.org
|
||||
/// @version 0.1
|
||||
/// </para>
|
||||
/// <para>Ported to C# by Are Bjolseth, teleplan.no</para>
|
||||
/// <para>
|
||||
/// <list type="bullet">
|
||||
/// <item><description>Implement Custom exceptions</description></item>
|
||||
/// <item><description>Add unit testing</description></item>
|
||||
/// <item><description>Add log4net</description></item>
|
||||
/// </list>
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public class JSONTokener
|
||||
{
|
||||
/// <summary>The index of the next character.</summary>
|
||||
private int myIndex;
|
||||
/// <summary>The source string being tokenized.</summary>
|
||||
private string mySource;
|
||||
|
||||
/// <summary>
|
||||
/// Construct a JSONTokener from a string.
|
||||
/// </summary>
|
||||
/// <param name="s">A source string.</param>
|
||||
public JSONTokener(string s)
|
||||
{
|
||||
myIndex = 0;
|
||||
mySource = s;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Back up one character. This provides a sort of lookahead capability,
|
||||
/// so that you can test for a digit or letter before attempting to parse
|
||||
/// the next number or identifier.
|
||||
/// </summary>
|
||||
public void back()
|
||||
{
|
||||
if (myIndex > 0)
|
||||
myIndex -= 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the hex value of a character (base16).
|
||||
/// </summary>
|
||||
/// <param name="c">
|
||||
/// A character between '0' and '9' or between 'A' and 'F' or
|
||||
/// between 'a' and 'f'.
|
||||
/// </param>
|
||||
/// <returns>An int between 0 and 15, or -1 if c was not a hex digit.</returns>
|
||||
public static int dehexchar(char c)
|
||||
{
|
||||
if (c >= '0' && c <= '9')
|
||||
{
|
||||
return c - '0';
|
||||
}
|
||||
if (c >= 'A' && c <= 'F')
|
||||
{
|
||||
return c + 10 - 'A';
|
||||
}
|
||||
if (c >= 'a' && c <= 'f')
|
||||
{
|
||||
return c + 10 - 'a';
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine if the source string still contains characters that next() can consume.
|
||||
/// </summary>
|
||||
/// <returns>true if not yet at the end of the source.</returns>
|
||||
public bool more()
|
||||
{
|
||||
return myIndex < mySource.Length;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the next character in the source string.
|
||||
/// </summary>
|
||||
/// <returns>The next character, or 0 if past the end of the source string.</returns>
|
||||
public char next()
|
||||
{
|
||||
char c = more() ? mySource[myIndex] : (char)0;
|
||||
myIndex +=1;
|
||||
return c;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the next n characters.
|
||||
/// </summary>
|
||||
/// <param name="n">The number of characters to take.</param>
|
||||
/// <returns>A string of n characters.</returns>
|
||||
public string next(int n)
|
||||
{
|
||||
int i = myIndex;
|
||||
int j = i + n;
|
||||
if (j >= mySource.Length)
|
||||
{
|
||||
string msg = "Substring bounds error";
|
||||
throw (new Exception(msg));
|
||||
}
|
||||
myIndex += n;
|
||||
return mySource.Substring(i,j);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the next char in the string, skipping whitespace
|
||||
/// and comments (slashslash and slashstar).
|
||||
/// </summary>
|
||||
/// <returns>A character, or 0 if there are no more characters.</returns>
|
||||
public char nextClean()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
char c = next();
|
||||
if (c == '/')
|
||||
{
|
||||
switch (next())
|
||||
{
|
||||
case '/':
|
||||
do
|
||||
{
|
||||
c = next();
|
||||
} while (c != '\n' && c != '\r' && c != 0);
|
||||
break;
|
||||
case '*':
|
||||
while (true)
|
||||
{
|
||||
c = next();
|
||||
if (c == 0)
|
||||
{
|
||||
throw (new Exception("Unclosed comment."));
|
||||
}
|
||||
if (c == '*')
|
||||
{
|
||||
if (next() == '/')
|
||||
{
|
||||
break;
|
||||
}
|
||||
back();
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
back();
|
||||
return '/';
|
||||
}
|
||||
}
|
||||
else if (c == 0 || c > ' ')
|
||||
{
|
||||
return c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the characters up to the next close quote character.
|
||||
/// Backslash processing is done. The formal JSON format does not
|
||||
/// allow strings in single quotes, but an implementation is allowed to
|
||||
/// accept them.
|
||||
/// </summary>
|
||||
/// <param name="quote">The quoting character, either " or '</param>
|
||||
/// <returns>A String.</returns>
|
||||
public string nextString(char quote)
|
||||
{
|
||||
char c;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
while (true)
|
||||
{
|
||||
c = next();
|
||||
if ((c == 0x00) || (c == 0x0A) || (c == 0x0D))
|
||||
{
|
||||
throw (new Exception("Unterminated string"));
|
||||
}
|
||||
// CTRL chars
|
||||
if (c == '\\')
|
||||
{
|
||||
c = next();
|
||||
switch (c)
|
||||
{
|
||||
case 'b': //Backspace
|
||||
sb.Append('\b');
|
||||
break;
|
||||
case 't': //Horizontal tab
|
||||
sb.Append('\t');
|
||||
break;
|
||||
case 'n': //newline
|
||||
sb.Append('\n');
|
||||
break;
|
||||
case 'f': //Form feed
|
||||
sb.Append('\f');
|
||||
break;
|
||||
case 'r': // Carriage return
|
||||
sb.Append('\r');
|
||||
break;
|
||||
case 'u':
|
||||
//sb.append((char)Integer.parseInt(next(4), 16)); // 16 == radix, ie. hex
|
||||
int iascii = int.Parse(next(4),System.Globalization.NumberStyles.HexNumber);
|
||||
sb.Append((char)iascii);
|
||||
break;
|
||||
default:
|
||||
sb.Append(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (c == quote)
|
||||
{
|
||||
return sb.ToString();
|
||||
}
|
||||
sb.Append(c);
|
||||
}
|
||||
}//END-while
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the next value as object. The value can be a Boolean, Double, Integer,
|
||||
/// JSONArray, JSONObject, or String, or the JSONObject.NULL object.
|
||||
/// </summary>
|
||||
/// <returns>An object.</returns>
|
||||
public object nextObject()
|
||||
{
|
||||
char c = nextClean();
|
||||
string s;
|
||||
|
||||
if (c == '"' || c == '\'')
|
||||
{
|
||||
return nextString(c);
|
||||
}
|
||||
// Object
|
||||
if (c == '{')
|
||||
{
|
||||
back();
|
||||
return new JSONObject(this);
|
||||
}
|
||||
|
||||
// JSON Array
|
||||
if (c == '[')
|
||||
{
|
||||
back();
|
||||
return new JSONArray(this);
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
char b = c;
|
||||
while (c >= ' ' && c != ':' && c != ',' && c != ']' && c != '}' && c != '/')
|
||||
{
|
||||
sb.Append(c);
|
||||
c = next();
|
||||
}
|
||||
back();
|
||||
|
||||
s = sb.ToString().Trim();
|
||||
if (s == "true")
|
||||
return bool.Parse("true");
|
||||
if (s == "false")
|
||||
return bool.Parse("false");
|
||||
if (s == "null")
|
||||
return JSONObject.NULL;
|
||||
|
||||
if ((b >= '0' && b <= '9') || b == '.' || b == '-' || b == '+')
|
||||
{
|
||||
try
|
||||
{
|
||||
return Convert.ToInt32(s);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
try
|
||||
{
|
||||
return Convert.ToDouble(s, NumberFormatInfo.InvariantInfo);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
if (s == "")
|
||||
{
|
||||
throw (new Exception("Missing value"));
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unescape the source text. Convert %hh sequences to single characters,
|
||||
/// and convert plus to space. There are Web transport systems that insist on
|
||||
/// doing unnecessary URL encoding. This provides a way to undo it.
|
||||
/// </summary>
|
||||
public void unescape()
|
||||
{
|
||||
mySource = unescape(mySource);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert %hh sequences to single characters, and convert plus to space.
|
||||
/// </summary>
|
||||
/// <param name="s">A string that may contain plus and %hh sequences.</param>
|
||||
/// <returns>The unescaped string.</returns>
|
||||
public static string unescape(string s)
|
||||
{
|
||||
int len = s.Length;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i=0; i < len; i++)
|
||||
{
|
||||
char c = s[i];
|
||||
if (c == '+')
|
||||
{
|
||||
c = ' ';
|
||||
}
|
||||
else if (c == '%' && (i + 2 < len))
|
||||
{
|
||||
int d = dehexchar(s[i+1]);
|
||||
int e = dehexchar(s[i+2]);
|
||||
if (d >= 0 && e >= 0)
|
||||
{
|
||||
c = (char)(d*16 + e);
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
sb.Append(c);
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user