//문자열 파싱용 함수 #region static async public void ParseStart(JSON.ParseCallback c, Action <JSONException> ex, string s = "") { if (JSONParseThread.Parsing) { throw new System.Exception("이미 파싱이 진행중입니다"); } if (!initialized) { Initialize(); } if (!JSONParseThread.Initialized) { JSONParseThread.Initialize(); } ComplexTree <object> CompTree = null; try { CompTree = CalculateComplexity(s); } catch (JSONException e) { ex(e); } if (CompTree == null || CompTree.Count == 0) {//파싱할 트리구조 자체가 없을 경우. 빈 오브젝트 하나를 반환한다. c(new JSONObject()); return; } JSONParseThread.Parsing = true; JSONParseThread.s = s; JSONParseThread.threadException = null; Task t = new Task(() => { JSONParseThread.ParseThread(CompTree[0]); }); t.Start(); await t; JSONParseThread.Parsing = false; if (JSONParseThread.threadException != null) { ex?.Invoke(JSONParseThread.threadException); } else { c(CompTree[0].node); } //JSONParseThread._s = ""; }
static public ComplexTree <object> CalculateComplexity(string s) { bool doublestring = false; bool isQuote = false; ComplexTree <object> rtn = new ComplexTree <object>(); ComplexTree <object> cursor = rtn; int quoteposition = -1; for (int i = 0; i < s.Length; i++) { while (s[i] <= ' ') { i++; } switch (s[i]) { case '"': if (s[i - 1] != '\\') { isQuote ^= true; if (isQuote) { if (doublestring) { throw new JSONSyntaxErrorCommaNotExist(i); } quoteposition = i; i = s.IndexOf('"', i + 1) - 1; doublestring = true; } else { quoteposition = -1; } } else //cause \" can only exist in " " { i = s.IndexOf('"', i + 1) - 1; } break; case ',': case ':': if (isQuote) { break; } cursor.separator.Enqueue(i); doublestring = false; break; case '[': case '{': { if (isQuote) { break; } doublestring = false; ComplexTree <object> child = new ComplexTree <object>() { StartPoint = i, parent = cursor }; cursor.Add(child); cursor = child; break; } case ']': case '}': { if (isQuote) { break; } doublestring = false; cursor.separator.Enqueue(i); cursor.EndPoint = i; cursor = cursor.parent; if (cursor == null) { throw new JSONSyntaxErrorNotClose(i - 1); } break; } } } if (!ReferenceEquals(rtn, cursor)) { throw new JSONSyntaxErrorNotClose(s.Length); } if (quoteposition > -1) { throw new JSONSyntaxErrorNotClose(quoteposition); } return(rtn); }
static public JSONNode Parse(ComplexTree <object> t) { JSONNode rtn = null; int ni = t.StartPoint + 1; //nowindex int ti = 0; //tree index int nei = 0; int nextSeparator; if (s[t.StartPoint] == '{') { rtn = new JSONObject(); if (t.separator.Count == 1) { nextSeparator = t.separator.Dequeue(); if (s[nextSeparator] == '}') { return(rtn); } else { threadException = new JSONSyntaxErrorCommaNotExist(nextSeparator); return(null); } } while (t.separator.Count > 0) { nextSeparator = t.separator.Dequeue(); while (s[ni] <= ' ') { ni++; //find next non whitespace } if (s[nextSeparator] != ':') { threadException = new JSONSyntaxErrorCollonNotExist(nextSeparator); return(null); } nei = nextSeparator - 1; while (s[nei] <= ' ') { --nei; //find end non whitespace } string keystr; if (s[nei] == '"' && s[ni] == '"') { keystr = s.Substring(ni + 1, nei - ni - 1); } else { threadException = new JSONSyntaxErrorKeyNotExist(ni); return(null); } ni = (nextSeparator + 1); nextSeparator = t.separator.Dequeue(); nei = nextSeparator - 1; while (s[nei] <= ' ') { --nei; //find end non whitespace } while (s[ni] <= ' ') { ni++; //find next non whitespace } char k = s[ni]; if (k != '{' && k != '[') { try { rtn[keystr] = _parse[k](ni, nei); } catch { threadException = new JSONSyntaxErrorValueNotExist(ni); return(null); } } else { if (t[ti].EndPoint != nei) { threadException = new JSONSyntaxErrorCommaNotExist(t[ti].EndPoint); return(null); } rtn[keystr] = Parse(t[ti]); ti++; } if (s[nextSeparator] != ',' && s[nextSeparator] != '}') { threadException = new JSONSyntaxErrorCommaNotExist(); return(null); } ni = nextSeparator + 1; } } else// if (_s[si] == '[') { rtn = new JSONArray(); if (t.separator.Count == 1) { nextSeparator = t.separator.Dequeue(); if (s[nextSeparator] == ']') { return(rtn); } else { threadException = new JSONSyntaxErrorCommaNotExist(); return(null); } } while (0 < t.separator.Count) { while (s[ni] <= ' ') { ni++; //find next non whitespace } nextSeparator = t.separator.Dequeue(); nei = nextSeparator - 1; while (s[nei] <= ' ') { --nei; //find end non whitespace } char k = s[ni]; if (k != '{' && k != '[') { try { rtn.Add(_parse[k](ni, nei)); } catch { threadException = new JSONSyntaxErrorValueNotExist(ni); return(null); } } else { if (t[ti].EndPoint != nei) { threadException = new JSONSyntaxErrorCommaNotExist(t[ti].EndPoint); return(null); } rtn.Add(Parse(t[ti])); ti++; } if (s[nextSeparator] != ',' && s[nextSeparator] != ']') { threadException = new JSONSyntaxErrorCommaNotExist(nextSeparator); return(null); } ni = nextSeparator + 1; } } return(rtn); }//for single thread
}//for multithread static private JSONNode CapsuleParse(ComplexTree <object> t, string _s) { return(Parse(t)); }
}//for single thread static public void ParseThread(ComplexTree <object> t) { //Console.WriteLine("ParseStart " + t.Index); foreach (ComplexTree <object> c in t) { if (c.EndPoint - c.StartPoint > ComplexityHighThreshold && t.Count > 1) { //Console.WriteLine(c.EndPoint - c.StartPoint); c.task = new Thread(() => ParseThread(c)); c.task.Start(); } /* * else if (c.EndPoint - c.Index > ComplexityLowThreshold && t.Count > 1) * { * c.task = new Thread(() => Parse(c)); * c.task.Start(); * }*/ } JSONNode rtn = null; int ni = t.StartPoint + 1; //nowindex int ti = 0; //tree index int nei = 0; int nextSeparator; if (s[t.StartPoint] == '{') { rtn = new JSONObject(); t.node = rtn; if (t.separator.Count == 1) { nextSeparator = t.separator.Dequeue(); if (s[nextSeparator] == '}') { return; } else { threadException = new JSONSyntaxErrorCommaNotExist(nextSeparator); return; } } while (0 < t.separator.Count) { nextSeparator = t.separator.Dequeue(); while (s[ni] <= ' ') { ni++; //find next non whitespace } if (s[nextSeparator] != ':') { threadException = new JSONSyntaxErrorCollonNotExist(nextSeparator); return; } nei = nextSeparator - 1; while (s[nei] <= ' ') { --nei; //find end non whitespace } string keystr; if (s[nei] == '"' && s[ni] == '"') { keystr = s.Substring(ni + 1, nei - ni - 1); } else { threadException = new JSONSyntaxErrorKeyNotExist(ni); return; } ni = (nextSeparator + 1); while (s[ni] <= ' ') { ni++; //find next non whitespace } nextSeparator = t.separator.Dequeue(); nei = nextSeparator - 1; while (s[nei] <= ' ') { --nei; //find end non whitespace } char k = s[ni]; if (k != '{' && k != '[') { try { rtn[keystr] = _parse[k](ni, nei); } catch { threadException = new JSONSyntaxErrorValueNotExist(ni); return; } } else { ComplexTree <object> child = t[ti]; if (child.EndPoint != nei) { threadException = new JSONSyntaxErrorCommaNotExist(t[ti].EndPoint); return; } if (child.task == null) { rtn[keystr] = Parse(child); } else { child.nodeIndex = rtn.Count; rtn[keystr] = JSONNull.NullStatic; } //rtn[keystr] = child.task == null ? Parse(child, _s) : child.task.Result; ti++; } if (s[nextSeparator] != ',' && s[nextSeparator] != '}') { threadException = new JSONSyntaxErrorCommaNotExist(nextSeparator); return; } ni = nextSeparator + 1; } } else// if (_s[si] == '[') { rtn = new JSONArray(); t.node = rtn; if (t.separator.Count == 1) { nextSeparator = t.separator.Dequeue(); if (s[nextSeparator] == ']') { return; } else { threadException = new JSONSyntaxErrorCommaNotExist(nextSeparator); return; } } while (0 < t.separator.Count) { nextSeparator = t.separator.Dequeue(); while (s[ni] <= ' ') { ni++; //find next non whitespace } nei = nextSeparator - 1; while (s[nei] <= ' ') { --nei; //find end non whitespace } char k = s[ni]; if (k != '{' && k != '[') { try { rtn.Add(_parse[k](ni, nei)); } catch { threadException = new JSONSyntaxErrorValueNotExist(ni); return; } } else { ComplexTree <object> child = t[ti]; if (child.EndPoint != nei) { threadException = new JSONSyntaxErrorCommaNotExist(t[ti].EndPoint); return; } if (child.task == null) { rtn.Add(Parse(child)); } else { child.nodeIndex = rtn.Count; rtn.Add(JSONNull.NullStatic); } //rtn.Add( child.task == null ? Parse(child, _s) :child.task.Result); ti++; } if (s[nextSeparator] != ',' && s[nextSeparator] != ']') { threadException = new JSONSyntaxErrorCommaNotExist(nextSeparator); return; } ni = nextSeparator + 1; } } if (threadException != null) { return; } foreach (ComplexTree <object> tree in t) { if (tree.task != null) { tree.task.Join(); rtn[tree.nodeIndex] = tree.node; } } //Console.WriteLine("ParseEnd " + t.Index); }//for multithread