| 35 | } |
| 36 | |
| 37 | void XmlDoc::readFile(const string & path) |
| 38 | { |
| 39 | reset(); |
| 40 | |
| 41 | ifstream ifile(path, ios_base::binary); |
| 42 | |
| 43 | if (!ifile.is_open()) return; |
| 44 | |
| 45 | struct stat st; |
| 46 | int r = stat(path.c_str(), &st); |
| 47 | auto size = 0; |
| 48 | if (r == 0) |
| 49 | size = st.st_size; |
| 50 | |
| 51 | if (size <= 4) return; |
| 52 | |
| 53 | vector<char> content(static_cast<size_t>(size)); |
| 54 | ifile.read(content.data(), size); |
| 55 | |
| 56 | #if IS_MSVC_AND_MSVC_VERSION_LT(1900) |
| 57 | typedef unsigned int uint32_t; |
| 58 | #endif |
| 59 | uint32_t signature = *reinterpret_cast<const uint32_t*>(content.data()); |
| 60 | |
| 61 | // Uncompressed document |
| 62 | // 1f8b08 |
| 63 | if ((signature & 0x00FFFFFF) != 0x00088b1f) |
| 64 | { |
| 65 | mDoc = xmlReadMemory(content.data(), size, path.c_str(), NULL, 0); |
| 66 | } |
| 67 | // Compressed document (gzip only) |
| 68 | else |
| 69 | { |
| 70 | vector<char> decompressed_content(*reinterpret_cast<const uint32_t*>(content.data() + content.size() - 4)); |
| 71 | #if IS_GNUC_AND_GNUC_VERSION_LT(5,1,1) |
| 72 | z_stream zInfo; |
| 73 | memset(&zInfo, 0, sizeof(zInfo)); |
| 74 | #else |
| 75 | z_stream zInfo {}; |
| 76 | #endif |
| 77 | zInfo.total_in = zInfo.avail_in = static_cast<uInt>(content.size()); |
| 78 | zInfo.total_out = zInfo.avail_out = static_cast<uInt>(decompressed_content.size()); |
| 79 | zInfo.next_in = reinterpret_cast<Bytef*>(content.data()); |
| 80 | zInfo.next_out = reinterpret_cast<Bytef*>(decompressed_content.data()); |
| 81 | |
| 82 | int nErr = inflateInit2(&zInfo, 16 + MAX_WBITS); |
| 83 | if (nErr == Z_OK) |
| 84 | { |
| 85 | nErr = inflate(&zInfo, Z_FINISH); |
| 86 | } |
| 87 | inflateEnd(&zInfo); |
| 88 | |
| 89 | if (nErr == Z_STREAM_END) |
| 90 | mDoc = xmlReadMemory(decompressed_content.data(), static_cast<int>(decompressed_content.size()), path.c_str(), NULL, 0); |
| 91 | } |
| 92 | |
| 93 | if (mDoc) |
| 94 | mDoc->_private = this; |