APIRecord

Record

A record is a tree of byte sequences with optional hashes:

(root) pressure location 45976389 7658333 picture 3a295f... addInteger(...) addInteger(...) 859000 addInteger(...) 4478000 addText('location') addReference(...) addText('picture') addText('pressure') addInteger(859000) #44... nthChild(0).asInteger() nthChild(2).asInteger() nthChild(1).asInteger() childWithText('location') referenceValue() childWithText('picture') childWithText('pressure') integerValue() Construction Querying

Each tree node is a record instance:

Record instances are mutable. Due to the nature of Condensation, however, records are rarely modified in-place. Most often, they are either constructed or queried.

Byte sequences may contain any type of data. The record type provides functions to deal with UTF-8 text, numbers, boolean values, and references. Other data must be encoded and decoded by the application.

Records can be serialized and deserialized very efficiently and compactly, and are therefore the data structure of choice for most applications. The root node of a record is not serialized.

Creation

		Record record = new Record();
		Record record = new Record(bytes);
		Record record = new Record(bytes, hash);
	
		var record = new cds.Record();
		var record = new cds.Record(bytes);
		var record = new cds.Record(bytes, hash);
	
		my $record = CDS::Record->new;
		my $record = CDS::Record->new($bytes);
		my $record = CDS::Record->new($bytes, $hash);
	

Creates a record.

Record record = Record.from(object);
var record = cds.recordFromObject(object);
my $record = CDS::Record->fromObject($object);

Parses an object. If the object is nullundef, or does not contain a valid record, nullundef is returned.

Record construction

		record.add(bytes, hash);
		record.add(text, hash);
		record.add(booleanValue, hash);
		record.add(integerValue, hash);
		record.addUnsigned(integerValue, hash);
		record.add(hash);
		record.add(hashAndKey);
		record.add(record);
		record.add(records);
	
		record.add(bytes, hash);
		record.addText(text, hash);
		record.addBoolean(value, hash);
		record.addInteger(value, hash);
		record.addUnsigned(value, hash);
		record.addHash(hash);
		record.addHashAndKey(hashAndKey);
		record.addRecord(record);
		record.addRecords(record);
	
		$record->add($bytes, $hash);
		$record->addText($text, $hash);
		$record->addBoolean($value, $hash);
		$record->addInteger($value, $hash);
		$record->addUnsigned($value, $hash);
		$record->addHash($hash);
		$record->addHashAndKey($hashAndKey);
		$record->addRecord(@records);
	

Adds a child node to the record and returns that child. The value is converted to a byte sequence. The second hash argument is optional.

Signed integers are supported up to a size of 52 bits. Unsigned integers are discouraged, as they are easily confused with signed integers, which may lead to errors that go unnoticed for a long time. Put this in a chapter under "notes" with examples, why text and integer are not easily mistaken, but unsigned and integer are.

A piece of record construction code may look as follows:

		record.add("pressure").add(859000);
		record.add("picture").add(pictureHashAndKey);
		Record location = record.add("location");
		location.add(latitude);
		location.add(longitude);
		location.add(altitude);
	
		record.addText('pressure').addInteger(859000);
		record.addText('picture').addHashAndKey(pictureHashAndKey);
		var location = record.add('location');
		location.addInteger(latitude);
		location.addInteger(longitude);
		location.addInteger(altitude);
	
		$record->addText('pressure')->addInteger(859000);
		$record->addText('picture')->addHashAndKey($pictureHashAndKey);
		my $location = $record->add('location');
		$location->addInteger($latitude);
		$location->addInteger($longitude);
		$location->addInteger($altitude);
	

Querying

		boolean result = record.contains(bytes);
		boolean result = record.contains(text);
	
		var result = record.contains(bytes);
		var result = record.containsText(text);
	
		my $result = $record->contains($bytes);
		my $result = $record->containsText($text);
	

Returns true if the record contains a child with the given bytes.

		Record child = record.child(bytes);
		Record child = record.child(text);
		Record child = record.firstChild();
		Record child = record.child(i);
	
		var child = record.child(bytes);
		var child = record.childWithText(text);
		var child = record.firstChild();
		var child = record.nthChild(i);
	
		my $result = $record->child($bytes);
		my $result = $record->childWithText($text);
		my $result = $record->firstChild;
		my $result = $record->nthChild($bytes);
	

Returns the respective child, or an empty record node. This is useful for records that are used as dictionaries or arrays.

		Bytes value = record.bytes;
		Hash hash = record.hash;                           // may be null
		boolean value = record.asBoolean();
		long value = record.asInteger();
		long value = record.asUnsigned();
		String text = record.asText();
		HashAndKey hashAndKey = record.asHashAndKey();     // may be null
	
		var value = record.bytes;
		var hash = record.hash;                     // may be null
		var value = record.asBoolean();
		var value = record.asInteger();
		var value = record.asUnsigned();
		var text = record.asText();
		var hashAndKey = record.asHashAndKey();     // may be null
	
		my $value = $record->bytes;
		my $hash = $record->hash;                   # may be undef
		my $value = $record->asBoolean;
		my $value = $record->asInteger;
		my $value = $record->asUnsigned;
		my $text = $record->asText;
		my $hashAndKey = $record->asHashAndKey;     # may be undef
	

Returns the node's value converted to the respective type.

		Bytes value = record.bytesValue();
		Hash hash = record.hashValue();                    // may be null
		boolean value = record.booleanValue();
		long value = record.integerValue();
		long value = record.unsignedValue();
		String text = record.textValue();
		HashAndKey hashAndKey = record.hashAndKeyValue();  // may be null
	
		var value = record.bytesValue();
		var hash = record.hashValue();              // may be null
		var value = record.booleanValue();
		var value = record.integerValue();
		var value = record.unsignedValue();
		var text = record.textValue();
		var hashAndKey = record.hashAndKeyValue();  // may be null
	
		my $value = $record->bytesValue;
		my $hash = $record->hashValue;              # may be undef
		my $value = $record->booleanValue;
		my $value = $record->integerValue;
		my $value = $record->unsignedValue;
		my $text = $record->textValue;
		my $hashAndKey = $record->hashAndKeyValue;  # may be undef
	

Returns the value of the first child converted to the respective type. This is useful to retrieve values from dictionary-style records:

long value = record.child("pressure").integerValue();
var value = record.childWithText('pressure').integerValue();
my $value = $record->child('pressure')->integerValue;

and a shortcut for:

long value = record.child("pressure").firstChild().asInteger();
var value = record.childWithText('pressure').firstChild().asInteger();
my $value = $record->child('pressure')->firstChild->asInteger;

Serialization and encryption

CondensationObject object = record.toObject();
var object = record.toObject();
my $object = $record->toObject;

Serializes the record to an object.

		CondensationObject object = record.toObject();
		Bytes key = object.cryptInplace();
		HashAndKey hashAndKey = new HashAndKey(object.calculateHash(), key);
	
		var object = record.toObject();
		var key = object.cryptInplace();
		var hashAndKey = new cds.HashAndKey(object.calculateHash(), key);
	
		my $key = CDS->randomKey;
		my $object = $record->toObject->crypt($key);
		my $hashAndKey = CDS::HashAndKey->new($object->calculateHash, $key);
	

Serializes and encrypts a record, and prepares the hash and key of the resulting object.

Threading

Records are not synchronized. However, they may be passed from one thread to another as long as they are accessed from a single thread at a time only.