Succesffuly implemented resource pack loading for configurations files. Improved loading speed times for phase 3.5,4,and 5 of loading process. Stage loading is currently broken. Release Build 12609.
All checks were successful
Emscripten Build / Build_and_Deploy_Web_Build (push) Successful in 7m17s

This commit is contained in:
sigonasr2 2026-02-18 15:13:25 -06:00
parent 2b541386ce
commit c7ce048e51
14 changed files with 8760 additions and 8713 deletions

View File

@ -753,7 +753,7 @@
</SubType>
</ClInclude>
<ClInclude Include="TileGroup.h" />
<ClInclude Include="TileGroupSaveData.h" />
<ClInclude Include="TileGroupDataFile.h" />
<ClInclude Include="Timer.h" />
<ClInclude Include="TitleScreen.h">
<SubType>

View File

@ -735,7 +735,7 @@
<ClInclude Include="FallEffect.h">
<Filter>Source Files\Effects</Filter>
</ClInclude>
<ClInclude Include="TileGroupSaveData.h">
<ClInclude Include="TileGroupDataFile.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="TileGroup.h">

View File

@ -86,7 +86,7 @@ All rights reserved.
#include <stacktrace>
#endif
#include <ranges>
#include"TileGroupSaveData.h"
#include"TileGroupDataFile.h"
INCLUDE_EMITTER_LIST
INCLUDE_ITEM_CATEGORIES
@ -2513,6 +2513,13 @@ void AiL::_PrepareLevel(MapName map,MusicChange changeMusic){
#pragma region Foreground and Upper Foreground Tile Fade Group Setup (Loading phase 4)
LoadingScreen::AddPhase([&](){
const std::string foregroundTileDataFilename{std::format("assets/cache/foregroundTileData_{}.data",GetCurrentLevel())};
const std::string upperForegroundTileDataFilename{std::format("assets/cache/upperForegroundTileData_{}.data",GetCurrentLevel())};
if(gamepack.FileExists(foregroundTileDataFilename)&&gamepack.FileExists(upperForegroundTileDataFilename)){
TileGroupDataFile::Load(gamepack,foregroundTileDataFilename,foregroundTileGroups);
TileGroupDataFile::Load(gamepack,upperForegroundTileDataFilename,upperForegroundTileGroups);
return true;
}
std::set<vi2d>foregroundTilesAdded,upperForegroundTilesAdded;
for(int x=0;x<GetCurrentMapData().width;x++){
for(int y=0;y<GetCurrentMapData().height;y++){
@ -2605,6 +2612,9 @@ void AiL::_PrepareLevel(MapName map,MusicChange changeMusic){
#pragma region Foreground and Upper Foreground Tile Fade Group Individual Object Grouping Splitting (Loading phase 5)
LoadingScreen::AddPhase([&](){
const std::string foregroundTileDataFilename{std::format("assets/cache/foregroundTileData_{}.data",GetCurrentLevel())};
const std::string upperForegroundTileDataFilename{std::format("assets/cache/upperForegroundTileData_{}.data",GetCurrentLevel())};
if(gamepack.FileExists(foregroundTileDataFilename)&&gamepack.FileExists(upperForegroundTileDataFilename))return true; //We already loaded the structures in the last loading phase, so we simply do not do anything here.
auto SplitUp=[&](std::vector<TileGroup>&group){
std::multimap<vi2d,TileRenderData>data;
using TileDataGroup=std::multimap<vi2d,TileRenderData>; //See below.
@ -2675,8 +2685,8 @@ void AiL::_PrepareLevel(MapName map,MusicChange changeMusic){
std::sort(upperForegroundTileGroups.begin(),upperForegroundTileGroups.end(),[&](TileGroup&group1,TileGroup&group2){
return group1.GetCollisionRange().middle().y<group2.GetCollisionRange().middle().y;
});
TileGroupSaveData foregroundTilesSaveData{gamepack,std::format("assets/cache/foregroundTileData_{}.data",GetCurrentMapName()),foregroundTileGroups};
TileGroupSaveData upperForegroundTilesSaveData{gamepack,std::format("assets/cache/upperForegroundTileData_{}.data",GetCurrentMapName()),upperForegroundTileGroups};
TileGroupDataFile::Save(gamepack,std::format("assets/cache/foregroundTileData_{}.data",GetCurrentMapName()),foregroundTileGroups);
TileGroupDataFile::Save(gamepack,std::format("assets/cache/upperForegroundTileData_{}.data",GetCurrentMapName()),upperForegroundTileGroups);
return true;
});
#pragma endregion
@ -2780,6 +2790,9 @@ void AiL::_PrepareLevel(MapName map,MusicChange changeMusic){
ClearGarbage();
GetPlayer()->OnLevelStart();
gamepack.SavePack("assets/"+"gamepack_file"_S,PACK_KEY);
return true;
});
}

View File

@ -38,7 +38,7 @@ All rights reserved.
#include "Map.h"
#include "AdventuresInLestoria.h"
#include "safemap.h"
#include"TileGroupSaveData.h"
#include"TileGroupDataFile.h"
INCLUDE_game

View File

@ -45,6 +45,9 @@ INCLUDE_game
INCLUDE_GFX
void Minimap::Initialize(){
Minimap::minimapChunkSize="Minimap.Chunk Size"_I;
Minimap::minimapMapExploreTransparency="Minimap.Map Explore Transparency"_I;
std::vector<vf2d>enlargedCircle;
for(int i=360;i>=0;i-=4){
float angle=util::degToRad(float(i))-PI/2;
@ -195,10 +198,10 @@ void Minimap::UpdateChunk(const MapName map,const vi2d chunkPos,const InitialLoa
if(game->GetCurrentMapName()!=map)return; //Don't update the minimap when the map name doesn't match the current map.
vi2d centerChunkPos=chunkPos*"Minimap.Chunk Size"_I;
vi2d centerChunkPos=chunkPos*Minimap::minimapChunkSize;
vi2d pixelPos=centerChunkPos-"Minimap.Chunk Size"_I*2;
vi2d chunkEndPixelPos=centerChunkPos+"Minimap.Chunk Size"_I*4;
vi2d pixelPos=centerChunkPos-Minimap::minimapChunkSize*2;
vi2d chunkEndPixelPos=centerChunkPos+Minimap::minimapChunkSize*4;
//We start twice the distance we are supposed to outwards.
for(int y=pixelPos.y;y<chunkEndPixelPos.y;y++){
@ -209,21 +212,21 @@ void Minimap::UpdateChunk(const MapName map,const vi2d chunkPos,const InitialLoa
if(cover.Sprite()->GetPixel(x,y).a==255||sourceCol.a==0)continue; //Already revealed or invisible anyways.
vi2d chunk=vi2d{x,y}/"Minimap.Chunk Size"_I;
vi2d chunk=vi2d{x,y}/Minimap::minimapChunkSize;
if(chunk==chunkPos){
if(initialLoad==InitialLoad::YES)sourceCol.a=std::min(sourceCol.a,uint8_t("Minimap.Map Explore Transparency"_I));
if(initialLoad==InitialLoad::YES)sourceCol.a=std::min(sourceCol.a,uint8_t(Minimap::minimapMapExploreTransparency));
cover.Sprite()->SetPixel(x,y,sourceCol);
if(sourceWasBlack)coverOutline.Sprite()->SetPixel(x,y,sourceCol);
}else{
const vi2d chunkOffset={"Minimap.Chunk Size"_I/2,"Minimap.Chunk Size"_I/2};
const vi2d chunkOffset={Minimap::minimapChunkSize/2,Minimap::minimapChunkSize/2};
const float distance=geom2d::line<float>(centerChunkPos+chunkOffset,vf2d{float(x),float(y)}).length();
const int alpha=std::clamp(float(util::lerp(255,0,(distance-"Minimap.Chunk Size"_I)/"Minimap.Chunk Size"_I)),0.f,255.f);
const int alpha=std::clamp(float(util::lerp(255,0,(distance-Minimap::minimapChunkSize)/Minimap::minimapChunkSize)),0.f,255.f);
if(cover.Sprite()->GetPixel(x,y).a>alpha)continue; //The distance was uncovered by another closer chunk, don't need to reveal it here.
sourceCol.a=alpha;
if(initialLoad==InitialLoad::YES)sourceCol.a=std::min(sourceCol.a,uint8_t("Minimap.Map Explore Transparency"_I));
if(initialLoad==InitialLoad::YES)sourceCol.a=std::min(sourceCol.a,uint8_t(Minimap::minimapMapExploreTransparency));
cover.Sprite()->SetPixel(x,y,sourceCol);
if(sourceWasBlack)coverOutline.Sprite()->SetPixel(x,y,sourceCol);
}

View File

@ -73,5 +73,8 @@ private:
std::unordered_map<MapName,std::unordered_set<std::string>>loadedChunks,revealedChunks;
MinimapMode displayMode=MinimapMode::SMALL;
static inline int minimapChunkSize{};
static inline int minimapMapExploreTransparency{};
bool MinimapVisible();
};

View File

@ -55,7 +55,7 @@ All rights reserved.
#include "ItemEnchant.h"
#include <ranges>
#include"MonsterAbility.h"
#include"TileGroupSaveData.h"
#include"TileGroupDataFile.h"
INCLUDE_ANIMATION_DATA
INCLUDE_MONSTER_DATA

View File

@ -39,10 +39,12 @@ All rights reserved.
#include"olcPixelGameEngine.h"
#include"Map.h"
#include"DEFINES.h"
INCLUDE_PACK_KEY
struct TileGroup{
friend class TileGroupSaveData;
friend class TileGroupLoadData;
friend class TileGroupDataFile;
private:
geom2d::rect<int>range;
geom2d::rect<float>collisionRange={{},{}};
@ -61,46 +63,52 @@ public:
float fadeFactor=0.f;
};
class TileGroupLoadData{
public:
TileGroupLoadData(ResourcePack&pack,const std::string& loadFilename,std::vector<TileGroup>&tilegroups){
datafile data;
datafile::Read(data,loadFilename);
tilegroups.clear();
for(const auto&[key,size]:data.GetOrderedKeys()){
enum TileReadTag:uint32_t{
TILESET_NAME,
FIRSTGID,
TILECOL,
POS_X,
POS_Y,
TILESHEETPOS_X,
TILESHEETPOS_Y,
TILEID,
LAYERID,
};
class TileGroupDataFile{
public:
static void Load(ResourcePack&pack,const std::string& loadFilename,std::vector<TileGroup>&tilegroups){
datafile data;
datafile::Read(data,loadFilename,pack);
tilegroups.clear();
for(const auto&[groupKey,size]:data.GetOrderedKeys()){ //Iterate through groups
for(const auto&[key,size]:data[groupKey].GetOrderedKeys()){ //Iterate through properties of groups
datafile&propData{data[groupKey][key]};
TileGroup&newGroup{tilegroups.emplace_back()};
if(key=="data"){
size_t itemInd{};
newGroup.range.pos.x=data[key].GetInt(itemInd++);
newGroup.range.pos.y=data[key].GetInt(itemInd++);
newGroup.range.size.x=data[key].GetInt(itemInd++);
newGroup.range.size.y=data[key].GetInt(itemInd++);
newGroup.collisionRange.pos.x=data[key].GetReal(itemInd++);
newGroup.collisionRange.pos.y=data[key].GetReal(itemInd++);
newGroup.collisionRange.size.x=data[key].GetReal(itemInd++);
newGroup.collisionRange.size.y=data[key].GetReal(itemInd++);
newGroup.minX=data[key].GetInt(itemInd++);
newGroup.minY=data[key].GetInt(itemInd++);
newGroup.maxX=data[key].GetInt(itemInd++);
newGroup.maxY=data[key].GetInt(itemInd++);
newGroup.range.pos.x=propData.GetInt(itemInd++);
newGroup.range.pos.y=propData.GetInt(itemInd++);
newGroup.range.size.x=propData.GetInt(itemInd++);
newGroup.range.size.y=propData.GetInt(itemInd++);
newGroup.collisionRange.pos.x=propData.GetReal(itemInd++);
newGroup.collisionRange.pos.y=propData.GetReal(itemInd++);
newGroup.collisionRange.size.x=propData.GetReal(itemInd++);
newGroup.collisionRange.size.y=propData.GetReal(itemInd++);
newGroup.minX=propData.GetInt(itemInd++);
newGroup.minY=propData.GetInt(itemInd++);
newGroup.maxX=propData.GetInt(itemInd++);
newGroup.maxY=propData.GetInt(itemInd++);
}else
if(key.starts_with("tileRenderData")){
size_t itemInd{};
TileRenderData&newTileData{newGroup.tiles.emplace_back()};
newTileData.pos.x=data[key].GetReal(itemInd++);
newTileData.pos.y=data[key].GetReal(itemInd++);
newTileData.tileSheetPos.x=data[key].GetInt(itemInd++);
newTileData.tileSheetPos.y=data[key].GetInt(itemInd++);
newTileData.tileID=data[key].GetInt(itemInd++);
newTileData.layerID=data[key].GetInt(itemInd++);
TilesheetData newTilesheetData{propData.GetString(TILESET_NAME),propData.GetInt(FIRSTGID),Pixel{uint32_t(propData.GetInt(TILECOL))}};
TileRenderData newData{newTilesheetData,vf2d{propData.GetReal(POS_X),propData.GetReal(POS_Y)},vi2d{propData.GetInt(TILESHEETPOS_X),propData.GetInt(TILESHEETPOS_Y)},propData.GetInt(TILEID),propData.GetInt(LAYERID)};
TileRenderData&newTileData{newGroup.tiles.emplace_back(newData)};
}else ERR("WARNING! Unknown key "<<key<<" found while trying to load cache for file "<<loadFilename);
}
};
};
class TileGroupSaveData{
public:
TileGroupSaveData(ResourcePack&pack,const std::string& saveFilename,const std::vector<TileGroup>&tilegroups){
}
};
static void Save(ResourcePack&pack,const std::string& saveFilename,const std::vector<TileGroup>&tilegroups){
const bool prevSetupState{datafile::INITIAL_SETUP_COMPLETE};
datafile::INITIAL_SETUP_COMPLETE=false;//Required to write to datafiles.
datafile saveData;
@ -122,14 +130,16 @@ public:
dataProps.SetInt(group.maxY,itemInd++);
TileRenderData:
for(size_t tileRenderInd{};const TileRenderData&tileData:group.tiles){
size_t itemInd{};
datafile&tileRenderData{groupData[std::format("tileRenderData{}",tileRenderInd)]};
tileRenderData.SetReal(tileData.pos.x,itemInd++);
tileRenderData.SetReal(tileData.pos.y,itemInd++);
tileRenderData.SetInt(tileData.tileSheetPos.x,itemInd++);
tileRenderData.SetInt(tileData.tileSheetPos.y,itemInd++);
tileRenderData.SetInt(tileData.tileID,itemInd++);
tileRenderData.SetInt(tileData.layerID,itemInd++);
tileRenderData.SetReal(tileData.pos.x,POS_X);
tileRenderData.SetReal(tileData.pos.y,POS_Y);
tileRenderData.SetInt(tileData.tileSheetPos.x,TILESHEETPOS_X);
tileRenderData.SetInt(tileData.tileSheetPos.y,TILESHEETPOS_Y);
tileRenderData.SetInt(tileData.tileID,TILEID);
tileRenderData.SetInt(tileData.layerID,LAYERID);
tileRenderData.SetString(tileData.tileSheet.tilesetName,TILESET_NAME);
tileRenderData.SetInt(tileData.tileSheet.firstgid,FIRSTGID);
tileRenderData.SetInt(tileData.tileSheet.tilecol.n,TILECOL);
tileRenderInd++;
}
ind++;

View File

@ -39,7 +39,7 @@ All rights reserved.
#define VERSION_MAJOR 1
#define VERSION_MINOR 3
#define VERSION_PATCH 0
#define VERSION_BUILD 12581
#define VERSION_BUILD 12609
#define stringify(a) stringify_(a)
#define stringify_(a) #a

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -731,6 +731,7 @@ namespace olc
bool SavePack(const std::string& sFile, const std::string& sKey);
ResourceBuffer GetFileBuffer(const std::string& sFile);
bool Loaded();
const bool FileExists(const std::string&filename)const;
private:
struct sResourceFile { uint32_t nSize; uint32_t nOffset; };
std::map<std::string, sResourceFile> mapFiles;
@ -1952,6 +1953,10 @@ namespace olc
bool ResourcePack::Loaded()
{ return baseFile.is_open(); }
const bool ResourcePack::FileExists(const std::string&filename)const{
return mapFiles.count(filename)>0;
}
std::vector<char> ResourcePack::scramble(const std::vector<char>& data, const std::string& key)
{
if (key.empty()) return data;

View File

@ -61,6 +61,7 @@ David Barr, aka javidx9, <20>OneLoneCoder 2019, 2020, 2021, 2022
#include <fstream>
#include <stack>
#include <sstream>
#include <strstream>
#include <numeric>
#include "Error.h"
#include<ranges>
@ -329,188 +330,200 @@ namespace olc::utils
return false;
}
inline static bool Read(datafile& n, const std::string& sFileName, olc::ResourcePack&pack, const char sListSep = ',', const OverwriteMode mode=OverwriteMode::NO_OVERWRITE)
{
ResourceBuffer buf{pack.GetFileBuffer(sFileName)};
if(buf.vMemory.size()==0)return true; //Nothing to read.
buf.vMemory.emplace_back('\0');
return _Read(n,buf.vMemory,sListSep,mode);
}
inline static bool Read(datafile& n, const std::string& sFileName, const char sListSep = ',', const OverwriteMode mode=OverwriteMode::NO_OVERWRITE)
{
std::ifstream fileStream{sFileName};
if(fileStream.fail()){
// File not found, so fail
ERR("WARNING! Could not open file "<<sFileName<<"!");
return false;
}
std::vector<char>data;
while(!fileStream.eof())data.emplace_back(fileStream.get());
data.emplace_back('\0');
if(data.size()==0)return true; //Nothing to read.
return _Read(n,data,sListSep,mode);
}
private:
inline static bool _Read(datafile& n,std::vector<char>&data, const char sListSep = ',', const OverwriteMode mode=OverwriteMode::NO_OVERWRITE){
bool previousSetupState=INITIAL_SETUP_COMPLETE;
INITIAL_SETUP_COMPLETE=false;
// Open the file!
std::ifstream file(sFileName);
if (file.is_open())
if(data.size()==0)ERR("WARNING! Nothing to read when trying to read from datafile!!");
std::istringstream inputStream{data.data()};
// These variables are outside of the read loop, as we will
// need to refer to previous iteration values in certain conditions
std::string sPropName = "";
std::string sPropValue = "";
// The file is fundamentally structured as a stack, so we will read it
// in a such, but note the data structure in memory is not explicitly
// stored in a stack, but one is constructed implicitly via the nodes
// owning other nodes (aka a tree)
// I dont want to accidentally create copies all over the place, nor do
// I want to use pointer syntax, so being a bit different and stupidly
// using std::reference_wrapper, so I can store references to datafile
// nodes in a std::container.
std::stack<std::reference_wrapper<datafile>> stkPath;
stkPath.push(n);
// Read file line by line and process
while (!inputStream.eof())
{
// These variables are outside of the read loop, as we will
// need to refer to previous iteration values in certain conditions
std::string sPropName = "";
std::string sPropValue = "";
// Read line
std::string line;
std::getline(inputStream, line);
// The file is fundamentally structured as a stack, so we will read it
// in a such, but note the data structure in memory is not explicitly
// stored in a stack, but one is constructed implicitly via the nodes
// owning other nodes (aka a tree)
// I dont want to accidentally create copies all over the place, nor do
// I want to use pointer syntax, so being a bit different and stupidly
// using std::reference_wrapper, so I can store references to datafile
// nodes in a std::container.
std::stack<std::reference_wrapper<datafile>> stkPath;
stkPath.push(n);
// Read file line by line and process
while (!file.eof())
// This little lambda removes whitespace from
// beginning and end of supplied string
auto trim = [](std::string& s)
{
// Read line
std::string line;
std::getline(file, line);
s.erase(0, s.find_first_not_of(" \t\n\r\f\v"));
s.erase(s.find_last_not_of(" \t\n\r\f\v") + 1);
};
// This little lambda removes whitespace from
// beginning and end of supplied string
auto trim = [](std::string& s)
trim(line);
// If line has content
if (!line.empty())
{
// Test if its a comment...
if (line[0] == '#')
{
s.erase(0, s.find_first_not_of(" \t\n\r\f\v"));
s.erase(s.find_last_not_of(" \t\n\r\f\v") + 1);
};
trim(line);
// If line has content
if (!line.empty())
// ...it is a comment, so ignore
datafile comment;
comment.m_bIsComment = true;
stkPath.top().get().m_vecObjects.push_back({ line, comment });
}
else
{
// Test if its a comment...
if (line[0] == '#')
// ...it is content, so parse. Firstly, find if the line
// contains an assignment. If it does then it's a property...
size_t x = line.find_first_of('=');
if (x != std::string::npos)
{
// ...it is a comment, so ignore
datafile comment;
comment.m_bIsComment = true;
stkPath.top().get().m_vecObjects.push_back({ line, comment });
}
else
{
// ...it is content, so parse. Firstly, find if the line
// contains an assignment. If it does then it's a property...
size_t x = line.find_first_of('=');
if (x != std::string::npos)
// ...so split up the property into a name, and its values!
// Extract the property name, which is all characters up to
// first assignment, trim any whitespace from ends
sPropName = line.substr(0, x);
trim(sPropName);
auto&top=stkPath.top().get();
if(mode==OverwriteMode::NO_OVERWRITE&&stkPath.top().get().HasProperty(sPropName))ERR(std::format("WARNING! Duplicate key found! Key {} already exists! Duplicate line: {}",sPropName,line));
// Extract the property value, which is all characters after
// the first assignment operator, trim any whitespace from ends
sPropValue = line.substr(x + 1, line.size());
trim(sPropValue);
// The value may be in list form: a, b, c, d, e, f etc and some of those
// elements may exist in quotes a, b, c, "d, e", f. So we need to iterate
// character by character and break up the value
bool bInQuotes = false;
bool bEscapeChar = false;
std::string sToken;
size_t nTokenCount = 0;
for (const auto c : sPropValue)
{
// ...so split up the property into a name, and its values!
// Extract the property name, which is all characters up to
// first assignment, trim any whitespace from ends
sPropName = line.substr(0, x);
trim(sPropName);
auto&top=stkPath.top().get();
if(mode==OverwriteMode::NO_OVERWRITE&&stkPath.top().get().HasProperty(sPropName))ERR(std::format("WARNING! Duplicate key found! Key {} already exists! Duplicate line: {}",sPropName,line));
// Extract the property value, which is all characters after
// the first assignment operator, trim any whitespace from ends
sPropValue = line.substr(x + 1, line.size());
trim(sPropValue);
// The value may be in list form: a, b, c, d, e, f etc and some of those
// elements may exist in quotes a, b, c, "d, e", f. So we need to iterate
// character by character and break up the value
bool bInQuotes = false;
bool bEscapeChar = false;
std::string sToken;
size_t nTokenCount = 0;
for (const auto c : sPropValue)
if (bEscapeChar&&c == 'n') //Parse a newline.
{
if (bEscapeChar&&c == 'n') //Parse a newline.
{
sToken.append(1, '\n');
bEscapeChar=false;
continue;
}
sToken.append(1, '\n');
bEscapeChar=false;
// Is character a quote...
if (c == '\"')
{
// ...yes, so toggle quote state
bInQuotes = !bInQuotes;
}
else
if (c == '\\')
{
// ...yes, so toggle quote state
bEscapeChar=true;
}
else
{
// ...no, so proceed creating token. If we are in quote state
// then just append characters until we exit quote state.
if (bInQuotes)
{
sToken.append(1, c);
}
else
{
// Is the character our seperator? If it is
if (c == sListSep)
{
// Clean up the token
trim(sToken);
// Add it to the vector of values for this property
stkPath.top().get()[sPropName].SetString(sToken, nTokenCount);
// Reset our token state
sToken.clear();
nTokenCount++;
}
else
{
// It isnt, so just append to token
sToken.append(1, c);
}
}
}
continue;
}
// Any residual characters at this point just make up the final token,
// so clean it up and add it to the vector of values
if (!sToken.empty())
bEscapeChar=false;
// Is character a quote...
if (c == '\"')
{
trim(sToken);
stkPath.top().get()[sPropName].SetString(sToken, nTokenCount);
// ...yes, so toggle quote state
bInQuotes = !bInQuotes;
}
}
else
{
// ...but if it doesnt, then it's something structural
if (line[0] == '{')
else
if (c == '\\')
{
// Open brace, so push this node to stack, subsequent properties
// will belong to the new node
stkPath.push(stkPath.top().get()[sPropName]);
// ...yes, so toggle quote state
bEscapeChar=true;
}
else
{
if (line[0] == '}')
// ...no, so proceed creating token. If we are in quote state
// then just append characters until we exit quote state.
if (bInQuotes)
{
// Close brace, so this node has been defined, pop it from the
// stack
stkPath.pop();
sToken.append(1, c);
}
else
{
// Line is a property with no assignment. Who knows whether this is useful,
// but we can simply add it as a valueless property...
sPropName = line;
// ...actually it is useful, as valuless properties are typically
// going to be the names of new datafile nodes on the next iteration
// Is the character our seperator? If it is
if (c == sListSep)
{
// Clean up the token
trim(sToken);
// Add it to the vector of values for this property
stkPath.top().get()[sPropName].SetString(sToken, nTokenCount);
// Reset our token state
sToken.clear();
nTokenCount++;
}
else
{
// It isnt, so just append to token
sToken.append(1, c);
}
}
}
}
// Any residual characters at this point just make up the final token,
// so clean it up and add it to the vector of values
if (!sToken.empty())
{
trim(sToken);
stkPath.top().get()[sPropName].SetString(sToken, nTokenCount);
}
}
else
{
// ...but if it doesnt, then it's something structural
if (line[0] == '{')
{
// Open brace, so push this node to stack, subsequent properties
// will belong to the new node
stkPath.push(stkPath.top().get()[sPropName]);
}
else
{
if (line[0] == '}')
{
// Close brace, so this node has been defined, pop it from the
// stack
stkPath.pop();
}
else
{
// Line is a property with no assignment. Who knows whether this is useful,
// but we can simply add it as a valueless property...
sPropName = line;
// ...actually it is useful, as valuless properties are typically
// going to be the names of new datafile nodes on the next iteration
}
}
}
}
}
// Close and exit!
file.close();
INITIAL_SETUP_COMPLETE=previousSetupState;
return true;
}
// File not found, so fail
ERR("WARNING! Could not open file "<<sFileName<<"!");
INITIAL_SETUP_COMPLETE=previousSetupState;
return false;
return true;
}
public: