| 3163 | |
| 3164 | #ifndef PUGIXML_NO_STL |
| 3165 | template <typename T> xml_parse_result load_stream_impl(xml_document& doc, std::basic_istream<T>& stream, unsigned int options, xml_encoding encoding) |
| 3166 | { |
| 3167 | // get length of remaining data in stream |
| 3168 | typename std::basic_istream<T>::pos_type pos = stream.tellg(); |
| 3169 | stream.seekg(0, std::ios::end); |
| 3170 | std::streamoff length = stream.tellg() - pos; |
| 3171 | stream.seekg(pos); |
| 3172 | |
| 3173 | if (stream.fail() || pos < 0) return make_parse_result(status_io_error); |
| 3174 | |
| 3175 | // guard against huge files |
| 3176 | size_t read_length = static_cast<size_t>(length); |
| 3177 | |
| 3178 | if (static_cast<std::streamsize>(read_length) != length || length < 0) return make_parse_result(status_out_of_memory); |
| 3179 | |
| 3180 | // read stream data into memory (guard against stream exceptions with buffer holder) |
| 3181 | buffer_holder buffer(global_allocate((read_length > 0 ? read_length : 1) * sizeof(T)), global_deallocate); |
| 3182 | if (!buffer.data) return make_parse_result(status_out_of_memory); |
| 3183 | |
| 3184 | stream.read(static_cast<T*>(buffer.data), static_cast<std::streamsize>(read_length)); |
| 3185 | |
| 3186 | // read may set failbit | eofbit in case gcount() is less than read_length (i.e. line ending conversion), so check for other I/O errors |
| 3187 | if (stream.bad()) return make_parse_result(status_io_error); |
| 3188 | |
| 3189 | // load data from buffer |
| 3190 | size_t actual_length = static_cast<size_t>(stream.gcount()); |
| 3191 | assert(actual_length <= read_length); |
| 3192 | |
| 3193 | return doc.load_buffer_inplace_own(buffer.release(), actual_length * sizeof(T), options, encoding); |
| 3194 | } |
| 3195 | #endif |
| 3196 | |
| 3197 | #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__MINGW32__) |
no test coverage detected