Merge branch 'thegang/vmu-icons' into falco/miami_settings_saving

This commit is contained in:
Falco Girgis
2025-03-30 01:01:19 -05:00
6 changed files with 223 additions and 66 deletions

View File

@@ -184,6 +184,7 @@ $(REPACK_GTA_DIR)/GTA3SF8.b: assets/GTA3SF8.b
cp $< $@ cp $< $@
$(REPACK_GTA_DIR)/0GDTEX.PVR: assets/0GDTEX.PVR $(REPACK_GTA_DIR)/0GDTEX.PVR: assets/0GDTEX.PVR
$(REPACK_GTA_DIR)/%.ico: %.ico
mkdir -p $(@D) mkdir -p $(@D)
cp $< $@ cp $< $@
@@ -202,20 +203,20 @@ IP.BIN:
rm -f IP.BIN rm -f IP.BIN
$(KOS_BASE)/utils/makeip/makeip ip.txt IP.BIN $(KOS_BASE)/utils/makeip/makeip ip.txt IP.BIN
$(PROJECT_NAME).iso: IP.BIN 1ST_READ.BIN $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTA3SF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR $(PROJECT_NAME).iso: IP.BIN 1ST_READ.BIN $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTA3SF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico
rm -f $(PROJECT_NAME).iso rm -f $(PROJECT_NAME).iso
rm -f $(REPACK_GTA_DIR)/1ST_READ.BIN rm -f $(REPACK_GTA_DIR)/1ST_READ.BIN
cp 1ST_READ.BIN $(REPACK_GTA_DIR) cp 1ST_READ.BIN $(REPACK_GTA_DIR)
mkisofs -C 0,11702 -V $(PROJECT_NAME) -G IP.BIN -r -J -l -o $(PROJECT_NAME).iso $(REPACK_GTA_DIR) mkisofs -C 0,11702 -V $(PROJECT_NAME) -G IP.BIN -r -J -l -o $(PROJECT_NAME).iso $(REPACK_GTA_DIR)
$(PROJECT_NAME)-no-repack.iso: IP.BIN 1ST_READ.BIN $(REPACK_GTA_DIR)/GTA3SF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR $(PROJECT_NAME)-no-repack.iso: IP.BIN 1ST_READ.BIN $(REPACK_GTA_DIR)/GTA3SF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico
rm -f $(PROJECT_NAME)-no-repack.iso rm -f $(PROJECT_NAME)-no-repack.iso
rm -f $(REPACK_GTA_DIR)/1ST_READ.BIN rm -f $(REPACK_GTA_DIR)/1ST_READ.BIN
cp 1ST_READ.BIN $(REPACK_GTA_DIR) cp 1ST_READ.BIN $(REPACK_GTA_DIR)
mkisofs -C 0,11702 -V $(PROJECT_NAME) -G IP.BIN -r -J -l -o $(PROJECT_NAME)-no-repack.iso $(REPACK_GTA_DIR) mkisofs -C 0,11702 -V $(PROJECT_NAME) -G IP.BIN -r -J -l -o $(PROJECT_NAME)-no-repack.iso $(REPACK_GTA_DIR)
$(PROJECT_NAME).ds.iso: IP.BIN 1ST_READ.BIN $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTA3SF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR $(PROJECT_NAME).ds.iso: IP.BIN 1ST_READ.BIN $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTA3SF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico
rm -f $(PROJECT_NAME).ds.iso rm -f $(PROJECT_NAME).ds.iso
rm -f $(REPACK_GTA_DIR)/1ST_READ.BIN rm -f $(REPACK_GTA_DIR)/1ST_READ.BIN
cp $(TARGET).bin $(REPACK_GTA_DIR)/1ST_READ.BIN cp $(TARGET).bin $(REPACK_GTA_DIR)/1ST_READ.BIN
@@ -226,7 +227,7 @@ $(PROJECT_NAME).ds.iso: IP.BIN 1ST_READ.BIN $(REPACK_DIR)/repacked $(REPACK_GTA_
$(KOS_BASE)/utils/scramble/scramble $(TARGET)-prebuilt.bin 1ST_READ_PREBUILT.BIN $(KOS_BASE)/utils/scramble/scramble $(TARGET)-prebuilt.bin 1ST_READ_PREBUILT.BIN
mkdir -p $(REPACK_GTA_DIR) mkdir -p $(REPACK_GTA_DIR)
$(PROJECT_NAME)-prebuilt.iso: IP.BIN 1ST_READ_PREBUILT.BIN $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTA3SF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR $(PROJECT_NAME)-prebuilt.iso: IP.BIN 1ST_READ_PREBUILT.BIN $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTA3SF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico
rm -f $(REPACK_GTA_DIR)/1ST_READ.BIN rm -f $(REPACK_GTA_DIR)/1ST_READ.BIN
cp 1ST_READ_PREBUILT.BIN $(REPACK_GTA_DIR)/1ST_READ.BIN cp 1ST_READ_PREBUILT.BIN $(REPACK_GTA_DIR)/1ST_READ.BIN
mkisofs -C 0,11702 -V $(PROJECT_NAME) -G IP.BIN -r -J -l -o $(PROJECT_NAME).iso $(REPACK_GTA_DIR) mkisofs -C 0,11702 -V $(PROJECT_NAME) -G IP.BIN -r -J -l -o $(PROJECT_NAME).iso $(REPACK_GTA_DIR)
@@ -245,15 +246,15 @@ $(PROJECT_NAME)-prebuilt.cdi: $(PROJECT_NAME)-prebuilt.iso
rm 1ST_READ_PREBUILT.BIN rm 1ST_READ_PREBUILT.BIN
@echo && echo && echo "*** CDI Baked Successfully ($@) ***" && echo && echo @echo && echo && echo "*** CDI Baked Successfully ($@) ***" && echo && echo
else else
$(PROJECT_NAME).cdi: $(TARGET) $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTA3SF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR $(PROJECT_NAME).cdi: $(TARGET) $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTA3SF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico
mkdcdisc -e $(TARGET) -o $(PROJECT_NAME).cdi -d $(REPACK_GTA_DIR)/ $(MKDCDISC_PAD_OPTION) -n $(PROJECT_NAME) -a $(TEAM_NAME) -s $(DISC_SERIAL) -r $(RELEASE_DATE) mkdcdisc -e $(TARGET) -o $(PROJECT_NAME).cdi -d $(REPACK_GTA_DIR)/ $(MKDCDISC_PAD_OPTION) -n $(PROJECT_NAME) -a $(TEAM_NAME) -s $(DISC_SERIAL) -r $(RELEASE_DATE)
@echo && echo && echo "*** CDI Baked Successfully ($@) ***" && echo && echo @echo && echo && echo "*** CDI Baked Successfully ($@) ***" && echo && echo
$(PROJECT_NAME)-no-repack.cdi: $(TARGET) $(REPACK_GTA_DIR)/GTA3SF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR $(PROJECT_NAME)-no-repack.cdi: $(TARGET) $(REPACK_GTA_DIR)/GTA3SF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico
mkdcdisc -e $(TARGET) -o $(PROJECT_NAME)-no-repack.cdi -d $(REPACK_GTA_DIR)/ $(MKDCDISC_PAD_OPTION) -n $(PROJECT_NAME) -a $(TEAM_NAME) -s $(DISC_SERIAL) -r $(RELEASE_DATE) mkdcdisc -e $(TARGET) -o $(PROJECT_NAME)-no-repack.cdi -d $(REPACK_GTA_DIR)/ $(MKDCDISC_PAD_OPTION) -n $(PROJECT_NAME) -a $(TEAM_NAME) -s $(DISC_SERIAL) -r $(RELEASE_DATE)
@echo && echo && echo "*** CDI Baked Successfully ($@) ***" && echo && echo @echo && echo && echo "*** CDI Baked Successfully ($@) ***" && echo && echo
$(PROJECT_NAME)-prebuilt.cdi: $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTA3SF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR $(PROJECT_NAME)-prebuilt.cdi: $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTA3SF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico
mkdcdisc -e $(TARGET) -o $(PROJECT_NAME).cdi -d $(REPACK_GTA_DIR)/ $(MKDCDISC_PAD_OPTION) -n $(PROJECT_NAME) -a $(TEAM_NAME) -s $(DISC_SERIAL) -r $(RELEASE_DATE) mkdcdisc -e $(TARGET) -o $(PROJECT_NAME).cdi -d $(REPACK_GTA_DIR)/ $(MKDCDISC_PAD_OPTION) -n $(PROJECT_NAME) -a $(TEAM_NAME) -s $(DISC_SERIAL) -r $(RELEASE_DATE)
@echo && echo && echo "*** CDI Baked Successfully ($@) ***" && echo && echo @echo && echo && echo "*** CDI Baked Successfully ($@) ***" && echo && echo
endif endif

BIN
liberty/settings.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 B

BIN
miami/settings.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 B

View File

@@ -94,6 +94,10 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <cctype> #include <cctype>
#ifdef DC_SH4
#include <dc/vmu_pkg.h>
#endif
namespace mINI namespace mINI
{ {
namespace INIStringUtil namespace INIStringUtil
@@ -335,6 +339,7 @@ namespace mINI
private: private:
std::ifstream fileReadStream; std::ifstream fileReadStream;
T_LineDataPtr lineData; T_LineDataPtr lineData;
std::size_t start_offt;
T_LineData readFile() T_LineData readFile()
{ {
@@ -343,7 +348,7 @@ namespace mINI
fileContents.resize(fileReadStream.tellg()); fileContents.resize(fileReadStream.tellg());
fileReadStream.seekg(0, std::ios::beg); fileReadStream.seekg(0, std::ios::beg);
std::size_t fileSize = fileContents.size(); std::size_t fileSize = fileContents.size();
fileReadStream.read(&fileContents[0], fileSize); fileReadStream.read(const_cast<char *>(fileContents.c_str()), fileSize);
fileReadStream.close(); fileReadStream.close();
T_LineData output; T_LineData output;
if (fileSize == 0) if (fileSize == 0)
@@ -352,7 +357,19 @@ namespace mINI
} }
std::string buffer; std::string buffer;
buffer.reserve(50); buffer.reserve(50);
for (std::size_t i = 0; i < fileSize; ++i) #ifdef DC_SH4
{
vmu_pkg_t vmu_pkg;
if(vmu_pkg_parse(reinterpret_cast<uint8*>(const_cast<int8*>(fileContents.c_str())), &vmu_pkg) != 0) {
// If we failed to parse, we assume it's raw with no VMS header.
start_offt = 0;
} else {
start_offt = reinterpret_cast<unsigned int>(vmu_pkg.data)
- reinterpret_cast<unsigned int>(fileContents.c_str());
}
}
#endif
for (std::size_t i = start_offt; i < fileSize; ++i)
{ {
char& c = fileContents[i]; char& c = fileContents[i];
if (c == '\n') if (c == '\n')
@@ -378,6 +395,8 @@ namespace mINI
{ {
lineData = std::make_shared<T_LineData>(); lineData = std::make_shared<T_LineData>();
} }
start_offt = 0;
} }
~INIReader() { } ~INIReader() { }
@@ -426,22 +445,71 @@ namespace mINI
{ {
private: private:
std::ofstream fileWriteStream; std::ofstream fileWriteStream;
std::stringstream memStream;
inline static std::ios_base::iostate lastError_;
public: public:
bool prettyPrint = false; bool prettyPrint = false;
INIGenerator(std::string const& filename) INIGenerator(std::string const& filename, bool prettyPrint_=false)
: fileWriteStream(filename, std::ios::out | std::ios::binary),
prettyPrint(prettyPrint_)
{ {
fileWriteStream.open(filename, std::ios::out | std::ios::binary); lastError_ = fileWriteStream.rdstate();
}
~INIGenerator()
{
if(!fileWriteStream.good()) {
return;
}
std::string str = memStream.str();
const char *buf = str.c_str();
int buf_size = memStream.tellp();
#ifdef DC_SH4
uint8_t *data;
uint8_t icon_buf[512 * 1];
vmu_pkg_t vmu_pkg = {
.desc_short = "DCA LC Settings",
.desc_long = "DCA Liberty City Settings File",
.app_id = "The Gang",
.icon_cnt = 1,
.icon_anim_speed = 0,
.data_len = buf_size,
.icon_data = icon_buf,
.data = reinterpret_cast<const uint8_t*>(buf),
};
if (vmu_pkg_load_icon(&vmu_pkg, "settings.ico") < 0) {
vmu_pkg.icon_cnt = 0;
}
if(vmu_pkg_build(&vmu_pkg, &data, &buf_size) < 0) {
lastError_ = std::ios_base::badbit;
return;
}
buf = reinterpret_cast<char*>(data);
#endif
fileWriteStream.write(buf, buf_size);
lastError_ = fileWriteStream.rdstate();
#ifdef DC_SH4
// Must free the internal buffer allocated by vmu_pkg_build().
free(data);
#endif
}
bool operator<<(const std::string& str)
{
memStream << str;
return true;
} }
~INIGenerator() { }
bool operator<<(INIStructure const& data) bool operator<<(INIStructure const& data)
{ {
if (!fileWriteStream.is_open())
{
return false;
}
if (!data.size()) if (!data.size())
{ {
return true; return true;
@@ -451,13 +519,13 @@ namespace mINI
{ {
auto const& section = it->first; auto const& section = it->first;
auto const& collection = it->second; auto const& collection = it->second;
fileWriteStream memStream
<< "[" << "["
<< section << section
<< "]"; << "]";
if (collection.size()) if (collection.size())
{ {
fileWriteStream << INIStringUtil::endl; memStream << INIStringUtil::endl;
auto it2 = collection.begin(); auto it2 = collection.begin();
for (;;) for (;;)
{ {
@@ -465,7 +533,7 @@ namespace mINI
INIStringUtil::replace(key, "=", "\\="); INIStringUtil::replace(key, "=", "\\=");
auto value = it2->second; auto value = it2->second;
INIStringUtil::trim(value); INIStringUtil::trim(value);
fileWriteStream memStream
<< key << key
<< ((prettyPrint) ? " = " : "=") << ((prettyPrint) ? " = " : "=")
<< value; << value;
@@ -473,21 +541,29 @@ namespace mINI
{ {
break; break;
} }
fileWriteStream << INIStringUtil::endl; memStream << INIStringUtil::endl;
} }
} }
if (++it == data.end()) if (++it == data.end())
{ {
break; break;
} }
fileWriteStream << INIStringUtil::endl; memStream << INIStringUtil::endl;
if (prettyPrint) if (prettyPrint)
{ {
fileWriteStream << INIStringUtil::endl; memStream << INIStringUtil::endl;
} }
} }
return true; return true;
} }
operator bool() const
{
return fileWriteStream.rdstate() == fileWriteStream.goodbit;
}
static std::ios_base::iostate lastError() { return lastError_; }
static bool wasGood() { return lastError_ == std::ios_base::goodbit; }
}; };
class INIWriter class INIWriter
@@ -667,12 +743,15 @@ namespace mINI
{ {
struct stat buf; struct stat buf;
bool fileExists = (stat(filename.c_str(), &buf) == 0); bool fileExists = (stat(filename.c_str(), &buf) == 0);
if (!fileExists) if (!fileExists)
{ {
INIGenerator generator(filename); if(INIGenerator generator(filename, prettyPrint); generator) {
generator.prettyPrint = prettyPrint; generator << data;
return generator << data;
} }
return INIGenerator::wasGood();
}
INIStructure originalData; INIStructure originalData;
T_LineDataPtr lineData; T_LineDataPtr lineData;
bool readSuccess = false; bool readSuccess = false;
@@ -688,23 +767,21 @@ namespace mINI
return false; return false;
} }
T_LineData output = getLazyOutput(lineData, data, originalData); T_LineData output = getLazyOutput(lineData, data, originalData);
std::ofstream fileWriteStream(filename, std::ios::out | std::ios::binary);
if (fileWriteStream.is_open())
{ {
if (output.size()) if (INIGenerator generator(filename, prettyPrint); generator && output.size())
{ {
auto line = output.begin(); auto line = output.begin();
for (;;) for (;;)
{ {
fileWriteStream << *line; generator << *line;
if (++line == output.end()) if (++line == output.end())
{ {
break; break;
} }
fileWriteStream << INIStringUtil::endl; generator << INIStringUtil::endl;
} }
} }
return true; return INIGenerator::wasGood();
} }
return false; return false;
} }
@@ -741,9 +818,10 @@ namespace mINI
{ {
return false; return false;
} }
INIGenerator generator(filename); if(INIGenerator generator(filename, pretty); generator) {
generator.prettyPrint = pretty; generator << data;
return generator << data; }
return INIGenerator::wasGood();
} }
bool write(INIStructure& data, bool pretty = false) const bool write(INIStructure& data, bool pretty = false) const
{ {

View File

@@ -201,7 +201,7 @@ mINI::INIFile ini(
#ifdef DC_SIM #ifdef DC_SIM
"reVC.ini" "reVC.ini"
#else #else
"/vmu/" VMU_DEFAULT_PATH "reVCini" "/vmu/" VMU_DEFAULT_PATH "/reVCini"
#endif #endif
); );
mINI::INIStructure cfg; mINI::INIStructure cfg;
@@ -492,7 +492,7 @@ void SaveINIControllerSettings()
StoreIni("Controller", "PadButtonsInited", ControlsManager.ms_padButtonsInited); StoreIni("Controller", "PadButtonsInited", ControlsManager.ms_padButtonsInited);
{ {
RAIIVmuBeep(VMU_DEFALT_PATH, 1.0f); RAIIVmuBeep(VMU_DEFAULT_PATH, 1.0f);
ini.write(cfg); ini.write(cfg);
} }
} }
@@ -500,7 +500,7 @@ void SaveINIControllerSettings()
bool LoadINISettings() bool LoadINISettings()
{ {
{ {
RAIIVmuBeep(VMU_DEFALT_PATH, 1.0f); RAIIVmuBeep(VMU_DEFAULT_PATH, 1.0f);
if (!ini.read(cfg)) if (!ini.read(cfg))
return false; return false;
} }

View File

@@ -94,6 +94,10 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <cctype> #include <cctype>
#ifdef DC_SH4
#include <dc/vmu_pkg.h>
#endif
namespace mINI namespace mINI
{ {
namespace INIStringUtil namespace INIStringUtil
@@ -335,6 +339,7 @@ namespace mINI
private: private:
std::ifstream fileReadStream; std::ifstream fileReadStream;
T_LineDataPtr lineData; T_LineDataPtr lineData;
std::size_t start_offt;
T_LineData readFile() T_LineData readFile()
{ {
@@ -343,7 +348,7 @@ namespace mINI
fileContents.resize(fileReadStream.tellg()); fileContents.resize(fileReadStream.tellg());
fileReadStream.seekg(0, std::ios::beg); fileReadStream.seekg(0, std::ios::beg);
std::size_t fileSize = fileContents.size(); std::size_t fileSize = fileContents.size();
fileReadStream.read(&fileContents[0], fileSize); fileReadStream.read(const_cast<char *>(fileContents.c_str()), fileSize);
fileReadStream.close(); fileReadStream.close();
T_LineData output; T_LineData output;
if (fileSize == 0) if (fileSize == 0)
@@ -352,7 +357,19 @@ namespace mINI
} }
std::string buffer; std::string buffer;
buffer.reserve(50); buffer.reserve(50);
for (std::size_t i = 0; i < fileSize; ++i) #ifdef DC_SH4
{
vmu_pkg_t vmu_pkg;
if(vmu_pkg_parse(reinterpret_cast<uint8*>(const_cast<int8*>(fileContents.c_str())), &vmu_pkg) != 0) {
// If we failed to parse, we assume it's raw with no VMS header.
start_offt = 0;
} else {
start_offt = reinterpret_cast<unsigned int>(vmu_pkg.data)
- reinterpret_cast<unsigned int>(fileContents.c_str());
}
}
#endif
for (std::size_t i = start_offt; i < fileSize; ++i)
{ {
char& c = fileContents[i]; char& c = fileContents[i];
if (c == '\n') if (c == '\n')
@@ -378,6 +395,8 @@ namespace mINI
{ {
lineData = std::make_shared<T_LineData>(); lineData = std::make_shared<T_LineData>();
} }
start_offt = 0;
} }
~INIReader() { } ~INIReader() { }
@@ -426,22 +445,71 @@ namespace mINI
{ {
private: private:
std::ofstream fileWriteStream; std::ofstream fileWriteStream;
std::stringstream memStream;
inline static std::ios_base::iostate lastError_;
public: public:
bool prettyPrint = false; bool prettyPrint = false;
INIGenerator(std::string const& filename) INIGenerator(std::string const& filename, bool prettyPrint_=false)
: fileWriteStream(filename, std::ios::out | std::ios::binary),
prettyPrint(prettyPrint_)
{ {
fileWriteStream.open(filename, std::ios::out | std::ios::binary); lastError_ = fileWriteStream.rdstate();
}
~INIGenerator()
{
if(!fileWriteStream.good()) {
return;
}
std::string str = memStream.str();
const char *buf = str.c_str();
int buf_size = memStream.tellp();
#ifdef DC_SH4
uint8_t *data;
uint8_t icon_buf[512 * 1];
vmu_pkg_t vmu_pkg = {
.desc_short = "DCA VC Settings",
.desc_long = "DCA Miami Settings File",
.app_id = "The Gang",
.icon_cnt = 1,
.icon_anim_speed = 0,
.data_len = buf_size,
.icon_data = icon_buf,
.data = reinterpret_cast<const uint8_t*>(buf),
};
if (vmu_pkg_load_icon(&vmu_pkg, "settings.ico") < 0) {
vmu_pkg.icon_cnt = 0;
}
if(vmu_pkg_build(&vmu_pkg, &data, &buf_size) < 0) {
lastError_ = std::ios_base::badbit;
return;
}
buf = reinterpret_cast<char*>(data);
#endif
fileWriteStream.write(buf, buf_size);
lastError_ = fileWriteStream.rdstate();
#ifdef DC_SH4
// Must free the internal buffer allocated by vmu_pkg_build().
free(data);
#endif
}
bool operator<<(const std::string& str)
{
memStream << str;
return true;
} }
~INIGenerator() { }
bool operator<<(INIStructure const& data) bool operator<<(INIStructure const& data)
{ {
if (!fileWriteStream.is_open())
{
return false;
}
if (!data.size()) if (!data.size())
{ {
return true; return true;
@@ -451,13 +519,13 @@ namespace mINI
{ {
auto const& section = it->first; auto const& section = it->first;
auto const& collection = it->second; auto const& collection = it->second;
fileWriteStream memStream
<< "[" << "["
<< section << section
<< "]"; << "]";
if (collection.size()) if (collection.size())
{ {
fileWriteStream << INIStringUtil::endl; memStream << INIStringUtil::endl;
auto it2 = collection.begin(); auto it2 = collection.begin();
for (;;) for (;;)
{ {
@@ -465,7 +533,7 @@ namespace mINI
INIStringUtil::replace(key, "=", "\\="); INIStringUtil::replace(key, "=", "\\=");
auto value = it2->second; auto value = it2->second;
INIStringUtil::trim(value); INIStringUtil::trim(value);
fileWriteStream memStream
<< key << key
<< ((prettyPrint) ? " = " : "=") << ((prettyPrint) ? " = " : "=")
<< value; << value;
@@ -473,21 +541,29 @@ namespace mINI
{ {
break; break;
} }
fileWriteStream << INIStringUtil::endl; memStream << INIStringUtil::endl;
} }
} }
if (++it == data.end()) if (++it == data.end())
{ {
break; break;
} }
fileWriteStream << INIStringUtil::endl; memStream << INIStringUtil::endl;
if (prettyPrint) if (prettyPrint)
{ {
fileWriteStream << INIStringUtil::endl; memStream << INIStringUtil::endl;
} }
} }
return true; return true;
} }
operator bool() const
{
return fileWriteStream.rdstate() == fileWriteStream.goodbit;
}
static std::ios_base::iostate lastError() { return lastError_; }
static bool wasGood() { return lastError_ == std::ios_base::goodbit; }
}; };
class INIWriter class INIWriter
@@ -667,12 +743,15 @@ namespace mINI
{ {
struct stat buf; struct stat buf;
bool fileExists = (stat(filename.c_str(), &buf) == 0); bool fileExists = (stat(filename.c_str(), &buf) == 0);
if (!fileExists) if (!fileExists)
{ {
INIGenerator generator(filename); if(INIGenerator generator(filename, prettyPrint); generator) {
generator.prettyPrint = prettyPrint; generator << data;
return generator << data;
} }
return INIGenerator::wasGood();
}
INIStructure originalData; INIStructure originalData;
T_LineDataPtr lineData; T_LineDataPtr lineData;
bool readSuccess = false; bool readSuccess = false;
@@ -688,23 +767,21 @@ namespace mINI
return false; return false;
} }
T_LineData output = getLazyOutput(lineData, data, originalData); T_LineData output = getLazyOutput(lineData, data, originalData);
std::ofstream fileWriteStream(filename, std::ios::out | std::ios::binary);
if (fileWriteStream.is_open())
{ {
if (output.size()) if (INIGenerator generator(filename, prettyPrint); generator && output.size())
{ {
auto line = output.begin(); auto line = output.begin();
for (;;) for (;;)
{ {
fileWriteStream << *line; generator << *line;
if (++line == output.end()) if (++line == output.end())
{ {
break; break;
} }
fileWriteStream << INIStringUtil::endl; generator << INIStringUtil::endl;
} }
} }
return true; return INIGenerator::wasGood();
} }
return false; return false;
} }
@@ -741,9 +818,10 @@ namespace mINI
{ {
return false; return false;
} }
INIGenerator generator(filename); if(INIGenerator generator(filename, pretty); generator) {
generator.prettyPrint = pretty; generator << data;
return generator << data; }
return INIGenerator::wasGood();
} }
bool write(INIStructure& data, bool pretty = false) const bool write(INIStructure& data, bool pretty = false) const
{ {