Example #1
0
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;
}
Example #2
0
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);
}
Example #3
0
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");
}
Example #4
0
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);
			}
		}
	}
}