Files
Brad Arant d7057ebb00 Fix JFile to normalize whitespace when loading JSON from disk
JString::operator=(ZString) already stripped whitespace between JSON
structural tokens before parsing, but JFile constructed via MFile file-
loading bypassed that path entirely, so any pretty-printed/hand-edited
JSON file silently failed every locate()/exists()/get*() call. Widen
removeWhitespace() to protected and call it from JFile constructor.
2026-08-25 19:14:14 -07:00

38 lines
1.6 KiB
C++

#include "JFile.h"
#include "ZString.h"
#include "Exception.h"
namespace coreutils {
// MFile and JString share a single virtual MString base (the diamond:
// both "MFile : virtual public MString" and "JString : virtual public
// MString"), and a virtual base is initialized only by the *most
// derived* class's constructor - so JString's own "{}" default
// initializer never runs here. Left alone, a JFile backed by a new or
// empty file starts as a raw empty string instead of a valid empty JSON
// object, and every subsequent locate()/set() call silently misbehaves
// (no leading "{" for ifNext("{") to match, so writes end up inserted
// at offset 0 with no braces or separators at all). Detect that case
// here and seed valid JSON explicitly.
JFile::JFile(ZString filename) : MFile(filename) {
if(getLength() == 0) {
*this << "{}";
} else {
// MFile's own file-loading reads the raw bytes straight into the
// shared MString buffer - it never goes through JString::operator=,
// which is the only other place this class normally strips
// whitespace before parsing (removeWhitespace()). Without this, a
// JFile backed by a hand-written or pretty-printed JSON file (any
// whitespace between tokens - indentation, newlines, spaces after
// ':'/',') fails every locate()/exists()/get*() call, since
// JString's parser expects compact JSON with no whitespace at all
// between structural tokens. In-memory JSON built via operator=
// never hit this because it already goes through the same
// normalization - loading from disk just missed it.
removeWhitespace();
}
}
}