Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/jackmawer/JacksWorld. An abandoned mini-project that I created while learning to use Unity with networking.
Something went wrong. Try again.
14 kB · 516 lines
C#
at master
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517/* * Copyright (c) 2013 Calvin Rien * * Based on the JSON parser by Patrick van Bergen * http://techblog.procurios.nl/k/618/news/view/14605/14863/How-do-I-write-my-own-parser-for-JSON.html * * Simplified it so that it doesn't throw exceptions * and can be used in Unity iPhone with maximum code stripping. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
using System;using System.Collections;using System.Collections.Generic;using System.IO;using System.Text;
namespace UnityEngine.Advertisements.MiniJSON { /// <summary> /// This class encodes and decodes JSON strings. /// Spec. details, see http://www.json.org/ /// /// JSON uses Arrays and Objects. These correspond here to the datatypes IList and IDictionary. /// All numbers are parsed to doubles. /// </summary>
public static class Json { /// <summary> /// Parses the string json into a value /// </summary> /// <param name="json">A JSON string.</param> /// <returns>An List<object>, a Dictionary<string, object>, a double, an integer,a string, null, true, or false</returns> public static object Deserialize(string json) { // save the string for debug information if(json == null) { return null; }
return Parser.Parse(json); }
sealed class Parser : IDisposable { const string WORD_BREAK = "{}[],:\"";
public static bool IsWordBreak(char c) { return Char.IsWhiteSpace(c) || WORD_BREAK.IndexOf(c) != -1; }
enum TOKEN { NONE, CURLY_OPEN, CURLY_CLOSE, SQUARED_OPEN, SQUARED_CLOSE, COLON, COMMA, STRING, NUMBER, TRUE, FALSE, NULL };
StringReader json;
Parser(string jsonString) { json = new StringReader(jsonString); }
public static object Parse(string jsonString) { using(var instance = new Parser(jsonString)) { return instance.ParseValue(); } }
public void Dispose() { json.Dispose(); json = null; }
Dictionary<string, object> ParseObject() { Dictionary<string, object> table = new Dictionary<string, object>();
// ditch opening brace json.Read();
// { while(true) { switch(NextToken) { case TOKEN.NONE: return null; case TOKEN.COMMA: continue; case TOKEN.CURLY_CLOSE: return table; default: // name string name = ParseString(); if(name == null) { return null; }
// : if(NextToken != TOKEN.COLON) { return null; } // ditch the colon json.Read();
// value table[name] = ParseValue(); break; } } }
List<object> ParseArray() { List<object> array = new List<object>();
// ditch opening bracket json.Read();
// [ var parsing = true; while(parsing) { TOKEN nextToken = NextToken;
switch(nextToken) { case TOKEN.NONE: return null; case TOKEN.COMMA: continue; case TOKEN.SQUARED_CLOSE: parsing = false; break; default: object value = ParseByToken(nextToken);
array.Add(value); break; } }
return array; }
object ParseValue() { TOKEN nextToken = NextToken; return ParseByToken(nextToken); }
object ParseByToken(TOKEN token) { switch(token) { case TOKEN.STRING: return ParseString(); case TOKEN.NUMBER: return ParseNumber(); case TOKEN.CURLY_OPEN: return ParseObject(); case TOKEN.SQUARED_OPEN: return ParseArray(); case TOKEN.TRUE: return true; case TOKEN.FALSE: return false; case TOKEN.NULL: return null; default: return null; } }
string ParseString() { StringBuilder s = new StringBuilder(); char c;
// ditch opening quote json.Read();
bool parsing = true; while(parsing) {
if(json.Peek() == -1) { parsing = false; break; }
c = NextChar; switch(c) { case '"': parsing = false; break; case '\\': if(json.Peek() == -1) { parsing = false; break; }
c = NextChar; switch(c) { case '"': case '\\': case '/': s.Append(c); break; case 'b': s.Append('\b'); break; case 'f': s.Append('\f'); break; case 'n': s.Append('\n'); break; case 'r': s.Append('\r'); break; case 't': s.Append('\t'); break; case 'u': var hex = new char[4];
for(int i=0; i< 4; i++) { hex[i] = NextChar; }
s.Append((char)Convert.ToInt32(new string(hex), 16)); break; } break; default: s.Append(c); break; } }
return s.ToString(); }
object ParseNumber() { string number = NextWord;
if(number.IndexOf('.') == -1) { long parsedInt; Int64.TryParse(number, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out parsedInt); return parsedInt; }
double parsedDouble; Double.TryParse(number, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out parsedDouble); return parsedDouble; }
void EatWhitespace() { while(Char.IsWhiteSpace(PeekChar)) { json.Read();
if(json.Peek() == -1) { break; } } }
char PeekChar { get { return Convert.ToChar(json.Peek()); } }
char NextChar { get { return Convert.ToChar(json.Read()); } }
string NextWord { get { StringBuilder word = new StringBuilder();
while(!IsWordBreak(PeekChar)) { word.Append(NextChar);
if(json.Peek() == -1) { break; } }
return word.ToString(); } }
TOKEN NextToken { get { EatWhitespace();
if(json.Peek() == -1) { return TOKEN.NONE; }
switch(PeekChar) { case '{': return TOKEN.CURLY_OPEN; case '}': json.Read(); return TOKEN.CURLY_CLOSE; case '[': return TOKEN.SQUARED_OPEN; case ']': json.Read(); return TOKEN.SQUARED_CLOSE; case ',': json.Read(); return TOKEN.COMMA; case '"': return TOKEN.STRING; case ':': return TOKEN.COLON; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '-': return TOKEN.NUMBER; }
switch(NextWord) { case "false": return TOKEN.FALSE; case "true": return TOKEN.TRUE; case "null": return TOKEN.NULL; }
return TOKEN.NONE; } } }
/// <summary> /// Converts a IDictionary / IList object or a simple type (string, int, etc.) into a JSON string /// </summary> /// <param name="json">A Dictionary<string, object> / List<object></param> /// <returns>A JSON encoded string, or null if object 'json' is not serializable</returns> public static string Serialize(object obj) { return Serializer.Serialize(obj); }
sealed class Serializer { StringBuilder builder;
Serializer() { builder = new StringBuilder(); }
public static string Serialize(object obj) { var instance = new Serializer();
instance.SerializeValue(obj);
return instance.builder.ToString(); }
void SerializeValue(object value) { IList asList; IDictionary asDict; string asStr;
if(value == null) { builder.Append("null"); } else if((asStr = value as string) != null) { SerializeString(asStr); } else if(value is bool) { builder.Append((bool)value ? "true" : "false"); } else if((asList = value as IList) != null) { SerializeArray(asList); } else if((asDict = value as IDictionary) != null) { SerializeObject(asDict); } else if(value is char) { SerializeString(new string((char)value, 1)); } else { SerializeOther(value); } }
void SerializeObject(IDictionary obj) { bool first = true;
builder.Append('{');
foreach(object e in obj.Keys) { if(!first) { builder.Append(','); }
SerializeString(e.ToString()); builder.Append(':');
SerializeValue(obj[e]);
first = false; }
builder.Append('}'); }
void SerializeArray(IList anArray) { builder.Append('[');
bool first = true;
foreach(object obj in anArray) { if(!first) { builder.Append(','); }
SerializeValue(obj);
first = false; }
builder.Append(']'); }
void SerializeString(string str) { builder.Append('\"');
char[] charArray = str.ToCharArray(); foreach(var c in charArray) { switch(c) { case '"': builder.Append("\\\""); break; case '\\': builder.Append("\\\\"); break; case '\b': builder.Append("\\b"); break; case '\f': builder.Append("\\f"); break; case '\n': builder.Append("\\n"); break; case '\r': builder.Append("\\r"); break; case '\t': builder.Append("\\t"); break; default: int codepoint = Convert.ToInt32(c); if((codepoint >= 32) && (codepoint <= 126)) { builder.Append(c); } else { builder.Append("\\u"); builder.Append(codepoint.ToString("x4")); } break; } }
builder.Append('\"'); }
void SerializeOther(object value) { // NOTE: decimals lose precision during serialization. // They always have, I'm just letting you know. // Previously floats and doubles lost precision too. if(value is float) { builder.Append(((float)value).ToString("R", System.Globalization.CultureInfo.InvariantCulture)); } else if(value is int || value is uint || value is long || value is sbyte || value is byte || value is short || value is ushort || value is ulong) { builder.Append(value); } else if(value is double || value is decimal) { builder.Append(Convert.ToDouble(value).ToString("R", System.Globalization.CultureInfo.InvariantCulture)); } else { SerializeString(value.ToString()); } } } }}