Skip to content

Foundation

Foundation is xcc’s standard object library: the root Object, value wrappers (Number, String, Data), containers (Array, Map, Set), and the protocols they are built on.

#import "Foundation.xc" // the umbrella

The umbrella pulls in Object, Comparable, Hashable, Enumerable, Copying, CharacterSet, Number, String, Data, Array, Map, Set, Bag, Range, BinaryHeap, Cache and Null, and Codable through Object. That is everything below except Coder and the Error protocol, which you import by name (#import <Coder.xc>, #import <Error.xc>).

All of it needs a real heap (-falloc=heap), which is the default on the 6502 xt layouts and on every native backend.

ObjectThe universal root class — pointer-identity equals, an address-derived hash, and the description hook every class inherits and overrides.
NumberWraps any sized integer or float; cross-kind conversion is lazy and cached. The box a typed collection stores a primitive in.
StringA heap-owned, NUL-terminated UTF-8 string. Methods name their unit — byteAt counts bytes, charAt counts code points.
DataAn owned heap byte block — opaque bytes, no trailing NUL, with growth, slicing, hex, and the String-encoding bridge.
ArrayAn ordered, resizable list of Object* with sorting and the callback-based functional methods (filtered, mapped, …).
MapA hash map keyed by anything Hashable + Comparable; iterates in insertion order.
SetA hash set with set algebra (unionWith, intersect, subtract, …).
BagA counted set: each member carries a count. From 0.72.
RangeA half-open index range [loc, loc + len), equal by value. From 0.72.
BinaryHeapA priority queue, smallest priority first. From 0.72.
CacheA bounded least-recently-used cache under string keys. From 0.72.
NullThe one shared object meaning “nothing here” in a collection. From 0.72.
JSONJSON text to Foundation objects and back. Not in the umbrella — import by name. From 0.72.
ExpressionAn arithmetic expression parsed once and evaluated against variables. Not in the umbrella — import by name. From 0.72.
NumberFormatterNumbers to display text and back: grouping, currency, percent. Not in the umbrella — import by name. From 0.72.
NotificationCenterA publish/subscribe bus with weakly held observers. Not in the umbrella — import by name. From 0.72.
UndoManagerUndo and redo through self-registering changes, in named groups. Not in the umbrella — import by name. From 0.72.
ProgressHow far work has got, as a tree of child progresses. Not in the umbrella — import by name. From 0.72.
StateMachineA finite state machine of named states and events. Not in the umbrella — import by name. From 0.72.
SearchIndexA small full-text index with ranked and prefix search. Not in the umbrella — import by name. From 0.72.
IndexSetA set of indexes kept as merged ranges: a table’s selection. Not in the umbrella — import by name. From 0.72.
AttributedStringText with named attributes over ranges, as merged runs. Not in the umbrella — import by name. From 0.72.
RegexRegular expressions: captures, lazy and counted quantifiers, replace, split. Not in the umbrella — import by name. From 0.72.
PredicateConditions over records, built in code or parsed from text. Not in the umbrella — import by name. From 0.72.
ValidatorRules a field’s text must pass, with a message for each. Not in the umbrella — import by name. From 0.72.
SortDescriptorA stable sort of records by one key and then the next. Not in the umbrella — import by name. From 0.72.
SocketA TCP connection, the same calls on every hosted target. Not in the umbrella — import by name. From 0.72.
CSVComma-separated values to rows of strings and back. Not in the umbrella — import by name. From 0.72.
CoderKeyed archiving of an object graph to JSON, optionally gzipped. Not in the umbrella — import by name.
ComparableRequired equals; optional compare (<0/0/>0). Every value has equality but not every value has an order, so a class may have one without the other.
Hashablehash + equals: equal keys must hash equally. Required for a value to be a Map/Set key.
EnumerableenumLength + enumAt — the two methods for (x in collection) dispatches through. The loop variable is borrowed.
Copyingcopy — an independent duplicate. String and Data conform.
CodableencodeWithCoder + initWithCoder, the pair a Coder calls. Object conforms, so every class does (not on xt6502).
ErrorA single message(), so anything thrown can describe itself. Not in the umbrella — import by name.

Every parentless class X inherits from the runtime’s built-in Object root, so a Number*, a String*, or any class of your own fits wherever an Object* is expected. No : Object annotation is needed.

Foundation exists twice. support/generic/lib/ is the 32-bit build (arm64, arm9, m68k, x86_64), with u32 indices and a u32 hash, bounded only by memory. support/xt6502/lib/ is the 6502 build, with u16 indices and a u8 hash, because four-byte index arithmetic on every compare is too costly on an 8-bit CPU.

Portable source compiles against both builds. A narrower caller index widens at the call boundary, so for (u16 i = 0; i < a.count(); i++) behaves the same on either target. The per-class pages list anything that differs. The most visible difference is Array<i64> / Array<double>, which need -DENABLE_64BIT=1 on xt6502 (see Number § availability).

Every container takes an optional element type in angle brackets. It is a compile-time check that is erased at run time: one Array implementation serves every element type, so there is no code-size cost per instantiation.

Array<String>* names = new Array(); // new Array() needs no type argument
names.add(String.withCString("ada"));
String* s = names.get((u32)0); // a String*, no cast
names.add(Number.withU32((u32)7)); // error: Number is not a subclass of String

Map<V> names the value type; keys are anything conforming to Hashable. Each collection takes one type argument; there is no Map<K,V> spelling yet. A primitive element type works and is enforced (Array<i32> refuses a float), but the value is stored boxed in a Number, and unboxing happens in assignment context: i32 v = a.get(i). Untyped Array* / Map* / Set* remain valid everywhere. See Collections & strings for the full discussion and the for … in caveat.

Containers hold a strong reference to everything they store, and release it when the element is removed or the container is deallocated. Sorting and reversing move pointers only, with no refcount changes. sorted(), filtered(), mapped(), subarray() and the Set algebra all return new containers and leave the originals untouched.

The default Object.hash is derived from an instance’s address, so hash order is not reproducible for a Map or Set keyed by objects of your own classes. For this reason both enumerate in insertion order. Override equals/hash together to give your class value semantics, as Number, String and Data do.