static int udf_name_conv_char(uint8_t *str_o, int str_o_max_len, int *str_o_idx, const uint8_t *str_i, int str_i_max_len, int *str_i_idx, int u_ch, int *needsCRC, int (*conv_f)(wchar_t, unsigned char *, int), int translate) { unicode_t c; int illChar = 0; int len, gotch = 0; while (!gotch && *str_i_idx < str_i_max_len) { if (*str_o_idx >= str_o_max_len) { *needsCRC = 1; return gotch; } len = get_utf16_char(str_i, str_i_max_len, *str_i_idx, u_ch, &c); /* These chars cannot be converted. Replace them. */ if (c == 0 || c > UNICODE_MAX || (conv_f && c > MAX_WCHAR_T) || (translate && c == '/')) { illChar = 1; if (!translate) gotch = 1; } else if (illChar) break; else gotch = 1; *str_i_idx += len; } if (illChar) { *needsCRC = 1; c = ILLEGAL_CHAR_MARK; gotch = 1; } if (gotch) { if (conv_f) { len = conv_f(c, &str_o[*str_o_idx], str_o_max_len - *str_o_idx); } else { len = utf32_to_utf8(c, &str_o[*str_o_idx], str_o_max_len - *str_o_idx); if (len < 0) len = -ENAMETOOLONG; } /* Valid character? */ if (len >= 0) *str_o_idx += len; else if (len == -ENAMETOOLONG) { *needsCRC = 1; gotch = 0; } else { str_o[(*str_o_idx)++] = ILLEGAL_CHAR_MARK; *needsCRC = 1; } } return gotch; }
std::string utf32_to_utf8(const std::u32string & str_u32){ std::string str_u8; str_u8.reserve(str_u32.length()); // just a guess. for(const uint32_t u32 : str_u32) str_u8.append(utf32_to_utf8(u32)); return str_u8; }
char* dsShow_getCurScrText(DaisyShow *thiz){ if(!thiz || !thiz->show_line){ return 0; } int i,start; size_t ret_in, ret_out; //for tts play ret_in = 0; start = thiz->start_line; for(i = start; i<(start + thiz->show_line) && i<thiz->total_line;i++) { ret_in += thiz->lineLen[i]; } DBGMSG("ret_in=%d\n",ret_in); ret_out = sizeof(thiz->pScrText)-2; memset(thiz->pScrText, 0, ret_out); utf32_to_utf8( (char*)thiz->pText + thiz->lineStart[start], &ret_in, thiz->pScrText, &ret_out ); return thiz->pScrText; }
static char* allocFromUTF16OrUTF32(const T* in, L len) { if (len == 0) return getEmptyString(); size_t bytes = 0; const T* end = in+len; const T* p = in; while (p < end) { bytes += utf32_to_utf8_bytes(*p); p++; } SharedBuffer* buf = SharedBuffer::alloc(bytes+1); LOG_ASSERT(buf, "Unable to allocate shared buffer"); if (buf) { p = in; char* str = (char*)buf->data(); char* d = str; while (p < end) { const T c = *p++; size_t len = utf32_to_utf8_bytes(c); utf32_to_utf8((uint8_t*)d, c, len); d += len; } *d = 0; return str; } return getEmptyString(); }
static int befs_nls2utf(struct super_block *sb, const char *in, int in_len, char **out, int *out_len) { struct nls_table *nls = BEFS_SB(sb)->nls; int i, o; wchar_t uni; int unilen, utflen; char *result; /* * There are nls characters that will translate to 3-chars-wide UTF-8 * characters, an additional byte is needed to save the final \0 * in special cases */ int maxlen = (3 * in_len) + 1; befs_debug(sb, "---> %s\n", __func__); if (!nls) { befs_error(sb, "%s called with no NLS table loaded.", __func__); return -EINVAL; } *out = result = kmalloc(maxlen, GFP_NOFS); if (!*out) { *out_len = 0; return -ENOMEM; } for (i = o = 0; i < in_len; i += unilen, o += utflen) { /* convert from nls to unicode */ unilen = nls->char2uni(&in[i], in_len - i, &uni); if (unilen < 0) goto conv_err; /* convert from unicode to UTF-8 */ utflen = utf32_to_utf8(uni, &result[o], 3); if (utflen <= 0) goto conv_err; } result[o] = '\0'; *out_len = o; befs_debug(sb, "<--- %s", __func__); return i; conv_err: befs_error(sb, "Name using character set %s contains a character that " "cannot be converted to unicode.", nls->charset); befs_debug(sb, "<--- %s", __func__); kfree(result); return -EILSEQ; }
FileInputHD(const u32string& file) : InputHD(1) { std::string utf8_f = utf32_to_utf8(file); m_stream.open(utf8_f.c_str()); mpz_class left(0); //this is 2^63 - 1 mpz_class right("9223372036854775807"); Range r(&left, &right); m_variance = tuple_t{{DIM_ZERO,Types::Range::create(r)}}; }
static int uni2char(wchar_t uni, unsigned char *out, int boundlen) { int n; if (boundlen <= 0) return -ENAMETOOLONG; n = utf32_to_utf8(uni, out, boundlen); if (n < 0) { *out = '?'; return -EINVAL; } return n; }
//-----------------------------------------------------------------// bool probe_file(const lstring& fn, bool dir) { #ifdef WIN32 struct _stat st; wchar_t* wfn = new wchar_t[fn.size() + 1]; for(uint32_t i = 0; i < fn.size(); ++i) { wfn[i] = fn[i]; } wfn[fn.size()] = 0; int ret = _wstat(wfn, &st); delete[] wfn; if(ret == 0) { #else std::string s; utf32_to_utf8(fn, s); struct stat st; if(stat(s.c_str(), &st) == 0) { #endif if(dir) { bool d = S_ISDIR(st.st_mode); if(d) return true; } else { return true; } } return false; } //-----------------------------------------------------------------// /*! @brief ファイルのサイズを返す @param[in] fn ファイル名 @return ファイルサイズ */ //-----------------------------------------------------------------// size_t get_file_size(const std::string& fn) { size_t fsz = 0; struct stat st; if(stat(fn.c_str(), &st) == 0) { fsz = st.st_size; } return fsz; }
std::string print_constant(const Constant& c) { std::ostringstream str; switch (c.index()) { case TYPE_INDEX_DIMENSION: str << "dimension: " << get_constant<dimension_index>(c); return str.str(); break; case TYPE_INDEX_INTMP: return Types::Intmp::get(c).get_str(); break; case TYPE_INDEX_SPECIAL: str << "special<" << get_constant<Special>(c) << ">"; return str.str(); break; case TYPE_INDEX_USTRING: str << "\"" << utf32_to_utf8(Types::String::get(c)) << "\""; return str.str(); break; case TYPE_INDEX_CALC: return "calc"; break; case TYPE_INDEX_DEMAND: return "demand"; break; case TYPE_INDEX_INTENSION: return "intension"; break; default: str << "unknown of index " << c.index(); return str.str(); break; } }
static char* allocFromUTF32(const char32_t* in, size_t len) { if (len == 0) { return getEmptyString(); } const ssize_t bytes = utf32_to_utf8_length(in, len); if (bytes < 0) { return getEmptyString(); } SharedBuffer* buf = SharedBuffer::alloc(bytes+1); if (!buf) { return getEmptyString(); } char* str = (char*) buf->data(); utf32_to_utf8(in, len, str); return str; }
static char* allocFromUTF32(const char32_t* in, size_t len) { if (len == 0) { return getEmptyString(); } const ssize_t resultStrLen = utf32_to_utf8_length(in, len) + 1; if (resultStrLen < 1) { return getEmptyString(); } SharedBuffer* buf = SharedBuffer::alloc(resultStrLen); ALOG_ASSERT(buf, "Unable to allocate shared buffer"); if (!buf) { return getEmptyString(); } char* resultStr = (char*) buf->data(); utf32_to_utf8(in, len, resultStr, resultStrLen); return resultStr; }
/** * [dentry] contains string encoded in coding system that corresponds * to [sf_g]->nls, we must convert it to UTF8 here and pass down to * [sf_make_path] which will allocate SHFLSTRING and fill it in */ int sf_path_from_dentry(const char *caller, struct sf_glob_info *sf_g, struct sf_inode_info *sf_i, struct dentry *dentry, SHFLSTRING **result) { int err; const char *d_name; size_t d_len; const char *name; size_t len = 0; TRACE(); d_name = dentry->d_name.name; d_len = dentry->d_name.len; if (sf_g->nls) { size_t in_len, i, out_bound_len; const char *in; char *out; in = d_name; in_len = d_len; out_bound_len = PATH_MAX; out = kmalloc(out_bound_len, GFP_KERNEL); name = out; for (i = 0; i < d_len; ++i) { /* We renamed the linux kernel wchar_t type to linux_wchar_t in the-linux-kernel.h, as it conflicts with the C++ type of that name. */ linux_wchar_t uni; int nb; nb = sf_g->nls->char2uni(in, in_len, &uni); if (nb < 0) { LogFunc(("nls->char2uni failed %x %d\n", *in, in_len)); err = -EINVAL; goto fail1; } in_len -= nb; in += nb; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31) nb = utf32_to_utf8(uni, out, out_bound_len); #else nb = utf8_wctomb(out, uni, out_bound_len); #endif if (nb < 0) { LogFunc(("nls->uni2char failed %x %d\n", uni, out_bound_len)); err = -EINVAL; goto fail1; } out_bound_len -= nb; out += nb; len += nb; } if (len >= PATH_MAX - 1) { err = -ENAMETOOLONG; goto fail1; } LogFunc(("result(%d) = %.*s\n", len, len, name)); *out = 0; } else { name = d_name; len = d_len; } err = sf_make_path(caller, sf_i, name, len, result); if (name != d_name) kfree(name); return err; fail1: kfree(name); return err; }
ssize_t encoder_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) { struct encoder_dev *dev = filp->private_data; int quantum = dev->quantum, qset = dev->qset; int s_pos, q_pos; ssize_t retval = -ENOMEM; if (down_interruptible(&dev->sem)) return -ERESTARTSYS; if (*f_pos >= quantum * qset) { retval = 0; goto out; } s_pos = (long) *f_pos / quantum; q_pos = (long) *f_pos % quantum; if (!dev->data) { dev->data = kmalloc(qset * sizeof(char *), GFP_KERNEL); if (!dev->data) goto out; memset(dev->data, 0, qset * sizeof(char *)); } if (!dev->data[s_pos]) { dev->data[s_pos] = kmalloc(quantum, GFP_KERNEL); if (!dev->data[s_pos]) goto out; } /* write only up to the end of this quantum */ char* encoded_new_data; switch(current_input_encoding){ case ENC_UTF8: encoded_new_data = dev->data[s_pos] + q_pos; break; case ENC_UTF16: count = utf16_to_utf8(dev->data[s_pos] + q_pos, count, encoded_new_data); break; case ENC_UTF32: count = utf32_to_utf8(dev->data[s_pos] + q_pos, count, encoded_new_data); break; case ENC_88591: /*do nothing*/ break; case ENC_88599: /*do nothing*/ break; } if (count > quantum - q_pos) count = quantum - q_pos; if (copy_from_user(encoded_new_data, buf, count)) { retval = -EFAULT; goto out; } *f_pos += count; retval = count; /* update the size */ if (dev->size < *f_pos) dev->size = *f_pos; out: up(&dev->sem); return retval; }
int worldfactory::show_worldgen_tab_confirm(WINDOW *win, WORLDPTR world) { const int iTooltipHeight = 1; const int iContentHeight = FULL_SCREEN_HEIGHT - 3 - iTooltipHeight; const int iOffsetX = (TERMX > FULL_SCREEN_WIDTH) ? (TERMX - FULL_SCREEN_WIDTH) / 2 : 0; const int iOffsetY = (TERMY > FULL_SCREEN_HEIGHT) ? (TERMY - FULL_SCREEN_HEIGHT) / 2 : 0; WINDOW *w_confirmation = newwin(iContentHeight, FULL_SCREEN_WIDTH - 2, iTooltipHeight + 2 + iOffsetY, 1 + iOffsetX); unsigned namebar_pos = 3 + utf8_width(_("World Name:")); int line = 1; bool noname = false; long ch; std::string worldname = world->world_name; do { mvwprintz(w_confirmation, 2, 2, c_ltgray, _("World Name:")); mvwprintz(w_confirmation, 2, namebar_pos, c_ltgray, "______________________________"); fold_and_print(w_confirmation, 10, 2, 76, c_ltgray, _("When you are satisfied with the world as it is and are ready to continue, press >")); fold_and_print(w_confirmation, 12, 2, 76, c_ltgray, _("To go back and review your world, press <")); fold_and_print(w_confirmation, 14, 2, 76, c_green, _("To pick a random name for your world, press ?.")); if (!noname) { mvwprintz(w_confirmation, 2, namebar_pos, c_ltgray, "%s", worldname.c_str()); if (line == 1) { wprintz(w_confirmation, h_ltgray, "_"); } } wrefresh(win); wrefresh(w_confirmation); refresh(); ch = input(); if (noname) { mvwprintz(w_confirmation, 2, namebar_pos, c_ltgray, "______________________________"); noname = false; } if (ch == '>') { if (worldname.size() == 0) { mvwprintz(w_confirmation, 2, namebar_pos, h_ltgray, _("______NO NAME ENTERED!!!!_____")); noname = true; wrefresh(w_confirmation); if (!query_yn(_("Are you SURE you're finished? World name will be randomly generated."))) { continue; continue; } else { world->world_name = pick_random_name(); if (!valid_worldname(world->world_name)) { continue; } return 1; } } else if (query_yn(_("Are you SURE you're finished?")) && valid_worldname(worldname)) { world->world_name = worldname; werase(w_confirmation); delwin(w_confirmation); return 1; } else { continue; } } else if (ch == '<') { world->world_name = worldname; werase(w_confirmation); delwin(w_confirmation); return -1; } else if (ch == '?') { mvwprintz(w_confirmation, 2, namebar_pos, c_ltgray, "______________________________"); world->world_name = worldname = pick_random_name(); } else if (ch == KEY_ESCAPE) { world->world_name = worldname; // cache the current worldname just in case they say No to the exit query return -999; } else { switch (line) { case 1: if (ch == KEY_BACKSPACE || ch == 127) { if (worldname.size() > 0) { //erase utf8 character TODO: make a function while(worldname.size() > 0 && ((unsigned char)worldname[worldname.size() - 1]) >= 128 && ((unsigned char)worldname[(int)worldname.size() - 1]) <= 191) { worldname.erase(worldname.size() - 1); } worldname.erase(worldname.size() - 1); mvwprintz(w_confirmation, 2, namebar_pos, c_ltgray, "______________________________ "); mvwprintz(w_confirmation, 2, namebar_pos, c_ltgray, "%s", worldname.c_str()); wprintz(w_confirmation, h_ltgray, "_"); } } else if (is_char_allowed(ch) && utf8_width(worldname.c_str()) < 30) { worldname.push_back(ch); } else if(ch == KEY_F(2)) { std::string tmp = get_input_string_from_file(); int tmplen = utf8_width(tmp.c_str()); if(tmplen > 0 && tmplen + utf8_width(worldname.c_str()) < 30) { worldname.append(tmp); } } //experimental unicode input else if(ch > 127) { std::string tmp = utf32_to_utf8(ch); int tmplen = utf8_width(tmp.c_str()); if(tmplen > 0 && tmplen + utf8_width(worldname.c_str()) < 30) { worldname.append(tmp); } } break; } } } while (true); return 0; }
std::string string_input_popup(std::string title, int max_length, std::string input) { std::string ret = input; int titlesize = utf8_width(title.c_str()); int startx = titlesize + 2; int iPopupWidth = (max_length == 0) ? FULL_SCREEN_WIDTH : max_length + titlesize + 4; if (iPopupWidth > FULL_SCREEN_WIDTH) { iPopupWidth = FULL_SCREEN_WIDTH; max_length = FULL_SCREEN_WIDTH - titlesize - 4; } WINDOW *w = newwin(3, iPopupWidth, (TERMY-3)/2, ((TERMX > iPopupWidth) ? (TERMX-iPopupWidth)/2 : 0)); wborder(w, LINE_XOXO, LINE_XOXO, LINE_OXOX, LINE_OXOX, LINE_OXXO, LINE_OOXX, LINE_XXOO, LINE_XOOX ); std::string underline = ""; for (int i = startx ; i < iPopupWidth-1; i++) underline.push_back('_'); mvwprintz(w, 1, 1, c_ltred, "%s", title.c_str()); mvwprintz(w, 1, startx, c_ltgray, "%s", underline.c_str()); if (input != "") mvwprintz(w, 1, startx, c_magenta, "%s", input.c_str()); int posx = startx + utf8_width(input.c_str()); mvwputch(w, 1, posx, h_ltgray, '_'); do { wrefresh(w); long ch = getch(); if (ch == 27) { // Escape werase(w); wrefresh(w); delwin(w); refresh(); return ""; } else if (ch == '\n') { werase(w); wrefresh(w); delwin(w); refresh(); return ret; } else if (ch == KEY_BACKSPACE || ch == 127) { // Move the cursor back and re-draw it if (ret.size() > 0) { //erease utf8 character TODO: make a function while(ret.size()>0 && ((unsigned char)ret[ret.size()-1])>=128 && ((unsigned char)ret[(int)ret.size()-1])<=191) { ret.erase(ret.size()-1); } ret.erase(ret.size()-1); } } else if(ch==KEY_F(2)) { std::string tmp = get_input_string_from_file(); int tmplen = utf8_width(tmp.c_str()); if(tmplen>0 && (tmplen+utf8_width(ret.c_str())<=max_length||max_length==0)) { ret.append(tmp); } } //experimental unicode input else { std::string tmp = utf32_to_utf8(ch); int tmplen = utf8_width(tmp.c_str()); if(tmplen>0 && (tmplen+utf8_width(ret.c_str())<=max_length||max_length==0)) { ret.append(tmp); } } mvwprintz(w, 1, startx, c_ltgray, "%s", underline.c_str()); mvwprintz(w, 1, startx, c_ltgray, "%s", ret.c_str()); wprintz(w, h_ltgray, "_"); } while (true); }
//-----------------------------------------------------------------// inline std::string utf32_to_utf8(const lstring& src) noexcept { std::string dst; utf32_to_utf8(src, dst); return dst; }
int worldfactory::show_worldgen_tab_confirm(WINDOW *win, WORLDPTR world) { const int iTooltipHeight = 1; const int iContentHeight = FULL_SCREEN_HEIGHT - 3 - iTooltipHeight; const int iOffsetX = (TERMX > FULL_SCREEN_WIDTH) ? (TERMX - FULL_SCREEN_WIDTH) / 2 : 0; const int iOffsetY = (TERMY > FULL_SCREEN_HEIGHT) ? (TERMY - FULL_SCREEN_HEIGHT) / 2 : 0; WINDOW *w_confirmation = newwin(iContentHeight, FULL_SCREEN_WIDTH - 2, iTooltipHeight + 2 + iOffsetY, 1 + iOffsetX); unsigned namebar_y = 1; unsigned namebar_x = 3 + utf8_width(_("World Name:")); int line = 1; bool noname = false; input_context ctxt("WORLDGEN_CONFIRM_DIALOG"); // Disabled because it conflicts with the "pick random world name" option, // feel free to enable it and change its keybinding in keybindings.json // ctxt.register_action("HELP_KEYBINDINGS"); ctxt.register_action("QUIT"); ctxt.register_action("ANY_INPUT"); ctxt.register_action("NEXT_TAB"); ctxt.register_action("PREV_TAB"); ctxt.register_action("PICK_RANDOM_WORLDNAME"); std::string worldname = world->world_name; do { mvwprintz(w_confirmation, namebar_y, 2, c_white, _("World Name:")); mvwprintz(w_confirmation, namebar_y, namebar_x, c_ltgray, "______________________________"); fold_and_print(w_confirmation, 3, 2, 76, c_ltgray, _("Press <color_yellow>?</color> to pick a random name for your world.")); fold_and_print(w_confirmation, FULL_SCREEN_HEIGHT / 2 - 2, 2, 76, c_ltgray, _("\ Press <color_yellow>></color> when you are satisfied with the world as it is and are ready \ to continue, or <color_yellow><</color> to go back and review your world.")); if (!noname) { mvwprintz(w_confirmation, namebar_y, namebar_x, c_ltgray, "%s", worldname.c_str()); if (line == 1) { wprintz(w_confirmation, h_ltgray, "_"); } } if (noname) { mvwprintz(w_confirmation, namebar_y, namebar_x, c_ltgray, "______________________________"); noname = false; } wrefresh(win); wrefresh(w_confirmation); refresh(); const std::string action = ctxt.handle_input(); if (action == "NEXT_TAB") { if (worldname.empty()) { mvwprintz(w_confirmation, namebar_y, namebar_x, h_ltgray, _("______NO NAME ENTERED!!!!_____")); noname = true; wrefresh(w_confirmation); if (!query_yn(_("Are you SURE you're finished? World name will be randomly generated."))) { continue; } else { world->world_name = pick_random_name(); if (!valid_worldname(world->world_name)) { continue; } return 1; } } else if (query_yn(_("Are you SURE you're finished?")) && valid_worldname(worldname)) { world->world_name = worldname; werase(w_confirmation); delwin(w_confirmation); return 1; } else { continue; } } else if (action == "PREV_TAB") { world->world_name = worldname; werase(w_confirmation); delwin(w_confirmation); return -1; } else if (action == "PICK_RANDOM_WORLDNAME") { mvwprintz(w_confirmation, namebar_y, namebar_x, c_ltgray, "______________________________"); world->world_name = worldname = pick_random_name(); } else if (action == "QUIT") { world->world_name = worldname; // cache the current worldname just in case they say No to the exit query return -999; } else if (action == "ANY_INPUT") { const long ch = ctxt.get_raw_input().get_first_input(); switch (line) { case 1: if (ch == KEY_BACKSPACE || ch == 127) { if (!worldname.empty()) { //erase utf8 character TODO: make a function while(!worldname.empty() && ((unsigned char)worldname[worldname.size() - 1]) >= 128 && ((unsigned char)worldname[(int)worldname.size() - 1]) <= 191) { worldname.erase(worldname.size() - 1); } worldname.erase(worldname.size() - 1); mvwprintz(w_confirmation, namebar_y, namebar_x, c_ltgray, "______________________________ "); mvwprintz(w_confirmation, namebar_y, namebar_x, c_ltgray, "%s", worldname.c_str()); wprintz(w_confirmation, h_ltgray, "_"); } } else if (is_char_allowed(ch) && utf8_width(worldname.c_str()) < 30) { worldname.push_back(ch); } else if(ch == KEY_F(2)) { std::string tmp = get_input_string_from_file(); int tmplen = utf8_width(tmp.c_str()); if(tmplen > 0 && tmplen + utf8_width(worldname.c_str()) < 30) { worldname.append(tmp); } } //experimental unicode input else if(ch > 127) { std::string tmp = utf32_to_utf8(ch); int tmplen = utf8_width(tmp.c_str()); if(tmplen > 0 && tmplen + utf8_width(worldname.c_str()) < 30) { worldname.append(tmp); } } break; } } } while (true); return 0; }
static utf8_string utf(utf32_char const* str, size_t size) { return utf32_to_utf8(str, size); }
std::pair<bool, u32string> build_escaped_characters ( Iterator& current, const Iterator& end ) { std::string building; bool error = false; int to_read = 0; while (*current == '\\' && error == false) { ++current; char32_t c = *current; switch(c) { case 'U': to_read = 8; ++current; break; case 'u': to_read = 4; ++current; break; case 'x': to_read = 2; ++current; break; case 'n': building += "\n"; ++current; break; case 'r': building += "\r"; ++current; break; case 't': building += "\t"; ++current; break; case '\'': building += "\'"; ++current; break; case '\"': building += "\""; ++current; break; case '\\': building += "\\"; ++current; break; default: //invalid control character error = true; break; } //read the requested number of characters std::string chars; if (to_read > 0) { while (to_read > 0 && current != end && *current != '\'') { c = *current; if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) { chars += c; } else { break; } --to_read; ++current; } } //if we didn't read everything then error if (to_read != 0) { error = true; } else { uint32_t value = 0; for (char c : chars) { if (c >= '0' && c <= '9') { value = value * 16 + (c - '0'); } else { value = value * 16 + (c - 'A' + 10); } } //it was a byte if it was two characters, otherwise it was a whole //character if (chars.length() == 2) { building += char(value & 0xFF); } else { building += utf32_to_utf8(u32string(1, value)); } } } u32string u32result = utf8_to_utf32(building); return std::make_pair(!error, u32result); }
std::string JsonIn::get_string() { std::string s = ""; char ch; bool backslash = false; char unihex[5] = "0000"; eat_whitespace(); int startpos = tell(); // the first character had better be a '"' stream->get(ch); if (ch != '"') { std::stringstream err; err << line_number(-1) << ": expecting string but got '" << ch << "'"; throw err.str(); } // add chars to the string, one at a time, converting: // \", \\, \/, \b, \f, \n, \r, \t and \uxxxx according to JSON spec. while (stream->good()) { stream->get(ch); if (ch == '\\') { if (backslash) { s += '\\'; backslash = false; } else { backslash = true; continue; } } else if (backslash) { backslash = false; if (ch == '"') { s += '"'; } else if (ch == '/') { s += '/'; } else if (ch == 'b') { s += '\b'; } else if (ch == 'f') { s += '\f'; } else if (ch == 'n') { s += '\n'; } else if (ch == 'r') { s += '\r'; } else if (ch == 't') { s += '\t'; } else if (ch == 'u') { // get the next four characters as hexadecimal stream->get(unihex, 5); // insert the appropriate unicode character in utf8 // TODO: verify that unihex is in fact 4 hex digits. char** endptr = 0; unsigned u = (unsigned)strtoul(unihex, endptr, 16); s += utf32_to_utf8(u); } else { // for anything else, just add the character, i suppose s += ch; } } else if (ch == '"') { // end of the string skip_separator(); return s; } else { s += ch; } } // if we get to here, probably hit a premature EOF? if (stream->fail()) { throw (std::string)"stream failure while reading string."; } else if (stream->eof()) { stream->clear(); seek(startpos); std::stringstream err; err << line_number() << ": "; err << "couldn't find end of string, reached EOF."; throw err.str(); } throw (std::string)"something went wrong D:"; }
static bool GetExpectedString( const char *src, char **dst, size_t *dst_len, int (*get_codepoint_function)(char32_t, char32_t, bool*)) { if (dst == NULL || dst_len == NULL) { return false; } if (src == NULL || *src == '\0') { src = STR_FOR_NULL_STR; } char32_t codepoints[MAX_CODEPOINTS]; // if array size is changed the for loop needs to be changed size_t src_len = utf8_length(src); if (src_len == 0) { return false; } bool next_is_consumed; size_t j = 0; for (size_t i = 0; i < src_len && j < MAX_CODEPOINTS;) { int32_t ret = utf32_at(src, src_len, i, &i); if (ret < 0) { // failed to parse UTF-8 return false; } ret = get_codepoint_function( static_cast<char32_t>(ret), i + 1 < src_len ? src[i + 1] : 0, &next_is_consumed); if (ret > 0) { codepoints[j] = static_cast<char32_t>(ret); j++; } if (next_is_consumed) { i++; } } size_t length = j; if (length == 0) { // If all of codepoints are invalid, we place the string at the end of // the list. codepoints[0] = 0x10000 + CODEPOINT_FOR_NULL_STR; length = 1; } size_t new_len = utf8_length_from_utf32(codepoints, length); *dst = static_cast<char *>(malloc(new_len + 1)); if (*dst == NULL) { return false; } if (utf32_to_utf8(codepoints, length, *dst, new_len + 1) != new_len) { free(*dst); *dst = NULL; return false; } *dst_len = new_len; return true; }