void DecodeURLComponentImpl::vector(const ColumnString::Chars_t & data, const ColumnString::Offsets_t & offsets, ColumnString::Chars_t & res_data, ColumnString::Offsets_t & res_offsets) { res_data.resize(data.size()); size_t size = offsets.size(); res_offsets.resize(size); size_t prev_offset = 0; size_t res_offset = 0; for (size_t i = 0; i < size; ++i) { const char * src_data = reinterpret_cast<const char *>(&data[prev_offset]); size_t src_size = offsets[i] - prev_offset; size_t dst_size = decodeURL(src_data, src_size, reinterpret_cast<char *>(res_data.data() + res_offset)); res_offset += dst_size; res_offsets[i] = res_offset; prev_offset = offsets[i]; } res_data.resize(res_offset); }
void convert(const String & from_charset, const String & to_charset, const ColumnString::Chars_t & from_chars, const ColumnString::Offsets_t & from_offsets, ColumnString::Chars_t & to_chars, ColumnString::Offsets_t & to_offsets) { auto converter = getConverter(CharsetsFromTo(from_charset, to_charset)); iconv_t iconv_state = converter->impl; to_chars.resize(from_chars.size()); to_offsets.resize(from_offsets.size()); ColumnString::Offset_t current_from_offset = 0; ColumnString::Offset_t current_to_offset = 0; size_t size = from_offsets.size(); for (size_t i = 0; i < size; ++i) { size_t from_string_size = from_offsets[i] - current_from_offset - 1; /// We assume that empty string is empty in every charset. if (0 != from_string_size) { /// reset state of iconv size_t res = iconv(iconv_state, nullptr, nullptr, nullptr, nullptr); if (static_cast<size_t>(-1) == res) throwFromErrno("Cannot reset iconv", ErrorCodes::CANNOT_ICONV); /// perform conversion; resize output buffer and continue if required char * in_buf = const_cast<char *>(reinterpret_cast<const char *>(&from_chars[current_from_offset])); size_t in_bytes_left = from_string_size; char * out_buf = reinterpret_cast<char *>(&to_chars[current_to_offset]); size_t out_bytes_left = to_chars.size() - current_to_offset; while (in_bytes_left) { size_t res = iconv(iconv_state, &in_buf, &in_bytes_left, &out_buf, &out_bytes_left); current_to_offset = to_chars.size() - out_bytes_left; if (static_cast<size_t>(-1) == res) { if (E2BIG == errno) { to_chars.resize(to_chars.size() * 2); out_buf = reinterpret_cast<char *>(&to_chars[current_to_offset]); out_bytes_left = to_chars.size() - current_to_offset; continue; } throwFromErrno("Cannot convert charset", ErrorCodes::CANNOT_ICONV); } } } if (to_chars.size() < current_to_offset + 1) to_chars.resize(current_to_offset + 1); to_chars[current_to_offset] = 0; ++current_to_offset; to_offsets[i] = current_to_offset; current_from_offset = from_offsets[i]; } to_chars.resize(current_to_offset); }