14 #include <boost/intrusive_ptr.hpp> 21 #pragma region CommonHeaders 22 #ifndef MAX_TABLE_STRING_LENGTH 23 #define MAX_TABLE_STRING_LENGTH 512 26 #ifndef MAX_DEBUG_STRING_LENGTH 27 #define MAX_DEBUG_STRING_LENGTH 1024 31 #define OUTPUT_LOG printf 34 #ifndef LUA_NUMBER_FMT 35 #define LUA_NUMBER_FMT "%.14g" 39 #define snprintf _snprintf 59 mutable long m_ref_count;
69 void intrusive_ptr_add_ref(T* ref)
76 void intrusive_ptr_release(T* ref)
79 if (--(ref->m_ref_count) == 0)
83 #pragma endregion CommonHeaders 95 typedef boost::intrusive_ptr<NPLObjectBase> NPLObjectBase_ptr;
96 typedef boost::intrusive_ptr<NPLTable> NPLTable_ptr;
97 typedef boost::intrusive_ptr<NPLNumberObject> NPLNumberObject_ptr;
98 typedef boost::intrusive_ptr<NPLBoolObject> NPLBoolObject_ptr;
99 typedef boost::intrusive_ptr<NPLStringObject> NPLStringObject_ptr;
101 #pragma region NPLParser 121 Zio(
const char *input,
size_t nSize) :p(input), n(nSize){};
139 #define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r') 142 static const char * token2string[] = {
143 "and",
"break",
"do",
"else",
"elseif",
144 "end",
"false",
"for",
"function",
"if",
145 "in",
"local",
"nil",
"not",
"or",
"repeat",
146 "return",
"then",
"true",
"until",
"while",
"*name",
147 "..",
"...",
"==",
">=",
"<=",
"~=",
148 "*number",
"*string",
"<eof>" 156 static const int EOZ = -1;
157 static const int MAX_INT = 65530;
158 static const int FIRST_RESERVED = 257;
161 static const int MAXNOCHECK = 5;
163 static const int EXTRABUFF = 32;
166 static const int TOKEN_LEN = (
sizeof(
"function") /
sizeof(
char));
170 TK_AND = FIRST_RESERVED, TK_BREAK,
171 TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION,
172 TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT,
173 TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE,
175 TK_NAME, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER,
179 static const int NUM_RESERVED = (int)TK_WHILE - FIRST_RESERVED + 1;
185 LexState * GetState(){
return &m_lexState; };
187 LexState * SetInput(
const char* input,
int nLen)
193 m_zio.n = strlen(input);
197 m_lexState.lookahead.token = TK_EOS;
198 m_lexState.z = &m_zio;
199 m_lexState.linenumber = 1;
200 m_lexState.lastline = 1;
201 m_lexState.buff.clear();
204 if (m_lexState.current ==
'#') {
207 }
while (m_lexState.current !=
'\n' && m_lexState.current != EOZ);
213 static void ThrowError(
LexState *ls,
const char* errorMsg)
219 static const char* FormatString(
const char * zFormat, ...)
221 static char buf_[MAX_DEBUG_STRING_LENGTH + 1];
223 va_start(args, zFormat);
224 vsnprintf(buf_, MAX_DEBUG_STRING_LENGTH, zFormat, args);
230 static const char * luaX_token2str(
LexState *ls,
int token)
232 if (token < FIRST_RESERVED) {
233 assert(token == (
unsigned char)token);
234 return FormatString(
"%c", token);
237 return token2string[token - FIRST_RESERVED];
241 static void luaX_lexerror(
LexState *ls,
const char *s,
int token)
244 luaX_error(ls, s, luaX_token2str(ls, token));
246 luaX_error(ls, s, &(ls->buff[0]));
249 static void luaX_errorline(
LexState *ls,
const char *s,
const char *token,
int line)
251 ThrowError(ls, FormatString(
"%d: %s near `%s'", line, s, token));
254 static void luaX_error(
LexState *ls,
const char *s,
const char *token)
256 luaX_errorline(ls, s, token, ls->linenumber);
259 static void luaX_syntaxerror(
LexState *ls,
const char *msg)
261 const char *lasttoken;
262 switch (ls->t.token) {
264 lasttoken = ls->t.seminfo.ts.c_str();
268 lasttoken = &(ls->buff[0]);
271 lasttoken = luaX_token2str(ls, ls->t.token);
274 luaX_error(ls, msg, lasttoken);
277 static void luaX_checklimit(
LexState *ls,
int val,
int limit,
const char *msg)
280 msg = FormatString(
"too many %s (limit=%d)", msg, limit);
281 luaX_syntaxerror(ls, msg);
285 static void inclinenumber(
LexState *LS)
289 luaX_checklimit(LS, LS->linenumber, MAX_INT,
"lines in a chunk");
297 save_and_next(LS, l);
298 if (currIsNewline(LS))
303 switch (LS->current) {
306 luaX_lexerror(LS, (seminfo) ?
"unfinished long string" :
307 "unfinished long comment", TK_EOS);
310 save_and_next(LS, l);
311 if (LS->current ==
'[') {
313 save_and_next(LS, l);
317 save_and_next(LS, l);
318 if (LS->current ==
']') {
319 if (cont == 0) bBreak =
true;
321 save_and_next(LS, l);
331 save_and_next(LS, l);
335 save_and_next(LS, l);
340 seminfo->ts.append(&(LS->buff[2]), l - 5);
348 save_and_next(LS, l);
349 while (LS->current != del) {
351 switch (LS->current) {
354 luaX_lexerror(LS,
"unfinished string", TK_EOS);
359 luaX_lexerror(LS,
"unfinished string", TK_STRING);
363 switch (LS->current) {
364 case 'a': save(LS,
'\a', l); next(LS);
break;
365 case 'b': save(LS,
'\b', l); next(LS);
break;
366 case 'f': save(LS,
'\f', l); next(LS);
break;
367 case 'n': save(LS,
'\n', l); next(LS);
break;
368 case 'r': save(LS,
'\r', l); next(LS);
break;
369 case 't': save(LS,
'\t', l); next(LS);
break;
370 case 'v': save(LS,
'\v', l); next(LS);
break;
373 save(LS,
'\n', l); inclinenumber(LS);
break;
376 if (!isdigit(LS->current))
377 save_and_next(LS, l);
382 c = 10 * c + (LS->current -
'0');
384 }
while (++i<3 && isdigit(LS->current));
387 luaX_lexerror(LS,
"escape sequence too large", TK_STRING);
396 save_and_next(LS, l);
400 save_and_next(LS, l);
405 seminfo->ts.append(&(LS->buff[1]), l - 3);
415 save_and_next(LS, l);
416 }
while (isalnum(LS->current) || LS->current ==
'_');
425 if (comma) save(LS,
'.', l);
426 while (isdigit(LS->current)) {
428 save_and_next(LS, l);
430 if (LS->current ==
'.') {
431 save_and_next(LS, l);
432 if (LS->current ==
'.') {
433 save_and_next(LS, l);
436 "ambiguous syntax (decimal point x string concatenation)",
440 while (isdigit(LS->current)) {
442 save_and_next(LS, l);
444 if (LS->current ==
'e' || LS->current ==
'E') {
445 save_and_next(LS, l);
446 if (LS->current ==
'+' || LS->current ==
'-')
447 save_and_next(LS, l);
448 while (isdigit(LS->current)) {
450 save_and_next(LS, l);
456 seminfo->r = atof(&LS->buff[0]);
460 luaX_lexerror(LS,
"malformed number", TK_NUMBER);
467 switch (LS->current) {
476 if (LS->current !=
'-')
return '-';
479 if (LS->current ==
'[' && (next(LS) ==
'['))
480 read_long_string(LS, NULL);
482 while (!currIsNewline(LS) && LS->current != EOZ)
488 if (LS->current !=
'[')
return '[';
490 read_long_string(LS, seminfo);
496 if (LS->current !=
'=')
return '=';
497 else { next(LS);
return TK_EQ; }
501 if (LS->current !=
'=')
return '<';
502 else { next(LS);
return TK_LE; }
506 if (LS->current !=
'=')
return '>';
507 else { next(LS);
return TK_GE; }
511 if (LS->current !=
'=')
return '~';
512 else { next(LS);
return TK_NE; }
516 read_string(LS, LS->current, seminfo);
521 if (LS->current ==
'.') {
523 if (LS->current ==
'.') {
527 else return TK_CONCAT;
529 else if (!isdigit(LS->current))
return '.';
531 read_numeral(LS, 1, seminfo);
539 if (isspace(LS->current)) {
543 else if (isdigit(LS->current)) {
544 read_numeral(LS, 0, seminfo);
547 else if (isalpha(LS->current) || LS->current ==
'_') {
549 int l = readname(LS);
551 ts.append(&(LS->buff[0]), l);
558 for (
int i = 0; i < NUM_RESERVED; ++i)
560 if (ts == token2string[i])
561 return i + FIRST_RESERVED;
570 luaX_error(LS,
"invalid control char",
571 FormatString(
"char(%d)", c));
585 static inline int next(
LexState *LS)
587 return LS->current = ((LS->z)->n--) > 0 ? (int)((
unsigned char)(*(LS->z)->p++)) : EOZ;
590 static void checkbuffer(
LexState *LS,
int len)
592 if (((len)+MAXNOCHECK)*
sizeof(
char) > LS->buff.size())
595 LS->buff.resize(len + EXTRABUFF);
599 LS->buff.resize(len * 2);
603 static void save(
LexState *LS,
char c,
int& l)
605 LS->buff[l++] = (char)c;
607 static void save_and_next(
LexState *LS,
int& l)
609 save(LS, LS->current, l);
626 static const int LUA_MAXPARSERLEVEL = 200;
640 ls->lastline = ls->linenumber;
641 if (ls->lookahead.token != NPLLex::TK_EOS) {
642 ls->t = ls->lookahead;
643 ls->lookahead.token = NPLLex::TK_EOS;
646 ls->t.token = NPLLex::luaX_lex(ls, &ls->t.seminfo);
651 assert(ls->lookahead.token == NPLLex::TK_EOS);
652 ls->lookahead.token = NPLLex::luaX_lex(ls, &ls->lookahead.seminfo);
655 static void error_expected(
LexState *ls,
int token)
657 NPLLex::luaX_syntaxerror(ls,
658 NPLLex::FormatString(
"`%s' expected", NPLLex::luaX_token2str(ls, token)));
661 static int testnext(
LexState *ls,
int c)
663 if (ls->t.token == c) {
670 static void check_condition(
LexState *ls,
void* c,
const char* msg)
673 NPLLex::luaX_syntaxerror(ls, msg);
676 static void check_match(
LexState *ls,
int what,
int who,
int where)
678 if (!testnext(ls, what)) {
679 if (where == ls->linenumber)
680 error_expected(ls, what);
682 NPLLex::luaX_syntaxerror(ls, NPLLex::FormatString(
"`%s' expected (to close `%s' at line %d)",
683 NPLLex::luaX_token2str(ls, what), NPLLex::luaX_token2str(ls, who), where));
688 static void check(
LexState *ls,
int c)
690 if (!testnext(ls, c))
691 error_expected(ls, c);
698 if (c == NPLLex::TK_TRUE || c == NPLLex::TK_NIL || c == NPLLex::TK_FALSE || c == NPLLex::TK_NUMBER || c == NPLLex::TK_STRING)
707 if (ls->t.token == NPLLex::TK_NUMBER)
730 else if (c == NPLLex::TK_NAME)
734 if (ls->t.token ==
'=')
737 if (!CheckPureDataBlock(ls))
748 if (ls->t.token == NPLLex::TK_NUMBER)
752 else if (ls->t.token == NPLLex::TK_STRING)
755 if (ls->t.seminfo.ts.empty())
761 if (ls->t.token ==
']')
764 if (ls->t.token ==
'=')
767 if (!CheckPureDataBlock(ls))
777 else if (c == NPLLex::TK_STRING || c == NPLLex::TK_NUMBER || c == NPLLex::TK_NIL || c == NPLLex::TK_FALSE || c == NPLLex::TK_TRUE)
784 if (!CheckPureDataBlock(ls))
801 static bool IsPureData(
const char* input,
int nLen)
804 LexState* ls = lex.SetInput(input, nLen);
809 if (CheckPureDataBlock(ls))
812 if (ls->t.token == NPLLex::TK_EOS)
818 catch (
const char* err)
826 OUTPUT_LOG(
"error: unknown error in NPLParser::IsPureData()\r\n");
832 static bool IsPureTable(
const char* input,
int nLen)
835 LexState* ls = lex.SetInput(input, nLen);
843 if (CheckPureDataBlock(ls))
846 if (ls->t.token == NPLLex::TK_EOS)
853 catch (
const char* err)
861 OUTPUT_LOG(
"error: unknown error in NPLParser::IsPureTable()\r\n");
867 static bool IsMsgData(
const char* input,
int nLen)
870 LexState* ls = lex.SetInput(input, nLen);
877 if (ls->t.token == NPLLex::TK_NAME && ls->t.seminfo.ts ==
"msg")
880 if (ls->t.token ==
'=')
883 if (CheckPureDataBlock(ls))
886 if (ls->t.token == NPLLex::TK_EOS)
894 catch (
const char* err)
902 OUTPUT_LOG(
"error: unknown error in NPLParser::IsMsgData()\r\n");
908 static bool IsIdentifier(
const char* str,
int nLength)
910 bool bIsIdentifier = !isdigit(str[0]);
911 for (
int i = 0; i < nLength && bIsIdentifier; ++i)
914 bIsIdentifier = (isalnum(c) || c ==
'_');
916 return bIsIdentifier;
919 static void enterlevel(
LexState *ls)
921 if (++(ls)->nestlevel > LUA_MAXPARSERLEVEL)
922 NPLLex::luaX_syntaxerror(ls,
"too many syntax levels");
925 static void leavelevel(
LexState *ls)
935 #pragma endregion NPLParser 937 #pragma region NPLObjectProxy 947 NPLObjectType_Number,
948 NPLObjectType_String,
954 inline NPLObjectType GetType(){
return m_type; }
957 NPLObjectType m_type;
970 void SetValue(
double value){ m_value = value; }
971 double GetValue() {
return m_value; }
973 NPLNumberObject& operator = (
double value) { SetValue(value);
return *
this; }
984 NPLBoolObject() :m_value(
false){ m_type = NPLObjectType_Bool; };
990 inline void SetValue(
bool value){ m_value = value; }
991 bool GetValue() {
return m_value; }
993 NPLBoolObject& operator = (
bool value) { SetValue(value);
return *
this; }
1006 NPLStringObject(
const std::string& value) :m_value(value){ m_type = NPLObjectType_String; };
1010 void SetValue(
const std::string& value){ m_value = value; }
1011 std::string& GetValue(){
return m_value; }
1013 NPLStringObject& operator = (
const std::string& value) { SetValue(value);
return *
this; }
1016 std::string m_value;
1046 if (
get() == 0 || GetType() != NPLObjectBase::NPLObjectType_Number)
1051 void operator = (
double value)
1053 if (
get() == 0 || GetType() != NPLObjectBase::NPLObjectType_Number)
1060 if (
get() == 0 || GetType() != NPLObjectBase::NPLObjectType_Bool)
1065 void operator = (
bool value)
1067 if (
get() == 0 || GetType() != NPLObjectBase::NPLObjectType_Bool)
1073 operator const string& ()
1075 if (
get() == 0 || GetType() != NPLObjectBase::NPLObjectType_String)
1080 bool operator == (
const string& value)
1082 if (
get() == 0 || GetType() != NPLObjectBase::NPLObjectType_String)
1087 bool operator == (
const char* value)
1089 if (
get() == 0 || GetType() != NPLObjectBase::NPLObjectType_String)
1095 void operator = (
const std::string& value)
1097 if (
get() == 0 || GetType() != NPLObjectBase::NPLObjectType_String)
1102 void operator = (
const char* value)
1104 if (
get() == 0 || GetType() != NPLObjectBase::NPLObjectType_String)
1111 if (
get() == 0 || GetType() != NPLObjectBase::NPLObjectType_Table)
1113 return ((T*)
get())->CreateGetField(sName);
1118 if (
get() == 0 || GetType() != NPLObjectBase::NPLObjectType_Table)
1120 return ((T*)
get())->CreateGetField(sName);
1126 if (
get() == 0 || GetType() != NPLObjectBase::NPLObjectType_Table)
1128 return ((T*)
get())->CreateGetField(nIndex);
1133 if (
get() == 0 || GetType() != NPLObjectBase::NPLObjectType_Table)
1139 return ((T*)
get())->GetField(sName);
1146 if (
get() == 0 || GetType() != NPLObjectBase::NPLObjectType_Table)
1152 return ((T*)
get())->GetField(sName);
1161 typename T::Iterator_Type begin()
1163 if (
get() == 0 || GetType() != NPLObjectBase::NPLObjectType_Table)
1165 return ((T*)
get())->begin();
1168 typename T::Iterator_Type end()
1170 if (
get() == 0 || GetType() != NPLObjectBase::NPLObjectType_Table)
1172 return ((T*)
get())->end();
1175 typename T::IndexIterator_Type index_begin()
1177 if (
get() == 0 || GetType() != NPLObjectBase::NPLObjectType_Table)
1179 return ((T*)
get())->index_begin();
1182 typename T::IndexIterator_Type index_end()
1184 if (
get() == 0 || GetType() != NPLObjectBase::NPLObjectType_Table)
1186 return ((T*)
get())->index_end();
1192 return (
get() != 0) ?
get()->GetType() : NPLObjectBase::NPLObjectType_Nil;
1222 typedef std::map<std::string, NPLObjectProxy> TableFieldMap_Type;
1223 typedef std::map<int, NPLObjectProxy> TableIntFieldMap_Type;
1224 typedef TableFieldMap_Type::iterator Iterator_Type;
1225 typedef TableIntFieldMap_Type::iterator IndexIterator_Type;
1237 void ToString(std::string& str)
1246 void SetField(
const string& sName,
const NPLObjectProxy& pObject)
1248 TableFieldMap_Type::iterator iter = m_fields.find(sName);
1249 if (iter == m_fields.end())
1251 if (pObject.get() != 0)
1253 m_fields[sName] = pObject;
1258 if (pObject.get() != 0)
1260 iter->second = pObject;
1264 m_fields.erase(iter);
1269 void SetField(
int nIndex,
const NPLObjectProxy& pObject)
1271 TableIntFieldMap_Type::iterator iter = m_index_fields.find(nIndex);
1272 if (iter == m_index_fields.end())
1274 if (pObject.get() != 0)
1276 m_index_fields[nIndex] = pObject;
1281 if (pObject.get() != 0)
1283 iter->second = pObject;
1287 m_index_fields.erase(iter);
1292 NPLObjectProxy GetField(
int nIndex)
1294 TableIntFieldMap_Type::iterator iter = m_index_fields.find(nIndex);
1295 return (iter != m_index_fields.end()) ? iter->second : NPLObjectProxy();
1298 NPLObjectProxy GetField(
const string& sName)
1300 TableFieldMap_Type::iterator iter = m_fields.find(sName);
1301 return (iter != m_fields.end()) ? iter->second : NPLObjectProxy();
1304 NPLObjectProxy& CreateGetField(
int nIndex)
1306 return m_index_fields[nIndex];
1309 NPLObjectProxy& CreateGetField(
const string& sName)
1311 return m_fields[sName];
1314 Iterator_Type begin() {
return m_fields.begin(); };
1315 Iterator_Type end() {
return m_fields.end(); };
1317 IndexIterator_Type index_begin() {
return m_index_fields.begin(); };
1318 IndexIterator_Type index_end() {
return m_index_fields.end(); };
1321 NPLObjectProxy& operator [](
const string& sName) {
return CreateGetField(sName); };
1322 NPLObjectProxy& operator [](
const char* sName) {
return CreateGetField(sName); };
1323 NPLObjectProxy& operator [](
int nIndex) {
return CreateGetField(nIndex); };
1325 TableFieldMap_Type m_fields;
1326 TableIntFieldMap_Type m_index_fields;
1330 #pragma endregion NPLObjectProxy 1332 #pragma region NPLHelper 1341 int c = ls->t.token;
1344 case NPLLex::TK_TRUE:
1346 NPLParser::next(ls);
1348 case NPLLex::TK_FALSE:
1350 NPLParser::next(ls);
1352 case NPLLex::TK_NIL:
1354 NPLParser::next(ls);
1356 case NPLLex::TK_NUMBER:
1357 objProxy = ls->t.seminfo.r;
1358 NPLParser::next(ls);
1360 case NPLLex::TK_STRING:
1361 objProxy = ls->t.seminfo.ts;
1362 NPLParser::next(ls);
1367 NPLParser::next(ls);
1368 if (ls->t.token == NPLLex::TK_NUMBER)
1370 objProxy = -ls->t.seminfo.r;
1371 NPLParser::next(ls);
1380 NPLObjectProxy tabMsg;
1382 NPLParser::enterlevel(ls);
1383 bool bBreak =
false;
1384 NPLParser::next(ls);
1386 int nTableAutoIndex = 1;
1393 NPLParser::leavelevel(ls);
1394 NPLParser::next(ls);
1398 else if (c == NPLLex::TK_NAME)
1400 NPLObjectProxy& proxy_ = tabMsg[ls->t.seminfo.ts];
1402 NPLParser::next(ls);
1403 if (ls->t.token ==
'=')
1405 NPLParser::next(ls);
1406 if (!DeserializePureNPLDataBlock(ls, proxy_))
1408 NPLParser::testnext(ls,
',');
1416 NPLParser::next(ls);
1417 if (ls->t.token == NPLLex::TK_NUMBER)
1420 NPLObjectProxy& proxy_ = tabMsg[(int)(ls->t.seminfo.r)];
1422 NPLParser::next(ls);
1423 if (ls->t.token ==
']')
1425 NPLParser::next(ls);
1426 if (ls->t.token ==
'=')
1428 NPLParser::next(ls);
1429 if (!DeserializePureNPLDataBlock(ls, proxy_))
1431 NPLParser::testnext(ls,
',');
1437 else if (ls->t.token == NPLLex::TK_STRING)
1440 if (ls->t.seminfo.ts.empty())
1443 NPLObjectProxy& proxy_ = tabMsg[ls->t.seminfo.ts];
1444 NPLParser::next(ls);
1445 if (ls->t.token ==
']')
1447 NPLParser::next(ls);
1448 if (ls->t.token ==
'=')
1450 NPLParser::next(ls);
1451 if (!DeserializePureNPLDataBlock(ls, proxy_))
1453 NPLParser::testnext(ls,
',');
1466 NPLObjectProxy& proxy_ = tabMsg[nTableAutoIndex++];
1467 if (!DeserializePureNPLDataBlock(ls, proxy_))
1469 NPLParser::testnext(ls,
',');
1488 nCodeSize = strlen(sCode);
1489 return NPLParser::IsMsgData(sCode, nCodeSize);
1498 nCodeSize = strlen(sCode);
1499 return NPLParser::IsPureData(sCode, nCodeSize);
1508 nCodeSize = strlen(sCode);
1509 return NPLParser::IsPureTable(sCode, nCodeSize);
1517 LexState* ls = lex.SetInput(input, nLen);
1522 NPLParser::next(ls);
1524 if (ls->t.token ==
'{')
1526 NPLObjectProxy output;
1527 if (DeserializePureNPLDataBlock(ls, output))
1529 NPLParser::testnext(ls,
';');
1530 if (ls->t.token == NPLLex::TK_EOS)
1537 catch (
const char* err)
1539 OUTPUT_LOG(
"error: %s in NPLHelper::StringToNPLTable()\n", err);
1540 return NPLObjectProxy();
1544 OUTPUT_LOG(
"error: unknown error in NPLHelper::StringToNPLTable()\n");
1545 return NPLObjectProxy();
1547 return NPLObjectProxy();
1555 LexState* ls = lex.SetInput(input, nLen);
1560 NPLParser::next(ls);
1562 if (ls->t.token == NPLLex::TK_NAME && ls->t.seminfo.ts ==
"msg")
1564 NPLParser::next(ls);
1565 if (ls->t.token ==
'=')
1567 NPLParser::next(ls);
1568 NPLObjectProxy output;
1569 if (DeserializePureNPLDataBlock(ls, output))
1571 NPLParser::testnext(ls,
';');
1572 if (ls->t.token == NPLLex::TK_EOS)
1580 catch (
const char* err)
1582 OUTPUT_LOG(
"error: %s in NPLHelper::StringToNPLTable()\n", err);
1583 return NPLObjectProxy();
1587 OUTPUT_LOG(
"error: unknown error in NPLHelper::StringToNPLTable()\n");
1588 return NPLObjectProxy();
1590 return NPLObjectProxy();
1593 template <
typename StringType>
1594 static bool SerializeNPLTableToString(
const char* sStorageVar, NPLObjectProxy& input, StringType& sCode,
int nCodeOffset)
1596 sCode.resize(nCodeOffset);
1598 int nStorageVarLen = 0;
1599 if (sStorageVar != NULL)
1601 nStorageVarLen = strlen(sStorageVar);
1602 if (nStorageVarLen > 0)
1604 sCode.append(sStorageVar, nStorageVarLen);
1609 NPLObjectBase::NPLObjectType nType = input.
GetType();
1612 case NPLObjectBase::NPLObjectType_Number:
1614 double value = input;
1616 int nLen = snprintf(buff, 40, LUA_NUMBER_FMT, value);
1617 sCode.append(buff, nLen);
1620 case NPLObjectBase::NPLObjectType_Bool:
1622 bool bValue = input;
1623 sCode.append(bValue ?
"true" :
"false");
1626 case NPLObjectBase::NPLObjectType_String:
1629 const string& str = input;
1630 EncodeStringInQuotation(sCode, (
int)(sCode.size()), str.c_str(), (int)(str.size()));
1633 case NPLObjectBase::NPLObjectType_Table:
1638 for (NPLTable::IndexIterator_Type itCur = input.index_begin(), itEnd = input.index_end(); itCur != itEnd; ++itCur)
1640 int nIndex = itCur->first;
1641 NPLObjectProxy& value = itCur->second;
1642 int nOldSize = (int)(sCode.size());
1643 if (nIndex != nNextIndex)
1647 int nLen = snprintf(buff, 40,
"%d", nIndex);
1648 sCode.append(buff, nLen);
1651 if (SerializeNPLTableToString(NULL, value, sCode, (
int)(sCode.size())))
1654 sCode.resize(nOldSize);
1655 nNextIndex = nIndex + 1;
1658 for (NPLTable::Iterator_Type itCur = input.begin(), itEnd = input.end(); itCur != itEnd; ++itCur)
1660 const string& key = itCur->first;
1661 const char* sKey = key.c_str();
1662 NPLObjectProxy& value = itCur->second;
1663 int nOldSize = (int)(sCode.size());
1666 int nSKeyCount = (int)(key.size());
1667 bool bIsIdentifier = NPLParser::IsIdentifier(sKey, nSKeyCount);
1670 sCode.append(sKey, nSKeyCount);
1676 EncodeStringInQuotation(sCode, (
int)(sCode.size()), sKey, nSKeyCount);
1679 if (SerializeNPLTableToString(NULL, value, sCode, (
int)(sCode.size())))
1685 sCode.resize(nOldSize);
1693 if (nStorageVarLen > 0)
1695 sCode.resize(nCodeOffset);
1704 template <
typename StringType>
1705 static void EncodeStringInQuotation(StringType& buff,
int nOutputOffset,
const char* str,
int nSize)
1710 nSize = strlen(str);
1711 int nFinalSize = nOutputOffset + nSize + 2;
1712 buff.resize(nFinalSize);
1715 int nPos = nOutputOffset;
1717 for (
int i = 0; i < nSize; ++i)
1722 case '"':
case '\\': {
1724 buff.resize(nFinalSize);
1726 buff[nPos++] =
'\\';
1733 buff.resize(nFinalSize);
1735 buff[nPos++] =
'\\';
1741 buff.resize(nFinalSize);
1743 buff[nPos++] =
'\\';
1749 buff.resize(nFinalSize);
1751 buff[nPos++] =
'\\';
1764 assert(nPos == nFinalSize && (
int)(buff.size()) == nFinalSize);
1768 static bool NPLTableToString(
const char* sStorageVar, NPLObjectProxy& input, std::string& sCode,
int nCodeOffset = 0){
1769 return SerializeNPLTableToString(sStorageVar, input, sCode, nCodeOffset);
1772 template <
typename StringType>
1773 static void EncodeStringInQuotation(StringType& output,
int nOutputOffset,
const std::string& input)
1775 EncodeStringInQuotation(output, nOutputOffset, input.c_str(), (int)input.size());
1777 template <
typename StringType>
1778 static void EncodeStringInQuotation(StringType& output,
int nOutputOffset,
const char* input)
1780 EncodeStringInQuotation(output, nOutputOffset, input, strlen(input));
1786 template void NPLHelper::EncodeStringInQuotation(std::string& output,
int nOutputOffset,
const char* input,
int nInputSize);
1787 template bool NPLHelper::SerializeNPLTableToString(
const char* sStorageVar, NPLObjectProxy& input, std::string& sCode,
int nCodeOffset);
1789 #pragma endregion NPLHelper 1791 #pragma region NPLWriter 1792 template <
typename StringBufferType = std::
string>
1821 template <
typename StringBufferType>
1825 typedef StringBufferType Buffer_Type;
1830 CNPLWriterT(Buffer_Type& buff_,
int nReservedSize = -1);
1834 void Reset(
int nReservedSize = -1);
1840 void WriteName(
const char* name,
bool bUseBrackets =
false);
1843 void WriteValue(
const char* value,
bool bInQuotation =
true);
1845 void WriteValue(
const char* buffer,
int nSize,
bool bInQuotation =
true);
1846 void WriteValue(
const string& sStr,
bool bInQuotation =
true);
1848 void WriteValue(
double value);
1856 void Append(
const char* text);
1857 void Append(
const char* pData,
int nSize);
1858 void Append(
const string& sText);
1863 char* AddMemBlock(
int nSize);
1873 #ifndef DISABLE_STATIC_VARIABLE 1875 static const Buffer_Type& GetNilMessage();
1878 static const Buffer_Type& GetEmptyMessage();
1882 Buffer_Type& m_sCode;
1884 bool m_bBeginAssignment;
1888 template <
typename StringBufferType>
1890 : m_sCode(m_buf), m_bBeginAssignment(false), m_nTableLevel(0)
1892 if (nReservedSize > 0)
1893 m_sCode.reserve(nReservedSize);
1896 template <
typename StringBufferType>
1898 : m_sCode(buff_), m_bBeginAssignment(false), m_nTableLevel(0)
1900 if (nReservedSize > 0)
1901 m_sCode.reserve(nReservedSize);
1904 template <
typename StringBufferType>
1910 template <
typename StringBufferType>
1914 if (nReservedSize > 0)
1915 m_sCode.reserve(nReservedSize);
1918 template <
typename StringBufferType>
1923 m_bBeginAssignment =
true;
1937 template <
typename StringBufferType>
1944 if (m_bBeginAssignment)
1950 NPLHelper::EncodeStringInQuotation(m_sCode, (
int)m_sCode.size(), value);
1956 if (m_nTableLevel > 0)
1958 m_bBeginAssignment =
false;
1961 template <
typename StringBufferType>
1968 if (m_bBeginAssignment)
1974 NPLHelper::EncodeStringInQuotation(m_sCode, (
int)m_sCode.size(), buffer, nSize);
1978 size_t nOldSize = m_sCode.size();
1979 m_sCode.resize(nOldSize + nSize);
1980 memcpy((
void*)(m_sCode.c_str() + nOldSize), buffer, nSize);
1982 if (m_nTableLevel > 0)
1984 m_bBeginAssignment =
false;
1987 template <
typename StringBufferType>
1991 snprintf(buff, 40, LUA_NUMBER_FMT, value);
1995 template <
typename StringBufferType>
1998 WriteValue(sStr.c_str(), (int)sStr.size(), bInQuotation);
2000 template <
typename StringBufferType>
2006 template <
typename StringBufferType>
2009 m_sCode += m_bBeginAssignment ?
"={" :
"{";
2011 m_bBeginAssignment =
false;
2014 template <
typename StringBufferType>
2018 if ((--m_nTableLevel) > 0)
2022 template <
typename StringBufferType>
2029 template <
typename StringBufferType>
2032 m_sCode.append(pData, nSize);
2035 template <
typename StringBufferType>
2041 template <
typename StringBufferType>
2046 m_sCode.resize(m_sCode.size() + nSize);
2047 return &(m_sCode[m_sCode.size() - nSize]);
2053 #ifndef DISABLE_STATIC_VARIABLE 2054 template <
typename StringBufferType>
2057 static const StringBufferType g_str =
"msg=nil;";
2061 template <
typename StringBufferType>
2064 static const StringBufferType g_str =
"msg={};";
2071 #pragma endregion NPLWriter NPLNumberObject(double value)
create the table from a serialized string.
Definition: NPLInterface.hpp:966
NPL object proxy.
Definition: NPLInterface.hpp:1035
Definition: NPLInterface.hpp:110
static bool DeserializePureNPLDataBlock(LexState *ls, NPLObjectProxy &objProxy)
Definition: NPLInterface.hpp:1338
for lexer for NPL files
Definition: NPLInterface.hpp:152
NPL helper class.
Definition: NPLInterface.hpp:1335
Definition: NPLInterface.hpp:116
NPLObjectBase::NPLObjectType GetType()
get the type
Definition: NPLInterface.hpp:1190
static const Buffer_Type & GetNilMessage()
return "msg=nil;"
Definition: NPLInterface.hpp:2055
base class for all NPL date members.
Definition: NPLInterface.hpp:940
bool bSucceed
true if no error
Definition: NPLInterface.hpp:136
void WriteName(const char *name, bool bUseBrackets=false)
write a parameter name
Definition: NPLInterface.hpp:1919
Definition: NPLInterface.hpp:43
static const Buffer_Type & GetEmptyMessage()
return "msg={};"
Definition: NPLInterface.hpp:2062
parser for NPL files.
Definition: NPLInterface.hpp:619
lex state
Definition: NPLInterface.hpp:125
a floating point number
Definition: NPLInterface.hpp:961
NPLTable()
this is an empty table
Definition: NPLInterface.hpp:1229
static bool CheckPureDataBlock(LexState *ls)
Definition: NPLInterface.hpp:694
void WriteNil()
write a parameter nil
Definition: NPLInterface.hpp:2001
CNPLWriterT(int nReservedSize=-1)
the internal buffer reserved size.
Definition: NPLInterface.hpp:1889
static bool IsPureTable(const char *sCode, int nCodeSize=-1)
it will return true if input string is a {table} containing only "false", "true", NUMBER...
Definition: NPLInterface.hpp:1506
void WriteValue(const char *value, bool bInQuotation=true)
if bInQuotation is true, it writes a parameter text value.
Definition: NPLInterface.hpp:1938
a boolean
Definition: NPLInterface.hpp:981
const Buffer_Type & ToString()
get the current NPL code.
Definition: NPLInterface.hpp:1869
a simple class for creating NPL script code, especially data table code.
Definition: NPLInterface.hpp:1793
static NPLObjectProxy StringToNPLTable(const char *input, int nLen=-1)
converting string to NPL table object
Definition: NPLInterface.hpp:1515
static NPLObjectProxy MsgStringToNPLTable(const char *input, int nLen=-1)
same as StringToNPLTable(), except that it begins with "msg={...}"
Definition: NPLInterface.hpp:1553
NPLStringObject(const std::string &value)
create the table from a serialized string.
Definition: NPLInterface.hpp:1006
Definition: NPLInterface.hpp:103
static bool IsSCodePureData(const char *sCode, int nCodeSize=-1)
verify the script code.
Definition: NPLInterface.hpp:1485
NPLBoolObject(bool value)
create the table from a serialized string.
Definition: NPLInterface.hpp:986
void BeginTable()
write begin table "{"
Definition: NPLInterface.hpp:2007
void WriteParamDelimiter()
write ";"
Definition: NPLInterface.hpp:1866
void EndTable()
write end table "}"
Definition: NPLInterface.hpp:2015
void Append(const char *text)
append any text
Definition: NPLInterface.hpp:2023
char * AddMemBlock(int nSize)
add a mem block of size nSize and return the address of the block.
Definition: NPLInterface.hpp:2042
a floating point number
Definition: NPLInterface.hpp:1001
single-threaded reference counted base class for boost::intrusive_ptr all boost::intrusive_ptr<T>, should derive from this class.
Definition: NPLInterface.hpp:56
this is a pure c++ implementation of lua table.
Definition: NPLInterface.hpp:1219
static bool NPLTableToString(const char *sStorageVar, NPLObjectProxy &input, std::string &sCode, int nCodeOffset=0)
same as SerializeNPLTableToString.
Definition: NPLInterface.hpp:1768
void Reset(int nReservedSize=-1)
reset the writer
Definition: NPLInterface.hpp:1911
static bool IsPureData(const char *sCode, int nCodeSize=-1)
it will return true if input string is "false", "true", NUMBER, STRING, and {table} ...
Definition: NPLInterface.hpp:1496