unsigned int FAR PASCAL SJIS2UTF8(WORD KCode, int *byte, char *locale) { wchar_t wchar; int ret; unsigned int code = KCode; unsigned int c, c1, c2, c3; unsigned char *ptr, buf[3]; unsigned short cset; int len = 0; *byte = 2; // CP932からUTF-16LEへ変換する setlocale(LC_ALL, locale); buf[0] = KCode >> 8; if (buf[0] > 0) { len++; } buf[len++] = KCode & 0xff; ret = mbtowc(&wchar, buf, len); if (ret <= 0) { // 変換失敗 cset = 0; if (_stricmp(locale, DEFAULT_LOCALE) == 0) { cset = ConvertUnicode(KCode, mapSJISToUnicode, sizeof(mapSJISToUnicode)/sizeof(mapSJISToUnicode[0])); } if (cset == 0) { c = 0xfffd; // U+FFFD: Replacement Character } else { c = cset; } } else { ptr = (unsigned char *)&wchar; c = ((ptr[1] << 8) | ptr[0]); } // UTF-16LEからUTF-8へ変換する if (0x00000000 <= c && c <= 0x0000007f) { code = (c & 0xff); *byte = 1; } else if (0x00000080 <= c && c <= 0x000007ff) { c1 = ((c >> 6) & 0x1f) | 0xc0; c2 = (c & 0x3f) | 0x80; code = (c1 << 8) | c2; *byte = 2; } else if (0x00000800 <= c && c <= 0x0000ffff) {
void ProcessNextChar(char c) { if (c == '\n') { state = jsBegin; // abandon current parse (if any) and start again return; } switch (state) { case jsBegin: // initial state, expecting '{' if (c == '{') { parser_watcher::StartReceivedMessage(); state = jsExpectId; fieldVal.clear(); fieldId.clear(); arrayDepth = 0; } break; case jsExpectId: // expecting a quoted ID switch (c) { case ' ': // ignore space break; case '"': state = jsId; break; case '}': // empty object, or extra comma at end of field list RemoveLastId(); if (fieldId.size() == 0) { // TODO: should we report this to the monitor as an error? parser_watcher::EndReceivedMessage(); state = jsBegin; } else { RemoveLastIdChar(); state = jsEndVal; } break; default: state = JsError(); break; } break; case jsId: // expecting an identifier, or in the middle of one switch (c) { case '"': state = jsHadId; break; default: if (c < ' ') { state = JsError(); } else if (c != ':' && c != '^') { if (!fieldId.add(c)) { state = JsError(); } } break; } break; case jsHadId: // had a quoted identifier, expecting ':' switch (c) { case ':': state = jsVal; break; case ' ': break; default: state = JsError(); break; } break; case jsVal: // had ':' or ':[', expecting value switch (c) { case ' ': break; case '"': fieldVal.clear(); state = jsStringVal; break; case '[': if (arrayDepth < MAX_ARRAY_NESTING && fieldId.add('^')) { arrayIndices[arrayDepth] = 0; // start an array ++arrayDepth; } else { state = JsError(); } break; case ']': if (InArray()) { EndArray(); // empty array state = jsEndVal; } else { state = JsError(); // ']' received without a matching '[' first } break; case '-': fieldVal.clear(); // TODO: an report error to the watcher state = (fieldVal.add(c)) ? jsNegIntVal : JsError(); break; case '{': // start of a nested object // TODO: report an error to the watcher state = (fieldId.add(':')) ? jsExpectId : JsError(); break; default: if (c >= '0' && c <= '9') { fieldVal.clear(); fieldVal.add(c); // must succeed because we just cleared fieldVal state = jsIntVal; break; } else { state = JsError(); } } break; case jsStringVal: // just had '"' and expecting a string value switch (c) { case '"': ConvertUnicode(); ProcessField(); state = jsEndVal; break; case '\\': state = jsStringEscape; break; default: if (c < ' ') { state = JsError(); } else { fieldVal.add(c); // ignore any error so that long string parameters // just get truncated } break; } break; case jsStringEscape: // just had backslash in a string if (!fieldVal.full()) { switch (c) { case '"': case '\\': case '/': if (!fieldVal.add(c)) { state = JsError(); } break; case 'n': case 't': if (!fieldVal.add(' ')) // replace newline and tab by space { // parser_watcher::ProcessError(); state = JsError(); } break; case 'b': case 'f': case 'r': default: break; } } state = jsStringVal; break; case jsNegIntVal: // had '-' so expecting a integer value // TODO: report an error to the watcher state = (c >= '0' && c <= '9' && fieldVal.add(c)) ? jsIntVal : JsError(); break; case jsIntVal: // receiving an integer value switch (c) { case '.': state = (fieldVal.add(c)) ? jsFracVal : JsError(); break; case ',': ProcessField(); if (InArray()) { ++arrayIndices[arrayDepth - 1]; fieldVal.clear(); state = jsVal; } else { RemoveLastId(); state = jsExpectId; } break; case ']': if (InArray()) { ProcessField(); ++arrayIndices[arrayDepth - 1]; EndArray(); state = jsEndVal; } else { state = JsError(); } break; case '}': if (InArray()) { state = JsError(); } else { ProcessField(); RemoveLastId(); if (fieldId.size() == 0) { parser_watcher::EndReceivedMessage(); state = jsBegin; } else { RemoveLastIdChar(); state = jsEndVal; } } break; default: if (!(c >= '0' && c <= '9' && fieldVal.add(c))) { state = JsError(); } break; } break; case jsFracVal: // receiving a fractional value switch (c) { case ',': ProcessField(); if (InArray()) { ++arrayIndices[arrayDepth - 1]; state = jsVal; } else { RemoveLastId(); state = jsExpectId; } break; case ']': if (InArray()) { ProcessField(); ++arrayIndices[arrayDepth - 1]; EndArray(); state = jsEndVal; } else { state = JsError(); } break; case '}': if (InArray()) { state = JsError(); } else { ProcessField(); RemoveLastId(); if (fieldId.size() == 0) { parser_watcher::EndReceivedMessage(); state = jsBegin; } else { RemoveLastIdChar(); state = jsEndVal; } } break; default: if (!(c >= '0' && c <= '9' && fieldVal.add(c))) { state = JsError(); } break; } break; case jsEndVal: // had the end of a string or array value, expecting comma // or ] or } switch (c) { case ',': if (InArray()) { ++arrayIndices[arrayDepth - 1]; fieldVal.clear(); state = jsVal; } else { RemoveLastId(); state = jsExpectId; } break; case ']': if (InArray()) { ++arrayIndices[arrayDepth - 1]; EndArray(); } else { state = JsError(); } break; case '}': if (InArray()) { state = JsError(); } else { RemoveLastId(); if (fieldId.size() == 0) { parser_watcher::EndReceivedMessage(); state = jsBegin; } else { RemoveLastIdChar(); // state = jsEndVal; // not needed, state == jsEndVal already } } break; default: break; } break; case jsError: // Ignore all characters. State will be reset to jsBegin at the start of // this function when we receive a newline. break; } }