2. Spezifikation der CBOR-Kodierung
Ein CBOR-kodiertes Datenelement ist wie in diesem Abschnitt beschrieben strukturiert und kodiert. Die Kodierung ist in Tabelle 5 zusammengefasst.
Das Anfangsbyte jedes Datenelements enthält sowohl Information über den Haupttyp (die 3 höherwertigen Bits, beschrieben in Abschnitt 2.1) als auch zusätzliche Informationen (die 5 niederwertigen Bits). Wenn der Wert der zusätzlichen Informationen kleiner als 24 ist, wird er direkt als kleine vorzeichenlose ganze Zahl verwendet. Wenn er 24 bis 27 beträgt, folgen unmittelbar die zusätzlichen Bytes für eine ganzzahlige Zahl variabler Länge; die Werte 24 bis 27 der zusätzlichen Informationen geben an, dass ihre Länge eine 1-, 2-, 4- oder 8-Byte große vorzeichenlose ganze Zahl ist. Der Wert 31 der zusätzlichen Informationen wird für Elemente mit unbestimmter Länge verwendet, beschrieben in Abschnitt 2.2. Die Werte 28 bis 30 der zusätzlichen Informationen sind für künftige Erweiterungen reserviert.
Bei allen Werten der zusätzlichen Informationen wird die resultierende ganze Zahl in Abhängigkeit vom Haupttyp interpretiert. Sie kann die eigentlichen Daten darstellen: Bei ganzzahligen Typen wird die resultierende ganze Zahl beispielsweise für den Wert selbst verwendet. Sie kann stattdessen auch Längeninformation liefern: Bei Byte-Zeichenfolgen gibt sie beispielsweise die Länge der nachfolgenden Byte-Zeichenfolgen-Daten an.
Eine CBOR-Decoder-Implementierung kann auf einer Sprungtabelle mit allen 256 definierten Werten für das Anfangsbyte basieren (Tabelle 5). Ein Decoder in einer eingeschränkten Implementierung kann stattdessen die Struktur des Anfangsbytes und der folgenden Bytes für kompakteren Code verwenden (siehe Anhang C für einen groben Eindruck, wie dies aussehen könnte).
2.1. Haupttypen
Im Folgenden sind die Haupttypen sowie die mit dem Typ verbundenen zusätzlichen Informationen und weiteren Bytes aufgeführt.
Haupttyp 0: eine vorzeichenlose ganze Zahl. Die 5-Bit-Information der zusätzlichen Informationen ist entweder die ganze Zahl selbst (für Werte der zusätzlichen Informationen von 0 bis 23) oder die Länge zusätzlicher Daten. Zusätzliche Information 24 bedeutet, dass der Wert in einem zusätzlichen uint8_t dargestellt wird, 25 bedeutet einen uint16_t, 26 einen uint32_t und 27 einen uint64_t. Beispielsweise wird die ganze Zahl 10 als das eine Byte 0b000_01010 bezeichnet (Haupttyp 0, zusätzliche Information 10). Die ganze Zahl 500 wäre 0b000_11001 (Haupttyp 0, zusätzliche Information 25), gefolgt von den zwei Bytes 0x01f4, was 500 im Dezimalsystem entspricht.
Haupttyp 1: eine negative ganze Zahl. Die Kodierung folgt den Regeln für vorzeichenlose ganze Zahlen (Haupttyp 0), mit der Ausnahme, dass der Wert dann -1 minus der kodierten vorzeichenlosen ganzen Zahl ist. Beispielsweise wäre die ganze Zahl -500 gleich 0b001_11001 (Haupttyp 1, zusätzliche Information 25), gefolgt von den zwei Bytes 0x01f3, was 499 im Dezimalsystem entspricht.
Haupttyp 2: eine Byte-Zeichenfolge. Die Länge der Zeichenfolge in Bytes wird nach den Regeln für positive ganze Zahlen (Haupttyp 0) dargestellt. Beispielsweise hätte eine Byte-Zeichenfolge mit der Länge 5 ein Anfangsbyte von 0b010_00101 (Haupttyp 2, zusätzliche Information 5 für die Länge), gefolgt von 5 Bytes Binärinhalt. Eine Byte-Zeichenfolge mit der Länge 500 hätte 3 Anfangsbytes von 0b010_11001 (Haupttyp 2, zusätzliche Information 25 zur Angabe einer Zwei-Byte-Länge), gefolgt von den zwei Bytes 0x01f4 für eine Länge von 500, gefolgt von 500 Bytes Binärinhalt.
Haupttyp 3: eine Text-Zeichenfolge, genauer eine Zeichenfolge von Unicode-Zeichen, die als UTF-8 kodiert ist [RFC3629]. Das Format dieses Typs ist identisch mit dem von Byte-Zeichenfolgen (Haupttyp 2), das heißt, wie bei Haupttyp 2 gibt die Länge die Anzahl der Bytes an. Dieser Typ ist für Systeme vorgesehen, die für Menschen lesbaren Text interpretieren oder anzeigen müssen, und ermöglicht die Unterscheidung zwischen unstrukturierten Bytes und Text mit einem festgelegten Repertoire und einer festgelegten Kodierung. Im Gegensatz zu Formaten wie JSON werden die Unicode-Zeichen in diesem Typ niemals maskiert ("escaped"). So wird ein Zeilenumbruchzeichen (U+000A) in einer Zeichenfolge immer als das Byte 0x0a dargestellt und niemals als die Bytes 0x5c6e (die Zeichen "" und "n") oder als 0x5c7530303061 (die Zeichen "", "u", "0", "0", "0" und "a").
Haupttyp 4: ein Array von Datenelementen. Arrays werden auch Listen, Sequenzen oder Tupel genannt. Die Länge des Arrays folgt den Regeln für Byte-Zeichenfolgen (Haupttyp 2), mit der Ausnahme, dass die Länge die Anzahl der Datenelemente angibt und nicht die Länge in Bytes, die das Array einnimmt. Die Elemente in einem Array müssen nicht alle vom gleichen Typ sein. Beispielsweise hätte ein Array, das 10 Elemente beliebigen Typs enthält, ein Anfangsbyte von 0b100_01010 (Haupttyp 4, zusätzliche Information 10 für die Länge), gefolgt von den 10 verbleibenden Elementen.
Haupttyp 5: eine Map von Paaren von Datenelementen. Maps werden auch Tabellen, Wörterbücher ("dictionaries"), Hashes oder Objekte (in JSON) genannt. Eine Map besteht aus Paaren von Datenelementen, wobei jedes Paar aus einem Schlüssel besteht, auf den unmittelbar ein Wert folgt. Die Länge der Map folgt den Regeln für Byte-Zeichenfolgen (Haupttyp 2), mit der Ausnahme, dass die Länge die Anzahl der Paare angibt und nicht die Länge in Bytes, die die Map einnimmt. Beispielsweise hätte eine Map, die 9 Paare enthält, ein Anfangsbyte von 0b101_01001 (Haupttyp 5, zusätzliche Information 9 für die Anzahl der Paare), gefolgt von den 18 verbleibenden Elementen. Das erste Element ist der erste Schlüssel, das zweite Element ist der erste Wert, das dritte Element ist der zweite Schlüssel und so weiter. Eine Map mit doppelten Schlüsseln kann wohlgeformt sein, sie ist jedoch nicht gültig und führt daher zu unbestimmter Dekodierung; siehe auch Abschnitt 3.7.
Haupttyp 6: optionale semantische Markierung ("tagging") der anderen Haupttypen. Siehe Abschnitt 2.4.
Haupttyp 7: Gleitkommazahlen und einfache Datentypen, die keinen Inhalt benötigen, sowie der "break"-Stoppcode. Siehe Abschnitt 2.3.
Diese acht Haupttypen führen zu einer einfachen Tabelle, die zeigt, welche der 256 möglichen Werte für das Anfangsbyte eines Datenelements verwendet werden (Tabelle 5).
Bei den Haupttypen 6 und 7 sind viele der möglichen Werte für künftige Spezifikationen reserviert. Siehe Abschnitt 7 für weitere Informationen zu diesen Werten.
2.2. Unbestimmte Längen bei einigen Haupttypen
Vier CBOR-Elemente (Arrays, Maps, Byte-Zeichenfolgen und Text-Zeichenfolgen) können mit unbestimmter Länge kodiert werden, indem der Wert 31 der zusätzlichen Informationen verwendet wird. Dies ist nützlich, wenn die Kodierung des Elements beginnen muss, bevor die Anzahl der Elemente im Array oder in der Map bzw. die Gesamtlänge der Zeichenfolge bekannt ist. (Die Anwendung dessen wird innerhalb eines Datenelements häufig als "Streaming" bezeichnet.)
Arrays und Maps mit unbestimmter Länge werden anders behandelt als Byte- und Text-Zeichenfolgen mit unbestimmter Länge.
2.2.1. Arrays und Maps mit unbestimmter Länge
Arrays und Maps mit unbestimmter Länge werden einfach geöffnet, ohne die Anzahl der Datenelemente anzugeben, die im Array oder in der Map enthalten sein werden, indem der Wert 31 der zusätzlichen Informationen verwendet wird. Auf das anfängliche Byte aus Haupttyp und zusätzlichen Informationen folgen die Elemente des Arrays oder der Map, genau wie bei anderen Arrays oder Maps. Das Ende des Arrays oder der Map wird dadurch angezeigt, dass ein "break"-Stoppcode an einer Stelle kodiert wird, an der normalerweise das nächste Datenelement enthalten wäre. Das "break" wird mit Haupttyp 7 und dem Wert 31 der zusätzlichen Informationen kodiert (0b111_11111), ist aber selbst kein Datenelement: Es ist lediglich ein syntaktisches Merkmal zum Abschluss des Arrays oder der Map. Das heißt, der "break"-Stoppcode steht nach dem letzten Element im Array oder in der Map und kann an keiner anderen Stelle anstelle eines Datenelements auftreten. Auf diese Weise sehen Arrays und Maps mit unbestimmter Länge genauso aus wie andere Arrays und Maps, außer dass sie mit dem Wert 31 der zusätzlichen Informationen beginnen und mit dem "break"-Stoppcode enden.
Arrays und Maps mit unbestimmter Länge erlauben eine beliebige Anzahl von Elementen (bei Arrays) und Schlüssel/Wert-Paaren (bei Maps) vor dem "break"-Stoppcode. Es gibt keine Einschränkung gegen das Verschachteln von Array- oder Map-Elementen mit unbestimmter Länge. Ein "break" beendet nur ein einzelnes Element, daher benötigen verschachtelte Elemente mit unbestimmter Länge genau so viele "break"-Stoppcodes, wie es Typbytes gibt, die ein Element mit unbestimmter Länge eröffnen.
Beispielsweise nehme man an, ein Encoder möchte das abstrakte Array [1, [2, 3], [4, 5]] darstellen. Die Kodierung mit bestimmter Länge wäre 0x8301820203820405:
83 -- Array of length 3 01 -- 1 82 -- Array of length 2 02 -- 2 03 -- 3 82 -- Array of length 2 04 -- 4 05 -- 5
Die Kodierung mit unbestimmter Länge könnte bei Bedarf unabhängig auf jedes der drei in diesem Datenelement kodierten Arrays angewendet werden, was zu Darstellungen wie den folgenden führt:
0x9f018202039f0405ffff 9F -- Start indefinite-length array 01 -- 1 82 -- Array of length 2 02 -- 2 03 -- 3 9F -- Start indefinite-length array 04 -- 4 05 -- 5 FF -- "break" (inner array) FF -- "break" (outer array)
0x9f01820203820405ff 9F -- Start indefinite-length array 01 -- 1 82 -- Array of length 2 02 -- 2 03 -- 3 82 -- Array of length 2 04 -- 4 05 -- 5 FF -- "break" 0x83018202039f0405ff 83 -- Array of length 3 01 -- 1 82 -- Array of length 2 02 -- 2 03 -- 3 9F -- Start indefinite-length array 04 -- 4 05 -- 5 FF -- "break"
0x83019f0203ff820405 83 -- Array of length 3 01 -- 1 9F -- Start indefinite-length array 02 -- 2 03 -- 3 FF -- "break" 82 -- Array of length 2 04 -- 4 05 -- 5
Ein Beispiel für eine Map mit unbestimmter Länge (die zufällig zwei Schlüssel/Wert-Paare hat) könnte so aussehen:
0xbf6346756ef563416d7421ff BF -- Start indefinite-length map 63 -- First key, UTF-8 string length 3 46756e -- "Fun" F5 -- First value, true 63 -- Second key, UTF-8 string length 3 416d74 -- "Amt" 21 -- -2 FF -- "break"
2.2.2. Byte- und Text-Zeichenfolgen mit unbestimmter Länge
Byte- und Text-Zeichenfolgen mit unbestimmter Länge sind tatsächlich eine Verkettung von null oder mehr Byte- oder Text-Zeichenfolgen mit bestimmter Länge ("Chunks"), die zusammen als eine zusammenhängende Zeichenfolge behandelt werden. Zeichenfolgen mit unbestimmter Länge werden mit dem Haupttyp und dem Wert 31 der zusätzlichen Informationen eröffnet, aber es folgt eine Reihe von Byte- oder Text-Zeichenfolgen mit bestimmten Längen (die Chunks). Das Ende der Reihe von Chunks wird dadurch angezeigt, dass der "break"-Stoppcode (0b111_11111) an einer Stelle kodiert wird, an der der nächste Chunk in der Reihe auftreten würde. Die Inhalte der Chunks werden aneinandergehängt, und die Gesamtlänge der Zeichenfolge mit unbestimmter Länge ist die Summe der Längen aller Chunks. Zusammenfassend lässt sich sagen, dass eine Zeichenfolge mit unbestimmter Länge ähnlich kodiert wird wie ein Array mit unbestimmter Länge ihrer Chunks, außer dass der Haupttyp der Zeichenfolge mit unbestimmter Länge der einer (Text- oder Byte-)Zeichenfolge ist und mit den Haupttypen ihrer Chunks übereinstimmt.
Bei Byte-Zeichenfolgen mit unbestimmter Länge MUSS jedes Datenelement (Chunk) zwischen dem Indikator für unbestimmte Länge und dem "break" ein Byte-Zeichenfolge-Element mit bestimmter Länge sein; wenn der Parser einen anderen Elementtyp als eine Byte-Zeichenfolge sieht, bevor er das "break" sieht, ist dies ein Fehler.
Beispielsweise sei die folgende Sequenz angenommen:
0b010_11111 0b010_00100 0xaabbccdd 0b010_00011 0xeeff99 0b111_11111
5F -- Start indefinite-length byte string 44 -- Byte string of length 4 aabbccdd -- Bytes content 43 -- Byte string of length 3 eeff99 -- Bytes content FF -- "break"
Nach dem Dekodieren ergibt dies eine einzige Byte-Zeichenfolge mit sieben Bytes: 0xaabbccddeeff99.
Text-Zeichenfolgen mit unbestimmter Länge verhalten sich genauso wie Byte-Zeichenfolgen mit unbestimmter Länge, mit der Ausnahme, dass alle ihre Chunks Text-Zeichenfolgen mit bestimmter Länge sein MÜSSEN. Hinweis: Dies impliziert, dass die Bytes eines einzelnen UTF-8-Zeichens nicht über Chunks verteilt werden können: Ein neuer Chunk kann nur an einer Zeichengrenze begonnen werden.
2.3. Gleitkommazahlen und Werte ohne Inhalt
Haupttyp 7 ist für zwei Arten von Daten vorgesehen: Gleitkommazahlen und "einfache Werte", die keinen Inhalt benötigen. Jeder Wert der 5-Bit-Information der zusätzlichen Informationen im Anfangsbyte hat seine eigene Bedeutung, wie in Tabelle 1 definiert. Wie bei den Haupttypen für ganze Zahlen enthalten Elemente dieses Haupttyps keine Inhaltsdaten; alle Informationen befinden sich in den Anfangsbytes.
| 5-Bit-Wert | Semantik |
|---|---|
| 0..23 | Einfacher Wert (Wert 0..23) |
| 24 | Einfacher Wert (Wert 32..255 im folgenden Byte) |
| 25 | IEEE-754-Gleitkommazahl mit halber Genauigkeit (16 Bits folgen) |
| 26 | IEEE-754-Gleitkommazahl mit einfacher Genauigkeit (32 Bits folgen) |
| 27 | IEEE-754-Gleitkommazahl mit doppelter Genauigkeit (64 Bits folgen) |
| 28-30 | (Nicht zugewiesen) |
| 31 | "break"-Stoppcode für Elemente mit unbestimmter Länge |
Tabelle 1: Werte für zusätzliche Informationen im Haupttyp 7
Wie bei allen anderen Haupttypen kennzeichnet der 5-Bit-Wert 24 eine Ein-Byte-Erweiterung: Ihm folgt ein zusätzliches Byte zur Darstellung des einfachen Werts. (Um Verwirrung zu minimieren, werden nur die Werte 32 bis 255 verwendet.) Dies bewahrt die Struktur der Anfangsbytes: Wie bei den anderen Haupttypen hängt deren Länge immer von den zusätzlichen Informationen im ersten Byte ab. Tabelle 2 listet die für einfache Typen zugewiesenen und verfügbaren Werte auf.
| Wert | Semantik |
|---|---|
| 0..19 | (Nicht zugewiesen) |
| 20 | False |
| 21 | True |
| 22 | Null |
| 23 | Undefined-Wert |
| 24..31 | (Reserviert) |
| 32..255 | (Nicht zugewiesen) |
Tabelle 2: Einfache Werte
Die 5-Bit-Werte 25, 26 und 27 stehen für 16-Bit-, 32-Bit- und 64-Bit-IEEE-754-Binär-Gleitkommawerte. Diese Gleitkommawerte werden in den zusätzlichen Bytes der jeweiligen Größe kodiert. (Siehe Anhang D für einige Informationen über 16-Bit-Gleitkommazahlen.)
2.4. Optionale Markierung von Elementen
In CBOR kann einem Datenelement wahlweise ein Tag vorangestellt werden, um ihm zusätzliche Semantik zu verleihen, während seine Struktur erhalten bleibt. Das Tag ist Haupttyp 6 und stellt eine ganze Zahl dar, wie durch den ganzzahligen Wert des Tags angegeben; das (einzige) Datenelement wird als Inhaltsdaten mitgeführt. Wenn ein Tag strukturierte Daten erfordert, wird diese Struktur in das verschachtelte Datenelement kodiert. Die Definition eines Tags schränkt üblicherweise ein, welche Art oder Arten von verschachtelten Datenelementen von einem Tag mitgeführt werden können.
Die Anfangsbytes des Tags folgen den Regeln für positive ganze Zahlen (Haupttyp 0). Auf das Tag folgt ein einzelnes Datenelement beliebigen Typs. Beispielsweise sei angenommen, dass eine Byte-Zeichenfolge der Länge 12 mit einem Tag markiert wird, um anzuzeigen, dass es sich um ein positives Bignum handelt (Abschnitt 2.4.2). Dies würde als 0b110_00010 (Haupttyp 6, zusätzliche Information 2 für das Tag) markiert, gefolgt von 0b010_01100 (Haupttyp 2, zusätzliche Information 12 für die Länge), gefolgt von den 12 Bytes des Bignums.
Decoder müssen Tags nicht verstehen, und daher können Tags in Anwendungen von geringem Wert sein, in denen die Implementierung, die ein bestimmtes CBOR-Datenelement erzeugt, und die Implementierung, die diesen Strom dekodiert, die semantische Bedeutung jedes Elements im Datenfluss kennen. Ihr Hauptzweck in dieser Spezifikation ist die Definition gemeinsamer Datentypen wie Datumsangaben. Ein zweiter Zweck besteht darin, eine optionale Markierung zu ermöglichen, wenn der Decoder ein generischer CBOR-Decoder ist, der möglicherweise von Hinweisen auf den Inhalt von Elementen profitieren kann. Das Verstehen der semantischen Tags ist für einen Decoder optional; er kann einfach über die Anfangsbytes des Tags springen und das markierte Datenelement selbst interpretieren.
Ein Tag bezieht sich immer auf das Element, das unmittelbar darauf folgt. Wenn also Tag A von Tag B gefolgt wird, auf das Datenelement C folgt, bezieht sich Tag A auf das Ergebnis der Anwendung von Tag B auf Datenelement C. Das heißt, ein markiertes Element ist ein Datenelement, das aus einem Tag und einem Wert besteht. Der Inhalt des markierten Elements ist das Datenelement (der Wert), das markiert wird.
IANA pflegt ein Register der Tag-Werte, wie in Abschnitt 7.2 beschrieben. Tabelle 3 enthält eine Liste der Anfangswerte, mit Definitionen im restlichen Teil dieses Abschnitts.
| Tag | Datenelement | Semantik |
|---|---|---|
| 0 | UTF-8-Zeichenfolge | Standard-Datums-/Zeitzeichenfolge; siehe Abschnitt 2.4.1 |
| 1 | mehrere | Epochenbasierte Datums-/Zeitangabe; siehe Abschnitt 2.4.1 |
| 2 | Byte-Zeichenfolge | Positives Bignum; siehe Abschnitt 2.4.2 |
| 3 | Byte-Zeichenfolge | Negatives Bignum; siehe Abschnitt 2.4.2 |
| 4 | Array | Dezimalbruch; siehe Abschnitt 2.4.3 |
| 5 | Array | Bigfloat; siehe Abschnitt 2.4.3 |
| 6..20 | (Nicht zugewiesen) | (Nicht zugewiesen) |
| 21 | mehrere | Erwartete Konvertierung in base64url-Kodierung; siehe Abschnitt 2.4.4.2 |
| 22 | mehrere | Erwartete Konvertierung in base64-Kodierung; siehe Abschnitt 2.4.4.2 |
| 23 | mehrere | Erwartete Konvertierung in base16-Kodierung; siehe Abschnitt 2.4.4.2 |
| 24 | Byte-Zeichenfolge | Kodiertes CBOR-Datenelement; siehe Abschnitt 2.4.4.1 |
| 25..31 | (Nicht zugewiesen) | (Nicht zugewiesen) |
| 32 | UTF-8-Zeichenfolge | URI; siehe Abschnitt 2.4.4.3 |
| 33 | UTF-8-Zeichenfolge | base64url; siehe Abschnitt 2.4.4.3 |
| 34 | UTF-8-Zeichenfolge | base64; siehe Abschnitt 2.4.4.3 |
| 35 | UTF-8-Zeichenfolge | Regulärer Ausdruck; siehe Abschnitt 2.4.4.3 |
| 36 | UTF-8-Zeichenfolge | MIME-Nachricht; siehe Abschnitt 2.4.4.3 |
| 37..55798 | (Nicht zugewiesen) | (Nicht zugewiesen) |
| 55799 | mehrere | Selbstbeschreibendes CBOR; siehe Abschnitt 2.4.5 |
| 55800+ | (Nicht zugewiesen) | (Nicht zugewiesen) |
Tabelle 3: Werte für Tags
2.4.1. Datum und Zeit
Tag-Wert 0 steht für Datums-/Zeitzeichenfolgen, die dem in [RFC3339] beschriebenen Standardformat folgen, wie durch Abschnitt 3.3 von [RFC4287] verfeinert.
Tag-Wert 1 steht für die numerische Darstellung von Sekunden relativ zu 1970-01-01T00:00Z in UTC-Zeit. (Für die nicht-negativen Werte, die die Portable Operating System Interface (POSIX) definiert, werden die Sekunden auf die gleiche Weise gezählt wie bei POSIX "seconds since the epoch" [TIME_T].) Das markierte Element kann eine positive oder negative ganze Zahl (Haupttypen 0 und 1) oder eine Gleitkommazahl (Haupttyp 7 mit zusätzlicher Information 25, 26 oder 27) sein. Hinweis: Die Zahl kann negativ sein (Zeit vor 1970-01-01T00:00Z) und kann im Fall einer Gleitkommazahl Bruchteile von Sekunden angeben.
2.4.2. Bignums
Bignums sind ganze Zahlen, die nicht in die von den Haupttypen 0 und 1 bereitgestellten grundlegenden ganzzahligen Darstellungen passen. Sie werden als Byte-Zeichenfolgen-Datenelement kodiert, das als vorzeichenlose ganze Zahl n in Netzwerk-Byte-Reihenfolge interpretiert wird. Für Tag-Wert 2 ist der Wert des Bignums n. Für Tag-Wert 3 ist der Wert des Bignums -1 - n. Decoder, die diese Tags verstehen, MÜSSEN in der Lage sein, Bignums mit führenden Nullen zu dekodieren.
Beispielsweise wird die Zahl 18446744073709551616 (2**64) als 0b110_00010 (Haupttyp 6, Tag 2) dargestellt, gefolgt von 0b010_01001 (Haupttyp 2, Länge 9), gefolgt von 0x010000000000000000 (ein Byte 0x01 und acht Bytes 0x00). In hexadezimaler Form:
C2 -- Tag 2 29 -- Byte string of length 9 010000000000000000 -- Bytes content
2.4.3. Dezimalbrüche und Bigfloats
Dezimalbrüche verbinden eine ganzzahlige Mantisse mit einem Skalierungsfaktor zur Basis 10. Sie sind am nützlichsten, wenn eine Anwendung die exakte Darstellung eines Dezimalbruchs wie 1.1 benötigt, weil es für viele Dezimalbrüche keine exakte Darstellung in binärer Gleitkommadarstellung gibt.
Bigfloats verbinden eine ganzzahlige Mantisse mit einem Skalierungsfaktor zur Basis 2. Es sind binäre Gleitkommawerte, die den Wertebereich oder die Genauigkeit der drei von CBOR unterstützten IEEE-754-Formate überschreiten können (Abschnitt 2.3). Bigfloats können auch von eingeschränkten Anwendungen verwendet werden, die eine grundlegende binäre Gleitkommafähigkeit benötigen, ohne IEEE 754 unterstützen zu müssen.
Ein Dezimalbruch oder ein Bigfloat wird als markiertes Array dargestellt, das genau zwei ganze Zahlen enthält: einen Exponenten e und eine Mantisse m. Dezimalbrüche (Tag 4) verwenden Exponenten zur Basis 10; der Wert eines Dezimalbruch-Datenelements ist m*(10e). Bigfloats (Tag 5) verwenden Exponenten zur Basis 2; der Wert eines Bigfloat-Datenelements ist m*(2e). Der Exponent e MUSS in einer ganzen Zahl des Haupttyps 0 oder 1 dargestellt werden, während die Mantisse auch ein Bignum sein kann (Abschnitt 2.4.2).
Ein Beispiel für einen Dezimalbruch: Die Zahl 273.15 könnte als 0b110_00100 (Haupttyp 6 für das Tag, zusätzliche Information 4 für die Art des Tags) dargestellt werden, gefolgt von 0b100_00010 (Haupttyp 4 für das Array, zusätzliche Information 2 für die Länge des Arrays), gefolgt von 0b001_00001 (Haupttyp 1 für die erste ganze Zahl, zusätzliche Information 1 für den Wert -2), gefolgt von 0b000_11001 (Haupttyp 0 für die zweite ganze Zahl, zusätzliche Information 25 für einen Zwei-Byte-Wert), gefolgt von 0b0110101010110011 (27315 in zwei Bytes). In hexadezimaler Form:
C4 -- Tag 4 82 -- Array of length 2 21 -- -2 19 6ab3 -- 27315
Ein Beispiel für einen Bigfloat: Die Zahl 1.5 könnte als 0b110_00101 (Haupttyp 6 für das Tag, zusätzliche Information 5 für die Art des Tags) dargestellt werden, gefolgt von 0b100_00010 (Haupttyp 4 für das Array, zusätzliche Information 2 für die Länge des Arrays), gefolgt von 0b001_00000 (Haupttyp 1 für die erste ganze Zahl, zusätzliche Information 0 für den Wert -1), gefolgt von 0b000_00011 (Haupttyp 0 für die zweite ganze Zahl, zusätzliche Information 3 für den Wert 3). In hexadezimaler Form:
C5 -- Tag 5 82 -- Array of length 2 20 -- -1 03 -- 3
Dezimalbrüche und Bigfloats bieten keine Darstellung für Infinity, -Infinity oder NaN; falls diese anstelle eines Dezimalbruchs oder Bigfloats benötigt werden, können die IEEE-754-Darstellungen mit halber Genauigkeit aus Abschnitt 2.3 verwendet werden. Bei eingeschränkten Anwendungen, bei denen die Wahl zwischen der Darstellung einer bestimmten Zahl als ganze Zahl und als Dezimalbruch oder Bigfloat besteht (beispielsweise wenn der Exponent klein und nicht-negativ ist), besteht die Erwartung an die Implementierungsqualität, dass die ganzzahlige Darstellung direkt verwendet wird.
2.4.4. Inhaltshinweise
Die Tags in diesem Abschnitt sind Inhaltshinweise, die von generischen CBOR-Prozessoren verwendet werden können.
2.4.4.1. Kodiertes CBOR-Datenelement
Mitunter ist es vorteilhaft, ein eingebettetes CBOR-Datenelement mitzuführen, das nicht unmittelbar zum Zeitpunkt des Parsens des umschließenden Datenelements dekodiert werden soll. Tag 24 (CBOR-Datenelement) kann verwendet werden, um die eingebettete Byte-Zeichenfolge als ein im CBOR-Format kodiertes Datenelement zu markieren.
2.4.4.2. Erwartete spätere Kodierung für CBOR-zu-JSON-Konverter
Die Tags 21 bis 23 zeigen an, dass eine Byte-Zeichenfolge beim Zusammenspiel mit einer textbasierten Darstellung möglicherweise eine bestimmte Kodierung erfordert. Diese Tags sind nützlich, wenn ein Encoder weiß, dass die von ihm geschriebenen Byte-Zeichenfolgen-Daten wahrscheinlich später in eine bestimmte JSON-basierte Verwendung konvertiert werden. Diese Verwendung legt fest, dass manche Zeichenfolgen als base64, base64url usw. kodiert werden. Der Encoder verwendet Byte-Zeichenfolgen, anstatt die Kodierung selbst vorzunehmen, um die Nachrichtengröße zu verringern, um die Codegröße des Encoders zu verringern oder beides. Der Encoder weiß nicht, ob der Konverter generisch sein wird, und möchte daher angeben, was seiner Ansicht nach der richtige Weg ist, binäre Zeichenfolgen nach JSON zu konvertieren.
Das markierte Datenelement kann eine Byte-Zeichenfolge oder ein beliebiges anderes Datenelement sein. Im letzteren Fall bezieht sich das Tag auf alle im Datenelement enthaltenen Byte-Zeichenfolgen-Datenelemente, mit Ausnahme derjenigen, die in einem verschachtelten Datenelement enthalten sind, das mit einer erwarteten Konvertierung markiert ist.
Diese drei Tag-Typen schlagen Konvertierungen in drei der in [RFC4648] definierten Basis-Datenkodierungen vor. Für die base64url-Kodierung wird kein Padding verwendet (siehe Abschnitt 3.2 von RFC 4648); das heißt, alle nachgestellten Gleichheitszeichen ("=") werden aus der base64url-kodierten Zeichenfolge entfernt. Spätere Tags könnten für andere Datenkodierungen von RFC 4648 oder für andere Wege definiert werden, Binärdaten in Zeichenfolgen zu kodieren.
2.4.4.3. Kodierter Text
Manche Text-Zeichenfolgen enthalten Daten in Formaten, die im Internet weit verbreitet sind, und mitunter können diese Formate vom Decoder validiert und der Anwendung in geeigneter Form bereitgestellt werden. Für einige dieser Formate gibt es Tags.
-
Tag 32 steht für URIs, wie in [RFC3986] definiert;
-
Die Tags 33 und 34 stehen für base64url- und base64-kodierte Text-Zeichenfolgen, wie in [RFC4648] definiert;
-
Tag 35 steht für reguläre Ausdrücke in Perl Compatible Regular Expressions (PCRE) / JavaScript-Syntax [ECMA262].
-
Tag 36 steht für MIME-Nachrichten (einschließlich aller Header), wie in [RFC2045] definiert;
Hinweis: Die Tags 33 und 34 unterscheiden sich von 21 und 22 dadurch, dass die Daten bei ersteren in basis-kodierter Form und bei letzteren in Form einer rohen Byte-Zeichenfolge transportiert werden.
2.4.5. Selbstbeschreibendes CBOR
In vielen Anwendungen wird aus dem Kontext ersichtlich sein, dass CBOR zur Kodierung eines Datenelements verwendet wird. Beispielsweise könnte ein bestimmtes Protokoll die Verwendung von CBOR festlegen, oder es wird ein Medientyp angegeben, der dessen Verwendung festlegt. Es kann jedoch Anwendungen geben, in denen solche Kontextinformationen nicht verfügbar sind, etwa wenn CBOR-Daten in einer Datei gespeichert werden und keine unterscheidenden Metadaten verwendet werden. Hier kann es hilfreich sein, einige unterscheidende Merkmale für die Daten selbst zu haben.
Tag 55799 ist für diesen Zweck definiert. Es verleiht dem nachfolgenden Datenelement keine besondere Semantik; das heißt, die Semantik eines mit Tag 55799 markierten Datenelements ist exakt identisch mit der Semantik des Datenelements selbst.
Die Serialisierung dieses Tags ist 0xd9d9f7, was offenbar nicht als Unterscheidungsmerkmal für häufig verwendete Dateitypen in Gebrauch ist. Insbesondere ist es kein gültiger Anfang eines Unicode-Textes in irgendeiner Unicode-Kodierung, sofern ein gültiges CBOR-Datenelement folgt.
Beispielsweise könnte ein Decoder in der Lage sein, sowohl CBOR als auch JSON zu parsen. Ein solcher Decoder müsste die beiden Formate mechanisch unterscheiden. Eine einfache Möglichkeit für einen Encoder, dem Decoder zu helfen, bestünde darin, das gesamte CBOR-Element mit Tag 55799 zu markieren, dessen Serialisierung niemals am Anfang eines JSON-Textes zu finden ist.