UString FoxPro::getString(const Record &record, size_t field) const { assert(field < _fields.size()); const Field &f = _fields[field]; if (f.type != kTypeString) throw Exception("Field is not of string type ('%c')", f.type); MemoryReadStream stream(record.fields[field], f.size); UString str = readStringFixed(stream, kEncodingLatin9, f.size); // xBase fields are padded with spaces... str.trimRight(); return str; }
Common::UString GFF4Struct::getString(Common::SeekableReadStream &data, Common::Encoding encoding) const { /* When the string is encoded in UTF-8, then length field specifies the length in bytes. * Otherwise, it's the length in characters. */ const size_t lengthMult = encoding == Common::kEncodingUTF8 ? 1 : Common::getBytesPerCodepoint(encoding); const size_t offset = data.pos(); const uint32 length = data.readUint32LE(); const size_t size = length * lengthMult; try { return readStringFixed(data, encoding, size); } catch (...) { } return Common::UString::format("GFF4: Invalid string encoding (0x%08X)", (uint) offset); }
void FoxPro::loadFields(SeekableReadStream &dbf, uint32 recordSize) { // Read all field descriptions, 0x0D is the end marker uint32 fieldsLength = 0; while (!dbf.eos() && (dbf.readByte() != 0x0D)) { Field field; dbf.seek(-1, SeekableReadStream::kOriginCurrent); field.name = readStringFixed(dbf, kEncodingASCII, 11); field.type = (Type) dbf.readByte(); field.offset = dbf.readUint32LE(); field.size = dbf.readByte(); field.decimals = dbf.readByte(); field.flags = dbf.readByte(); field.autoIncNext = dbf.readUint32LE(); field.autoIncStep = dbf.readByte(); dbf.skip(8); // Reserved if (field.offset != (fieldsLength + 1)) throw Exception("Field offset makes no sense (%d != %d)", field.offset, fieldsLength + 1); if (field.type == kTypeMemo) _hasMemo = true; fieldsLength += field.size; _fields.push_back(field); } if (recordSize != (fieldsLength + 1)) throw Exception("Length of all fields does not equal the record size"); }
void ZipFile::load(SeekableReadStream &zip) { size_t endPos = findCentralDirectoryEnd(zip); if (endPos == 0) throw Exception("End of central directory record not found"); zip.seek(endPos); zip.skip(4); // Header, already checked uint16 curDisk = zip.readUint16LE(); uint16 centralDirDisk = zip.readUint16LE(); uint16 curDiskDirs = zip.readUint16LE(); uint16 totalDirs = zip.readUint16LE(); if ((curDisk != 0) || (curDisk != centralDirDisk) || (curDiskDirs != totalDirs)) throw Exception("Unsupported multi-disk ZIP file"); zip.skip(4); // Size of central directory uint32 centralDirPos = zip.readUint32LE(); zip.seek(centralDirPos); uint32 tag = zip.readUint32LE(); if (tag != 0x02014B50) throw Exception("Unknown ZIP record %08X", tag); _iFiles.reserve(totalDirs); while (tag == 0x02014B50) { File file; IFile iFile; zip.skip(20); iFile.size = zip.readUint32LE(); uint16 nameLength = zip.readUint16LE(); uint16 extraLength = zip.readUint16LE(); uint16 commentLength = zip.readUint16LE(); uint16 diskNum = zip.readUint16LE(); if (diskNum != 0) throw Exception("Unsupported multi-disk ZIP file"); zip.skip(6); // File attributes iFile.offset = zip.readUint32LE(); file.name = readStringFixed(zip, kEncodingASCII, nameLength).toLower(); zip.skip(extraLength); zip.skip(commentLength); tag = zip.readUint32LE(); if ((tag != 0x02014B50) && (tag != 0x06054B50)) throw Exception("Unknown ZIP record %08X", tag); // Ignore empty file names if (!file.name.empty()) { // HACK: Skip any filename with a trailing slash because it's // a directory. The proper solution would be to interpret the // file attributes. if (*(--file.name.end()) != '/') { file.index = _iFiles.size(); _files.push_back(file); _iFiles.push_back(iFile); } } } }