/** * @brief Deserialize the integer value from the specified input stream. * @param __s Reference to the input stream. */ void load(std::basic_istream<CharT, Traits> &__s) { // We must ensure that subsequent actions will be performed // for very likely integer value, otherwise and exception // should be raised. if (__s.peek() != basic_value_type::integer_token) { throw type_error( "bencode::integer::load the specified stream does " "not contain interpretable bencode integer value\n"); } // Read the leading "i" symbol from the provided stream. __s.get(); // Define the integer symbol representation placeholder. std::basic_stringstream<CharT, Traits> __i; // Define the input stream iterator of the provided stream to // be able to read the integer value symbol by symbol. auto __si = std::istream_iterator<CharT, CharT, Traits>(__s); // Define the output stream to as a buffer for the integer // value, which will be later converted. auto __ival = std::ostream_iterator<CharT, CharT, Traits>(__i); // Copy the values from the input stream into the integer // placeholder string stream. auto __result = copy_until(__si, __ival, [&__s](const CharT& __ch) { // Additionally, check that we did not exceed the // length of the stream to prevent hangs. return !__s.eof() && __ch != basic_value_type::end_token; }, basic_value_type::integer_length); // Covert the value from the string into the integer. __i >> _M_value; // The "e" symbol should be already extracted at this moment, // so validate that the iterator pointing right to it. if (*__result != basic_value_type::end_token) { std::ostringstream __error; __error << "bencode::integer::load the end of the integer " "`e` expected, but `" << CharT(*__result) << "` found\n"; throw encoding_error(__error.str()); } // Validate that decoded value is an actual integer. if (!_M_value && __i.str() != std::basic_string< CharT, Traits>(1, CharT('0'))) { std::ostringstream __error; __error << "bencode::integer::load the specified " "value is not a number\n"; throw value_error(__error.str()); } }
inline char decode_raw_byte(codepoint c) { if (!is_raw_byte(c)) { throw encoding_error("codepoint is not an encoded raw byte"); } return c & 0xFF; }
inline codepoint encode_raw_byte(char byte) { codepoint c = codepoint(byte) & 0xFF; if (c == 0) { throw encoding_error("null or zero byte cannot be raw-data encoded"); } return c | 0xF800; }
typename boost::enable_if_c<bit_size<typename std::iterator_traits<T>::value_type>::value >= 21, codepoint>::type next(T& it, T const& end) { codepoint c = codepoint(*it); if (!is_valid(c)) { throw encoding_error("invalid codepoint"); } ++it; return c; }
bool Gobby::OperationOpen::on_idle() { static const unsigned int CONVERT_BUFFER_SIZE = 1024; const char* inbuffer = &m_raw_content[m_raw_pos]; char* inbuf = const_cast<char*>(inbuffer); gsize inbytes = m_raw_content.size() - m_raw_pos; char outbuffer[CONVERT_BUFFER_SIZE]; gchar* outbuf = outbuffer; gsize outbytes = CONVERT_BUFFER_SIZE; /* iconv is defined as libiconv on Windows, or at least when using the * binary packages from ftp.gnome.org. Therefore we can't propely * call Glib::IConv::iconv. Therefore, we use the C API here. */ const std::size_t result = g_iconv(m_iconv->gobj(), &inbuf, &inbytes, &outbuf, &outbytes); bool more_to_process = (inbytes != 0); if(result == static_cast<std::size_t>(-1)) { if(errno == EILSEQ) { // Invalid text for the current encoding encoding_error(); return false; } if(errno == EINVAL) { // If EINVAL is set, this means that an incomplete // multibyte sequence was at the end of the input. // We might have some more bytes, but those do not // make up a whole character, so we need to wait for // more input. if(!m_stream) { // However, if we already read all input, then // there is no more input to come. We // consider this an error since the file // should not end with an incomplete multibyte // sequence. encoding_error(); return false; } else { // Otherwise, we need to wait for more data // to process. more_to_process = false; } } } m_raw_pos += (inbuf - inbuffer); // We now have outbuf - outbuffer bytes of valid UTF-8 in outbuffer. char* prev = outbuffer; char* pos; const char to_find[] = { '\r', '\n', '\0' }; /* TODO: Write directly into the buffer here, * instead of memmoving stuff. */ while( (pos = std::find_first_of<char*>(prev, outbuf, to_find, to_find + sizeof(to_find))) != outbuf) { if(*pos == '\0') { // There is a nullbyte in the conversion. As normal // text files don't contain nullbytes, this only // occurs when converting for example a UTF-16 from // ISO-8859-1 to UTF-8 (note that the UTF-16 file is // valid ISO-8859-1, it just contains lots of // nullbytes). We therefore produce an error here. encoding_error(); return false; } else { // We convert everything to '\n' as line separator, // but remember the current eol-style to correctly // save the document back to disk. prev = pos + 1; if(*pos == '\r' && prev != outbuf && *prev == '\n') { // CRLF style line break std::memmove(prev, prev + 1, outbuf - prev - 1); m_eol_style = DocumentInfoStorage::EOL_CRLF; --outbuf; } else if(*pos == '\r') { *pos = '\n'; m_eol_style = DocumentInfoStorage::EOL_CR; } else { m_eol_style = DocumentInfoStorage::EOL_LF; } } } GtkTextIter insert_iter; gtk_text_buffer_get_end_iter(m_content, &insert_iter); gtk_text_buffer_insert(m_content, &insert_iter, outbuffer, outbuf - outbuffer); // Done reading and converting the whole file if(!more_to_process && !m_stream) read_finish(); return more_to_process; }
/** * @brief Deserialize the string value from the specified input stream. * @param __s Reference to the input stream. */ void load(std::basic_istream<CharT, Traits>& __s) { // Define the integer symbol representation placeholder. std::basic_stringstream<CharT, Traits> __i; // Define the input stream iterator of the provided stream to // be able to read the string length value symbol by symbol. auto __si = std::istream_iterator<CharT, CharT, Traits>(__s); // Define the output stream to as a buffer for the integer // value, which will be later converted. auto __ival = std::ostream_iterator<CharT, CharT, Traits>(__i); // Copy the symbols from the input stream to the integer // placeholder until the ":" delimiter value. auto __result = copy_until(__si, __ival, [&__s](const CharT& __ch) { // Additionally, check that we did not exceed the // length of the stream to prevent hangs. return !__s.eof() && __ch != basic_value_type::delimiter_token; }, basic_value_type::integer_length); if (*__result != basic_value_type::delimiter_token) { std::ostringstream __error; __error << "bencode::string::load the delimiter `:` " "expected, but `" << CharT(*__result) << "` found\n"; throw encoding_error(__error.str()); } // Save the length of the string. int64_t __count; __i >> __count; if (!__count && __i.str() != std::basic_string< CharT, Traits>(1, CharT('0'))) { std::ostringstream __error; __error << "bencode::string::load the specified string " "length is not a number\n"; throw value_error(__error.str()); } // Ensure that the string length is a non-negative value. if (__count < 0) { std::ostringstream __error; __error << "bencode::string::load the length of the string " "value must be a positive integer: `" << __count << "`\n"; throw value_error(__error.str()); } // Allocate the list of symbols of the specified string length. std::unique_ptr<CharT[]> __str(new CharT[__count+1]); // Read the string value into the symbol list. __s.get(__str.get(), std::streamsize(__count+1)); auto __strval = string_type(__str.get()); // Ensure that valid count of the symbols was extracted from // the provided input stream. if (int64_t(__strval.length()) != __count) { std::ostringstream __error; __error << "bencode::string::load the specified string " "decoded length is not equal to the real one: `" << __count << "` != `" << __strval.length() << "`\n"; throw value_error(__error.str()); } // Initialize the internal value with a new string. _M_value = __strval; }