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:
John Hurliman
2006-07-28 14:54:49 +00:00
parent 11a68287ba
commit 5d11fedced
17 changed files with 80 additions and 327 deletions

View 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;
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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();
}
}
}