mirror of
https://github.com/GerbilSoft/mst06.git
synced 2025-06-20 04:25:37 -04:00
Mst: Added overloads that take FILE* instead of a filename.
main.cpp: Use these overloads.
This commit is contained in:
parent
490bfe1413
commit
c2014f11e1
103
src/Mst.cpp
103
src/Mst.cpp
@ -25,8 +25,14 @@
|
|||||||
|
|
||||||
// C includes. (C++ namespace)
|
// C includes. (C++ namespace)
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
|
#include <cstdio>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# define fseeko(stream, offset, whence) _fseeki64((stream), (offset), (whence))
|
||||||
|
# define ftello(stream) _ftelli64(stream)
|
||||||
|
#endif
|
||||||
|
|
||||||
// C++ includes.
|
// C++ includes.
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -61,6 +67,27 @@ int Mst::loadMST(const TCHAR *filename)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FILE *f_mst = _tfopen(filename, _T("rb"));
|
||||||
|
if (!f_mst) {
|
||||||
|
// Error opening the file.
|
||||||
|
return -errno;
|
||||||
|
}
|
||||||
|
int ret = loadMST(f_mst);
|
||||||
|
fclose(f_mst);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load an MST string table.
|
||||||
|
* @param fp MST string table file.
|
||||||
|
* @return 0 on success; negative POSIX error code on error.
|
||||||
|
*/
|
||||||
|
int Mst::loadMST(FILE *fp)
|
||||||
|
{
|
||||||
|
if (!fp) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
// Clear the current string tables.
|
// Clear the current string tables.
|
||||||
@ -68,26 +95,18 @@ int Mst::loadMST(const TCHAR *filename)
|
|||||||
m_vStrTbl.clear();
|
m_vStrTbl.clear();
|
||||||
m_vStrLkup.clear();
|
m_vStrLkup.clear();
|
||||||
|
|
||||||
FILE *f_mst = _tfopen(filename, _T("rb"));
|
|
||||||
if (!f_mst) {
|
|
||||||
// Error opening the file.
|
|
||||||
return -errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read the MST header.
|
// Read the MST header.
|
||||||
MST_Header mst;
|
MST_Header mst;
|
||||||
size_t size = fread(&mst, 1, sizeof(mst), f_mst);
|
size_t size = fread(&mst, 1, sizeof(mst), fp);
|
||||||
if (size != sizeof(mst)) {
|
if (size != sizeof(mst)) {
|
||||||
// Read error.
|
// Read error.
|
||||||
// TODO: Store more comprehensive error information.
|
// TODO: Store more comprehensive error information.
|
||||||
fclose(f_mst);
|
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the BINA magic number.
|
// Check the BINA magic number.
|
||||||
if (mst.bina_magic != cpu_to_be32(BINA_MAGIC)) {
|
if (mst.bina_magic != cpu_to_be32(BINA_MAGIC)) {
|
||||||
// TODO: Store more comprehensive error information.
|
// TODO: Store more comprehensive error information.
|
||||||
fclose(f_mst);
|
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,7 +114,6 @@ int Mst::loadMST(const TCHAR *filename)
|
|||||||
if (mst.version != '1' || (mst.endianness != 'B' && mst.endianness != 'L')) {
|
if (mst.version != '1' || (mst.endianness != 'B' && mst.endianness != 'L')) {
|
||||||
// Unsupported version and/or invalid endianness.
|
// Unsupported version and/or invalid endianness.
|
||||||
// TODO: Store more comprehensive error information.
|
// TODO: Store more comprehensive error information.
|
||||||
fclose(f_mst);
|
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
m_version = 1;
|
m_version = 1;
|
||||||
@ -115,12 +133,10 @@ int Mst::loadMST(const TCHAR *filename)
|
|||||||
if (mst.file_size < sizeof(MST_Header) + sizeof(WTXT_Header) + sizeof(WTXT_MsgPointer)) {
|
if (mst.file_size < sizeof(MST_Header) + sizeof(WTXT_Header) + sizeof(WTXT_MsgPointer)) {
|
||||||
// Sanity check: File is too small.
|
// Sanity check: File is too small.
|
||||||
// TODO: Store more comprehensive error information.
|
// TODO: Store more comprehensive error information.
|
||||||
fclose(f_mst);
|
|
||||||
return -EIO;
|
return -EIO;
|
||||||
} else if (mst.file_size > 16U*1024*1024) {
|
} else if (mst.file_size > 16U*1024*1024) {
|
||||||
// Sanity check: Must be 16 MB or less.
|
// Sanity check: Must be 16 MB or less.
|
||||||
// TODO: Store more comprehensive error information.
|
// TODO: Store more comprehensive error information.
|
||||||
fclose(f_mst);
|
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,17 +144,17 @@ int Mst::loadMST(const TCHAR *filename)
|
|||||||
if ((uint64_t)sizeof(MST_Header) + (uint64_t)mst.doff_tbl_offset + (uint64_t)mst.doff_tbl_length > mst.file_size) {
|
if ((uint64_t)sizeof(MST_Header) + (uint64_t)mst.doff_tbl_offset + (uint64_t)mst.doff_tbl_length > mst.file_size) {
|
||||||
// Offset table error.
|
// Offset table error.
|
||||||
// TODO: Store more comprehensive error information.
|
// TODO: Store more comprehensive error information.
|
||||||
fclose(f_mst);
|
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the entire file.
|
// Read the entire file.
|
||||||
|
// NOTE: Using a relative seek in case the file pointer was set by
|
||||||
|
// the caller to not be at the beginning of the file.
|
||||||
unique_ptr<uint8_t[]> mst_data(new uint8_t[mst.file_size]);
|
unique_ptr<uint8_t[]> mst_data(new uint8_t[mst.file_size]);
|
||||||
rewind(f_mst);
|
fseeko(fp, -(off_t)(sizeof(mst)), SEEK_CUR);
|
||||||
errno = 0;
|
errno = 0;
|
||||||
size = fread(mst_data.get(), 1, mst.file_size, f_mst);
|
size = fread(mst_data.get(), 1, mst.file_size, fp);
|
||||||
err = errno;
|
err = errno;
|
||||||
fclose(f_mst);
|
|
||||||
if (size != mst.file_size) {
|
if (size != mst.file_size) {
|
||||||
// Short read.
|
// Short read.
|
||||||
// TODO: Store more comprehensive error information.
|
// TODO: Store more comprehensive error information.
|
||||||
@ -348,22 +364,37 @@ int Mst::loadXML(const TCHAR *filename, std::vector<std::string> *pVecErrs)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear the current string tables.
|
|
||||||
m_name.clear();
|
|
||||||
m_vStrTbl.clear();
|
|
||||||
m_vStrLkup.clear();
|
|
||||||
|
|
||||||
// Open the XML document.
|
// Open the XML document.
|
||||||
FILE *f_xml = _tfopen(filename, _T("r"));
|
FILE *f_xml = _tfopen(filename, _T("r"));
|
||||||
if (!f_xml) {
|
if (!f_xml) {
|
||||||
// Error opening the XML document.
|
// Error opening the XML document.
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
|
int ret = loadXML(f_xml, pVecErrs);
|
||||||
|
fclose(f_xml);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load an XML string table.
|
||||||
|
* @param fp [in] XML file.
|
||||||
|
* @param pVecErrs [out,opt] Vector of user-readable error messages.
|
||||||
|
* @return 0 on success; negative POSIX error code or positive TinyXML2 error code on error.
|
||||||
|
*/
|
||||||
|
int Mst::loadXML(FILE *fp, std::vector<std::string> *pVecErrs)
|
||||||
|
{
|
||||||
|
if (!fp) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear the current string tables.
|
||||||
|
m_name.clear();
|
||||||
|
m_vStrTbl.clear();
|
||||||
|
m_vStrLkup.clear();
|
||||||
|
|
||||||
// Parse the XML document.
|
// Parse the XML document.
|
||||||
XMLDocument xml;
|
XMLDocument xml;
|
||||||
int ret = xml.LoadFile(f_xml);
|
int ret = xml.LoadFile(fp);
|
||||||
fclose(f_xml);
|
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
// Error parsing the XML document.
|
// Error parsing the XML document.
|
||||||
if (pVecErrs) {
|
if (pVecErrs) {
|
||||||
@ -515,6 +546,23 @@ int Mst::saveXML(const TCHAR *filename) const
|
|||||||
return -ENODATA; // TODO: Better error code?
|
return -ENODATA; // TODO: Better error code?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FILE *f_xml = _tfopen(filename, _T("w"));
|
||||||
|
if (!f_xml) {
|
||||||
|
// Error opening the XML file.
|
||||||
|
return -errno;
|
||||||
|
}
|
||||||
|
int ret = saveXML(f_xml);
|
||||||
|
fclose(f_xml);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save the string table as XML.
|
||||||
|
* @param fp XML file.
|
||||||
|
* @return 0 on success; negative POSIX error code or positive TinyXML2 error code on error.
|
||||||
|
*/
|
||||||
|
int Mst::saveXML(FILE *fp) const
|
||||||
|
{
|
||||||
// Create an XML document.
|
// Create an XML document.
|
||||||
XMLDocument xml;
|
XMLDocument xml;
|
||||||
XMLDeclaration *const xml_decl = xml.NewDeclaration();
|
XMLDeclaration *const xml_decl = xml.NewDeclaration();
|
||||||
@ -536,15 +584,8 @@ int Mst::saveXML(const TCHAR *filename) const
|
|||||||
|
|
||||||
// Save the XML document.
|
// Save the XML document.
|
||||||
// NOTE: Using our custom XMLPrinter for tabs instead of spaces.
|
// NOTE: Using our custom XMLPrinter for tabs instead of spaces.
|
||||||
FILE *f_xml = _tfopen(filename, _T("w"));
|
MstXMLPrinter stream(fp, false);
|
||||||
if (!f_xml) {
|
|
||||||
// Error opening the XML file.
|
|
||||||
return -errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
MstXMLPrinter stream(f_xml, false);
|
|
||||||
xml.Print(&stream);
|
xml.Print(&stream);
|
||||||
fclose(f_xml);
|
|
||||||
return xml.ErrorID();
|
return xml.ErrorID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
26
src/Mst.hpp
26
src/Mst.hpp
@ -23,6 +23,10 @@
|
|||||||
|
|
||||||
#include "tcharx.h"
|
#include "tcharx.h"
|
||||||
|
|
||||||
|
// C includes. (C++ namespace)
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
// C++ includes.
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -46,6 +50,13 @@ class Mst
|
|||||||
*/
|
*/
|
||||||
int loadMST(const TCHAR *filename);
|
int loadMST(const TCHAR *filename);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load an MST string table.
|
||||||
|
* @param fp MST string table file.
|
||||||
|
* @return 0 on success; negative POSIX error code on error.
|
||||||
|
*/
|
||||||
|
int loadMST(FILE *fp);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load an XML string table.
|
* Load an XML string table.
|
||||||
* @param filename [in] XML filename.
|
* @param filename [in] XML filename.
|
||||||
@ -54,6 +65,14 @@ class Mst
|
|||||||
*/
|
*/
|
||||||
int loadXML(const TCHAR *filename, std::vector<std::string> *pVecErrs = nullptr);
|
int loadXML(const TCHAR *filename, std::vector<std::string> *pVecErrs = nullptr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load an XML string table.
|
||||||
|
* @param fp [in] XML file.
|
||||||
|
* @param pVecErrs [out,opt] Vector of user-readable error messages.
|
||||||
|
* @return 0 on success; negative POSIX error code or positive TinyXML2 error code on error.
|
||||||
|
*/
|
||||||
|
int loadXML(FILE *fp, std::vector<std::string> *pVecErrs = nullptr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save the string table as XML.
|
* Save the string table as XML.
|
||||||
* @param filename XML filename.
|
* @param filename XML filename.
|
||||||
@ -61,6 +80,13 @@ class Mst
|
|||||||
*/
|
*/
|
||||||
int saveXML(const TCHAR *filename) const;
|
int saveXML(const TCHAR *filename) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save the string table as XML.
|
||||||
|
* @param fp XML file.
|
||||||
|
* @return 0 on success; negative POSIX error code or positive TinyXML2 error code on error.
|
||||||
|
*/
|
||||||
|
int saveXML(FILE *fp) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// TODO: Save MST, Load XML
|
// TODO: Save MST, Load XML
|
||||||
// TODO: Iterator and mutator functions.
|
// TODO: Iterator and mutator functions.
|
||||||
|
10
src/main.cpp
10
src/main.cpp
@ -52,7 +52,6 @@ int _tmain(int argc, TCHAR *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Open the file and check if it's MST or XML.
|
// Open the file and check if it's MST or XML.
|
||||||
// TODO: loadMST() overload for FILE*.
|
|
||||||
FILE *f_in = _tfopen(argv[1], _T("rb"));
|
FILE *f_in = _tfopen(argv[1], _T("rb"));
|
||||||
if (!f_in) {
|
if (!f_in) {
|
||||||
_ftprintf(stderr, _T("*** ERROR opening %s: %s\n"), argv[1], _tcserror(errno));
|
_ftprintf(stderr, _T("*** ERROR opening %s: %s\n"), argv[1], _tcserror(errno));
|
||||||
@ -63,12 +62,12 @@ int _tmain(int argc, TCHAR *argv[])
|
|||||||
errno = 0;
|
errno = 0;
|
||||||
size_t size = fread(buf, 1, sizeof(buf), f_in);
|
size_t size = fread(buf, 1, sizeof(buf), f_in);
|
||||||
int err = errno;
|
int err = errno;
|
||||||
fclose(f_in);
|
|
||||||
if (size != sizeof(buf)) {
|
if (size != sizeof(buf)) {
|
||||||
if (err == 0) err = EIO;
|
if (err == 0) err = EIO;
|
||||||
_ftprintf(stderr, _T("*** ERROR reading file %s: %s\n"), argv[1], _tcserror(errno));
|
_ftprintf(stderr, _T("*** ERROR reading file %s: %s\n"), argv[1], _tcserror(errno));
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
rewind(f_in);
|
||||||
|
|
||||||
Mst mst;
|
Mst mst;
|
||||||
int ret;
|
int ret;
|
||||||
@ -81,15 +80,18 @@ int _tmain(int argc, TCHAR *argv[])
|
|||||||
// Parse as XML and convert to MST.
|
// Parse as XML and convert to MST.
|
||||||
out_ext = _T(".mst");
|
out_ext = _T(".mst");
|
||||||
writeMST = true;
|
writeMST = true;
|
||||||
ret = mst.loadXML(argv[1]);
|
ret = mst.loadXML(f_in);
|
||||||
|
fclose(f_in);
|
||||||
} else if (!memcmp(&buf[0x18], "BINA", 4)) {
|
} else if (!memcmp(&buf[0x18], "BINA", 4)) {
|
||||||
// This is an MST file.
|
// This is an MST file.
|
||||||
// Parse as MST and convert to XML.
|
// Parse as MST and convert to XML.
|
||||||
out_ext = _T(".xml");
|
out_ext = _T(".xml");
|
||||||
writeXML = true;
|
writeXML = true;
|
||||||
ret = mst.loadMST(argv[1]);
|
ret = mst.loadMST(f_in);
|
||||||
|
fclose(f_in);
|
||||||
} else {
|
} else {
|
||||||
// Unrecognized file format.
|
// Unrecognized file format.
|
||||||
|
fclose(f_in);
|
||||||
_ftprintf(stderr, _T("*** ERROR: File %s is not recognized.\n"), argv[1]);
|
_ftprintf(stderr, _T("*** ERROR: File %s is not recognized.\n"), argv[1]);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user