API — ICoreEssentials/Text
The public contract of 16 header(s) under ICoreEssentials/Text — 24 class/struct definition(s), 487 declaration(s). Each section shows the header's banner and its public (and protected-virtual) surface exactly as the file writes it.
ICoreByteArray.h#
ICoreEssentials/Text/ICoreByteArray.h
⚠ A GUARDED
#include <QByteArray>STOOD HERE (2026-09-10 main merge) ANDLQ.14DELETED IT ON 2026-09-17, with the three members below it.
ICoreByteArray#
ICoreByteArray.h:97 · class · 101 declaration(s)
ICoreByteArray -- the project's own byte buffer.
class ICoreByteArray {
public:
using value_type = char;
// ⚠ char* rather than QByteArray's own iterators. Measured: NOTHING
// outside this tier names ICoreByteArray::iterator or ::const_iterator,
// so changing what they mean cannot break a call site that spells the old
// type -- there is no such call site. A byte array iterates over bytes on
// either store.
using iterator = char*;
using const_iterator = const char*;
// Task Q4.6 re-pointed these at the project's own value-pinned enums
// (Text/ICoreTextEnums.h). A call site spelling ICoreByteArray::
// Base64UrlEncoding is untouched -- see the constants below, which did not
// exist before and are what makes the alias usable without naming Qt.
using Base64Option = ICoreBase64Option;
using Base64Options = ICoreBase64Options;
static constexpr Base64Option Base64Encoding = ICoreBase64Option::Base64Encoding;
static constexpr Base64Option Base64UrlEncoding = ICoreBase64Option::Base64UrlEncoding;
static constexpr Base64Option KeepTrailingEquals = ICoreBase64Option::KeepTrailingEquals;
static constexpr Base64Option OmitTrailingEquals = ICoreBase64Option::OmitTrailingEquals;
static constexpr Base64Option IgnoreBase64DecodingErrors = ICoreBase64Option::IgnoreBase64DecodingErrors;
static constexpr Base64Option AbortOnBase64DecodingErrors = ICoreBase64Option::AbortOnBase64DecodingErrors;
// --- construction ------------------------------------------------------
// The storage: one QByteArray, measured at 24 bytes / align 8 on this
// tree's Qt 6.10.2 -- a QArrayDataPointer, not a single d-pointer. Pinned
// by static_asserts in the .cpp.
//
// *** AND ONE std::string, WHICH IS 24 NOWHERE BUT libc++. ***
// Backends/Native/ICoreByteArray.cpp holds a std::string and asserted
// `== 24`; it is 32 on libstdc++, 32 under MSVC /MD and 40 under MSVC /MDd.
// The same defect as ICoreString's, found in the same sweep and with the
// same shape: a constant derived from the QT store, inherited by the NATIVE
// store without being re-derived. W9.1, 2026-08-24.
//
// *** THE STORE IS A STANDARD-LIBRARY TYPE, SO ITS SIZE BELONGS TO THE
// TOOLCHAIN. *** The buffer is an UPPER BOUND and the .cpp pins it with
// `<=`, never `==`. Measured 2026-08-24:
//
// QByteArray libc++ libstdc++ MSVC /MD MSVC /MDd
// std::string - 24 32 32 40
// QByteArray 24 - - - -
//
// See docs/source/architecture/opaque-buffers.md for why the max is taken
// once rather than branched on _DEBUG.
static constexpr std::size_t kNativeStorageSize = 40;
static constexpr std::size_t kNativeStorageAlign = 8;
// ⚠ NONE OF THESE CAN BE `= default` ANY MORE -- a defaulted special member
// would copy the raw bytes of the buffer and never touch the refcount.
ICoreByteArray();
ICoreByteArray(const ICoreByteArray&);
ICoreByteArray(ICoreByteArray&&) noexcept;
ICoreByteArray& operator=(const ICoreByteArray&);
ICoreByteArray& operator=(ICoreByteArray&&) noexcept;
~ICoreByteArray();
// ⚠⚠ TWO QT CONSTRUCTORS STOOD HERE AND ARE GONE (A9.6, 2026-08-23):
// `ICoreByteArray(const QByteArray&)`, implicit, and an
// `ICoreByteArray(QByteArray&&)` beside it. They are `icoreFromQt()` in
// Text/QtSeam/ICoreByteArrayQt.h [deleted, LQ.13] -- as ONE function, not two.
//
// 📌 THE RVALUE TWIN WAS DELETED RATHER THAN MOVED, and its own comment is
// why: it said "NOT A MOVE, AND IT CANNOT BE on the native store -- there
// is nothing to steal from a QByteArray into a std::string". It did the
// same work as its sibling and existed only to be preferred for a prvalue.
// A free function taking `const QByteArray&` binds a prvalue perfectly
// well, so the overload had nothing left to win.
ICoreByteArray(const char* s);
ICoreByteArray(const char* s, std::ptrdiff_t n);
ICoreByteArray(std::ptrdiff_t n, char fill);
// --- named constructors ------------------------------------------------
static ICoreByteArray fromStdString(const std::string& s);
static ICoreByteArray fromBase64(const ICoreByteArray& b);
static ICoreByteArray fromHex(const ICoreByteArray& b);
static ICoreByteArray fromRawData(const char* s, std::ptrdiff_t n);
static ICoreByteArray number(int n, int base = 10);
static ICoreByteArray number(unsigned int n, int base = 10);
static ICoreByteArray number(long n, int base = 10);
static ICoreByteArray number(unsigned long n, int base = 10);
static ICoreByteArray number(long long n, int base = 10);
static ICoreByteArray number(unsigned long long n, int base = 10);
static ICoreByteArray number(double n, char format = 'g', int precision = 6);
// --- interop with the Qt backing store ---------------------------------
// ⚠⚠ `operator const QByteArray&() const noexcept` STOOD HERE AND IS GONE
// (2026-08-22, A9.6/A9.8). A std::string store has no QByteArray to return
// a reference to -- the third time this exact argument has removed the
// third of three implicit Qt conversions in this tier, after
// `operator const QString&` at 198 call sites (§0.102) and
// `operator const QStringList&` at five (§0.119).
//
// 📌 THIS ONE HAD **ONE**, measured across 992 TUs before it was touched:
// UI/Backends/Qt/Media/ICoreSvg.cpp, inside a zone where naming Qt is legal
// and which appkit drops anyway. It spells toQByteArray() now.
//
// ⚠ AND toQByteArray() WENT BY VALUE for the same reason, exactly as
// toQString() went by value one class over -- then stopped being a member
// at all on 2026-08-23. It is `icoreToQt()` in
// Text/QtSeam/ICoreByteArrayQt.h [deleted, LQ.13], still written over constData()/size() so
// ONE definition serves both stores, and still dropped whole on a build
// with no Qt in it. **27 call expressions moved with it and every one was
// already inside a dropped zone**; not one line outside them changed.
// --- size and state ----------------------------------------------------
bool isEmpty() const noexcept;
bool isNull() const noexcept;
std::ptrdiff_t size() const noexcept;
std::ptrdiff_t length() const noexcept;
void clear();
void resize(std::ptrdiff_t n);
void reserve(std::ptrdiff_t n);
void squeeze();
void truncate(std::ptrdiff_t n);
void chop(std::ptrdiff_t n);
ICoreByteArray& fill(char c, std::ptrdiff_t n = -1);
// --- element access ----------------------------------------------------
char at(std::ptrdiff_t i) const;
char operator[](std::ptrdiff_t i) const;
char& operator[](std::ptrdiff_t i);
char front() const;
char back() const;
char* data() noexcept;
const char* data() const noexcept;
const char* constData() const noexcept;
// ===========================================================================
// ⚠⚠ TEMPORARY Qt COMPATIBILITY SEAM -- ADDED BY THE 2026-09-10 main MERGE.
//
// EVERYTHING BELOW IS SCHEDULED FOR DELETION. It exists because main is the
// tested release and its Qt code is written against the wrapper contract this
// class USED to have: implicit conversion to and from the toolkit type. ui-swap
// removed that contract (A9.5/A9.6 moved it to QtSeam/, LQ.4 deleted QtSeam/),
// and the merge brought main's callers back. Restoring the conversion here was
// the owner's ruling: take main's functionality now, swap the Qt later.
//
// ⚠ THIS BREAKS R2 ON PURPOSE AND THE CENSUS WILL SAY SO. That is the honest
// reading -- this header names Qt again. Do not silence the row; it is
// measuring a real, deliberate, temporary regression.
//
// ⚠ DO NOT BUILD ON IT. No NEW caller may use these. Every use is one more
// thing the swap has to unpick, and the guard below is what makes the
// deletion mechanical: when the last caller is gone, delete the block.
//
// Owned by: W10.31 (Windows), A10.8 (Apple), L9.62 (Linux) -- and LQ.14 is the
// row that removes the seam itself once all three are closed.
// ===========================================================================
// ⚠ THE SEAM'S THREE MEMBERS STOOD HERE -- `ICoreByteArray(const QByteArray&)`,
// `operator QByteArray()` and `toQByteArray()`, restored by the 2026-09-10
// main merge and deleted by `LQ.14` on 2026-09-17. The free functions are in
// `Text/QtSeam/ICoreByteArrayQt.h [deleted, LQ.13]`.
iterator begin();
iterator end();
const_iterator begin() const;
const_iterator end() const;
const_iterator cbegin() const;
const_iterator cend() const;
const_iterator constBegin() const;
const_iterator constEnd() const;
// --- non-mutating transforms -------------------------------------------
ICoreByteArray trimmed() const;
ICoreByteArray simplified() const;
ICoreByteArray toLower() const;
ICoreByteArray toUpper() const;
ICoreByteArray left(std::ptrdiff_t n) const;
ICoreByteArray right(std::ptrdiff_t n) const;
ICoreByteArray mid(std::ptrdiff_t pos, std::ptrdiff_t n = -1) const;
ICoreByteArray sliced(std::ptrdiff_t pos) const;
ICoreByteArray sliced(std::ptrdiff_t pos, std::ptrdiff_t n) const;
ICoreByteArray chopped(std::ptrdiff_t n) const;
ICoreByteArray first(std::ptrdiff_t n) const;
ICoreByteArray last(std::ptrdiff_t n) const;
ICoreByteArray repeated(std::ptrdiff_t times) const;
ICoreByteArray toBase64(Base64Options options = ICoreBase64Option::Base64Encoding) const;
ICoreByteArray toHex(char separator = '\0') const;
ICoreByteArray toPercentEncoding() const;
// H8: a container of the wrapper is not a container of the Qt
// type, so this returns QList<ICoreByteArray> and the mechanical rename of
// the call site's declaration lands on the same type.
// ⚠ RETURNED QList<ICoreByteArray> UNTIL A9.6. A Qt type in a RETURN
// position is a link blocker, and this one was invisible to every text
// search: its single caller in the tree writes
// `for (const ICoreByteArray& line : block.split('\n'))` and never spells
// the container at all. ICoreList is this project's own list and iterates
// the same way, so that caller is untouched.
ICoreList<ICoreByteArray> split(char sep) const;
// --- mutating ----------------------------------------------------------
//
// ⚠ H11: every member below that is overloaded on BOTH
// `const ICoreByteArray&` and `const char*` needs a third overload taking
// `const QByteArray&`, and it is not redundant. QByteArray declares an
// implicit `operator const char*()` (it is only suppressed by
// QT_NO_CAST_FROM_BYTEARRAY, which this project does not define), so a
// plain QByteArray argument -- one still coming out of Qt, or out of a
// wrapper whose phase-1 signature has not been narrowed yet -- converts
// equally well to both, and the call is ambiguous. `m_sseBuffer.append(
// m_reply->readAll())` in ICoreLLMBackend.cpp is where it was found.
// The QByteArray overload is an exact match on the reference and settles
// it. This is H5's mechanism seen from the other side: there a QT method
// went ambiguous for OUR argument, here OUR method goes ambiguous for a
// Qt argument.
ICoreByteArray& append(const ICoreByteArray& b);
ICoreByteArray& append(const char* s);
ICoreByteArray& append(char c);
ICoreByteArray& prepend(const ICoreByteArray& b);
ICoreByteArray& prepend(const char* s);
ICoreByteArray& prepend(char c);
ICoreByteArray& insert(std::ptrdiff_t i, const ICoreByteArray& b);
ICoreByteArray& remove(std::ptrdiff_t pos, std::ptrdiff_t n);
ICoreByteArray& replace(const ICoreByteArray& before, const ICoreByteArray& after);
ICoreByteArray& replace(const char* before, const ICoreByteArray& after);
ICoreByteArray& replace(char before, char after);
// --- searching ---------------------------------------------------------
// Each of these carries the QByteArray overload for H11's reason -- see
// the note above append().
bool contains(const ICoreByteArray& b) const;
bool contains(const char* s) const;
bool contains(char c) const;
bool startsWith(const ICoreByteArray& b) const;
bool startsWith(const char* s) const;
bool startsWith(char c) const;
bool endsWith(const ICoreByteArray& b) const;
bool endsWith(const char* s) const;
bool endsWith(char c) const;
std::ptrdiff_t indexOf(const ICoreByteArray& b, std::ptrdiff_t from = 0) const;
std::ptrdiff_t indexOf(const char* s, std::ptrdiff_t from = 0) const;
std::ptrdiff_t indexOf(char c, std::ptrdiff_t from = 0) const;
std::ptrdiff_t lastIndexOf(const ICoreByteArray& b) const;
std::ptrdiff_t lastIndexOf(char c) const;
std::ptrdiff_t count() const noexcept;
std::ptrdiff_t count(char c) const;
// --- conversions out ---------------------------------------------------
std::string toStdString() const;
int toInt(bool* ok = nullptr, int base = 10) const;
unsigned int toUInt(bool* ok = nullptr, int base = 10) const;
long long toLongLong(bool* ok = nullptr, int base = 10) const;
unsigned long long toULongLong(bool* ok = nullptr, int base = 10) const;
double toDouble(bool* ok = nullptr) const;
float toFloat(bool* ok = nullptr) const;
// --- compound assignment -----------------------------------------------
ICoreByteArray& operator+=(const ICoreByteArray& b);
// ⚠ THE `const QByteArray&` OVERLOAD STOOD HERE AND IS A FREE FUNCTION NOW
// (A9.6, 2026-08-23), beside the mixed comparisons it belongs with. A
// compound assignment does not have to be a member, and this one never
// touched the store -- it forwarded to the portable append().
ICoreByteArray& operator+=(const char* s);
ICoreByteArray& operator+=(char c);
};
ICoreByteArrayData.h#
ICoreEssentials/Text/ICoreByteArrayData.h
ICoreByteArrayData#
ICoreByteArrayData.h:37 · class · 26 declaration(s)
ICoreByteArrayData -- the project's own byte store.
class ICoreByteArrayData {
public:
using size_type = ICoreTextDetail::ICoreBufferSize;
// A default-constructed store is NULL, not empty -- the distinction
// QByteArray::isNull() draws, which the conformance suite pins.
constexpr ICoreByteArrayData() noexcept : m_block(nullptr) {}
// Adopts an immortal block. Not constexpr, for the reason spelled out on
// ICoreStringData::immortal(): a class with a non-trivial destructor is not
// a literal type. The compile-time half of the trick is the BLOCK.
static ICoreByteArrayData immortal(const ICoreTextDetail::ICoreCowBlock* block) noexcept
{
return ICoreByteArrayData(const_cast<ICoreTextDetail::ICoreCowBlock*>(block));
}
ICoreByteArrayData(const ICoreByteArrayData& other) noexcept;
ICoreByteArrayData(ICoreByteArrayData&& other) noexcept;
ICoreByteArrayData& operator=(const ICoreByteArrayData& other) noexcept;
ICoreByteArrayData& operator=(ICoreByteArrayData&& other) noexcept;
~ICoreByteArrayData();
// n < 0 means "measure it with strlen", which is the ONLY place in this
// type a NUL is treated as a terminator, and only because the caller asked
// by passing -1.
static ICoreByteArrayData fromBytes(const char* s, size_type n = -1);
static ICoreByteArrayData filled(size_type n, char fill);
static ICoreByteArrayData empty();
bool isNull() const noexcept { return m_block == nullptr; }
bool isEmpty() const noexcept { return size() == 0; }
size_type size() const noexcept { return m_block ? m_block->size : 0; }
size_type capacity() const noexcept { return m_block ? m_block->capacity : 0; }
// Always NUL-terminated, and never null itself: a null store reads as the
// empty array, which is what QByteArray::constData() does.
const char* constData() const noexcept;
bool isImmortal() const noexcept;
bool isShared() const noexcept;
int refCount() const noexcept;
char* mutableData();
void detach();
void reserve(size_type n);
void resize(size_type n, char fill = '\0');
void truncate(size_type n);
void clear();
void squeeze();
void assign(const char* s, size_type n);
void append(const char* s, size_type n);
void append(char c);
void prepend(const char* s, size_type n);
void insert(size_type pos, const char* s, size_type n);
void remove(size_type pos, size_type n);
void replaceRange(size_type pos, size_type n, const char* s, size_type m);
};
ICoreChar.h#
ICoreEssentials/Text/ICoreChar.h
ICoreChar#
ICoreChar.h:82 · class · 18 declaration(s)
ICoreChar -- the project's own character: ONE UTF-16 CODE UNIT, held in an opaque two-byte buffer.
class ICoreChar {
public:
// ⚠ MEASURED: QChar is 2 bytes / align 2, TRIVIALLY COPYABLE and TRIVIALLY
// DESTRUCTIBLE on this tree's Qt 6.10.2. Both of those matter here in a way
// they did not for ICoreString:
//
// * Trivially copyable means the implicit copy and move -- a two-byte
// memcpy of the buffer -- are CORRECT, so this type declares none of the
// five and stays trivially copyable itself. That is load-bearing: an
// ICoreChar is passed BY VALUE in ICoreString's signatures and in every
// operator below, and a user-declared copy constructor would move it out
// of a register and into memory at every one of those call sites.
// * Trivially destructible means no destructor is needed either.
//
// So only the three CONSTRUCTORS have bodies to move, and they are the only
// members that touch the buffer through placement new. The .cpp pins all
// four properties with static_asserts.
static constexpr std::size_t kNativeStorageSize = 2;
static constexpr std::size_t kNativeStorageAlign = 2;
// --- construction ------------------------------------------------------
ICoreChar();
// ⚠⚠ THE PORTABLE CHARACTER CONSTRUCTOR, ADDED 2026-08-23 (A9.13), AND IT
// IS A LINK FIX RATHER THAN A CONVENIENCE. Before it, this class had no
// constructor taking a code unit at all, so the tree's ordinary spelling
//
// ICoreChar(u'_')
//
// bound `char16_t -> QChar` (Qt's own implicit constructor) and then
// `ICoreChar(QChar)`. **83 translation units reached QtCore through that
// chain, 61 of them inside `src/ICoreSDK`** -- a module the architecture
// census proves free of Qt NAMES across 1341 files, and correctly, because
// not one of those call sites spells a Qt type. §0.131's note 1 on this
// tier's board is exactly this shape: a hit-count measures what a file
// NAMES, the link measures what it NEEDS.
//
// This overload was an EXACT MATCH for a u'x' literal, so it beat the
// QChar chain (which costs a user-defined conversion) at every one of
// those sites with no call-site churn at all. ⚠ THERE IS NO CHAIN TO BEAT
// ANY MORE -- A9.6 removed ICoreChar(QChar) on 2026-08-23 -- so this is now
// the ONLY way to build the type from a code unit rather than the better of
// two. It stays implicit on its own merits: `c == ICoreChar(u'x')` and the
// ICoreString members taking a character by value both want it.
ICoreChar(char16_t c) noexcept;
// ⚠⚠ TWO QT CONSTRUCTORS STOOD HERE AND ARE GONE (A9.6, 2026-08-23):
// `ICoreChar(QChar)` -- implicit -- and `explicit ICoreChar(QLatin1Char)`.
// They are `icoreFromQt()` in Text/QtSeam/ICoreCharQt.h [deleted, LQ.13] now.
//
// 📌 AND ONE ARGUMENT RETIRED WITH THEM RATHER THAN MOVING. The `explicit`
// on the second was plan §6 H4: an implicit one gave `qLatin1Char ==
// qChar` two candidates each costing one user-defined conversion and tied
// them, in unmigrated files naming neither ICoreChar nor this refactor.
// **A named free function is never a conversion candidate**, so the hazard
// cannot arise and the seam's overload carries no `explicit` at all. A
// rule whose mechanism has gone is worth deleting rather than porting.
// ⚠ THE PROJECT'S OWN LATIN-1 CHARACTER, ADDED 2026-08-22 (phase 3).
// ICoreLatin1Char used to be `using ICoreLatin1Char = QLatin1Char`, so one
// constructor answered both spellings and this one was unnecessary. It is a
// real class now (ICoreStringLiteral.h) and the two are different types, so
// each needs its own.
//
// ⚠ AND IT IS THE ONLY ONE LEFT: the note here used to end "the Qt-typed
// one stays because the sites that spell Qt's name still compile against
// it", and that ceased to be true on 2026-08-23 (A9.6) -- the QLatin1Char
// constructor is `icoreFromQt()` in the seam now. The plan item this note
// called "B20 absorbs QLatin1Char and retires them" is therefore closed for
// THIS class, by a different route than it expected.
explicit ICoreChar(ICoreLatin1Char c) noexcept;
// --- interop with Qt ----------------------------------------------------
//
// ⚠⚠ THERE IS NONE, AND THAT IS THE STATE RATHER THAN AN OVERSIGHT. Two
// members stood here -- `operator QChar()` and `QChar toQChar()` -- and
// both are free functions in Text/QtSeam/ICoreCharQt.h [deleted, LQ.13] since 2026-08-23.
// This heading is kept so the next reader looking for them finds where they
// went instead of concluding they were never declared.
//
// 📌 THE STEP BEFORE THIS ONE PUT THEM BEHIND `ICORE_QT_IN_BUILD`, AND
// THAT DEFINE IS STILL LIVE FOR A9.5 AND A9.7 -- do not delete it because
// this class stopped using it. Its whole argument is in CMakeLists.txt: the
// guard cannot be `ICORE_CORE_BACKEND_NATIVE`, because `qt`+`native` sets
// the native backend AND compiles the seam, and it needs a per-target
// exemption for `ICorePreReleaseTests`, which keeps Qt in every
// configuration by owner ruling (§0.134).
//
// ⚠ AND THE HEADING IS NOW HONEST ON BOTH SIDES: this class holds a
// `char16_t` on the native store (§0.132), so "the Qt backing store" -- what
// this comment used to say -- was true of one seat only. There was never a
// Qt store to interop WITH here; there was a Qt CONVERSION, and it is
// scaffolding with a demolition date under the owner's zero-Qt ruling.
// --- classification ----------------------------------------------------
bool isNull() const noexcept;
bool isDigit() const noexcept;
bool isLetter() const noexcept;
bool isLetterOrNumber() const noexcept;
bool isNumber() const noexcept;
bool isSpace() const noexcept;
bool isPunct() const noexcept;
bool isUpper() const noexcept;
bool isLower() const noexcept;
bool isPrint() const noexcept;
// --- case --------------------------------------------------------------
ICoreChar toUpper() const noexcept;
ICoreChar toLower() const noexcept;
// --- value -------------------------------------------------------------
char16_t unicode() const noexcept;
char toLatin1() const noexcept;
int digitValue() const noexcept;
};
ICoreCowBuffer.h#
ICoreEssentials/Text/ICoreCowBuffer.h
ICoreCowBuffer -- the copy-on-write block machinery, once, for every store in Text/.
W9.1.
ICoreStringData(UTF-16) andICoreByteArrayData(bytes) are the same allocator, the same refcount, the same growth curve and the same immortal-literal trick over a different element size. This header is that shared half, and the two stores are thin handles on top of it.⚠ WHY SHARED RATHER THAN COPIED, WHICH IS THE CHEAPER-LOOKING OPTION. Refcounting written twice is refcounting that DRIFTS, and the drift is silent: a fix to the detach rule, the immortal check or the growth curve lands in one store and not the other, and the store that missed it fails later, under load, in the corner nobody re-reads. The cost of sharing is one
ICoreCowBlock#
ICoreCowBuffer.h:51 · struct · 0 declaration(s)
⚠ THE HEADER OF EVERY BLOCK, STATIC OR HEAP, AND THE TWO MUST AGREE ON LAYOUT.
struct ICoreCowBlock {
public:
// mutable: an immortal block is declared `static const` at its use site,
// and a shared heap block is reference-counted through a const handle.
mutable std::atomic<int> ref;
ICoreBufferSize size;
ICoreBufferSize capacity;
};
};
File-scope declarations#
// The tree's size type for text and bytes, spelled without Qt. `qsizetype` IS
// `ptrdiff_t` on every platform this tree builds for.
using ICoreBufferSize = std::ptrdiff_t;
ICoreDoubleText.h#
ICoreEssentials/Text/ICoreDoubleText.h
ICoreDoubleText -- a double as text, exactly, in any process locale.
write()/toString() print the SHORTEST decimal that reads back as the very same double, and parse()/fromString() read it back. The pair round-trips every double bit for bit -- subnormals, the extremes and -0 included -- so a value can be saved as text and loaded without moving by a single ulp:
ICoreDoubleText::toString(0.1) == "0.1" ICoreDoubleText::toString(1234.5678) == "1234.5678" ICoreDoubleText::toString(1e22) == "1e+22" ICoreDoubleText::toString(5e-324) == "5e-324" ICoreDoubleText::fromString("0.1", &ok) == 0.1 (the same bits)
Neither direction reads the process locale. gtk_init() calls
ICoreDoubleText#
ICoreDoubleText.h:52 · class · 5 declaration(s)
class ICoreDoubleText {
public:
ICoreDoubleText() = delete;
// The longest text write() produces, plus its terminating NUL.
static constexpr std::size_t bufferSize = 32;
// Writes value's text and a terminating NUL into `buffer`, which must hold
// at least bufferSize chars, and returns the text's length.
static std::size_t write(double value, char* buffer);
[[nodiscard]] static ICoreString toString(double value);
// Parses [first, last) as ONE number in the grammar above. On success
// stores the value and returns true; on failure returns false and leaves
// *value alone.
[[nodiscard]] static bool parse(const char* first, const char* last, double* value);
// Parses the whole of `text`. Returns 0.0 and sets *ok to false when it is
// not one number in the grammar above.
[[nodiscard]] static double fromString(const ICoreString& text, bool* ok = nullptr);
};
};
ICoreLocale.h#
ICoreEssentials/Text/ICoreLocale.h
ICoreLocale#
ICoreLocale.h:133 · class · 2 declaration(s)
ICoreLocale -- locale-aware number parsing.
class ICoreLocale {
public:
// The invariant "C" locale: '.' decimal separator, no group separator.
[[nodiscard]] static ICoreLocale c();
// Parse a decimal number. `ok` is set false when `s` is not a complete,
// valid, FINITE number -- callers rely on that to reject partial input
// rather than silently taking the 0.0 that a failed parse also returns.
// See the equivalence note above for what "complete" and "finite" mean and
// where they differ from the QLocale version this replaced.
double toDouble(const ICoreString& s, bool* ok = nullptr) const;
};
ICoreRegex.h#
ICoreEssentials/Text/ICoreRegex.h
⚠⚠ FOUR QT INCLUDES STOOD HERE AND ARE GONE (A9.7, 2026-08-23): <QRegularExpression>, <QRegularExpressionMatch>, <QRegularExpressionMatchIterator> and <QString>. They served five members -- two converting constructors, one iterator constructor and the two
operator const Q…&-- and all five are deleted.⚠⚠ AND THEY WERE DELETED, NOT RELOCATED, WHICH IS DIFFERENT FROM EVERY OTHER CONVERSION THIS TIER HAS MOVED. ICoreChar, ICoreByteArray and ICoreStringList convert through a PUBLIC portable surface -- unicode(), constData()/size(), at() -- so their conversions became free functions in Text/QtSeam/ [deleted, LQ.13]. These two returned a REFERENCE INTO AN 8-BYTE PRIVATE STORE, and a free function has no access to a private buffer. There was nowhere to move them to.
ICoreRegexMatch#
ICoreRegex.h:95 · class · 16 declaration(s)
ICoreRegex / ICoreRegexMatch / ICoreRegexMatchIterator -- the project's own regular expressions.
class ICoreRegexMatch {
public:
// One QRegularExpressionMatch, pinned by static_asserts in the .cpp.
static constexpr std::size_t kNativeStorageSize = 8;
static constexpr std::size_t kNativeStorageAlign = 8;
ICoreRegexMatch();
ICoreRegexMatch(const ICoreRegexMatch& other);
ICoreRegexMatch(ICoreRegexMatch&& other) noexcept;
ICoreRegexMatch& operator=(const ICoreRegexMatch& other);
ICoreRegexMatch& operator=(ICoreRegexMatch&& other) noexcept;
~ICoreRegexMatch();
bool hasMatch() const;
bool hasPartialMatch() const;
bool isValid() const;
ICoreString captured(std::ptrdiff_t n = 0) const;
ICoreString captured(const ICoreString& name) const;
ICoreStringList capturedTexts() const;
std::ptrdiff_t capturedStart(std::ptrdiff_t n = 0) const;
std::ptrdiff_t capturedEnd(std::ptrdiff_t n = 0) const;
std::ptrdiff_t capturedLength(std::ptrdiff_t n = 0) const;
std::ptrdiff_t lastCapturedIndex() const;
};
ICoreRegexMatchIterator#
ICoreRegex.h:150 · class · 10 declaration(s)
class ICoreRegexMatchIterator {
public:
// One QRegularExpressionMatchIterator, pinned by static_asserts in the .cpp.
static constexpr std::size_t kNativeStorageSize = 8;
static constexpr std::size_t kNativeStorageAlign = 8;
ICoreRegexMatchIterator();
ICoreRegexMatchIterator(const ICoreRegexMatchIterator& other);
ICoreRegexMatchIterator(ICoreRegexMatchIterator&& other) noexcept;
ICoreRegexMatchIterator& operator=(const ICoreRegexMatchIterator& other);
ICoreRegexMatchIterator& operator=(ICoreRegexMatchIterator&& other) noexcept;
~ICoreRegexMatchIterator();
bool isValid() const;
bool hasNext() const;
ICoreRegexMatch next();
ICoreRegexMatch peekNext() const;
};
ICoreRegex#
ICoreRegex.h:177 · class · 21 declaration(s)
class ICoreRegex {
public:
// Enum aliases. They USED to point at Qt's enums, so that the mechanical
// rename did not have to special-case a qualified enumerator; task Q0.4
// re-pointed them at the project's own value-pinned enums in
// ICoreTextEnums.h. Both halves of that still hold -- a call site that
// writes ICoreRegex::CaseInsensitiveOption compiles unchanged -- but the
// parameter lists below no longer name a Qt type, which is the point.
using PatternOption = ICoreRegexPatternOption;
using PatternOptions = ICoreRegexPatternOptions;
using MatchType = ICoreRegexMatchType;
using MatchOption = ICoreRegexMatchOption;
using MatchOptions = ICoreRegexMatchOptions;
static constexpr PatternOption NoPatternOption = ICoreRegexPatternOption::NoPatternOption;
static constexpr PatternOption CaseInsensitiveOption = ICoreRegexPatternOption::CaseInsensitiveOption;
static constexpr PatternOption DotMatchesEverythingOption = ICoreRegexPatternOption::DotMatchesEverythingOption;
static constexpr PatternOption MultilineOption = ICoreRegexPatternOption::MultilineOption;
static constexpr PatternOption ExtendedPatternSyntaxOption = ICoreRegexPatternOption::ExtendedPatternSyntaxOption;
static constexpr PatternOption InvertedGreedinessOption = ICoreRegexPatternOption::InvertedGreedinessOption;
static constexpr PatternOption DontCaptureOption = ICoreRegexPatternOption::DontCaptureOption;
static constexpr PatternOption UseUnicodePropertiesOption = ICoreRegexPatternOption::UseUnicodePropertiesOption;
static constexpr MatchType NormalMatch = ICoreRegexMatchType::NormalMatch;
static constexpr MatchType PartialPreferCompleteMatch = ICoreRegexMatchType::PartialPreferCompleteMatch;
static constexpr MatchType PartialPreferFirstMatch = ICoreRegexMatchType::PartialPreferFirstMatch;
static constexpr MatchType NoMatch = ICoreRegexMatchType::NoMatch;
static constexpr MatchOption NoMatchOption = ICoreRegexMatchOption::NoMatchOption;
static constexpr MatchOption AnchorAtOffsetMatchOption = ICoreRegexMatchOption::AnchorAtOffsetMatchOption;
static constexpr MatchOption DontCheckSubjectStringMatchOption = ICoreRegexMatchOption::DontCheckSubjectStringMatchOption;
// One QRegularExpression, pinned by static_asserts in the .cpp.
static constexpr std::size_t kNativeStorageSize = 8;
static constexpr std::size_t kNativeStorageAlign = 8;
// --- construction ------------------------------------------------------
ICoreRegex();
// EXPLICIT, mirroring QRegularExpression's own explicit string constructor
// -- see the second design note. This is not the H4 rule; it is Qt's rule.
explicit ICoreRegex(const ICoreString& pattern, PatternOptions options = ICoreRegexPatternOption::NoPatternOption);
ICoreRegex(const ICoreRegex& other);
ICoreRegex(ICoreRegex&& other) noexcept;
ICoreRegex& operator=(const ICoreRegex& other);
ICoreRegex& operator=(ICoreRegex&& other) noexcept;
~ICoreRegex();
// --- interop with the Qt backing store ---------------------------------
// --- pattern -----------------------------------------------------------
ICoreString pattern() const;
void setPattern(const ICoreString& pattern);
PatternOptions patternOptions() const;
void setPatternOptions(PatternOptions options);
bool isValid() const;
ICoreString errorString() const;
std::ptrdiff_t patternErrorOffset() const;
int captureCount() const;
ICoreStringList namedCaptureGroups() const;
// --- matching ----------------------------------------------------------
ICoreRegexMatch match(const ICoreString& subject,
std::ptrdiff_t offset = 0,
MatchType type = ICoreRegexMatchType::NormalMatch,
MatchOptions options = ICoreRegexMatchOption::NoMatchOption) const;
ICoreRegexMatchIterator globalMatch(const ICoreString& subject,
std::ptrdiff_t offset = 0,
MatchType type = ICoreRegexMatchType::NormalMatch,
MatchOptions options = ICoreRegexMatchOption::NoMatchOption) const;
// --- statics -----------------------------------------------------------
static ICoreString escape(const ICoreString& s);
// A single character is the shape ICoreParityBlockFilter's wildcard builder
// needs, and it cannot reach the overload above: ICoreChar -> QChar ->
// ICoreString is two user-defined conversions. A static member joins no Qt
// overload set (A14's rule), so this is free of H4 exposure.
static ICoreString escape(ICoreChar c);
static ICoreString anchoredPattern(const ICoreString& s);
static ICoreString wildcardToRegularExpression(const ICoreString& s);
// --- the backing store, as an opaque pointer ---------------------------
//
// ⚠⚠ THIS REPLACED `operator const QRegularExpression&() const noexcept`
// (A9.7, 2026-08-23), which was this class's whole Qt surface and the last
// Qt name in this header.
//
// 📌 IT COULD NOT BECOME A FREE FUNCTION IN A SEAM, which is how ICoreChar,
// ICoreByteArray and ICoreStringList moved theirs: those convert through a
// PUBLIC portable surface, while this one returned a REFERENCE INTO
// m_storage, and a free function cannot reach a private buffer. So the
// reference stays a member's to give and what is published is a pointer
// that names no toolkit type — each seat knows what it put in the buffer
// and casts. It is the OUTBOUND half of the `void* nativeState`
// constructors the two classes above have used since §0.48, and it is what
// lets BOTH backends satisfy one declaration.
//
// ⚠⚠ PUBLIC, AND IT WAS PRIVATE-WITH-A-FRIEND FOR ONE BUILD. The header
// surface rule permits exactly two private lines, `class Impl;` and the
// impl pointer — so `private: const void* nativeState() const;` is a
// private HELPER and R4.2 failed on it. Narrowing visibility is not
// available here; the honest form is public, which is also consistent with
// `kNativeStorageSize` and `kNativeStorageAlign` already being public.
//
// ⚠ ITS ONLY CALLER IN THE TREE IS `ICoreString`'s six regex members
// (`remove`, `replace`, `contains`, `indexOf`, `lastIndexOf`, `split`),
// measured before the change and all inside a zone a Qt-free build drops.
// **Do not add a second one without asking what it really wants** — a
// pointer into another class's buffer is not an API, it is a seam.
const void* nativeState() const noexcept;
};
ICoreRegexEngine.h#
ICoreEssentials/Text/ICoreRegexEngine.h
ICoreRegexEngine -- the project's own regular-expression engine.
W9.1, §42.5 decision 2: "a hand-rolled backtracking engine over the MEASURED subset, plus a guard that fails when a pattern outside it appears". PCRE2 was rejected on D2 (the rule that made W0.8 write an SVG reader by hand); std::wregex was rejected on the syntax highlighter, which runs 40 rules per line and is the workload std::regex is worst at.
It names NO TOOLKIT: this header includes <cstddef>, <string> and <vector>, and the .cpp adds only the project's own character tier.
⚠⚠ THE SUBSET IS MEASURED, AND THE MEASUREMENT CORRECTED THE DECISION.
§42.5 recorded "71 distinct pattern literals ... no lookaround". Re-run by
ICoreRegexCapture#
ICoreRegexEngine.h:133 · struct · 0 declaration(s)
One capture's span, or {-1, -1} when the group did not participate.
struct ICoreRegexCapture {
public:
long start = -1;
long end = -1;
};
};
ICoreRegexEngine#
ICoreRegexEngine.h:138 · class · pImpl · 10 declaration(s)
class ICoreRegexEngine {
public:
ICoreRegexEngine();
~ICoreRegexEngine();
ICoreRegexEngine(const ICoreRegexEngine&) = delete;
ICoreRegexEngine& operator=(const ICoreRegexEngine&) = delete;
ICoreRegexEngine(ICoreRegexEngine&&) noexcept;
ICoreRegexEngine& operator=(ICoreRegexEngine&&) noexcept;
// Compiles, or leaves the engine invalid with an error to report. Returns
// isValid() for convenience at a call site that wants to branch at once.
bool compile(const char16_t* pattern, std::size_t length,
ICoreRegexEngineOption options = ICoreRegexEngineOption::None);
bool isValid() const noexcept;
// Empty when valid. Names the construct, not just "syntax error", because
// the whole point of the refusal is that a human can act on it.
const std::string& errorString() const noexcept;
// -1 when valid; otherwise the offset INTO THE PATTERN where the refusal
// happened, which is what ICoreRegex::patternErrorOffset() reports.
long errorOffset() const noexcept;
// The number of CAPTURING groups; group 0 (the whole match) is not counted,
// matching QRegularExpression::captureCount().
int captureCount() const noexcept;
// Searches from `offset`. `captures` is resized to captureCount() + 1 and
// filled; index 0 is the whole match. Returns false and leaves `captures`
// untouched when there is no match.
//
// `anchored` requires the match to START at `offset` -- Qt's
// AnchorAtOffsetMatchOption -- rather than searching forward for one.
//
// `notEmptyAtStart` forbids a ZERO-LENGTH match beginning at `offset`, and
// only there. It is PCRE2's NOTEMPTY_ATSTART, and it exists for one caller:
// the global-match loop, which must be able to ask "is there a longer
// answer at this same position?" after an empty one. Without it an iterator
// has to guess, and the guess is wrong -- MEASURED against Qt 6.9.2:
//
// /(?:)|a/ over "aa" -> 0,0) [0,1) [1,1) [1,2) [2,2)
//
// The second span is the retry. An iterator that simply advanced one
// character after an empty match would report [0,0) [1,1) [2,2) and would
// agree with Qt on every pattern whose empty match means "nothing else
// fits" -- which is every pattern in this product's corpus, and is why the
// wrong rule survives a corpus sweep. It parts company as soon as a lazy
// quantifier or an empty alternation branch can start a match.
bool match(const char16_t* subject, std::size_t length, std::size_t offset,
std::vector<ICoreRegexCapture>& captures, bool anchored = false,
bool notEmptyAtStart = false) const;
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
File-scope declarations#
// The options this engine honours. They mirror the three ICoreRegexPatternOption
// values the product actually sets; the rest of Qt's options have no call site
// and are not invented here (Rule 3).
enum class ICoreRegexEngineOption : unsigned {
None = 0,
CaseInsensitive = 1u << 0,
Multiline = 1u << 1,
DotMatchesAll = 1u << 2,
};
ICoreString.h#
[ICoreEssentials/Text/ICoreString.h
⚠ A GUARDED
#include <QString>STOOD HERE (2026-09-10 main merge) ANDLQ.14DELETED IT ON 2026-09-17, with the three members below it. This header names no toolkit type again, in its text AND in its preprocessor.
ArgIsText#
ICoreString.h:199 · struct · template · bases std::false_type · 0 declaration(s)
"is this argument a placeholder VALUE?" -- the mirror of Qt's is_string_like<T>, which is simply is_convertible<T, QAnyStringView>.
template <class T>
struct ArgIsText : std::false_type {
};
ArgText#
ICoreString.h:207 · struct · template · bases ArgIsText<ArgDecay<T>> · 0 declaration(s)
template <class T>
struct ArgText : ArgIsText<ArgDecay<T>> {
};
ICoreString#
ICoreString.h:243 · class · 139 declaration(s)
class ICoreString {
public:
// ⚠ THESE THREE PUBLISHED QT AS THIS TYPE'S CONTRACT UNTIL A9.5.
// `value_type` was `QChar` and the iterators were `QString`'s own, so a
// caller writing `ICoreString::value_type` or ranging over one got a Qt
// type without ever spelling a Qt name.
//
// ⚠ THE MEASUREMENT THAT MADE THIS SAFE, and it is stronger than the
// board's own claim: `QChar` occurs in **0** files outside
// src/ICoreEssentials/Text/ — comments, strings and block comments
// stripped, over src/, testingLabs/ and include/. Not "nothing iterates
// as QChar"; nothing outside this tier NAMES QChar at all. So changing
// what these three mean cannot break a call site that spells the old
// type, because there is no such call site.
//
// ⚠ ICoreChar* AND NOT char16_t*, AND THE CALL SITE IS WHY. The first cut
// of this row used char16_t on the argument that QChar is layout-
// compatible with it and an ICoreChar* would be reinterpreting one
// wrapper as another. The build answered: `ICoreParityBlockFilter.cpp:35`
// ranges over an ICoreString as `const ICoreChar`, and it was the ONLY
// site in the tree that iterates one at all.
//
// ⚠ SO THE BOARD'S "ZERO code iterates an ICoreString as QChar" IS TRUE
// AND WAS READ AS "nothing iterates one", WHICH IS NOT. Iteration exists;
// it simply never spelled a Qt name, so no census keyed on `QChar` could
// see it. The one caller wants an ICoreChar, so that is what begin() and
// end() hand it -- §0.28's rule, decided by counting rather than taste.
//
// The cast is sound for the same reason the char16_t one would have been:
// ICoreChar is 2 bytes, align 2, trivially copyable, holding one QChar,
// and its .cpp pins all four with static_asserts.
using value_type = ICoreChar;
using iterator = ICoreChar*;
using const_iterator = const ICoreChar*;
// Enum aliases. These exist so the mechanical `QString` -> `ICoreString`
// rename does not have to special-case qualified enum names: a call site
// written QString::SectionSkipEmpty becomes ICoreString::SectionSkipEmpty
// and still compiles.
//
// Task Q4.4 re-pointed all five families at the project's own value-pinned
// enums (Text/ICoreTextEnums.h). Every call site that spells one of the
// constants below is untouched by that -- the ~34 sites writing
// ICoreString::CaseInsensitive or ICoreString::SkipEmptyParts still
// compile, and now they no longer resolve to a Qt type.
using SectionFlag = ICoreSectionFlag;
using SectionFlags = ICoreSectionFlags;
using NormalizationForm = ICoreNormalizationForm;
static constexpr SectionFlag SectionDefault = ICoreSectionFlag::Default;
static constexpr SectionFlag SectionSkipEmpty = ICoreSectionFlag::SkipEmpty;
static constexpr SectionFlag SectionIncludeLeadingSep = ICoreSectionFlag::IncludeLeadingSep;
static constexpr SectionFlag SectionIncludeTrailingSep = ICoreSectionFlag::IncludeTrailingSep;
static constexpr SectionFlag SectionCaseInsensitiveSeps = ICoreSectionFlag::CaseInsensitiveSeps;
static constexpr NormalizationForm NormalizationForm_D = ICoreNormalizationForm::D;
static constexpr NormalizationForm NormalizationForm_C = ICoreNormalizationForm::C;
static constexpr NormalizationForm NormalizationForm_KD = ICoreNormalizationForm::KD;
static constexpr NormalizationForm NormalizationForm_KC = ICoreNormalizationForm::KC;
// Same aliasing trick, for the two enums that searching/split members below
// default to case-sensitive / keep-empty-parts. A call site that wants the
// non-default value used to have to spell Qt:: itself; now it spells
// ICoreString:: instead, same as every other enum on this type.
using CaseSensitivity = ICoreCaseSensitivity;
static constexpr CaseSensitivity CaseSensitive = ICoreCaseSensitivity::Sensitive;
static constexpr CaseSensitivity CaseInsensitive = ICoreCaseSensitivity::Insensitive;
using SplitBehavior = ICoreSplitBehavior;
static constexpr SplitBehavior KeepEmptyParts = ICoreSplitBehavior::KeepEmptyParts;
static constexpr SplitBehavior SkipEmptyParts = ICoreSplitBehavior::SkipEmptyParts;
// ⚠ MEASURED at 24 bytes / align 8 on this tree's Qt 6.10.2, macOS arm64 --
// NOT one d-pointer. Qt 6's QString holds a QStringPrivate, which is three
// words (the shared d, the data pointer and the size), where Qt 5's held a
// single pointer. The first cut of this row assumed sizeof(void*) and the
// static_assert in the .cpp caught it on the first build, which is exactly
// what it is there for. See the buffer note at the top of the file for why
// this is a buffer and not a heap Impl.
//
// *** THAT 24 IS QString's, AND A SECOND STORE INHERITED IT WITHOUT BEING
// RE-DERIVED. *** Backends/Native/ICoreString.cpp holds a std::u16string and
// asserted `== 24`. std::u16string is 24 on libc++ ONLY -- the one standard
// library that seat was written against. It is 32 on libstdc++, 32 under
// MSVC /MD and 40 under MSVC /MDd, so the native seat could not compile on
// Windows OR Linux; nobody had hit it because both still configure
// ICORE_CORE_BACKEND=qt. Found and re-pinned by W9.1 on 2026-08-24.
//
// *** THE STORE IS A STANDARD-LIBRARY TYPE, SO ITS SIZE BELONGS TO THE
// TOOLCHAIN AND NOT TO THIS TREE. *** The buffer is an UPPER BOUND and the
// .cpp pins it with `<=`, never `==`. Measured 2026-08-24, one probe TU per
// column, not inferred:
//
// QString libc++ libstdc++ MSVC /MD MSVC /MDd
// std::u16string - 24 32 32 40
// QString 24 - - - -
//
// 40 is the max and 40 is what EVERY configuration carries -- one layout per
// platform rather than one per build type, because this SDK ships and a
// public sizeof() that moves with _DEBUG changes object layout while changing
// no mangled name: a build that straddles it links perfectly and corrupts
// memory at run time. The 16 bytes over libc++'s need are the price of that,
// and the trade is the owner's to reverse:
// docs/source/architecture/opaque-buffers.md.
static constexpr std::size_t kNativeStorageSize = 40;
static constexpr std::size_t kNativeStorageAlign = 8;
// --- construction ------------------------------------------------------
// ⚠ NONE OF THESE CAN BE `= default` ANY MORE. A defaulted special member
// would copy the raw bytes of the buffer and never touch QString's
// refcount; each one is written out in the .cpp, constructing or assigning
// the QString in place. The move operations stay noexcept because QString's
// are, and a moved-from ICoreString is a moved-from QString -- valid and
// empty, exactly as before.
ICoreString();
ICoreString(const ICoreString&);
ICoreString(ICoreString&&) noexcept;
ICoreString& operator=(const ICoreString&);
ICoreString& operator=(ICoreString&&) noexcept;
~ICoreString();
// Implicit on purpose -- see the note at the top of the file.
// ⚠⚠ FIVE QT MEMBERS WERE DELETED FROM THIS CLASS ON 2026-08-22, MEASURED
// RATHER THAN JUDGED, under the owner's zero-Qt ruling:
//
// ICoreString(QString&&) 0 callers
// explicit ICoreString(QStringView) 0 callers
// operator QVariant() 0 callers
// operator QJsonValue() 0 callers
// operator+=(const QString&) 0 callers
//
// "0 callers" here means: remove the declaration and the whole tree still
// compiles -- 987 translation units, by
// testingLabs/tests/string_seal_census/seal_census.py, which since the same
// day refuses to answer at all for a member this header uses itself.
// The ruling is that a conversion is scaffolding with a demolition date, so
// a member with no callers is not moved to a seam, it is DELETED.
//
// ⚠ THE ONE THAT SURVIVED IS `operator QAnyStringView`, and its number is
// why: 52 TUs, 144 call sites. It is what lets QStringLiteral("%1 %2").arg()
// take ICoreString arguments, and the note at the top of this file explains
// the SFINAE constraint that makes it load-bearing.
//
// What remains after a deletion is still a fall-back, not a hole:
// `s += aQString` now converts through ICoreString(const QString&) and
// operator+=(const ICoreString&); `ICoreString(std::move(q))` binds the
// const& overload. Both compile, and the census says nobody writes either.
// ⚠⚠ `ICoreString(const QString&)` STOOD HERE AND IS `icoreFromQt()` IN
// Text/QtSeam/ICoreStringQt.h [deleted, LQ.13] SINCE 2026-08-23 (§0.145 Ruling 1). Its
// 7,915 macro expansions follow it through ICoreStringLiteral's Qt branch;
// its 192 genuine callers -- every one inside a zone the Qt-free build
// drops -- spell the seam function now. §0.85's lesson stands: an implicit
// converting constructor has no call syntax, so only the compiler could
// count either population.
ICoreString(const char* s);
ICoreString(ICoreChar c);
// EXPLICIT, and it has to stay explicit. QLatin1String already converts
// implicitly to QString, so an implicit ICoreString(QLatin1String) gives
// every expression of the form `qstring + latin1` a second one-conversion
// candidate (ours) that ties with Qt's, making it ambiguous -- in files
// that have not been migrated and do not mention ICoreString at all.
// That is how `builtInRoot + QLatin1Char('/') + QLatin1String(...)` in
// ICoreTemplateLibrary.cpp broke. The comparison operators and the member
// overloads below take QLatin1String directly, which covers the idiomatic
// uses; anything else spells it ICoreString(QLatin1String(...)).
explicit ICoreString(ICoreLatin1String s);
// EXPLICIT for the same reason QLatin1String is: Qt compares QString
// against std::string through its own string-like overloads, and an
// implicit ICoreString(std::string) adds a tying candidate that makes
// `qstring == stdstring` ambiguous in unmigrated code -- it broke
// ICoreGraphicsComboBoxDialog.cpp. Use ICoreString::fromStdString(s),
// which is what the codebase already writes 551 times.
explicit ICoreString(const std::string& s);
ICoreString(std::ptrdiff_t size, ICoreChar fill);
// --- named constructors ------------------------------------------------
static ICoreString fromStdString(const std::string& s);
static ICoreString fromStdWString(const std::wstring& s);
static ICoreString fromUtf8(const ICoreByteArray& b);
static ICoreString fromUtf8(const char* s, std::ptrdiff_t n = -1);
static ICoreString fromLatin1(const ICoreByteArray& b);
static ICoreString fromLatin1(const char* s, std::ptrdiff_t n = -1);
static ICoreString fromLocal8Bit(const ICoreByteArray& b);
static ICoreString fromLocal8Bit(const char* s, std::ptrdiff_t n = -1);
// ⚠ THE ONE NAMED CONSTRUCTOR THAT NAMES NO QT TYPE AND BOTH STORES MUST
// HAVE (A9.8, 2026-08-22). It exists because ICoreStringLiteral needs to
// build an ICoreString from a compile-time `u"..."` array without going
// through QStringLiteral, and because the Qt interop seam needs the same
// operation. `n < 0` means "NUL-terminated", matching fromUtf8's rule.
static ICoreString fromUtf16(const char16_t* s, std::ptrdiff_t n = -1);
static ICoreString fromUcs4(const char32_t* s, std::ptrdiff_t n = -1);
static ICoreString number(int n, int base = 10);
static ICoreString number(unsigned int n, int base = 10);
static ICoreString number(long n, int base = 10);
static ICoreString number(unsigned long n, int base = 10);
static ICoreString number(long long n, int base = 10);
static ICoreString number(unsigned long long n, int base = 10);
static ICoreString number(double n, char format = 'g', int precision = 6);
// --- interop with the Qt backing store ---------------------------------
//
// ⚠⚠ `operator const QString&() const noexcept` STOOD HERE AND IS GONE
// (A9.5, 2026-08-22). It is the row's headline item and the reason the row
// exists: a native store cannot return a reference to a QString it does not
// have, so the seal could not proceed while this member had a caller.
//
// The note that stood here said "implicit both ways ... toQString() is the
// explicit spelling for the places where an implicit conversion would be
// ambiguous or unclear". toQString() is now the spelling EVERYWHERE, which
// is a smaller change than it sounds: an implicit conversion has no syntax,
// so no call site ever said what it was doing, and 198 of them now do.
//
// ⚠ HOW MANY THERE WERE COULD ONLY BE ANSWERED BY THE COMPILER, and the
// board's estimate was wrong in both directions before it was asked:
// §0.76 recorded "52 files, measured"; the real answer was 67 files and 198
// call sites, of which 48 files were inside zones where naming Qt is legal
// and 10 were in src/ICoreSDK, which may not name a Qt type at all and was
// reaching one through this member. testingLabs/tests/string_seal_census/
// is the instrument; re-run it against any other member before removing it.
// ⚠⚠ `operator QAnyStringView() const noexcept` STOOD HERE AND IS DELETED,
// NOT RELOCATED (A9.5, 2026-08-23) -- and unlike every other conversion this
// board has moved, **there is no free-function form of it at all**.
//
// 📌 WHY IT CANNOT BE MOVED. Qt constrains `QString::arg`'s string-like
// overloads on `is_convertible<T, QAnyStringView>`. Only an IMPLICIT
// conversion satisfies a trait; a named function cannot. So the choice was
// never move-or-keep, it was keep-or-migrate-the-call-sites, and the
// zero-Qt ruling settles that.
//
// ⚠ THE NOTE THAT STOOD HERE PUT ITS POPULATION AT **52 TUs, 144 call
// sites**, and that number was an estimate of the same family as this
// tier's other two ("~100 boundaries", measured at 7 and at 5). What it
// actually cost is in §0.139, measured by deleting it.
// Conversions to the Qt "sink" types that take a QString implicitly.
// Without these, `jsonObject["k"] = icoreString` and
// `settings.setValue(k, icoreString)` do not compile at all -- reaching
// QJsonValue or QVariant through operator const QString& would be two
// user-defined conversions in one sequence, and the language allows one.
// These are the single viable path, so they add no ambiguity. They are
// also the honest statement of where Qt still owns the data model; phase 3
// replaces the sinks themselves and these two lines go with them.
// ⚠⚠ BY VALUE SINCE 2026-08-22, AND THE MUTABLE OVERLOAD IS GONE (A9.8).
// This used to be `const QString& toQString() const` -- a reference INTO
// the store -- plus a `QString&` twin handing out a writable one. Neither
// can exist on a store that is not a QString, which is the same argument
// that removed `operator const QString&` at 198 call sites one member
// earlier (§0.102). The const one is by value and DEFINED IN
// Text/QtSeam/ICoreString.cpp [deleted] over constData()/size(), so one body serves
// both seats; the mutable one had zero callers outside the store's own
// .cpp and was deleted rather than relocated, per the owner's zero-Qt
// ruling. Cost: one QString copy per call at 248 sites, measured not to
// move the regression suite's runtime.
// ⚠⚠ `QString toQString() const` STOOD HERE AND IS `icoreToQt()` IN
// Text/QtSeam/ICoreStringQt.h [deleted, LQ.13] SINCE 2026-08-23 (A9.5).
//
// 📌 **179 call expressions across 56 files moved with it, and 174 of them
// were inside a zone a Qt-free build already drops.** The five that were
// not are in testingLabs/GuiLab, which keeps Qt by owner ruling (§0.132).
// So the 2026-08-22 ruling's headline -- *"248 calls across 64 files"* --
// ended at **zero** call sites needing migration outside the Qt build, and
// the difference between 248 and 179 is what A9.5's earlier phases had
// already removed.
// --- size and state ----------------------------------------------------
bool isEmpty() const noexcept;
bool isNull() const noexcept;
std::ptrdiff_t size() const noexcept;
std::ptrdiff_t length() const noexcept;
void clear();
void resize(std::ptrdiff_t n);
void resize(std::ptrdiff_t n, ICoreChar fill);
void reserve(std::ptrdiff_t n);
void squeeze();
void truncate(std::ptrdiff_t n);
void chop(std::ptrdiff_t n);
ICoreString& fill(ICoreChar c, std::ptrdiff_t n = -1);
// --- element access ----------------------------------------------------
ICoreChar at(std::ptrdiff_t i) const;
ICoreChar operator[](std::ptrdiff_t i) const;
ICoreChar front() const;
ICoreChar back() const;
// NO data(). It is deliberately absent — see H5 in the refactor plan.
// data() plus size() is exactly QStringView's "compatible container"
// recipe, so having it let QStringView be constructed from ICoreString in
// one user-defined conversion. Every QString member overloaded on both
// (const QString&) and (QStringView) — contains, startsWith, endsWith,
// indexOf, compare, … — then had two equally-good candidates for an
// ICoreString argument and became ambiguous. constData() and unicode()
// give the same pointer under names std::data() does not find; use
// toQString().data() for the mutable one.
// UTF-16 code units. These returned `const QChar*` until A9.5; every
// caller either passed the pointer straight back to a Qt API inside the
// Qt zone or read code units off it, and neither needs the wrapper.
const char16_t* constData() const noexcept;
// ===========================================================================
// ⚠⚠ TEMPORARY Qt COMPATIBILITY SEAM -- ADDED BY THE 2026-09-10 main MERGE.
//
// EVERYTHING BELOW IS SCHEDULED FOR DELETION. It exists because main is the
// tested release and its Qt code is written against the wrapper contract this
// class USED to have: implicit conversion to and from the toolkit type. ui-swap
// removed that contract (A9.5/A9.6 moved it to QtSeam/, LQ.4 deleted QtSeam/),
// and the merge brought main's callers back. Restoring the conversion here was
// the owner's ruling: take main's functionality now, swap the Qt later.
//
// ⚠ THIS BREAKS R2 ON PURPOSE AND THE CENSUS WILL SAY SO. That is the honest
// reading -- this header names Qt again. Do not silence the row; it is
// measuring a real, deliberate, temporary regression.
//
// ⚠ DO NOT BUILD ON IT. No NEW caller may use these. Every use is one more
// thing the swap has to unpick, and the guard below is what makes the
// deletion mechanical: when the last caller is gone, delete the block.
//
// Owned by: W10.31 (Windows), A10.8 (Apple), L9.62 (Linux) -- and LQ.14 is the
// row that removes the seam itself once all three are closed.
// ===========================================================================
// ⚠ THE SEAM'S THREE MEMBERS STOOD HERE -- `ICoreString(const QString&)`,
// `operator QString()` and `toQString()`, restored by the 2026-09-10 main
// merge and deleted by `LQ.14` on 2026-09-17. The free-function forms in
// `Text/QtSeam/ICoreStringQt.h [deleted, LQ.13]` are what a Qt caller uses, and there is no
// Qt caller left in anything this tree compiles.
const char16_t* unicode() const noexcept;
iterator begin();
iterator end();
const_iterator begin() const;
const_iterator end() const;
const_iterator cbegin() const;
const_iterator cend() const;
const_iterator constBegin() const;
const_iterator constEnd() const;
// --- non-mutating transforms -------------------------------------------
ICoreString trimmed() const;
ICoreString simplified() const;
ICoreString toLower() const;
ICoreString toUpper() const;
ICoreString left(std::ptrdiff_t n) const;
ICoreString right(std::ptrdiff_t n) const;
ICoreString mid(std::ptrdiff_t pos, std::ptrdiff_t n = -1) const;
ICoreString sliced(std::ptrdiff_t pos) const;
ICoreString sliced(std::ptrdiff_t pos, std::ptrdiff_t n) const;
ICoreString chopped(std::ptrdiff_t n) const;
ICoreString first(std::ptrdiff_t n) const;
ICoreString last(std::ptrdiff_t n) const;
ICoreString repeated(std::ptrdiff_t times) const;
ICoreString leftJustified(std::ptrdiff_t width, ICoreChar fill = ICoreChar(u' '), bool truncate = false) const;
ICoreString rightJustified(std::ptrdiff_t width, ICoreChar fill = ICoreChar(u' '), bool truncate = false) const;
ICoreString toHtmlEscaped() const;
ICoreString normalized(ICoreNormalizationForm form) const;
ICoreString section(ICoreChar sep, std::ptrdiff_t start, std::ptrdiff_t end = -1, ICoreSectionFlags flags = ICoreSectionFlag::Default) const;
ICoreString section(const ICoreString& sep, std::ptrdiff_t start, std::ptrdiff_t end = -1, ICoreSectionFlags flags = ICoreSectionFlag::Default) const;
// --- mutating -----------------------------------------------------------
ICoreString& append(const ICoreString& s);
ICoreString& append(ICoreChar c);
ICoreString& append(const char* s);
ICoreString& append(ICoreLatin1String s);
ICoreString& prepend(const ICoreString& s);
ICoreString& prepend(ICoreLatin1String s);
ICoreString& prepend(ICoreChar c);
ICoreString& insert(std::ptrdiff_t i, const ICoreString& s);
ICoreString& insert(std::ptrdiff_t i, ICoreChar c);
ICoreString& remove(std::ptrdiff_t pos, std::ptrdiff_t n);
ICoreString& remove(ICoreChar c, ICoreCaseSensitivity cs = ICoreCaseSensitivity::Sensitive);
ICoreString& remove(const ICoreString& s, ICoreCaseSensitivity cs = ICoreCaseSensitivity::Sensitive);
// Defined in ICoreString.cpp -- see the note above the class.
ICoreString& remove(const ICoreRegex& re);
ICoreString& replace(std::ptrdiff_t pos, std::ptrdiff_t n, const ICoreString& after);
ICoreString& replace(ICoreChar before, ICoreChar after, ICoreCaseSensitivity cs = ICoreCaseSensitivity::Sensitive);
ICoreString& replace(const ICoreString& before, const ICoreString& after, ICoreCaseSensitivity cs = ICoreCaseSensitivity::Sensitive);
ICoreString& replace(ICoreLatin1String before, ICoreLatin1String after, ICoreCaseSensitivity cs = ICoreCaseSensitivity::Sensitive);
// Replacing ONE character with a longer literal — escaping a quote as "''",
// a backslash as "\\\\". QString has this overload and the M-code codec
// (A14) is built on it; without it the call site has to materialise an
// ICoreString temporary per replacement, because ICoreString(QLatin1String)
// is explicit (H4). Safe to add for the same reason every QLatin1String
// overload above is: the receiver is an ICoreString, so this joins no Qt
// overload set and cannot tie against one (that was H5's mechanism).
ICoreString& replace(ICoreChar before, ICoreLatin1String after, ICoreCaseSensitivity cs = ICoreCaseSensitivity::Sensitive);
ICoreString& remove(ICoreLatin1String s, ICoreCaseSensitivity cs = ICoreCaseSensitivity::Sensitive);
ICoreString& replace(const ICoreRegex& re, const ICoreString& after);
void push_back(ICoreChar c);
void push_back(const ICoreString& s);
// --- searching ----------------------------------------------------------
bool contains(ICoreChar c, ICoreCaseSensitivity cs = ICoreCaseSensitivity::Sensitive) const;
bool contains(const ICoreString& s, ICoreCaseSensitivity cs = ICoreCaseSensitivity::Sensitive) const;
bool contains(ICoreLatin1String s, ICoreCaseSensitivity cs = ICoreCaseSensitivity::Sensitive) const;
bool contains(const ICoreRegex& re) const;
// The (re, QRegularExpressionMatch*) overload is GONE, not swapped. It was
// a Qt-declared POINTER out-parameter, which no conversion operator reaches
// and which ICoreRegexMatch deliberately offers no mutable accessor for
// (see ICoreRegex.h's third design note). It had no call site in the tree,
// so Rule 3 retires it rather than inventing an accessor to preserve it:
// `re.match(s).hasMatch()` is the spelling, and it is what the tree already
// writes. Same for the indexOf/lastIndexOf out-params below.
bool startsWith(ICoreChar c, ICoreCaseSensitivity cs = ICoreCaseSensitivity::Sensitive) const;
bool startsWith(const ICoreString& s, ICoreCaseSensitivity cs = ICoreCaseSensitivity::Sensitive) const;
bool startsWith(ICoreLatin1String s, ICoreCaseSensitivity cs = ICoreCaseSensitivity::Sensitive) const;
bool endsWith(ICoreChar c, ICoreCaseSensitivity cs = ICoreCaseSensitivity::Sensitive) const;
bool endsWith(const ICoreString& s, ICoreCaseSensitivity cs = ICoreCaseSensitivity::Sensitive) const;
bool endsWith(ICoreLatin1String s, ICoreCaseSensitivity cs = ICoreCaseSensitivity::Sensitive) const;
std::ptrdiff_t indexOf(ICoreChar c, std::ptrdiff_t from = 0, ICoreCaseSensitivity cs = ICoreCaseSensitivity::Sensitive) const;
std::ptrdiff_t indexOf(const ICoreString& s, std::ptrdiff_t from = 0, ICoreCaseSensitivity cs = ICoreCaseSensitivity::Sensitive) const;
std::ptrdiff_t indexOf(const ICoreRegex& re, std::ptrdiff_t from = 0) const;
std::ptrdiff_t lastIndexOf(ICoreChar c, std::ptrdiff_t from = -1, ICoreCaseSensitivity cs = ICoreCaseSensitivity::Sensitive) const;
std::ptrdiff_t lastIndexOf(const ICoreString& s, std::ptrdiff_t from = -1, ICoreCaseSensitivity cs = ICoreCaseSensitivity::Sensitive) const;
std::ptrdiff_t lastIndexOf(const ICoreRegex& re) const;
std::ptrdiff_t count() const noexcept;
std::ptrdiff_t count(ICoreChar c, ICoreCaseSensitivity cs = ICoreCaseSensitivity::Sensitive) const;
std::ptrdiff_t count(const ICoreString& s, ICoreCaseSensitivity cs = ICoreCaseSensitivity::Sensitive) const;
int compare(const ICoreString& other, ICoreCaseSensitivity cs = ICoreCaseSensitivity::Sensitive) const;
// Case-insensitive comparison against a literal, without building a
// temporary — the shape `value.compare(ICoreLatin1String("inf"), ICoreString::CaseInsensitive)`.
// Same rationale and same safety argument as the QChar/QLatin1String
// replace() above, and it matches contains/startsWith/endsWith/remove,
// which already carry a QLatin1String overload each.
int compare(ICoreLatin1String other, ICoreCaseSensitivity cs = ICoreCaseSensitivity::Sensitive) const;
// ⚠ RETURNS ICoreStringList, NOT QStringList (A9.5 phase 3, 2026-08-22).
// Returning by value against an INCOMPLETE type is legal in a declaration
// and is the only shape available here -- see the forward declaration above
// for why this header cannot include the list's.
ICoreStringList split(ICoreChar sep, ICoreSplitBehavior behavior = ICoreSplitBehavior::KeepEmptyParts, ICoreCaseSensitivity cs = ICoreCaseSensitivity::Sensitive) const;
ICoreStringList split(const ICoreString& sep, ICoreSplitBehavior behavior = ICoreSplitBehavior::KeepEmptyParts, ICoreCaseSensitivity cs = ICoreCaseSensitivity::Sensitive) const;
ICoreStringList split(const ICoreRegex& re, ICoreSplitBehavior behavior = ICoreSplitBehavior::KeepEmptyParts) const;
// --- conversions out ----------------------------------------------------
std::string toStdString() const;
std::wstring toStdWString() const;
ICoreByteArray toUtf8() const;
ICoreByteArray toLatin1() const;
ICoreByteArray toLocal8Bit() const;
int toInt(bool* ok = nullptr, int base = 10) const;
unsigned int toUInt(bool* ok = nullptr, int base = 10) const;
short toShort(bool* ok = nullptr, int base = 10) const;
unsigned short toUShort(bool* ok = nullptr, int base = 10) const;
long toLong(bool* ok = nullptr, int base = 10) const;
unsigned long toULong(bool* ok = nullptr, int base = 10) const;
long long toLongLong(bool* ok = nullptr, int base = 10) const;
unsigned long long toULongLong(bool* ok = nullptr, int base = 10) const;
double toDouble(bool* ok = nullptr) const;
float toFloat(bool* ok = nullptr) const;
// --- formatting ---------------------------------------------------------
// Forwards every argument to QString::arg, unwrapping ICoreString on the
// way so both the single-argument overloads and the variadic one apply.
//
// ⚠ THIS ONE STAYS IN THE HEADER, and it is exemption 1, not an oversight:
// a member template's body has to be visible where it is instantiated.
// What DID change is that it no longer touches the storage -- it goes
// through the public toQString(), so the buffer stays private to the .cpp.
// It is also why this row banks 141->1 rather than 141->0; the guard's
// template exemption is class-scoped, so a member template of a plain class
// is always counted. Same shape as H2.22 (ICoreLog).
template <typename... Args>
ICoreString arg(Args&&... args) const
{
return ICoreDetail::argRun(*this, std::forward<Args>(args)...);
}
// --- compound assignment -------------------------------------------------
ICoreString& operator+=(const ICoreString& s);
ICoreString& operator+=(const char* s);
ICoreString& operator+=(ICoreChar c);
ICoreString& operator+=(ICoreLatin1String s);
// ⚠ ADDED 2026-08-22 (phase 3), and its absence is a worked example of what
// the alias was hiding. While ICoreLatin1Char WAS QLatin1Char, `s += c`
// resolved through Qt's own QLatin1Char -> QChar -> QString chain and no
// overload was needed here. The type is this project's own now, that chain
// does not exist, and the operation the call sites were relying on turns
// out never to have been declared anywhere in this class.
ICoreString& operator+=(ICoreLatin1Char c);
};
ICoreStringData.h#
ICoreEssentials/Text/ICoreStringData.h
ICoreStringData -- the project's own UTF-16 string store.
W9.1. This is the backing the owner chose in §42.5 decision 1, and every property below is the reason it was chosen over std::u16string, UTF-8 and ICU. It names NO TOOLKIT: this header includes <atomic> and <cstddef> and nothing else, and neither does its .cpp.
THE FOUR PROPERTIES THAT ARE THE WHOLE POINT. Each one is pinned by a check in testingLabs/tests/string_store/, and each one is a thing a "simpler" store silently loses:
- ONE POINTER. sizeof(ICoreStringData) == sizeof(void*), so ICoreString's
opaque buffer static_asserts are RE-PINNED rather than retired. A std::u16string member would be ~32 bytes on every string in the tree.
ICoreStringStaticBlock#
ICoreStringData.h:71 · struct · 0 declaration(s)
struct ICoreStringStaticBlock {
public:
ICoreStringBlock header;
char16_t data[N];
};
};
ICoreStringData#
ICoreStringData.h:99 · class · 29 declaration(s)
class ICoreStringData {
public:
using size_type = ICoreTextDetail::ICoreStringSize;
// A default-constructed store is NULL, not empty -- the distinction
// QString::isNull() draws and 41 call sites in this tree read.
constexpr ICoreStringData() noexcept : m_block(nullptr) {}
// Property 2's adopter. ⚠ NOT constexpr, and the first cut of this file
// said it was: a class with a non-trivial destructor is not a literal
// type, so `constexpr` here is invalid and g++ says so
// (-Winvalid-constexpr). Nothing is lost, because the compile-time half of
// the literal path is the BLOCK, not the handle -- the block is
// constant-initialised data and this is a pointer copy at the call site.
// The block is const because the literal's storage is, and the const_cast
// is safe because an immortal block is never written: detach() copies it
// before any mutation can reach it.
static ICoreStringData immortal(const ICoreTextDetail::ICoreStringBlock* block) noexcept
{
return ICoreStringData(const_cast<ICoreTextDetail::ICoreStringBlock*>(block));
}
ICoreStringData(const ICoreStringData& other) noexcept;
ICoreStringData(ICoreStringData&& other) noexcept;
ICoreStringData& operator=(const ICoreStringData& other) noexcept;
ICoreStringData& operator=(ICoreStringData&& other) noexcept;
~ICoreStringData();
// --- named constructors -------------------------------------------------
// n < 0 means "measure it" for every pointer form.
static ICoreStringData fromUtf16(const char16_t* s, size_type n = -1);
static ICoreStringData fromUtf8(const char* s, size_type n = -1);
static ICoreStringData fromLatin1(const char* s, size_type n = -1);
static ICoreStringData fromWide(const wchar_t* s, size_type n = -1);
static ICoreStringData fromUcs4(const char32_t* s, size_type n = -1);
static ICoreStringData filled(size_type n, char16_t fill);
// Non-null and empty -- QString("") rather than QString().
static ICoreStringData empty();
// --- observers ----------------------------------------------------------
bool isNull() const noexcept { return m_block == nullptr; }
bool isEmpty() const noexcept { return size() == 0; }
size_type size() const noexcept { return m_block ? m_block->size : 0; }
size_type capacity() const noexcept { return m_block ? m_block->capacity : 0; }
// Always NUL-terminated (property 4), and never null itself: a null store
// reads as the empty string, which is what QString::constData() does.
const char16_t* constData() const noexcept;
const char16_t* data() const noexcept { return constData(); }
// --- sharing, and the three questions the suite asks it ------------------
bool isImmortal() const noexcept { return m_block && m_block->ref.load(std::memory_order_relaxed) < 0; }
bool isShared() const noexcept;
int refCount() const noexcept;
// --- mutation (every one of these detaches first) -----------------------
char16_t* mutableData();
void detach();
void reserve(size_type n);
void resize(size_type n, char16_t fill = u'\0');
void truncate(size_type n);
void clear();
void squeeze();
void assign(const char16_t* s, size_type n);
void append(const char16_t* s, size_type n);
void append(char16_t c);
void prepend(const char16_t* s, size_type n);
void insert(size_type pos, const char16_t* s, size_type n);
void remove(size_type pos, size_type n);
void replaceRange(size_type pos, size_type n, const char16_t* s, size_type m);
};
File-scope declarations#
// ⚠ THE SIZE TYPE, THE REFCOUNT SENTINEL AND THE BLOCK HEADER NOW LIVE IN
// ICoreCowBuffer.h AND ARE SHARED WITH THE BYTE STORE -- refcounting written
// twice is refcounting that drifts. These aliases exist so every spelling in
// this header and its callers is unchanged by that move.
using ICoreStringSize = ICoreBufferSize;
using ICoreStringBlock = ICoreCowBlock;
ICoreStringList.h#
ICoreEssentials/Text/ICoreStringList.h
⚠ FOUR INCLUDES WERE HERE AND ARE DEAD (A9.6, 2026-08-23): <QChar>, <QLatin1String>, <QString> and <Qt>. Not one of those types is NAMED anywhere in this header any more -- the element type became ICoreString when the store moved to std::vector (§0.122), and the Qt:: enumerators were replaced by ICoreTextEnums.h's value-pinned ones.
📌 THIS IS §0.116's PARAGRAPH ONE HEADER OVER, and its argument is what makes the removal safe to reason about: a DEAD include is not a transitive-supply question -- nothing here needs the type at all -- so unlike the four below, removing these cannot make this header depend on a sibling's includes. ⚠ It can still break a CALLER that was getting <QString> through this header and never said so, which is why it was verified by building both configurations rather than by reading.
ICoreStringList#
ICoreStringList.h:109 · class · 84 declaration(s)
class ICoreStringList {
public:
// ⚠⚠ THESE THREE PUBLISHED QT AS THIS TYPE'S CONTRACT UNTIL 2026-08-22
// (A9.6), exactly as ICoreString's `value_type = QChar` and QString
// iterators did until A9.5 -- and with the same consequence: a caller
// ranging over an ICoreStringList got a Qt type WITHOUT SPELLING A QT NAME,
// so no text census could see it. Eighteen syntax highlighters were doing
// it in one line each (§0.121):
//
// for (const auto& k : keywords) // k was const QString&
// addRule(ICoreRegex("\b" + k + "\b"), ...); // -> Qt's operator+
//
// ⚠ THE ITERATORS ARE RAW POINTERS, AND THAT IS THE POINT. `QList<T>::
// iterator` would still name Qt; a proxy iterator returning by value would
// break `for (auto& e : list)`, which this header's own design note tells
// people to write. A contiguous store gives both for free, and every store
// this class will ever have -- std::vector today, QList if it ever went
// back -- is contiguous.
// ⚠ THE ITERATORS ARE THE STORE'S OWN, NOT RAW POINTERS, AND THE FIRST
// DRAFT LEARNED WHY THE HARD WAY. `ICoreString*` compiles, ranges
// correctly, and makes
//
// list.insert(0, s);
//
// AMBIGUOUS -- `0` is a null-pointer constant, so it matches both
// `insert(std::ptrdiff_t, const ICoreString&)` and
// `insert(const_iterator, const ICoreString&)`. Both overloads have four
// translation units apiece, so neither could be dropped. A class-type
// iterator has no conversion from `0` and the ambiguity does not arise.
// 📌 A9.9 had already settled this for `ICoreList` -- its native backend
// aliases the store's iterator for the same reason -- so this follows the
// tree's own precedent rather than inventing one.
using value_type = ICoreString;
using iterator = std::vector<ICoreString>::iterator;
using const_iterator = std::vector<ICoreString>::const_iterator;
using reverse_iterator = std::vector<ICoreString>::reverse_iterator;
using const_reverse_iterator = std::vector<ICoreString>::const_reverse_iterator;
// Same alias trick as ICoreString (see its header note): contains()/sort()
// below default to case-sensitive, so a call site that wants the
// case-insensitive value spells ICoreStringList:: instead of naming Qt::.
using CaseSensitivity = ICoreCaseSensitivity;
static constexpr CaseSensitivity CaseSensitive = ICoreCaseSensitivity::Sensitive;
static constexpr CaseSensitivity CaseInsensitive = ICoreCaseSensitivity::Insensitive;
// The storage. See the buffer note at the top of the file.
//
// *** THE STORE IS A STANDARD-LIBRARY TYPE, SO ITS SIZE BELONGS TO THE
// TOOLCHAIN AND NOT TO THIS TREE. *** The buffer is an UPPER BOUND and the
// .cpp pins it with `<=`, never `==`. A9.6 swapped the store from
// QStringList to std::vector<ICoreString> and kept the 24, on the note that
// "std::vector measures 24 bytes / align 8 on this toolchain whatever it
// holds" -- true of THAT toolchain, and the sentence names it. MSVC's debug
// STL gives every container an iterator-validation _Myproxy pointer, so the
// same vector is 32 under /MDd -- and the winui configure is Debug, which is
// how this assert took a whole configure down. Measured 2026-08-24, W9.1:
//
// QStringList libc++ libstdc++ MSVC /MD MSVC /MDd
// std::vector<ICoreString> - 24 24 24 32
// QStringList 24 - - - -
//
// See docs/source/architecture/opaque-buffers.md.
static constexpr std::size_t kNativeStorageSize = 32;
static constexpr std::size_t kNativeStorageAlign = 8;
// --- construction ------------------------------------------------------
// ⚠ NONE OF THESE CAN BE `= default` ANY MORE -- a defaulted special member
// would copy the raw bytes of the buffer and never touch the QStringList's
// refcount. All six are written out in the .cpp.
ICoreStringList();
ICoreStringList(const ICoreStringList&);
ICoreStringList(ICoreStringList&&) noexcept;
ICoreStringList& operator=(const ICoreStringList&);
ICoreStringList& operator=(ICoreStringList&&) noexcept;
~ICoreStringList();
// ⚠⚠ TWO QT CONSTRUCTORS STOOD HERE AND ARE GONE (A9.6, 2026-08-23). They
// are ONE free function, `icoreFromQt()`, in
// Text/QtSeam/ICoreStringListQt.h [deleted, LQ.13] -- the rvalue twin was deleted rather
// than moved, because its own comment already said it was "NOT A MOVE ANY
// MORE, AND IT CANNOT BE" once the store stopped being a QStringList.
//
// 📌 THE NOTE THAT STOOD HERE READ "implicit on purpose -- QStringList
// arrives from Qt at ~100 boundaries", AND THAT NUMBER HAS ALREADY BEEN
// MEASURED WRONG ONCE ON THIS CLASS: the same "~100 boundary crossings"
// argument was made for `operator const QStringList&`, which turned out to
// have FIVE call sites across 988 translation units (§0.119). Do not carry
// either estimate forward -- an implicit constructor has no call syntax, so
// the only instrument that can count one is the compiler.
ICoreStringList(const ICoreString& s);
ICoreStringList(std::initializer_list<ICoreString> items);
// Iterator pair, for building a list out of a set. RunnerSuites drains a
// QSet<ICoreString> this way before sorting it; the element type there is
// the wrapper, not QString, so the loop unwraps rather than copies through.
//
// ⚠ THIS ONE STAYS IN THE HEADER -- it is a constructor TEMPLATE, so its
// body must be visible where it is instantiated (exemption 1). What changed
// is that it no longer touches the storage: it delegates to the default
// constructor and appends through the PUBLIC append(), which does exactly
// what the old body did by hand. That is the narrowing answer -- no
// accessor was added to reach the buffer from here.
template <typename It>
ICoreStringList(It first_, It last_) : ICoreStringList()
{
for (It it = first_; it != last_; ++it) append(ICoreString(*it));
}
// ⚠⚠ `explicit ICoreStringList(const QList<ICoreString>& items)` STOOD HERE
// AND IS DELETED, NOT RELOCATED (A9.6, 2026-08-23). The note it carried
// called it H8 and justified it this way: "QHash<ICoreString, T>::keys()
// hands back QList<ICoreString>, which is not a QStringList and which Qt
// will not convert."
//
// 📌 BOTH HALVES OF THAT ARE NOW FALSE. A census of every
// `ICoreStringList(` construction across src/, testingLabs/ and include/
// finds **no caller** -- only the definition itself -- and it is `explicit`,
// so there is no implicit use a grep could have missed. And `ICoreHashMap`
// has no `keys()` member at all any more, so the type it was built to
// receive is not produced anywhere. It took `#include <QList>` with it.
//
// A9.11 set the precedent when it removed `ICoreProcess::qt()` outright
// once its last caller was migrated: declared-and-undefined buys a backend
// time, but **a member with no callers is only a Qt name in a portable
// header**.
// --- interop with the Qt backing store ---------------------------------
// ⚠⚠ `operator const QStringList&() const noexcept` STOOD HERE AND IS GONE
// (2026-08-22, A9.6). A store of ICoreString has no QStringList to return a
// reference to -- the same argument that removed ICoreString's
// `operator const QString&` at 198 call sites (§0.102), one class over.
//
// ⚠ AND THE COST WAS MEASURED BEFORE THE CHANGE, NOT ARGUED. The design
// note below says this conversion is why the store was a QStringList, and
// puts the crossings at "~100". The census says **THREE FILES, FIVE CALL
// SITES** across 988 TUs -- ICoreCompleter, ICoreTree, ICoreInputDialog,
// all three in UI/Backends/Qt/ where naming Qt is legal. Each spells the
// seam's conversion now and pays one list copy (§0.119).
//
// ⚠⚠ AND `QStringList toQStringList() const` STOOD HERE TOO UNTIL
// 2026-08-23 (A9.6). It is `icoreToQt()` in
// Text/QtSeam/ICoreStringListQt.h [deleted, LQ.13]. **All 12 of its call expressions were
// already inside a dropped zone**, so nothing outside them changed; the
// one hit a census showed outside was the inline debug writer at the foot
// of this very file, which moved with it.
// --- size and state ----------------------------------------------------
bool isEmpty() const noexcept;
std::ptrdiff_t size() const noexcept;
std::ptrdiff_t count() const noexcept;
std::ptrdiff_t length() const noexcept;
void clear();
void reserve(std::ptrdiff_t n);
void resize(std::ptrdiff_t n);
void squeeze();
// --- element access ----------------------------------------------------
// These return QString& / const QString& rather than the wrapper, for the
// reason in the header note: the store is a QStringList and handing back a
// reference to a wrapper it does not contain is not possible. Call sites
// that want the wrapper get it by assignment, which converts.
// ⚠⚠ THESE EIGHT RETURNED `const QString&` AND THE FIVE MUTABLE OVERLOADS
// BESIDE THEM RETURNED `QString&`, UNTIL 2026-08-22 (A9.6). They are the
// reason A9.5 could not close, and the mechanism is worth stating because
// no guard on this board can see it: `list.at(0)` IS a `const QString&`, so
//
// ICoreStringLiteral("… %1 …").arg(args.at(0))
//
// instantiates `ICoreString::arg<QString const&>` **inside src/ICoreSDK** --
// a module that may not name a Qt type, and does not. `R2.1` and `R2.2` read
// PASS at zero across 1341 files throughout, correctly: the Qt type is a
// DEDUCED TEMPLATE ARGUMENT and no Qt name appears on the line. Five TUs
// did this, four of them in the SDK (§0.118).
//
// BY VALUE, and the cost is one QString refcount increment per call -- the
// same trade `toQString()` took one member earlier (§0.106), and the same
// one the header's own note already accepted for
// `for (const ICoreString& s : list)`.
//
// ⚠ THE FIVE MUTABLE OVERLOADS ARE DELETED RATHER THAN RETYPED, ON A
// MEASUREMENT: they were ALREADY UNUSABLE from portable code and had been
// since A9.5 removed `operator const QString&`. `c[0] = anICoreString`,
// `c.first() = anICoreString` and `*it += anICoreString` do not compile --
// there is no conversion left to get an ICoreString INTO a QString element,
// and the only spelling that works names `QString`, which the SDK cannot.
// A reference nobody can write through is not a mutable accessor. The probe
// pins this as a compile-time fact (`CanAssignElement`, `CanAppendElement`)
// so it cannot quietly change back (§0.119).
// ⚠⚠ `const ICoreString` BY VALUE, AND THE `const` IS LOAD-BEARING -- IT IS
// NOT THE USUAL "const on a return type is pointless" CASE. Without it this
// seal introduces a SILENT NO-OP, which the probe caught within a minute of
// the change:
//
// list[0] = anICoreString; // before: COMPILE ERROR (no conversion
// // from ICoreString into QString&)
// // after, returning plain ICoreString:
// // COMPILES, assigns to the
// // temporary, MUTATES NOTHING
//
// Assigning to a prvalue of class type is legal C++, so deleting the
// mutable overloads turned a diagnosed error into a working-looking line
// that does nothing. `const` restores the error. `CanAssignElement` in
// testingLabs/tests/string_behaviour_probe/ reads FALSE on both sides of
// this change and is the reason it was noticed at all (§0.119, §0.120).
//
// ⚠ The cost is a copy where a move would do -- one QString refcount
// increment -- and it is paid deliberately in exchange for the diagnostic.
const ICoreString at(std::ptrdiff_t i) const;
const ICoreString operator[](std::ptrdiff_t i) const;
const ICoreString first() const;
const ICoreString last() const;
const ICoreString constFirst() const;
const ICoreString constLast() const;
const ICoreString front() const;
const ICoreString back() const;
// ⚠ `value_type`, `iterator` and `const_iterator` are DELIBERATELY STILL
// Qt's, and this is a stopping point rather than an oversight. Retyping the
// iterators means the STORE has to hold `ICoreString` elements -- a proxy
// iterator returning by value would break `for (auto& e : list)` at 27
// translation units, which is the sanctioned spelling this header's own
// fourth design note tells people to use. That store swap is the next step
// and it is landable on its own; §0.119 measured the one thing that used to
// block it (`operator const QStringList&`: FIVE call sites, all in
// `UI/Backends/Qt/`, not the ~100 the note below claims).
ICoreString value(std::ptrdiff_t i) const;
ICoreString value(std::ptrdiff_t i, const ICoreString& fallback) const;
iterator begin();
iterator end();
const_iterator begin() const;
const_iterator end() const;
const_iterator cbegin() const;
const_iterator cend() const;
const_iterator constBegin() const;
const_iterator constEnd() const;
// ⚠ SPELLED OUT, where they said `auto` before. A function with a DEDUCED
// return type cannot have its body in a .cpp: a caller in another TU has
// only the declaration and has nothing to deduce from. The deduced type was
// always exactly these, so no call site changes -- every one spells `auto`
// on its own side.
reverse_iterator rbegin();
reverse_iterator rend();
const_reverse_iterator rbegin() const;
const_reverse_iterator rend() const;
// --- adding and removing -----------------------------------------------
void append(const ICoreString& s);
void append(const ICoreStringList& other);
// `append(const QStringList&)` is a free function in the seam since A9.6.
void prepend(const ICoreString& s);
void push_back(const ICoreString& s);
void push_front(const ICoreString& s);
void insert(std::ptrdiff_t i, const ICoreString& s);
iterator insert(const_iterator before, const ICoreString& s);
// ⚠ ADDED 2026-08-22 (A9.6) AS THE REPLACEMENT FOR THE MUTABLE ELEMENT
// ACCESSORS, and it is what they should always have been. Writing one
// element used to mean `list[i] = value`, which needed a `QString&` handed
// out of the store -- so the only spelling that worked named a Qt type, and
// BOTH of the tree's two such call sites were in `src/ICoreSDK`, ending in
// `.toQString()` for exactly that reason. An indexed SETTER needs no
// reference into the store, so it is implementable on any backing store,
// names nothing, and is what those two sites say now.
void replace(std::ptrdiff_t i, const ICoreString& s);
void removeAt(std::ptrdiff_t i);
std::ptrdiff_t removeAll(const ICoreString& s);
bool removeOne(const ICoreString& s);
void removeFirst();
void removeLast();
ICoreString takeAt(std::ptrdiff_t i);
ICoreString takeFirst();
ICoreString takeLast();
iterator erase(const_iterator pos);
iterator erase(const_iterator first_, const_iterator last_);
void swapItemsAt(std::ptrdiff_t i, std::ptrdiff_t j);
void move(std::ptrdiff_t from, std::ptrdiff_t to);
// --- searching ---------------------------------------------------------
bool contains(const ICoreString& s, ICoreCaseSensitivity cs = ICoreCaseSensitivity::Sensitive) const;
bool contains(ICoreLatin1String s, ICoreCaseSensitivity cs = ICoreCaseSensitivity::Sensitive) const;
std::ptrdiff_t indexOf(const ICoreString& s, std::ptrdiff_t from = 0) const;
// QStringList's own case-insensitive search, which QList does not have --
// ICoreParityCommands reads its --blocks/--seed flags with it.
std::ptrdiff_t indexOf(const ICoreString& s, std::ptrdiff_t from, ICoreCaseSensitivity cs) const;
// Defined at the foot of ICoreRegex.h -- see the note above ICoreString.
std::ptrdiff_t indexOf(const ICoreRegex& re, std::ptrdiff_t from = 0) const;
std::ptrdiff_t lastIndexOf(const ICoreString& s, std::ptrdiff_t from = -1) const;
// No Qt::CaseSensitivity overload: QStringList has one for contains() and
// deliberately none for count(), so neither does this.
std::ptrdiff_t count(const ICoreString& s) const;
// --- QStringList's own vocabulary --------------------------------------
ICoreString join(const ICoreString& sep) const;
ICoreString join(ICoreChar sep) const;
ICoreString join(ICoreLatin1String sep) const;
ICoreStringList filter(const ICoreString& needle, ICoreCaseSensitivity cs = ICoreCaseSensitivity::Sensitive) const;
ICoreStringList filter(const ICoreRegex& re) const;
ICoreStringList& replaceInStrings(const ICoreString& before, const ICoreString& after, ICoreCaseSensitivity cs = ICoreCaseSensitivity::Sensitive);
ICoreStringList& replaceInStrings(const ICoreRegex& re, const ICoreString& after);
void sort(ICoreCaseSensitivity cs = ICoreCaseSensitivity::Sensitive);
void removeDuplicates();
ICoreStringList mid(std::ptrdiff_t pos, std::ptrdiff_t n = -1) const;
ICoreStringList sliced(std::ptrdiff_t pos) const;
ICoreStringList sliced(std::ptrdiff_t pos, std::ptrdiff_t n) const;
ICoreStringList first(std::ptrdiff_t n) const;
ICoreStringList last(std::ptrdiff_t n) const;
// --- compound operators (members, so they join no Qt overload set) ------
ICoreStringList& operator<<(const ICoreString& s);
ICoreStringList& operator<<(const ICoreStringList& other);
ICoreStringList& operator+=(const ICoreStringList& other);
// ⚠ THE TWO `const QStringList&` COMPOUND OPERATORS STOOD HERE (`<<` and
// `+=`) AND ARE FREE FUNCTIONS IN THE SEAM SINCE A9.6. The comment on this
// block says these are members "so they join no Qt overload set" -- which
// was the right instinct and is not weakened by the move: the seam header
// is compiled only where Qt exists, so the overload cannot be seen by a
// build that has no QStringList to pass it.
ICoreStringList operator+(const ICoreStringList& other) const;
};
ICoreStringLiteral.h#
ICoreEssentials/Text/ICoreStringLiteral.h
⚠ <QLatin1Char> AND <QLatin1String> STOOD HERE AND ARE GONE (phase 3, 2026-08-22): the two types below are this project's own now, and nothing in this header names a Qt Latin-1 type.
⚠⚠ AND <QStringLiteral> WAS PER-BACKEND HERE (A9.8, 2026-08-22) AND IS NOW GONE FROM THIS FILE ALTOGETHER (L9.8, 2026-08-25). The note that stood here said it "cannot stop being one until the string STORE moves (A9.8)" -- and the store HAS moved, so the condition it named is discharged. This header was the LAST thing supplying <QString> transitively to ICoreString.h: every Qt include in that header could be deleted individually and it still parsed, because this one pulled Qt in behind it. That is the ICoreChar.h defect of §0.106 in a second place, and it is why the include was made conditional rather than deleted -- a Qt build must still get it honestly, from the header that uses it. ⚠ IT STILL DOES: the include did not
ICoreLatin1Char#
ICoreStringLiteral.h:269 · class · 2 declaration(s)
A single Latin-1 character: one byte, no allocation, no encoding decision.
class ICoreLatin1Char {
public:
constexpr ICoreLatin1Char() noexcept = default;
// EXPLICIT, and for the reason ICoreChar's own header gives for the
// constructor it mirrors: an implicit one would give `latin1Char == char`
// two candidates each costing one conversion.
explicit constexpr ICoreLatin1Char(char c) noexcept : m_ch(c) {}
[[nodiscard]] constexpr char toLatin1() const noexcept { return m_ch; }
[[nodiscard]] constexpr unsigned char unicode() const noexcept {
return static_cast<unsigned char>(m_ch);
}
};
ICoreLatin1String#
ICoreStringLiteral.h:301 · class · 1 declaration(s)
A borrowed view of Latin-1 text: a pointer and a length, copied freely and owning nothing.
class ICoreLatin1String {
public:
constexpr ICoreLatin1String() noexcept = default;
// EXPLICIT from a bare pointer, as QLatin1String is, so that a `const char*`
// never silently becomes a Latin-1 view at a parameter expecting one.
// ⚠ NOT constexpr: it has to measure the array, and the 428 call sites in
// this tree pass string literals whose length the compiler folds anyway.
explicit ICoreLatin1String(const char* s) noexcept
: m_data(s), m_size(s ? static_cast<std::ptrdiff_t>(__builtin_strlen(s)) : 0) {}
constexpr ICoreLatin1String(const char* s, std::ptrdiff_t n) noexcept
: m_data(s), m_size(n) {}
[[nodiscard]] constexpr const char* data() const noexcept { return m_data; }
[[nodiscard]] constexpr std::ptrdiff_t size() const noexcept { return m_size; }
[[nodiscard]] constexpr bool isEmpty() const noexcept { return m_size == 0; }
[[nodiscard]] constexpr bool isNull() const noexcept { return m_data == nullptr; }
};
ICoreTextEnums.h#
ICoreEssentials/Text/ICoreTextEnums.h
ICore names for the Qt:: / QString:: / QByteArray:: / QRegularExpression:: constants that the Text tier's signatures used to spell. Tasks Q0.3 and Q0.4 of QT_PARAM_SWAP.md.
SAME CONTRACT AS UI/Events/ICoreInputEnums.h, deliberately, so there is one rule to learn and not two: every enumerator's underlying value EQUALS its Qt counterpart, the wrapper headers translate with a static_cast, and that equality was not trusted to this comment -- it was pinned by static_asserts in Text/QtSeam/ICoreTextEnumsVerify.cpp, which included the real Qt headers and refused to compile the moment Qt and this file disagreed. ⚠ THAT PIN IS GONE WITH ITS SUBJECT:
LQ.13deleted the file on 2026-09-18 (Linux backend plan §L175). No configuration had compiled it sinceLQ.2, and with no Qt left in the tree the values have nothing to be equal TO. They are kept as they are, because changing one now would change no behaviour and
File-scope declarations#
// NOTE the enumerator names are Insensitive/Sensitive, not CaseInsensitive/
// CaseSensitive: the enum class already carries the word "Case", and
// ICoreCaseSensitivity::CaseInsensitive stutters. Call sites do not spell
// either one -- they write ICoreString::CaseInsensitive, which is a static
// constant on the wrapper and is what the ~34 existing sites already say.
enum class ICoreCaseSensitivity : int {
Insensitive = 0,
Sensitive = 1,
};
enum class ICoreSplitBehavior : int {
KeepEmptyParts = 0,
SkipEmptyParts = 0x1,
};
// D/C/KD/KC are the Unicode standard's own names for the four forms
// (canonical/compatibility x decomposed/composed), so the Qt prefix carries no
// information the enum class name does not already give.
enum class ICoreNormalizationForm : int {
D = 0,
C = 1,
KD = 2,
KC = 3,
};
// The flag families below follow ICoreAlignment's shape, which is the pattern
// already in the tree: an or-able enum class plus a combining operator, and a
// plural ALIAS of the same type for the parameter position. There is
// deliberately no separate QFlags-style holder -- ICoreAlignment has done
// without one since it was written, and inventing a second flags mechanism for
// four enums would be a type nobody asked for.
enum class ICoreSectionFlag : unsigned int {
Default = 0x00,
SkipEmpty = 0x01,
IncludeLeadingSep = 0x02,
IncludeTrailingSep = 0x04,
CaseInsensitiveSeps = 0x08,
};
using ICoreSectionFlags = ICoreSectionFlag;
// Three independent two-value choices packed into one flag set, exactly as Qt
// packs them, which is why three enumerators are 0: Base64Encoding,
// KeepTrailingEquals and IgnoreBase64DecodingErrors are the absence of their
// partners rather than values of their own. Duplicate enumerator values are
// legal and are what makes `Base64UrlEncoding | OmitTrailingEquals` mean what
// it says.
enum class ICoreBase64Option : unsigned int {
Base64Encoding = 0,
Base64UrlEncoding = 1,
KeepTrailingEquals = 0,
OmitTrailingEquals = 2,
IgnoreBase64DecodingErrors = 0,
AbortOnBase64DecodingErrors = 4,
};
using ICoreBase64Options = ICoreBase64Option;
// The enumerators keep Qt's spelling, "Option" suffix and all, because
// ICoreRegex re-exports each one as a static constant and the ~12 call sites
// that name one write ICoreRegex::CaseInsensitiveOption today. Renaming them
// here would buy tidiness at the cost of every one of those sites.
enum class ICoreRegexPatternOption : unsigned int {
NoPatternOption = 0x0000,
CaseInsensitiveOption = 0x0001,
DotMatchesEverythingOption = 0x0002,
MultilineOption = 0x0004,
ExtendedPatternSyntaxOption = 0x0008,
InvertedGreedinessOption = 0x0010,
DontCaptureOption = 0x0020,
UseUnicodePropertiesOption = 0x0040,
};
using ICoreRegexPatternOptions = ICoreRegexPatternOption;
// Not a flag set -- these four are alternatives, and Qt declares them without
// Q_DECLARE_FLAGS for that reason.
enum class ICoreRegexMatchType : int {
NormalMatch = 0,
PartialPreferCompleteMatch = 1,
PartialPreferFirstMatch = 2,
NoMatch = 3,
};
// Qt's AnchoredMatchOption is deliberately absent: it is a deprecated alias of
// AnchorAtOffsetMatchOption (renamed at Qt 6.0) and no call site names it.
enum class ICoreRegexMatchOption : unsigned int {
NoMatchOption = 0x0000,
AnchorAtOffsetMatchOption = 0x0001,
DontCheckSubjectStringMatchOption = 0x0002,
};
using ICoreRegexMatchOptions = ICoreRegexMatchOption;
ICoreTranslator.h#
ICoreEssentials/Text/ICoreTranslator.h
ICoreTranslator -- translated user-visible text, with plural forms.
ICoreTranslator german; german.loadPoFile(dir + "/de.po", &error); // gettext catalog ICoreTranslator::setCurrent(german); // app-wide
ICoreTranslator::tr("Open File"); // "Datei öffnen" ICoreTranslator::trn("%1 file", "%1 files", n); // the right form for n ICoreTranslator::arg(ICoreTranslator::trn("%1 file", "%1 files", n), {std::to_string(n)});
Catalogs are gettext .po files -- the format every translation tool and service reads and writes. Entries may carry a context (msgctxt) to tell apart two uses of the same English text. Fuzzy entries (#, fuzzy) and obsolete ones (#~) are skipped, like msgfmt does; an entry whose translation
ICoreTranslator#
ICoreTranslator.h:48 · class · pImpl · 23 declaration(s)
Opened by row PS5.26 of the Platform SDK product plan.
class ICoreTranslator {
public:
ICoreTranslator();
~ICoreTranslator();
ICoreTranslator(const ICoreTranslator& other);
ICoreTranslator& operator=(const ICoreTranslator& other);
// Adds the entries of a .po document; later entries replace earlier ones.
// False, with the 1-based line in `error`, when the text is malformed or
// its Plural-Forms expression cannot be read.
bool loadPo(std::string_view poText, std::string* error);
bool loadPoFile(const ICoreString& path, std::string* error);
void insert(std::string_view context, std::string_view source, std::string_view translation);
void insertPlural(std::string_view context, std::string_view singular, std::string_view plural,
const std::vector<std::string>& forms);
// A gettext Plural-Forms value; false when it cannot be parsed.
bool setPluralForms(std::string_view header);
[[nodiscard]] int pluralFormCount() const noexcept;
[[nodiscard]] int pluralIndex(std::int64_t n) const;
// The "Language:" header of the last loaded catalog, e.g. "de".
[[nodiscard]] std::string language() const;
[[nodiscard]] bool isEmpty() const noexcept;
[[nodiscard]] std::string translate(std::string_view source) const;
[[nodiscard]] std::string translate(std::string_view context, std::string_view source) const;
[[nodiscard]] std::string translatePlural(std::string_view singular, std::string_view plural, std::int64_t n) const;
[[nodiscard]] std::string translatePlural(std::string_view context, std::string_view singular,
std::string_view plural, std::int64_t n) const;
// --- the app-wide catalog --------------------------------------------------
static void setCurrent(const ICoreTranslator& translator);
static void clearCurrent();
[[nodiscard]] static std::string tr(std::string_view source);
[[nodiscard]] static std::string tr(std::string_view context, std::string_view source);
[[nodiscard]] static std::string trn(std::string_view singular, std::string_view plural, std::int64_t n);
// A handle to remove the handler with; handlers run in the order added.
static int addChangedHandler(std::function<void()> handler);
static void removeChangedHandler(int handle);
// "%1 of %2" with args {"3", "7"} -> "3 of 7". %1..%99, each any number of
// times; "%%" is a literal percent sign; a number with no argument stays.
[[nodiscard]] static std::string arg(std::string_view pattern, const std::vector<std::string>& args);
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICoreUnicodeData.h#
ICoreEssentials/Text/ICoreUnicodeData.h
ICoreUnicode -- the character-property tier the hand-rolled text store needs.
W9.1, and specifically §42.5's THIRD decision, the one the row did not know it needed: QString and QChar carry full Unicode tables today, so a hand-rolled tier has to say in writing what toLower(), isLetter() and friends do above U+007F. The owner's answer was an ASCII fast path plus a generated compact table, and this file is both halves of it.
It names NO TOOLKIT: this header includes <cstdint> and nothing else, and its .cpp includes <cstdint> and the generated table.
THE TWO PROPERTIES THAT ARE THE POINT
- ASCII TAKES A BRANCH AND NEVER TOUCHES THE TABLE. Every function below is
FlagRange#
ICoreUnicodeData.h:126 · struct · 0 declaration(s)
The four generated row shapes.
struct FlagRange {
public:
std::uint32_t first;
std::uint32_t last;
std::uint16_t flags;
};
};
CaseRange#
ICoreUnicodeData.h:131 · struct · 0 declaration(s)
struct CaseRange {
public:
std::uint32_t first;
std::uint32_t last;
std::int32_t upperDelta;
std::int32_t lowerDelta;
};
};
DigitRange#
ICoreUnicodeData.h:137 · struct · 0 declaration(s)
struct DigitRange {
public:
std::uint32_t first;
std::uint32_t last;
std::int16_t firstValue;
};
};
CategoryRange#
ICoreUnicodeData.h:142 · struct · 0 declaration(s)
struct CategoryRange {
public:
std::uint32_t first;
std::uint32_t last;
std::uint8_t category;
};
};
File-scope declarations#
// Mirrors QChar::Category value for value, which is what lets the generated
// table store the raw number and what keeps a ported call site meaning the same
// thing. Other_NotAssigned is the table's default, so every unassigned code
// point costs no row.
//
// ⚠ THAT DEFAULT IS **13**, NOT 0. This comment read "Other_NotAssigned is 0"
enum class Category : unsigned char {
Mark_NonSpacing = 0,
Mark_SpacingCombining,
Mark_Enclosing,
Number_DecimalDigit,
Number_Letter,
Number_Other,
Separator_Space,
Separator_Line,
Separator_Paragraph,
Other_Control,
Other_Format,
Other_Surrogate,
Other_PrivateUse,
Other_NotAssigned,
Letter_Uppercase,
Letter_Lowercase,
Letter_Titlecase,
Letter_Modifier,
Letter_Other,
Punctuation_Connector,
Punctuation_Dash,
Punctuation_Open,
Punctuation_Close,
Punctuation_InitialQuote,
Punctuation_FinalQuote,
Punctuation_Other,
Symbol_Math,
Symbol_Currency,
Symbol_Modifier,
Symbol_Other,
};
// The bit order the generator writes and the ASCII table below repeats. It is
// spelled once, here, because a generator and a consumer that each carry their
// own copy of a bit order is a defect waiting for the next predicate.
enum Flag : std::uint16_t {
FlagPrint = 1u << 0,
FlagSpace = 1u << 1,
FlagPunct = 1u << 2,
FlagLetter = 1u << 3,
FlagNumber = 1u << 4,
FlagDigit = 1u << 5,
FlagUpper = 1u << 6,
FlagLower = 1u << 7,
FlagLetterOrNumber = 1u << 8,
};
ICoreIcu.h#
ICoreEssentials/Text/Backends/Native/ICoreIcu.h
The ONE place the native Text store spells ICU -- W9.16, 2026-08-27.
⚠⚠ ICU IS NOT SPELLED THE SAME WAY ON EVERY PLATFORM, AND UNTIL THIS HEADER THE NATIVE STORE ASSUMED IT WAS.
ICoreString.cppopened with<unicode/normalizer2.h>,<unicode/uchar.h>,<unicode/ustring.h>andICoreChar.cppwith the second of the three -- the upstream ICU layout, which is what macOS ships in its SDK and what a Linuxicu-develpackage installs. Windows has nounicode/include directory at all. The Windows SDK ships ICU as a single merged header,Include/<ver>/um/icu.h, autogenerated from the upstream ones with the C++ API and the unsupported parts removed, beside the legacyicucommon.h/icui18n.hpair.So the failure W9.16 was opened against ("no ICU on the Windows link line") was the second half of the problem and not the first: the native store did
Declares no class of its own — see the file.