示例#1
0
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);
	}