Mst: Added overloads that take FILE* instead of a filename.

main.cpp: Use these overloads.
This commit is contained in:
David Korth 2019-05-12 14:40:29 -04:00
parent 490bfe1413
commit c2014f11e1
3 changed files with 104 additions and 35 deletions

View File

@ -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();
} }

View File

@ -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.

View File

@ -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;
} }