Reflex C++

Reflex Core

The Core module provides the fundamental building blocks: the Object system, reference counting, containers, strings, and key/hash utilities. Everything else in Reflex builds on top of these.

Primitive Types

Reflex defines its own fixed-width numeric types for cross-platform consistency. These are used throughout the framework instead of raw int, float, etc. to guarantee consistent behaviour across platforms.

Signed Integers

TypeDescription
Int88-bit signed integer
Int1616-bit signed integer
Int3232-bit signed integer
Int6464-bit signed integer

Unsigned Integers

TypeDescription
UInt88-bit unsigned integer
UInt1616-bit unsigned integer
UInt3232-bit unsigned integer
UInt6464-bit unsigned integer

Floating Point & Character

TypeDescription
Float3232-bit floating point
Float6464-bit floating point
WCharWide character (platform-dependent width)

Object & Lifetime Management

Reflex::Object is the root of Reflex's object system. It provides intrusive reference counting and a generic property interface. You almost never call retain/release directly — use Reference<T> for automatic lifetime management.

Reflex::Object

Reference counting methods and the generic property system.

Reference Counting

void Object::RetainSt(); // Single-threaded retain
void Object::ReleaseSt(); // Single-threaded release
void Object::RetainMt(); // Multi-threaded retain (atomic)
void Object::ReleaseMt(); // Multi-threaded release (atomic)

Property System

void Object::SetProperty(Key32 id, TYPE& property);
void Object::UnsetProperty(Key32 id);
TYPE* Object::QueryProperty(Key32 id, TYPE& property);
const TYPE* Object::QueryProperty(Key32 id, TYPE& property);
Allocator* Object::GetAllocator();

The generic property methods on Object are a no-op by default. They only store data on classes that implement the property interface, such as Data::PropertySet and its derivatives (including GLX::Object). Prefer the free-function helpers (SetProperty, GetProperty, AcquireProperty) over calling these methods directly.

Object Creation

// Heap-allocated, returns TRef<T> (caller must manage lifetime)
TRef<TYPE> New(VARGS... args);
// Heap-allocated, returns Reference<T> (automatic lifetime)
Reference<TYPE> Make(VARGS... args);
// Wrap an existing object for scope-based release
Reference<TYPE> AutoRelease(TYPE& object);

Usage examples:

// Typical creation — parent takes ownership
auto btn = New<GLX::Button>(L"OK");
GLX::AddInline(parent, btn); // parent retains btn
// When you need to hold onto it yourself
auto panel = Make<GLX::Object>(); // Reference keeps it alive
// Scope-based lifetime
auto http = AutoRelease(System::HTTP::Create(true, "domain", "resource"));
// http is released at end of scope

Reference Types

TypeRetains?Purpose
Reference<T>YesOwnership — auto retains/releases
TRef<T>NoTransfer reference — caller must retain
ConstTRef<T>NoConst non-retaining reference
ConstReference<T>YesConst retaining reference

A function returning TRef<T> signals "here's your object, you're responsible for it." A function returning Reference<T> says "I'm handing you a retained reference."

Both TRef<T> and Reference<T> default-construct to the type's null-instance (never nullptr), and convert to bool to test validity:

TRef<GLX::Object> obj = SomeFunction();
if (obj) // true if not the null instance
{
// safe to use
}

ObjectOf<TYPE>

Promotes any value type into an Object, allowing it to be heap-allocated and passed through object-based APIs.

auto a = New<ObjectOf<Array<Int32>>>(); // Heap-allocated array-of-int
auto f = New<ObjectOf<Float32>>(3.14f); // Heap-allocated float

Property Accessors

Defined in generic_properties.h. Work on any Object, but only meaningful on classes implementing the property interface (typically Data::PropertySet derivatives).

Reference<TYPE> AcquireProperty(Object& object, Key32 id);
Reference<TYPE> AcquireProperty(Object& object, Key32 id, VARGS...);
ConstTRef<TYPE> GetProperty(Object& object, Key32 id);

Example:

Data::PropertySet example;
SetProperty(example, "my_id", 1);
auto b = GetProperty<Int32>(example, "my_id")->value;
auto f = AcquireProperty<Float32>(example, "my_id")->value; // Creates if missing

Containers

Reflex provides its own container types optimised for the framework's memory model and reference-counted object system.

Array<TYPE>

Reflex's native dynamic array. Strings (CString, WString) are typedefs of Array<char> and Array<WChar> respectively, so all array operations work on strings too.

Capacity

void Array::Allocate(UInt32 capacity); // Pre-allocate
UInt32 Array::GetCapacity();
void Array::Compact(); // Shrink to fit

Size & Content

void Array::Clear();
void Array::SetSize(UInt32 size);
UInt32 Array::GetSize();

Adding Elements

TYPE& Array::Push(); // Add default element, return ref
TYPE& Array::Push(const TYPE& value); // Add copy
TYPE& Array::Insert(UInt32 idx); // Insert at position
TYPE& Array::Insert(UInt32 idx, const TYPE& value);
void Array::Append(const ArrayView<TYPE>& values); // Append range

Removing & Access

void Array::Pop();
TYPE& Array::operator[](UInt32 idx);
const TYPE& Array::operator[](UInt32 idx);
TYPE* Array::GetData();
const TYPE* Array::GetData();
bool Array::operator bool(); // True if non-empty

Comparison

bool Array::operator<(const ArrayView<TYPE>& value);
bool Array::operator==(const ArrayView<TYPE>& value);
bool Array::operator!=(const ArrayView<TYPE>& value);

CString and WString specialisations guarantee null-termination after every operation, so GetData() returns a C-compatible string. Normal Array<T> does not null-terminate.

ArrayView<TYPE>

A non-owning, read-only slice into contiguous memory. Zero-allocation substring/subarray operations.

const TYPE* ArrayView::data;
UInt32 ArrayView::size;

The view becomes invalid if the underlying memory is freed or reallocated. Use for temporaries and function parameters, not long-lived storage.

ArrayRegion<TYPE>

A mutable, non-owning region. Used primarily in drawing functions that need to modify point data in-place.

TYPE* ArrayRegion::data;
UInt32 ArrayRegion::size;

Map<KEY, VALUE>

Sorted, unique-key associative container.

void Map::Clear();
TYPE2& Map::Set(const TYPE1& key, const TYPE2& value);
void Map::Unset(const TYPE1& key);
TYPE2* Map::Search(const TYPE1& key, TYPE2* fallback);
const TYPE2* Map::Search(const TYPE1& key, const TYPE2* fallback);
TYPE2& Map::operator[](const TYPE1& idx);

Sequence<KEY, VALUE>

Sorted heap, allows non-unique keys. Useful when ordering matters and duplicate keys are valid.

Idx Sequence::Search(const KEY& key);
void Sequence::Clear();
TYPE2* Sequence::SearchValue(const TYPE1& key, TYPE2* fallback);
TYPE2& Sequence::Set(const TYPE1& key, const TYPE2& value);
TYPE2& Sequence::Insert(const TYPE1& key, const TYPE2& value);
TYPE2& Sequence::Acquire(const TYPE1& key, VARGS...); // Get or create
void Sequence::Remove(UInt32 idx);
void Sequence::Remove(UInt32 idx, UInt32 n);
UInt32 Sequence::GetSize();
TYPE2& Sequence::operator[](UInt32 idx);

List<TYPE> & Item<TYPE>

Intrusive doubly-linked list. Items must derive from Item<TYPE>.

// List
UInt32 List::GetNumItem();
bool List::Empty();
Item<TYPE>* List::GetFirst();
Item<TYPE>* List::GetLast();
// Item
List<TYPE>* Item::GetList();
Item<TYPE>* Item::GetPrev();
Item<TYPE>* Item::GetNext();

Queue<TYPE, SIZE>

Fixed-capacity lock-free queue, typically used for inter-thread communication.

void Queue::Push(const TYPE& value);
bool Queue::Pop(TYPE& out);
bool Queue::Flush(TYPE& last_out); // Drains queue, returns last value

Function<RTN(VARGS...)>

Type-erased callable wrapper (similar to std::function).

void Function::Clear();
RTN Function::Invoke(VARGS...);
RTN Function::operator()(VARGS...);

Strings

Reflex strings are built on top of the Array type. CString and WString are typedefs of Array<char> and Array<WChar>, so all array operations work on strings and vice versa.

String Types

using CString = Array<char>; // Null-terminated char array
using CString::View = ArrayView<char>; // Non-owning char slice
using WString = Array<WChar>; // Null-terminated wide string
using WString::View = ArrayView<WChar>; // Non-owning wide slice

All string functions that work on Array/ArrayView work on strings and vice versa. String specialisations guarantee null-termination after every operation, so GetData() always returns a C-compatible string.

String Manipulation Functions

Free functions that operate on ArrayView<TYPE>, meaning they work on both strings and arrays.

Joining & Splitting

Array<TYPE> Join(const VARGS...& ...);
Array<ArrayView<TYPE>> Split(const ArrayView<TYPE>& view, const TYPE& delimiter);
void Merge(const ArrayView<TYPE>& view, const ArrayView<TYPE>& delimiter);

Searching

Idx Search(const ArrayView<TYPE>& view, const TYPE& element_or_array);
Idx ReverseSearch(const ArrayView<TYPE>& view, const TYPE& element_or_array);

Substrings & Slicing

ArrayView<TYPE> Left(const ArrayView<TYPE>& view, UInt32 position);
ArrayView<TYPE> Right(const ArrayView<TYPE>& view, UInt32 position);
ArrayView<TYPE> Mid(const ArrayView<TYPE>& view, UInt32 position);
ArrayView<TYPE> Mid(const ArrayView<TYPE>& view, UInt32 position, UInt32 length);

Splitting at Position

Returns a pair of before/after views at the given position.

Pair<ArrayView<TYPE>, ArrayView<TYPE>> Splice(const ArrayView<TYPE>& view, UInt32 position);
Pair<ArrayView<TYPE>, ArrayView<TYPE>> ReverseSplice(const ArrayView<TYPE>& view, UInt32 position);

Modifying

void Remove(Array<TYPE>& array, const TYPE& element_or_array);
Array<TYPE> Replace(const ArrayView<TYPE>& view, const TYPE& element_or_array);

Case Conversion

void Lowercase(const TYPE& string);
char Lowercase(char character);
void Uppercase(const TYPE& string);
char Uppercase(char character);

Raw String Utilities

For working with raw C strings directly.

UInt32 RawStringLength(const TYPE* string);
UInt32 RawStringLength(const TYPE* string, UInt32 capacity);
UInt32 RawStringCopy(const TYPE* from, TYPE* to, UInt32 capacity);

Example

CString path = "usr/local/bin";
auto parts = Split(CString::View(path), '/'); // ["usr", "local", "bin"]
auto left = Left(CString::View(path), 3); // "usr"
auto idx = Search(CString::View(path), '/'); // Idx{3}

Conversion Functions

Convert between string types and between strings and numeric types.

String ↔ String

CString ToCString(const WString::View& string);
WString ToWString(const CString::View& string);

Numeric → String

CString ToCString(UInt32 value);
CString ToCString(Int32 value);
CString ToCString(Float32 value, UInt32 precision, bool discard_zeros);
// ... also UInt64, Int64, Float64 variants
WString ToWString(UInt32 value);
WString ToWString(Int32 value);
WString ToWString(Float32 value, UInt32 precision, bool discard_zeros);
// ... also UInt64, Int64, Float64 variants

String → Numeric

Float32 ToFloat32(const CString::View& string);
Float32 ToFloat32(const WString::View& string);
Float64 ToFloat64(const CString::View& string);
Int32 ToInt32(const CString::View& string);
Int64 ToInt64(const CString::View& string);
UInt32 ToUInt32(const CString::View& string);
UInt64 ToUInt64(const CString::View& string);
// ... all have both CString::View and WString::View overloads

Example

WString label = ToWString(42); // L"42"
CString formatted = ToCString(3.14159f, 2, true); // "3.14"
Int32 value = ToInt32(CString::View("123")); // 123

Utility Types

Foundational types used throughout the framework for keys, indices, geometry, signals, debugging, and more.

Key32

Compile-time 32-bit hash key. Used extensively as property identifiers, event IDs, and style names. String literals are automatically hashed to Key32 at compile time.

using Key32 = Key<UInt32>;
TYPE Key::value;

Idx

Safe index type with validity checking.

UInt32 Idx::value;
bool Idx::operator bool(); // True if index is valid

Example:

auto idx = Search(myArray, target);
if (idx) // Found
{
auto& item = myArray[idx.value];
}

Geometry Types

Fundamental geometry types used throughout the framework.

// Point
TYPE Point::x;
TYPE Point::y;
// Size
TYPE Size::w;
TYPE Size::h;
// Rect
Point<TYPE> Rect::origin;
Size<TYPE> Rect::size;

Pair & Tuple

// Pair — used throughout the API for returning dual values
// (implicit .a and .b members)
// Tuple — generic N-element tuple
TYPE1 Tuple::a;
TYPE2 Tuple::b;
VARGS... Tuple::c; // etc.

Margin

Four-sided margin, used heavily in GLX for padding, borders, and corners.

Size Margin::near; // left/top
Size Margin::far; // right/bottom

Range

Float32 Range::start;
Float32 Range::length;

Address

Object address descriptor.

Key32 Address::id;
UInt32 Address::type_id;

State & State::Monitor

State monitoring for reactive patterns.

void Monitor::Connect(const State& state);
void Monitor::Reconnect();
void Monitor::Disconnect();
bool Monitor::Poll(); // Returns true if state changed since last poll

Signal<VARGS...>

Type-safe signal/slot mechanism for event-driven communication.

Node<TYPE>

Tree node type for hierarchical data structures.

DebugOutput

Console logging utility.

void DebugOutput::Log(VARGS... args);
void DebugOutput::Warn(VARGS... args);
void DebugOutput::Error(VARGS... args);

Example:

Debug::Output output("MyApp");
Print(output, "Width: ", width, " Height: ", height);