61 if (cell.
empty() || (cell ==
"****"))
69 if (cell.
empty() || (cell ==
"****"))
77 if (cell.
empty() || (cell ==
"****"))
85 if (cell.
empty() || (cell ==
"****"))
93 if (cell.
empty() || (cell ==
"****"))
101 if (cell.
empty() || (cell ==
"****"))
109 if (cell.
empty() || (cell ==
"****"))
121 if (n >=
_data.size())
129 _defaultInt(0), _defaultFloat(0.0f), _emptyRow(*this) {
135 _defaultInt(0), _defaultFloat(0.0f), _emptyRow(*this) {
166 e.
add(
"Failed reading 2DA file");
204 std::vector<Common::UString> defaultRow;
205 tokenize.
getTokens(twoda, defaultRow, 2);
207 if (defaultRow[0].equalsIgnoreCase(
"Default:"))
232 const size_t columnCount =
_headers.size();
234 while (!twoda.
eos()) {
245 size_t count = tokenize.
getTokens(twoda, row->_data, columnCount, columnCount,
"****");
268 while (!header.
empty()) {
283 _rows.resize(rowCount, 0);
302 const size_t columnCount =
_headers.size();
303 const size_t rowCount =
_rows.size();
304 const size_t cellCount = columnCount * rowCount;
312 for (
size_t i = 0; i < cellCount; i++)
317 const size_t dataOffset = twoda.
pos();
319 for (
size_t i = 0; i < rowCount; i++) {
322 _rows[i]->_data.resize(columnCount);
324 for (
size_t j = 0; j < columnCount; j++) {
325 const size_t offset = dataOffset + offsets[i * columnCount + j];
330 if (
_rows[i]->_data[j].empty())
331 _rows[i]->_data[j] =
"****";
337 for (
size_t i = 0; i <
_headers.size(); i++)
363 switch (headers[j].type) {
386 if (
_rows[i]->_data[j].empty())
387 _rows[i]->_data[j] =
"****";
393 e.
add(
"Failed reading GDA file");
413 HeaderMap::const_iterator column =
_headerMap.find(header);
418 return column->second;
434 for (std::vector<TwoDARow *>::const_iterator row =
_rows.begin(); row !=
_rows.end(); ++row) {
435 if ((*row)->getString(columnIndex).equalsIgnoreCase(value))
453 std::vector<size_t> colLength;
454 colLength.resize(
_headers.size() + 1, 0);
457 colLength[0] = maxRow.
size();
459 for (
size_t i = 0; i <
_headers.size(); i++)
460 colLength[i + 1] =
_headers[i].size();
462 for (
size_t i = 0; i <
_rows.size(); i++) {
463 for (
size_t j = 0; j <
_rows[i]->_data.size(); j++) {
464 const bool needQuote =
_rows[i]->_data[j].contains(
' ');
465 const size_t length = needQuote ?
_rows[i]->_data[j].size() + 2 :
_rows[i]->_data[j].size();
467 colLength[j + 1] = MAX<size_t>(colLength[j + 1], length);
475 for (
size_t i = 0; i <
_headers.size(); i++)
482 for (
size_t i = 0; i <
_rows.size(); i++) {
485 for (
size_t j = 0; j <
_rows[i]->_data.size(); j++) {
486 const bool needQuote =
_rows[i]->_data[j].contains(
' ');
492 cellString =
_rows[i]->_data[j];
506 if (!file.
open(fileName))
516 const size_t columnCount =
_headers.size();
517 const size_t rowCount =
_rows.size();
518 const size_t cellCount = columnCount * rowCount;
524 for (std::vector<Common::UString>::const_iterator h =
_headers.begin(); h !=
_headers.end(); ++h) {
533 for (
size_t i = 0; i < rowCount; i++) {
553 std::vector<Common::UString> data;
554 std::vector<size_t> offsets;
556 data.reserve(cellCount);
557 offsets.reserve(cellCount);
561 std::vector<size_t> cells;
562 cells.reserve(cellCount);
564 for (
size_t i = 0; i < rowCount; i++) {
567 for (
size_t j = 0; j < columnCount; j++) {
572 for (
size_t k = 0; k < data.size(); k++) {
573 if (data[k] == cell) {
581 foundCell = data.size();
583 data.push_back(cell);
584 offsets.push_back(dataSize);
586 dataSize += data.back().size() + 1;
588 if (dataSize > 65535)
593 cells.push_back(offsets[foundCell]);
598 for (std::vector<size_t>::const_iterator c = cells.begin(); c != cells.end(); ++c)
605 for (std::vector<Common::UString>::const_iterator d = data.begin(); d != data.end(); ++d) {
613 if (!file.
open(fileName))
625 for (
size_t i = 0; i <
_headers.size(); i++) {
626 const bool needQuote =
_headers[i].contains(
',');
643 for (
size_t i = 0; i <
_rows.size(); i++) {
644 for (
size_t j = 0; j <
_rows[i]->_data.size(); j++) {
645 const bool needQuote =
_rows[i]->_data[j].contains(
',');
650 if (
_rows[i]->_data[j] !=
"****")
656 if (j < (
_rows[i]->_data.size() - 1))
668 if (!file.
open(fileName))
Class to hold the two-dimensional array of a 2DA file.
static const uint32 k2DAID
#define MKTAG(a0, a1, a2, a3)
A wrapper macro used around four character constants, like 'DATA', to ensure portability.
uint16 readUint16LE()
Read an unsigned 16-bit word stored in little endian (LSB first) order from the stream and return it...
TwoDAFile(Common::SeekableReadStream &twoda)
void add(const char *s,...) GCC_PRINTF(2
Handling BioWare's GDAs (2DAs, two-dimensional array, within V4.0 GFFs).
void readHeaders2b(Common::SeekableReadStream &twoda)
uint32 readUint32LE()
Read an unsigned 32-bit word stored in little endian (LSB first) order from the stream and return it...
void load(Common::SeekableReadStream &twoda)
Common::UString getString(uint32 field, Common::Encoding encoding, const Common::UString &def="") const
Return a field string, read from the given encoding.
const Common::UString & getString(size_t column) const
Return the contents of a cell as a string.
virtual void flush()
Commit any buffered data to the underlying channel or storage medium; unbuffered streams can use the ...
A class holding an UTF-8 string.
virtual size_t seek(ptrdiff_t offset, Origin whence=kOriginBegin)=0
Sets the stream position indicator for the stream.
void writeString(const UString &str)
Write the given string to the stream, encoded as UTF-8.
PointerType release()
Returns the plain pointer value and releases ScopedPtr.
int64 getSint(uint32 field, int64 def=0) const
void skipRowNames2b(Common::SeekableReadStream &twoda)
UString composeString(T value)
Convert any POD integer, float/double or bool type into a string.
virtual bool eos() const =0
Returns true if a read failed because the stream has been reached.
UString getToken(SeekableReadStream &stream)
Parse a token out of the stream.
static const uint32 k2DAIDTab
std::vector< Common::UString > _headers
void addChunkEnd(uint32 c)
Add a character marking the end of a chunk.
Common::UString _defaultString
The default string to return should a cell not exist.
const char * findGDAHeader(uint32 hash)
size_t getRowCount() const
Return the number of rows in the array.
Utility templates and functions for working with strings and streams.
Exception that provides a stack of explanations.
static void readHeader(Common::ReadStream &stream, uint32 &id, uint32 &version, bool &utf16le)
Read the header out of a stream.
A simple scoped smart pointer template.
static const uint32 kVersion2b
Handling version V4.0/V4.1 of BioWare's GFFs (generic file format).
Basic exceptions to throw.
UString readStringLine(SeekableReadStream &stream, Encoding encoding)
Read a line with the given encoding out of a stream.
const char * c_str() const
Return the (utf8 encoded) string data.
size_t getColumnCount() const
Return the number of columns in the array.
void writeCSV(Common::WriteStream &out) const
Write the 2DA data into a CSV stream.
bool open(const UString &fileName)
Try to open the file with the given fileName.
int32 _defaultInt
The default int to return should a cell not exist.
static UString format(const char *s,...) GCC_PRINTF(1
Print formatted data into an UString object, similar to sprintf().
void readRows2b(Common::SeekableReadStream &twoda)
double getDouble(uint32 field, double def=0.0) const
Utility templates and functions.
Handling BioWare's 2DAs (two-dimensional array).
std::vector< Common::UString > _data
virtual size_t skip(ptrdiff_t offset)
Skip the specified number of bytes, adding that offset to the current position in the stream...
void writeASCII(Common::WriteStream &out) const
Write the 2DA data into an V2.0 ASCII 2DA.
static const uint32 kVersion2a
Utility functions for working with differing string encodings.
bool empty() const
Is the string empty?
void writeUint16LE(uint16 value)
void read2a(Common::SeekableReadStream &twoda)
uint32 _id
The file's ID.
void addIgnore(uint32 c)
Add a character to ignore.
void writeBinary(Common::WriteStream &out) const
Write the 2DA data into an V2.b binary 2DA.
A scoped plain pointer, allowing pointer-y access and normal deletion.
uint32 _version
The file's version.
void writeByte(byte value)
int32 getInt(size_t column) const
Return the contents of a cell as an int.
Basic reading stream interfaces.
virtual size_t pos() const =0
Obtains the current value of the stream position indicator of the stream.
Generic interface for a writable data stream.
size_t getRowCount() const
Return the number of rows in the array.
void readDefault2a(Common::SeekableReadStream &twoda, Common::StreamTokenizer &tokenize)
static float parseFloat(const Common::UString &str)
size_t getColumnCount() const
Return the number of columns in the array.
const GFF4Struct * getRow(size_t row) const
Get a row as a GFF4 struct.
void findFirstToken(SeekableReadStream &stream)
Find the first token character, skipping past separators.
Basic type definitions to handle files used in BioWare's Aurora engine.
const std::vector< Common::UString > & getHeaders() const
Return the columns' headers.
Plain, unextended ASCII (7bit clean).
bool empty(size_t column) const
Check if the cell is empty.
void close()
Close the file, if open.
size_t getTokens(SeekableReadStream &stream, std::vector< UString > &list, size_t min=0, size_t max=SIZE_MAX, const UString &def="")
Parse tokens out of the stream.
const TwoDARow & getRow(size_t row) const
Get a row.
size_t size() const
Return the size of the string, in characters.
UString debugTag(uint32 tag, bool trim)
Create an elaborate string from an integer tag, for debugging purposes.
void readRows2a(Common::SeekableReadStream &twoda, Common::StreamTokenizer &tokenize)
Parse tokens out of a stream.
static const uint32 kFieldIDInvalid
void nextChunk(SeekableReadStream &stream)
Skip past end of chunk characters.
Ignore all repeated separators.
Implementing the stream writing interfaces for files.
void readHeaders2a(Common::SeekableReadStream &twoda, Common::StreamTokenizer &tokenize)
Common::PtrVector< TwoDARow > _rows
std::vector< Header > Headers
float _defaultFloat
The default float to return should a cell not exist.
const Common::UString & getCell(size_t n) const
const Headers & getHeaders() const
Get the column headers.
static int32 parseInt(const Common::UString &str)
void addSeparator(uint32 c)
Add a character on where to split tokens.
TwoDAFile * _parent
The parent 2DA.
void skipToken(SeekableReadStream &stream, size_t n=1)
Skip a number of tokens.
uint64 getUint(uint32 field, uint64 def=0) const
A simple streaming file writing class.
void read2b(Common::SeekableReadStream &twoda)
void addQuote(uint32 c)
Add a character able to enclose (quote) separators and chunk ends.
Interface for a seekable & readable data stream.
void writeUint32LE(uint32 value)
void parseString(const UString &str, T &value, bool allowEmpty)
Parse a string into any POD integer, float/double or bool type.
size_t headerToColumn(const Common::UString &header) const
Translate a column header to a column index.
TwoDARow(TwoDAFile &parent)
Class to hold the GFF'd two-dimensional array of a GDA file.
float getFloat(size_t column) const
Return the contents of a cell as a float.
static const Common::UString kEmpty