added fixed-length string writing

This commit is contained in:
Jack Andersen 2015-06-19 10:12:25 -10:00
parent 242a06915b
commit 3dfb001f3d
7 changed files with 216 additions and 75 deletions

View File

@ -1,7 +1,7 @@
# PKGBUILD for atdna # PKGBUILD for atdna
_pkgname=atdna _pkgname=atdna
pkgname=$_pkgname-git pkgname=$_pkgname-git
pkgver=1.1.0.35.gfd3db3e pkgver=1.1.0.36.g242a069
pkgrel=1 pkgrel=1
pkgdesc="Companion DNA utility for libAthena" pkgdesc="Companion DNA utility for libAthena"
arch=('i686' 'x86_64') arch=('i686' 'x86_64')

View File

@ -412,7 +412,7 @@ public:
} }
else if (arg.getKind() == clang::TemplateArgument::Expression) else if (arg.getKind() == clang::TemplateArgument::Expression)
{ {
const clang::Expr* expr = arg.getAsExpr(); const clang::Expr* expr = arg.getAsExpr()->IgnoreImpCasts();
if (idx == 1) if (idx == 1)
{ {
sizeArg = &arg; sizeArg = &arg;
@ -506,13 +506,13 @@ public:
fileOut << " " << fieldName << ".clear();\n"; fileOut << " " << fieldName << ".clear();\n";
fileOut << " " << fieldName << ".reserve(" << sizeExpr << ");\n"; fileOut << " " << fieldName << ".reserve(" << sizeExpr << ");\n";
if (isDNAType) if (isDNAType)
fileOut << " for (int i=0 ; i<(" << sizeExpr << ") ; ++i)\n" fileOut << " for (size_t i=0 ; i<(" << sizeExpr << ") ; ++i)\n"
" {\n" " {\n"
" " << fieldName << ".emplace_back();\n" " " << fieldName << ".emplace_back();\n"
" " << fieldName << ".back()." << ioOp << "\n" " " << fieldName << ".back()." << ioOp << "\n"
" }\n"; " }\n";
else else
fileOut << " for (int i=0 ; i<(" << sizeExpr << ") ; ++i)\n" fileOut << " for (size_t i=0 ; i<(" << sizeExpr << ") ; ++i)\n"
" " << fieldName << ".push_back(" << ioOp << ");\n"; " " << fieldName << ".push_back(" << ioOp << ");\n";
} }
else else
@ -533,7 +533,7 @@ public:
{ {
if (arg.getKind() == clang::TemplateArgument::Expression) if (arg.getKind() == clang::TemplateArgument::Expression)
{ {
const clang::UnaryExprOrTypeTraitExpr* uExpr = (clang::UnaryExprOrTypeTraitExpr*)arg.getAsExpr(); const clang::UnaryExprOrTypeTraitExpr* uExpr = (clang::UnaryExprOrTypeTraitExpr*)arg.getAsExpr()->IgnoreImpCasts();
if (uExpr->getStmtClass() == clang::Stmt::UnaryExprOrTypeTraitExprClass && if (uExpr->getStmtClass() == clang::Stmt::UnaryExprOrTypeTraitExprClass &&
uExpr->getKind() == clang::UETT_SizeOf) uExpr->getKind() == clang::UETT_SizeOf)
{ {
@ -585,7 +585,7 @@ public:
{ {
if (arg.getKind() == clang::TemplateArgument::Expression) if (arg.getKind() == clang::TemplateArgument::Expression)
{ {
const clang::Expr* expr = arg.getAsExpr(); const clang::Expr* expr = arg.getAsExpr()->IgnoreImpCasts();
const clang::UnaryExprOrTypeTraitExpr* uExpr = (clang::UnaryExprOrTypeTraitExpr*)expr; const clang::UnaryExprOrTypeTraitExpr* uExpr = (clang::UnaryExprOrTypeTraitExpr*)expr;
llvm::APSInt sizeLiteral; llvm::APSInt sizeLiteral;
if (expr->getStmtClass() == clang::Stmt::UnaryExprOrTypeTraitExprClass && if (expr->getStmtClass() == clang::Stmt::UnaryExprOrTypeTraitExprClass &&
@ -609,7 +609,12 @@ public:
if (!p) if (!p)
fileOut << " " << fieldName << " = reader.readString(" << sizeExprStr << ");\n"; fileOut << " " << fieldName << " = reader.readString(" << sizeExprStr << ");\n";
else else
fileOut << " writer.writeString(" << fieldName << ");\n"; {
fileOut << " writer.writeString(" << fieldName;
if (sizeExprStr.size())
fileOut << ", " << sizeExprStr;
fileOut << ");\n";
}
} }
else if (!tsDecl->getNameAsString().compare("WString")) else if (!tsDecl->getNameAsString().compare("WString"))
{ {
@ -644,7 +649,7 @@ public:
{ {
if (arg.getKind() == clang::TemplateArgument::Expression) if (arg.getKind() == clang::TemplateArgument::Expression)
{ {
const clang::Expr* expr = arg.getAsExpr(); const clang::Expr* expr = arg.getAsExpr()->IgnoreImpCasts();
if (idx == 0) if (idx == 0)
{ {
llvm::APSInt sizeLiteral; llvm::APSInt sizeLiteral;
@ -719,7 +724,12 @@ public:
if (!p) if (!p)
fileOut << " " << fieldName << " = reader.readWString(" << sizeExprStr << ");\n"; fileOut << " " << fieldName << " = reader.readWString(" << sizeExprStr << ");\n";
else else
fileOut << " writer.writeWString(" << fieldName << ");\n"; {
fileOut << " writer.writeWString(" << fieldName;
if (sizeExprStr.size())
fileOut << ", " << sizeExprStr;
fileOut << ");\n";
}
} }
else if (!tsDecl->getNameAsString().compare("UTF8")) else if (!tsDecl->getNameAsString().compare("UTF8"))
{ {
@ -729,7 +739,7 @@ public:
{ {
if (arg.getKind() == clang::TemplateArgument::Expression) if (arg.getKind() == clang::TemplateArgument::Expression)
{ {
const clang::Expr* expr = arg.getAsExpr(); const clang::Expr* expr = arg.getAsExpr()->IgnoreImpCasts();
const clang::UnaryExprOrTypeTraitExpr* uExpr = (clang::UnaryExprOrTypeTraitExpr*)expr; const clang::UnaryExprOrTypeTraitExpr* uExpr = (clang::UnaryExprOrTypeTraitExpr*)expr;
llvm::APSInt sizeLiteral; llvm::APSInt sizeLiteral;
if (expr->getStmtClass() == clang::Stmt::UnaryExprOrTypeTraitExprClass && if (expr->getStmtClass() == clang::Stmt::UnaryExprOrTypeTraitExprClass &&
@ -753,12 +763,18 @@ public:
if (!p) if (!p)
fileOut << " " << fieldName << " = reader.readUnicode(" << sizeExprStr << ");\n"; fileOut << " " << fieldName << " = reader.readUnicode(" << sizeExprStr << ");\n";
else else
fileOut << " writer.writeUnicode(" << fieldName << ");\n"; {
fileOut << " writer.writeUnicode(" << fieldName;
if (sizeExprStr.size())
fileOut << ", " << sizeExprStr;
fileOut << ");\n";
}
} }
else if (!tsDecl->getNameAsString().compare("Seek")) else if (!tsDecl->getNameAsString().compare("Seek"))
{ {
size_t idx = 0; size_t idx = 0;
llvm::APSInt offset(64, 0); const clang::Expr* offsetExpr = nullptr;
std::string offsetExprStr;
llvm::APSInt direction(64, 0); llvm::APSInt direction(64, 0);
const clang::Expr* directionExpr = nullptr; const clang::Expr* directionExpr = nullptr;
bool bad = false; bool bad = false;
@ -766,19 +782,25 @@ public:
{ {
if (arg.getKind() == clang::TemplateArgument::Expression) if (arg.getKind() == clang::TemplateArgument::Expression)
{ {
const clang::Expr* expr = arg.getAsExpr(); const clang::Expr* expr = arg.getAsExpr()->IgnoreImpCasts();
if (!idx) if (!idx)
{ {
if (!expr->isIntegerConstantExpr(offset, context)) offsetExpr = expr;
const clang::UnaryExprOrTypeTraitExpr* uExpr = (clang::UnaryExprOrTypeTraitExpr*)expr;
llvm::APSInt offsetLiteral;
if (expr->getStmtClass() == clang::Stmt::UnaryExprOrTypeTraitExprClass &&
uExpr->getKind() == clang::UETT_SizeOf)
{ {
if (!p) const clang::Expr* argExpr = uExpr->getArgumentExpr();
{ while (argExpr->getStmtClass() == clang::Stmt::ParenExprClass)
clang::DiagnosticBuilder diag = context.getDiagnostics().Report(expr->getLocStart(), AthenaError); argExpr = ((clang::ParenExpr*)argExpr)->getSubExpr();
diag.AddString("Unable to use non-constant offset expression in Athena"); offsetExpr = argExpr;
diag.AddSourceRange(clang::CharSourceRange(expr->getSourceRange(), true)); llvm::raw_string_ostream strStream(offsetExprStr);
argExpr->printPretty(strStream, nullptr, context.getPrintingPolicy());
} }
bad = true; else if (expr->isIntegerConstantExpr(offsetLiteral, context))
break; {
offsetExprStr = offsetLiteral.toString(10);
} }
} }
else else
@ -802,7 +824,6 @@ public:
if (bad) if (bad)
continue; continue;
int64_t offsetVal = offset.getSExtValue();
int64_t directionVal = direction.getSExtValue(); int64_t directionVal = direction.getSExtValue();
if (directionVal < 0 || directionVal > 2) if (directionVal < 0 || directionVal > 2)
{ {
@ -828,23 +849,23 @@ public:
if (directionVal == 0) if (directionVal == 0)
{ {
if (!p) if (!p)
fileOut << " reader.seek(" << offsetVal << ", Athena::Begin);\n"; fileOut << " reader.seek(" << offsetExprStr << ", Athena::Begin);\n";
else else
fileOut << " writer.seek(" << offsetVal << ", Athena::Begin);\n"; fileOut << " writer.seek(" << offsetExprStr << ", Athena::Begin);\n";
} }
else if (directionVal == 1) else if (directionVal == 1)
{ {
if (!p) if (!p)
fileOut << " reader.seek(" << offsetVal << ", Athena::Current);\n"; fileOut << " reader.seek(" << offsetExprStr << ", Athena::Current);\n";
else else
fileOut << " writer.seek(" << offsetVal << ", Athena::Current);\n"; fileOut << " writer.seek(" << offsetExprStr << ", Athena::Current);\n";
} }
else if (directionVal == 2) else if (directionVal == 2)
{ {
if (!p) if (!p)
fileOut << " reader.seek(" << offsetVal << ", Athena::End);\n"; fileOut << " reader.seek(" << offsetExprStr << ", Athena::End);\n";
else else
fileOut << " writer.seek(" << offsetVal << ", Athena::End);\n"; fileOut << " writer.seek(" << offsetExprStr << ", Athena::End);\n";
} }
} }

View File

@ -44,9 +44,9 @@ public:
void writeBool(bool val); void writeBool(bool val);
void writeVec3f(atVec3f vec); void writeVec3f(atVec3f vec);
void writeVec4f(atVec4f vec); void writeVec4f(atVec4f vec);
void writeString(const std::string& val); void writeString(const std::string& val, atInt32 fixedLen = -1);
void writeWString(const std::wstring& str); void writeWString(const std::wstring& str, atInt32 fixedLen = -1);
void writeUnicode(const std::string& str); void writeUnicode(const std::string& str, atInt32 fixedLen = -1);
void fill(atInt8 byte, atUint64 len); void fill(atInt8 byte, atUint64 len);
void fill(atUint8 byte, atUint64 len); void fill(atUint8 byte, atUint64 len);
private: private:

View File

@ -38,9 +38,9 @@ public:
virtual void writeBool(bool) = 0; virtual void writeBool(bool) = 0;
virtual void writeVec3f(atVec3f vec) = 0; virtual void writeVec3f(atVec3f vec) = 0;
virtual void writeVec4f(atVec4f vec) = 0; virtual void writeVec4f(atVec4f vec) = 0;
virtual void writeString(const std::string&) = 0; virtual void writeString(const std::string&, atInt32 = -1) = 0;
virtual void writeWString(const std::wstring&) = 0; virtual void writeWString(const std::wstring&, atInt32 = -1) = 0;
virtual void writeUnicode(const std::string&) = 0; virtual void writeUnicode(const std::string&, atInt32 = -1) = 0;
virtual void fill(atUint8, atUint64) = 0; virtual void fill(atUint8, atUint64) = 0;
virtual void fill(atInt8, atUint64) = 0; virtual void fill(atInt8, atUint64) = 0;
}; };

View File

@ -267,22 +267,25 @@ public:
* *
* \sa Endian * \sa Endian
* \param str The string to write to the buffer * \param str The string to write to the buffer
* \param fixedLen If not -1, the number of characters to zero-fill string to
*/ */
void writeUnicode(const std::string& str); void writeUnicode(const std::string& str, atInt32 fixedLen = -1);
/*! \brief Writes an string to the buffer and advances the buffer. /*! \brief Writes an string to the buffer and advances the buffer.
* *
* \sa Endian * \sa Endian
* \param str The string to write to the buffer * \param str The string to write to the buffer
* \param fixedLen If not -1, the number of characters to zero-fill string to
*/ */
void writeString(const std::string& str); void writeString(const std::string& str, atInt32 fixedLen = -1);
/*! \brief Writes an wstring to the buffer and advances the buffer. /*! \brief Writes an wstring to the buffer and advances the buffer.
* *
* \sa Endian * \sa Endian
* \param str The string to write to the buffer * \param str The string to write to the buffer
* \param fixedLen If not -1, the number of characters to zero-fill string to
*/ */
void writeWString(const std::wstring& str); void writeWString(const std::wstring& str, atInt32 fixedLen = -1);
void fill(atUint8 val, atUint64 length); void fill(atUint8 val, atUint64 length);

View File

@ -298,53 +298,117 @@ void FileWriter::writeVec4f(atVec4f vec)
THROW_IO_EXCEPTION("Unable to write to stream"); THROW_IO_EXCEPTION("Unable to write to stream");
} }
void FileWriter::writeString(const std::string& val) void FileWriter::writeString(const std::string& val, atInt32 fixedLen)
{ {
if (!isOpen()) if (!isOpen())
THROW_INVALID_OPERATION_EXCEPTION("File not open for writing"); THROW_INVALID_OPERATION_EXCEPTION("File not open for writing");
m_bitValid = false; m_bitValid = false;
char term = '\0'; char term = '\0';
if (fixedLen < 0)
{
if (fwrite(val.c_str(), 1, val.length(), m_fileHandle) != val.length()) if (fwrite(val.c_str(), 1, val.length(), m_fileHandle) != val.length())
THROW_IO_EXCEPTION("Unable to write to stream"); THROW_IO_EXCEPTION("Unable to write to stream");
if (fwrite(&term, 1, 1, m_fileHandle) != 1) if (fwrite(&term, 1, 1, m_fileHandle) != 1)
THROW_IO_EXCEPTION("Unable to write to stream"); THROW_IO_EXCEPTION("Unable to write to stream");
}
else
{
if (val.length() >= fixedLen)
{
if (fwrite(val.c_str(), 1, fixedLen, m_fileHandle) != fixedLen)
THROW_IO_EXCEPTION("Unable to write to stream");
}
else
{
if (fwrite(val.c_str(), 1, val.length(), m_fileHandle) != val.length())
THROW_IO_EXCEPTION("Unable to write to stream");
for (atUint32 i=val.length() ; i<fixedLen ; ++i)
{
if (fwrite(&term, 1, 1, m_fileHandle) != 1)
THROW_IO_EXCEPTION("Unable to write to stream");
}
}
}
} }
void FileWriter::writeWString(const std::wstring& val) void FileWriter::writeWString(const std::wstring& val, atInt32 fixedLen)
{ {
if (!isOpen()) if (!isOpen())
THROW_INVALID_OPERATION_EXCEPTION("File not open for writing"); THROW_INVALID_OPERATION_EXCEPTION("File not open for writing");
m_bitValid = false; m_bitValid = false;
wchar_t term = L'\0'; wchar_t term = L'\0';
if (fixedLen < 0)
{
if (fwrite(val.c_str(), 2, val.length(), m_fileHandle) != val.length()) if (fwrite(val.c_str(), 2, val.length(), m_fileHandle) != val.length())
THROW_IO_EXCEPTION("Unable to write to stream"); THROW_IO_EXCEPTION("Unable to write to stream");
if (fwrite(&term, 2, 1, m_fileHandle) != 1) if (fwrite(&term, 2, 1, m_fileHandle) != 1)
THROW_IO_EXCEPTION("Unable to write to stream"); THROW_IO_EXCEPTION("Unable to write to stream");
}
else
{
if (val.length() >= fixedLen)
{
if (fwrite(val.c_str(), 2, fixedLen, m_fileHandle) != fixedLen)
THROW_IO_EXCEPTION("Unable to write to stream");
}
else
{
if (fwrite(val.c_str(), 2, val.length(), m_fileHandle) != val.length())
THROW_IO_EXCEPTION("Unable to write to stream");
for (atUint32 i=val.length() ; i<fixedLen ; ++i)
{
if (fwrite(&term, 2, 1, m_fileHandle) != 1)
THROW_IO_EXCEPTION("Unable to write to stream");
}
}
}
} }
void FileWriter::writeUnicode(const std::string& str) void FileWriter::writeUnicode(const std::string& str, atInt32 fixedLen)
{ {
if (!isOpen()) if (!isOpen())
THROW_INVALID_OPERATION_EXCEPTION("File not open for writing"); THROW_INVALID_OPERATION_EXCEPTION("File not open for writing");
std::string tmpStr = "\xEF\xBB\xBF" + str; std::string tmpStr = "\xEF\xBB\xBF" + str;
std::vector<short> tmp; std::vector<atUint16> tmp;
utf8::utf8to16(tmpStr.begin(), tmpStr.end(), back_inserter(tmp)); utf8::utf8to16(tmpStr.begin(), tmpStr.end(), back_inserter(tmp));
if (fixedLen < 0)
{
for (atUint16 chr : tmp) for (atUint16 chr : tmp)
{ {
if (chr != 0xFEFF) if (chr != 0xFEFF)
writeInt16(chr); writeUint16(chr);
}
writeUint16(0);
}
else
{
auto it = tmp.begin();
for (atInt32 i=0 ; i<fixedLen ; ++i)
{
atUint16 chr;
if (it == tmp.end())
chr = 0;
else
chr = *it++;
if (chr == 0xFEFF)
{
--i;
continue;
}
writeUint16(chr);
}
} }
} }

View File

@ -497,25 +497,50 @@ void MemoryWriter::writeVec4f(atVec4f vec)
m_position += 16; m_position += 16;
} }
void MemoryWriter::writeUnicode(const std::string& str) void MemoryWriter::writeUnicode(const std::string& str, atInt32 fixedLen)
{ {
std::string tmpStr = "\xEF\xBB\xBF" + str; std::string tmpStr = "\xEF\xBB\xBF" + str;
std::vector<short> tmp; std::vector<atUint16> tmp;
utf8::utf8to16(tmpStr.begin(), tmpStr.end(), back_inserter(tmp)); utf8::utf8to16(tmpStr.begin(), tmpStr.end(), back_inserter(tmp));
if (fixedLen < 0)
{
for (atUint16 chr : tmp) for (atUint16 chr : tmp)
{ {
if (chr != 0xFEFF) if (chr != 0xFEFF)
writeInt16(chr); writeUint16(chr);
}
writeUint16(0);
}
else
{
auto it = tmp.begin();
for (atInt32 i=0 ; i<fixedLen ; ++i)
{
atUint16 chr;
if (it == tmp.end())
chr = 0;
else
chr = *it++;
if (chr == 0xFEFF)
{
--i;
continue;
}
writeUint16(chr);
}
} }
writeInt16(0);
} }
void MemoryWriter::writeString(const std::string& str) void MemoryWriter::writeString(const std::string& str, atInt32 fixedLen)
{ {
if (fixedLen < 0)
{
for (atUint8 c : str) for (atUint8 c : str)
{ {
writeUByte(c); writeUByte(c);
@ -523,12 +548,27 @@ void MemoryWriter::writeString(const std::string& str)
if (c == '\0') if (c == '\0')
break; break;
} }
writeUByte(0); writeUByte(0);
}
else
{
auto it = str.begin();
for (atInt32 i=0 ; i<fixedLen ; ++i)
{
atUint8 chr;
if (it == str.end())
chr = 0;
else
chr = *it++;
writeUByte(chr);
}
}
} }
void MemoryWriter::writeWString(const std::wstring& str) void MemoryWriter::writeWString(const std::wstring& str, atInt32 fixedLen)
{ {
if (fixedLen < 0)
{
for (atUint16 c : str) for (atUint16 c : str)
{ {
writeUint16(c); writeUint16(c);
@ -536,8 +576,21 @@ void MemoryWriter::writeWString(const std::wstring& str)
if (c == L'\0') if (c == L'\0')
break; break;
} }
writeUint16(0); writeUint16(0);
}
else
{
auto it = str.begin();
for (atInt32 i=0 ; i<fixedLen ; ++i)
{
atUint16 chr;
if (it == str.end())
chr = 0;
else
chr = *it++;
writeUint16(chr);
}
}
} }
void MemoryWriter::fill(atUint8 val, atUint64 length) void MemoryWriter::fill(atUint8 val, atUint64 length)