Data
Data is an Object that owns a heap-allocated block
of bytes of a given length. Unlike String it adds
no trailing NUL and treats the bytes as opaque, with no character-class
operations. It is the value type for a raw blob: a file’s contents, a packet, an
encoded string.
#import "Foundation.xc" // or #import "Data.xc"Overview
Section titled “Overview”A Data owns a growable byte buffer and a length. It grows geometrically
(16, then doubling), so a run of appendByte is amortised O(1)
per byte instead of O(n) for reallocating on every byte.
capacity reports bytes allocated, length bytes used.
The buffer is a raw u8*, not a class pointer, so Data frees it in
dealloc; the automatic aggregate walker does not reclaim raw
allocations. bytes returns that pointer for direct access. It stays
valid as long as the Data does.
Searches and slices follow the same conventions as String: a search miss is
Data.notFound(), and an out-of-range slice clamps to empty
rather than faulting.
Data also holds the byte/encoding bridge with String. Both directions
live here (withString, stringValue,
withStringEncoded) because Data already imports
String, and the reverse import would make the two files cyclic.
Conforms to
Section titled “Conforms to”Comparable:comparegives memcmp-order total ordering, soDatacan be sorted and used as a key.Hashable:hash(FNV-1a over the bytes) makes aDataaMap/Setkey.Copying:copyreturns an independent duplicate over the same bytes.
Every Data* is also an Object* and fits anywhere one
is expected.
Topics
Section titled “Topics”Creating · withBytes · withCapacity · withLength · withData · init
Reading · length · isEmpty · bytes · byteAt · capacity
Mutating · setByteAt · appendByte · append · appendBytes · increaseLengthBy · setLength · reserve
Slicing · subdata · subdataFrom
Searching · indexOfByte · containsByte · notFound
String bridge · withString · stringValue · withStringEncoded
Text · hexString
Protocol methods · description · equals · compare · hash · copy · dealloc
Creating
Section titled “Creating”withBytes
Section titled “withBytes”static Data* withBytes(u8* src, u32 len)Copies len bytes from src into a new heap allocation. The caller’s source
pointer can be freed or reused immediately afterwards. This is the usual
constructor.
withCapacity
Section titled “withCapacity”static Data* withCapacity(u32 len)Reserves room for len bytes but returns an empty Data (length 0);
grow it with the append methods. This avoids reallocation while building up to
len bytes. It does not pre-fill; use withLength for that.
withLength
Section titled “withLength”static Data* withLength(u32 len)Allocates len zero-filled bytes, with length already len. Use when you
want to fill the bytes in place via setByteAt before handing the
Data off.
withData
Section titled “withData”static Data* withData(Data* other)An independent copy of other’s bytes (same as copy). A null other
yields an empty Data.
void init(void)The default initializer: an empty Data (null buffer, zero length). Prefer the
with… factories; you rarely call init directly.
Reading
Section titled “Reading”length
Section titled “length”u32 length(void)Number of valid bytes. O(1).
isEmpty
Section titled “isEmpty”bool isEmpty(void)true when the length is zero.
u8* bytes(void)A borrowed pointer to the Data’s own buffer, for direct access. It is
valid as long as the Data instance is, until the buffer grows: an append may
reallocate, after which an earlier pointer dangles.
byteAt
Section titled “byteAt”u8 byteAt(u32 idx)The raw byte at idx.
capacity
Section titled “capacity”u32 capacity(void)Bytes currently allocated in the backing buffer (≥ length). See
reserve.
Mutating
Section titled “Mutating”setByteAt
Section titled “setByteAt”void setByteAt(u32 idx, u8 value)Writes value at idx (in range [0, length)).
appendByte
Section titled “appendByte”void appendByte(u8 b)Appends one byte, growing the buffer geometrically if needed.
append
Section titled “append”void append(Data* other)Appends every byte of other. A null or empty other is a no-op.
appendBytes
Section titled “appendBytes”void appendBytes(u8* src, u32 n)Appends n bytes from src.
increaseLengthBy
Section titled “increaseLengthBy”void increaseLengthBy(u32 n)Grows the length by n zero bytes (Foundation’s increaseLengthBy:). The
new bytes are zeroed rather than left with the allocator’s previous contents.
setLength
Section titled “setLength”void setLength(u32 n)Truncates to n bytes, or extends with zeroes (via
increaseLengthBy) if n is larger than the current
length.
reserve
Section titled “reserve”void reserve(u32 need)Grows the buffer so at least need bytes fit without reallocating, which
amortises a known series of appends. A request that already fits does not touch
the heap.
Slicing
Section titled “Slicing”Out-of-range clamps to empty, as String’s slicing
does. Each returns a new Data*.
subdata
Section titled “subdata”Data* subdata(u32 from, u32 len)A new Data of len bytes starting at byte from (clamped to what is
available).
subdataFrom
Section titled “subdataFrom”Data* subdataFrom(u32 from)Everything from byte from to the end.
Searching
Section titled “Searching”indexOfByte
Section titled “indexOfByte”u32 indexOfByte(u8 needle)First offset of byte needle, or Data.notFound() if absent.
containsByte
Section titled “containsByte”bool containsByte(u8 needle)true if needle occurs anywhere (indexOfByte(needle) != notFound()).
notFound
Section titled “notFound”static u32 notFound(void) // 0xFFFFFFFFThe sentinel returned by indexOfByte on a miss.
String bridge
Section titled “String bridge”The byte/encoding bridge with String. Both directions
live on Data (see Overview); the exported bytes never include a
trailing NUL.
withString
Section titled “withString”static Data* withString(String* s)The string’s bytes as a Data, without the trailing NUL (Foundation’s
dataUsingEncoding: UTF-8 form). A null s yields an empty Data.
stringValue
Section titled “stringValue”String* stringValue(void)These bytes as a String. An embedded NUL is copied
like any other byte, so the length is preserved, but cString() on the result
stops at that NUL (a limit of the C representation).
withStringEncoded
Section titled “withStringEncoded”(0.4)
static Data* withStringEncoded(String* s, StrEncoding enc)Encodes a String as enc bytes: ENC_UTF8 / ENC_ASCII / ENC_LATIN1 /
ENC_UTF16LE / ENC_UTF16BE. A code point the target encoding cannot express
(Latin-1 above U+00FF, ASCII above U+007F) becomes ?. UTF-16 emits
surrogate pairs above the BMP. ENC_UTF8 is a plain byte copy including any
invalid bytes; call s.sanitizedUtf8() first if you want repair. This is the
encoding counterpart to
String.withEncodedBytes; see
String § other encodings.
hexString
Section titled “hexString”String* hexString(void)The bytes as lowercase hex with no separators, for example "deadbeef". Useful
for writing a blob to a log line or comparing it in a test.
Protocol methods
Section titled “Protocol methods”The Object / Comparable
/ Hashable / Copying
hooks.
description
Section titled “description”String* description(void)The %@ hook: <Data 4: deadbeef> (the length, then hexString).
equals
Section titled “equals”bool equals(Data* other)bool equals(Object* other)Byte-exact equality (equal length and equal bytes). The Object* overload is
the protocol slot heterogeneous containers use; it returns false against a
non-Data.
compare
Section titled “compare”i8 compare(Data* other)i8 compare(Object* other)Total ordering: lexicographic by unsigned byte, then by length (memcmp order),
so a shorter buffer that is a prefix of a longer one sorts first. Returns
negative / zero / positive. The Object* overload returns 0 against a
non-Data.
u32 hash(void)FNV-1a over the bytes. This is the Hashable method,
so a Data can key a Map or Set.
Equal byte sequences always hash the same.
Data* copy(void)An independent duplicate over the same bytes (the Copying
method). Data owns its buffer, so this copies it rather than sharing.
dealloc
Section titled “dealloc”void dealloc(void)Frees the backing buffer. ARC calls it when the last reference goes away; you do not call it directly.
Worked example
Section titled “Worked example”#import "Stdio.xc"#import "Foundation.xc"
i32 main(void){ u8 raw[4] = { $DE, $AD, $BE, $EF }; Data* d = Data.withBytes(&raw[0], (u32)4);
Stdio.printf("%s\n", d.hexString().cString()); // deadbeef Stdio.printf("%s\n", d.description().cString()); // <Data 4: deadbeef>
d.appendByte((u8)$FF); Stdio.printf("%d\n", (i16)d.length()); // 5 return 0;}