void FoxPro::loadRecords(SeekableReadStream &dbf, uint32 recordSize, uint32 recordCount) { _pool.push_back(new byte[recordSize * recordCount]); byte *recordData = _pool.back(); if (dbf.read(recordData, recordSize * recordCount) != (recordSize * recordCount)) throw Exception(kReadError); if (dbf.readByte() != 0x1A) throw Exception("Record end marker missing"); uint32 fieldCount = _fields.size(); // Create the records array _records.resize(recordCount); for (uint32 i = 0; i < recordCount; i++) { Record &record = _records[i]; const byte *data = recordData + i * recordSize; char status = *data++; if ((status != ' ') && (status != '*')) throw Exception("Unknown record status '%c'", status); record.deleted = status == '*'; record.fields.resize(fieldCount); for (uint32 j = 0; j < fieldCount; j++) { record.fields[j] = data; data += _fields[j].size; } } }
size_t ZipFile::findCentralDirectoryEnd(SeekableReadStream &zip) { const size_t uSizeFile = zip.size(); const size_t uMaxBack = MIN<size_t>(0xFFFF, uSizeFile); // Maximum size of global comment byte buf[BUFREADCOMMENT + 4]; size_t uPosFound = 0; size_t uBackRead = 4; while ((uPosFound == 0) && (uBackRead < uMaxBack)) { uBackRead = MIN<size_t>(uMaxBack, uBackRead + BUFREADCOMMENT); const size_t uReadPos = uSizeFile - uBackRead; const size_t uReadSize = MIN<size_t>(BUFREADCOMMENT + 4, uSizeFile - uReadPos); try { zip.seek(uReadPos); } catch (...) { return 0; } if (zip.read(buf, uReadSize) != uReadSize) { uPosFound = 0; break; } for (size_t i = (uReadSize - 3); i-- > 0; ) if (READ_LE_UINT32(buf + i) == 0x06054B50) { uPosFound = uReadPos + i; break; } } return uPosFound; }
UString readStringFixed(SeekableReadStream &stream, Encoding encoding, size_t length) { std::vector<byte> output; output.resize(length); length = stream.read(&output[0], length); output.resize(length); return createString(output, encoding); }
void printDataHex(SeekableReadStream &stream, size_t size) { size_t pos = stream.pos(); size = MIN<size_t>(stream.size() - pos, size); if (size == 0) return; uint32 offset = 0; byte rowData[16]; while (size > 0) { // At max 16 bytes printed per row uint32 n = MIN<size_t>(size, 16); if (stream.read(rowData, n) != n) throw Exception(kReadError); // Print an offset std::fprintf(stderr, "%08X ", offset); // 2 "blobs" of each 8 bytes per row for (uint32 i = 0; i < 2; i++) { for (uint32 j = 0; j < 8; j++) { uint32 m = i * 8 + j; if (m < n) // Print the data std::fprintf(stderr, "%02X ", rowData[m]); else // Last row, data count not aligned to 16 std::fprintf(stderr, " "); } // Separate the blobs by an extra space std::fprintf(stderr, " "); } std::fprintf(stderr, "|"); // If the data byte is a printable character, print it. If not, substitute a '.' for (uint32 i = 0; i < n; i++) std::fprintf(stderr, "%c", std::isprint(rowData[i]) ? rowData[i] : '.'); std::fprintf(stderr, "|\n"); size -= n; offset += n; } // Seek back stream.seek(pos); }
static uint32 readFakeChar(SeekableReadStream &stream, Encoding encoding) { byte data[2]; switch (encoding) { case kEncodingASCII: case kEncodingLatin9: case kEncodingUTF8: case kEncodingCP1250: case kEncodingCP1251: case kEncodingCP1252: case kEncodingCP932: case kEncodingCP936: case kEncodingCP949: case kEncodingCP950: if (stream.read(data, 1) != 1) return 0; return data[0]; case kEncodingUTF16LE: if (stream.read(data, 2) != 2) return 0; return READ_LE_UINT16(data); case kEncodingUTF16BE: if (stream.read(data, 2) != 2) return 0; return READ_BE_UINT16(data); default: break; } return 0; }
void FoxPro::loadMemos(SeekableReadStream &fpt) { fpt.skip(4); // Next free block fpt.skip(2); // Unused _memoBlockSize = fpt.readUint16BE(); if (_memoBlockSize < 33) _memoBlockSize *= 1024; fpt.skip(504); // Unused while (!fpt.eos()) { _memos.push_back(new byte[_memoBlockSize]); byte *data = _memos.back(); fpt.read(data, _memoBlockSize); } }
size_t searchBackwards(SeekableReadStream &haystack, const byte *needle, size_t needleSize, size_t maxReadBack) { if (needleSize == 0 || maxReadBack == 0) return SIZE_MAX; assert(maxReadBack >= needleSize); static const size_t kReadBufferSize = 0x400; const size_t sizeFile = haystack.size(); const size_t maxBack = MIN<size_t>(maxReadBack, sizeFile); ScopedArray<byte> buf(new byte[kReadBufferSize + needleSize]); size_t backRead = needleSize; while (backRead < maxBack) { backRead = MIN<size_t>(maxBack, backRead + kReadBufferSize); const size_t readPos = sizeFile - backRead; const size_t readSize = MIN<size_t>(kReadBufferSize + needleSize, sizeFile - readPos); try { haystack.seek(readPos); } catch (...) { break; } if (haystack.read(buf.get(), readSize) != readSize) break; for (size_t i = (readSize - (needleSize - 1)); i-- > 0; ) if (!memcmp(buf.get() + i, needle, needleSize)) return readPos + i; } return SIZE_MAX; }