/// <summary> /// converting string to NPL table object /// </summary> /// <param name="input">such as "{nid=10, name=\"value\", tab={name1=\"value1\"}}"</param> /// <returns>may return null if failed.</returns> public static NPLObjectProxy StringToNPLTable(string input) { NPLLex lex = new NPLLex(); NPLLex.LexState ls = lex.SetInput(input); ls.nestlevel = 0; try { NPLParser.next(ls); /* read first token */ if(ls.t.token == '{') { NPLObjectProxy output = new NPLObjectProxy(); if (DeserializePureNPLDataBlock(ls, ref output)) { NPLParser.testnext(ls, ';'); if (ls.t.token == (int)NPLLex.RESERVED.TK_EOS) { return output; } } } } catch (Exception err) { ParaGlobal.applog("error:" + err.ToString() + "in NPLHelper::StringToNPLTable()"); return null; } return null; }
public static bool NPLTableToString(string sStorageVar, NPLObjectProxy input, StringBuilder sCode, int nCodeOffset) { return SerializeNPLTableToString(sStorageVar, input, sCode, nCodeOffset); }
/// <summary> /// safe convert the NPL table to string. if the input is nil, output is not assigned. /// </summary> /// <param name="sStorageVar">if null, output is pure table{}, otherwise it is sStorageVar={}</param> /// <param name="input"></param> /// <param name="sCode"></param> /// <param name="nCodeOffset"></param> /// <returns>true if input is a string object and value is written to output. </returns> public static bool SerializeNPLTableToString(string sStorageVar, NPLObjectProxy input, StringBuilder sCode, int nCodeOffset) { sCode.Length = nCodeOffset; int nStorageVarLen = 0; if(sStorageVar!= null) { nStorageVarLen = sStorageVar.Length; if (nStorageVarLen > 0) { sCode.Append(sStorageVar); sCode.Append("="); } } NPLObjectType nType = input.GetMyType(); switch(nType) { case NPLObjectType.NPLObjectType_Number: { double value = (double)input; sCode.Append(value); break; } case NPLObjectType.NPLObjectType_Bool: { bool bValue = (bool)input; sCode.Append(bValue ? "true" : "false"); break; } case NPLObjectType.NPLObjectType_String: { // this is something like string.format("%q") in NPL. string str = (string)input; EncodeStringInQuotation(ref sCode, sCode.Length, str); break; } case NPLObjectType.NPLObjectType_Table: { sCode.Append("{"); foreach (KeyValuePair<string, NPLObjectProxy> pair in input) { // we only serialize item with a string key string key = pair.Key; NPLObjectProxy value = pair.Value; int nOldSize = sCode.Length; // if sKey contains only alphabetic letters, we will use sKey=data,otherwise, we go the safer one ["sKey"]=data. // the first is more efficient in disk space. if (NPLParser.IsIdentifier(key)) { sCode.Append(key); sCode.Append("="); } else { sCode.Append("["); EncodeStringInQuotation(ref sCode, sCode.Length, key); sCode.Append("]="); } if(SerializeNPLTableToString(null, value, sCode, sCode.Length)) { sCode.Append(","); } else { sCode.Length = nOldSize; } } sCode.Append("}"); break; } default: // we will escape any functions, etc. if(nStorageVarLen > 0) { sCode.Length = nCodeOffset; } return false; //break; } return true; }
public static bool DeserializePureNPLDataBlock(NPLLex.LexState ls, ref NPLObjectProxy objProxy) { // data int c = ls.t.token; switch (c) { case (int)NPLLex.RESERVED.TK_TRUE: objProxy.Assign(true); NPLParser.next(ls); return true; case (int)NPLLex.RESERVED.TK_FALSE: objProxy.Assign(false); NPLParser.next(ls); return true; case (int)NPLLex.RESERVED.TK_NIL: objProxy.MakeNil(); NPLParser.next(ls); return true; case (int)NPLLex.RESERVED.TK_NUMBER: objProxy.Assign(ls.t.seminfo.r); NPLParser.next(ls); return true; case (int)NPLLex.RESERVED.TK_STRING: objProxy.Assign(ls.t.seminfo.ts); NPLParser.next(ls); return true; case '-': { // negative number NPLParser.next(ls); if(ls.t.token == (int)NPLLex.RESERVED.TK_NUMBER) { objProxy.Assign(- ls.t.seminfo.r); NPLParser.next(ls); return true; } else return false; } case '{': { // table object NPLObjectProxy tabMsg = objProxy; NPLParser.enterlevel(ls); bool bBreak = false; NPLParser.next(ls); // auto table index that begins with 1. int nTableAutoIndex = 1; while (!bBreak) { c = ls.t.token; if(c == '}') { // end of table NPLParser.leavelevel(ls); NPLParser.next(ls); bBreak = true; } else if (c == (int)NPLLex.RESERVED.TK_NAME) { NPLObjectProxy proxy_ = tabMsg[ls.t.seminfo.ts]; // by name assignment, such as name = data|table NPLParser.next(ls); if(ls.t.token == '=') { NPLParser.next(ls); if (!DeserializePureNPLDataBlock(ls, ref proxy_)) return false; NPLParser.testnext(ls, ','); } else return false; } else if(c == '[') { // by integer or string key assignment, such as [number|string] = data|table NPLParser.next(ls); if (ls.t.token == (int)NPLLex.RESERVED.TK_NUMBER) { // verify that it is an integer, instead of a floating value. NPLObjectProxy proxy_ = tabMsg[(int)(ls.t.seminfo.r)]; NPLParser.next(ls); if(ls.t.token == ']') { NPLParser.next(ls); if(ls.t.token == '=') { NPLParser.next(ls); if (!DeserializePureNPLDataBlock(ls, ref proxy_)) return false; NPLParser.testnext(ls, ','); } else return false; } } else if (ls.t.token == (int)NPLLex.RESERVED.TK_STRING) { // verify that the string is a value key(non-empty); if(ls.t.seminfo.ts == string.Empty) return false; NPLObjectProxy proxy_ = tabMsg[ls.t.seminfo.ts]; NPLParser.next(ls); if(ls.t.token == ']') { NPLParser.next(ls); if(ls.t.token == '=') { NPLParser.next(ls); if (!DeserializePureNPLDataBlock(ls, ref proxy_)) return false; NPLParser.testnext(ls, ','); } else return false; } } else return false; } /// Fixed: 2008.6.3 LiXizhi /// the following is for auto indexed table items {"string1", "string2\r\n", 213, nil,["A"]="B", true, false, {"another table", "field1"}} else { NPLObjectProxy proxy_ = tabMsg[nTableAutoIndex++]; if( ! DeserializePureNPLDataBlock(ls, ref proxy_) ) return false; NPLParser.testnext(ls, ','); } } return true; } default: break; } return false; }