|
| 1 | +CBOR |
| 2 | +==== |
| 3 | + |
| 4 | +A C# and Java implementation of Concise Binary Object Representation, a general-purpose binary data format defined in RFC 7049. According to that RFC, CBOR's data model "is an extended version of the JSON data model", supporting many more types of data than JSON. "CBOR was inspired by MessagePack", but "is not intended as a version of or replacement for MessagePack." |
| 5 | + |
| 6 | +This implementation was written by Peter O. and is released to the Public Domain under the [CC0 Declaration](http://creativecommons.org/publicdomain/zero/1.0/). |
| 7 | + |
| 8 | +This implementation also doubles as a reader and writer of JSON, and can convert data from JSON to CBOR and back. |
| 9 | + |
| 10 | +Finally, this implementation supports arbitrary-precision binary and decimal floating-point numbers and rational numbers with arbitrary-precision components. |
| 11 | + |
| 12 | +How to Install |
| 13 | +--------- |
| 14 | +Starting with version 0.21.0, the C# implementation is available in the |
| 15 | +NuGet Package Gallery under the name |
| 16 | +[PeterO.Cbor](https://www.nuget.org/packages/PeterO.Cbor). To install |
| 17 | +this library as a NuGet package, enter `Install-Package PeterO.Cbor` in the |
| 18 | +NuGet Package Manager Console. |
| 19 | + |
| 20 | +Starting with version 0.23.0, the Java implementation is available |
| 21 | +as an [artifact](https://search.maven.org/#search|ga|1|g%3A%22com.upokecenter%22%20AND%20a%3A%22cbor%22) in the Central Repository. To add this library to a Maven |
| 22 | +project, add the following to the `dependencies` section in your `pom.xml` file: |
| 23 | + |
| 24 | +```xml |
| 25 | +<dependency> |
| 26 | + <groupId>com.upokecenter</groupId> |
| 27 | + <artifactId>cbor</artifactId> |
| 28 | + <version>1.3.0</version> |
| 29 | +</dependency> |
| 30 | +``` |
| 31 | + |
| 32 | +In other Java-based environments, the library can be referred to by its |
| 33 | +group ID (`com.upokecenter`), artifact ID (`cbor`), and version, as given above. |
| 34 | + |
| 35 | +Documentation |
| 36 | +------------ |
| 37 | + |
| 38 | +This library defines one class, called CBORObject, that allows you to read and |
| 39 | +write CBOR objects to and from data streams and byte arrays, and to convert JSON |
| 40 | +text to CBOR objects and back. |
| 41 | + |
| 42 | +See the [Wiki](https://github.com/peteroupc/CBOR/wiki) for Java API documentation. |
| 43 | + |
| 44 | +See [docs/APIDocs.md](https://github.com/peteroupc/CBOR/blob/master/docs/APIDocs.md) for C# (.NET) API documentation. |
| 45 | + |
| 46 | +More About the Different Versions |
| 47 | +----------- |
| 48 | + |
| 49 | +This repository contains code in two languages: C# and Java. |
| 50 | +C# is the main language of the project, and the C# implementation has the most features. |
| 51 | + |
| 52 | +The C# implementation is designed as a Portable Class Library, making it usable not only in the .NET |
| 53 | +Framework, but also Silverlight 5 and Windows Phone 8. |
| 54 | + |
| 55 | +The Java version is a translation from the C# version. It contains almost as many features as the C# version |
| 56 | +and has all the important ones, such as reading and writing CBOR objects, |
| 57 | +CBOR/JSON conversion, and support for decimal fractions and bigfloats. |
| 58 | + |
| 59 | +Examples |
| 60 | +---------- |
| 61 | + |
| 62 | +This code is in C#, but the Java version of the code would be very similar. |
| 63 | + |
| 64 | +```c# |
| 65 | +// The following creates a CBOR map and adds |
| 66 | +// several kinds of objects to it |
| 67 | +var cbor = CBORObject.NewMap() |
| 68 | + .Add("item", "any string") |
| 69 | + .Add("number", 42) |
| 70 | + .Add("map", CBORObject.NewMap().Add("number", 42)) |
| 71 | + .Add("array", CBORObject.NewArray().Add(999f).Add("xyz")) |
| 72 | + .Add("bytes", new byte[] { 0, 1, 2 }); |
| 73 | +// The following converts the map to CBOR |
| 74 | +byte[] bytes = cbor.EncodeToBytes(); |
| 75 | +// The following converts the map to JSON |
| 76 | +string json = cbor.ToJSONString(); |
| 77 | +Console.WriteLine(json); |
| 78 | +``` |
| 79 | + |
| 80 | +Reading data from a file (C#). Note that all the examples for |
| 81 | +reading and writing to files assume that the platform supports |
| 82 | +file I/O; the portable class library doesn't make that assumption. |
| 83 | + |
| 84 | +```c# |
| 85 | + // Read all the bytes from a file and decode the CBOR object |
| 86 | + // from it. However, there are two disadvantages to this approach: |
| 87 | + // 1. The byte array might be very huge, so a lot of memory to store |
| 88 | + // the array may be needed. |
| 89 | + // 2. The decoding will succeed only if the entire array, |
| 90 | + // not just the start of the array, consists of a CBOR object. |
| 91 | + var cbor = CBORObject.DecodeFromBytes(File.ReadAllBytes("object.cbor")); |
| 92 | +``` |
| 93 | + |
| 94 | +Another example of reading data from a file: |
| 95 | + |
| 96 | +```c# |
| 97 | + // C# |
| 98 | + // Open the file stream |
| 99 | + using (var stream = new FileStream("object.cbor", FileMode.Open)) { |
| 100 | + // Read the CBOR object from the stream |
| 101 | + var cbor = CBORObject.Read(stream); |
| 102 | + // At this point, the object is read, but the file stream might |
| 103 | + // not have ended yet. Here, the code may choose to read another |
| 104 | + // CBOR object, check for the end of the stream, or just ignore the |
| 105 | + // rest of the file. The following is an example of checking for the |
| 106 | + // end of the stream. |
| 107 | + if (stream.Position != stream.Length) { |
| 108 | + // The end of the stream wasn't reached yet. |
| 109 | + } else { |
| 110 | + // The end of the stream was reached. |
| 111 | + } |
| 112 | + } |
| 113 | +``` |
| 114 | + |
| 115 | +```java |
| 116 | + // Java |
| 117 | + // Open the file stream |
| 118 | + try (FileInputStream stream = new FileInputStream("object.cbor")) { |
| 119 | + // Read the CBOR object from the stream |
| 120 | + var cbor = CBORObject.Read(stream); |
| 121 | + // At this point, the object is read, but the file stream might |
| 122 | + // not have ended yet. Here, the code may choose to read another |
| 123 | + // CBOR object, check for the end of the stream, or just ignore the |
| 124 | + // rest of the file. The following is an example of checking for the |
| 125 | + // end of the stream. |
| 126 | + if (stream.getChannel().position() != stream.getChannel().size()) { |
| 127 | + // The end of the stream wasn't reached yet. |
| 128 | + } else { |
| 129 | + // The end of the stream was reached. |
| 130 | + } |
| 131 | + } |
| 132 | +``` |
| 133 | + |
| 134 | +Writing CBOR data to a file (C#): |
| 135 | + |
| 136 | +```c# |
| 137 | +// This example assumes that the variable "cbor" refers |
| 138 | +// to a CBORObject object. |
| 139 | +using (var stream = new FileStream("object.cbor", FileMode.Create)) { |
| 140 | + cbor.WriteTo(stream); |
| 141 | +} |
| 142 | +``` |
| 143 | + |
| 144 | +Writing multiple objects to a file, including arbitrary objects: |
| 145 | + |
| 146 | +```c# |
| 147 | +// C# |
| 148 | +// This example writes different kinds of objects in CBOR |
| 149 | +// format to the same file. |
| 150 | +using (var stream = new FileStream("object.cbor", FileMode.Create)) { |
| 151 | + CBORObject.Write(true, stream); |
| 152 | + CBORObject.Write(422.5, stream); |
| 153 | + CBORObject.Write("some string", stream); |
| 154 | + CBORObject.Write(CBORObject.Undefined, stream); |
| 155 | + CBORObject.NewArray().Add(42).WriteTo(stream); |
| 156 | +} |
| 157 | +``` |
| 158 | + |
| 159 | +```java |
| 160 | +// Java |
| 161 | +// This example uses the "try-with-resources" statement from Java 7. |
| 162 | +// This example writes different kinds of objects in CBOR |
| 163 | +// format to the same file. |
| 164 | +try (FileOutputStream stream = new FileOutputStream("object.cbor")) { |
| 165 | + CBORObject.Write(true, stream); |
| 166 | + CBORObject.Write(422.5, stream); |
| 167 | + CBORObject.Write("some string", stream); |
| 168 | + CBORObject.Write(CBORObject.Undefined, stream); |
| 169 | + CBORObject.NewArray().Add(42).WriteTo(stream); |
| 170 | +} |
| 171 | +``` |
| 172 | + |
| 173 | +Reading JSON from a file: |
| 174 | + |
| 175 | +```c# |
| 176 | + // Open the file stream |
| 177 | + using (var stream = new FileStream("object.json", FileMode.Open)) { |
| 178 | + // Read the JSON object from the stream |
| 179 | + // as a CBOR object |
| 180 | + var cbor = CBORObject.ReadJSON(stream); |
| 181 | + } |
| 182 | +``` |
| 183 | + |
| 184 | +Writing a CBOR object as JSON: |
| 185 | + |
| 186 | +```c# |
| 187 | +// This example assumes that the variable "cbor" refers |
| 188 | +// to a CBORObject object. |
| 189 | +// NOTE: Specifying Encoding.UTF8 as the third parameter |
| 190 | +// would add a byte order mark to the beginning of the text, |
| 191 | +// but conforming JSON implementations are forbidden from |
| 192 | +// adding it this way in JSON texts they generate. |
| 193 | +File.WriteAllText( |
| 194 | + "object.json", |
| 195 | + cbor.ToJSONString(), |
| 196 | + new System.Text.Encoding.UTF8Encoding(false)); |
| 197 | + |
| 198 | +// This is an alternative way to write the CBOR object |
| 199 | +// and is now supported in version 1.2. |
| 200 | +using (var stream = new FileStream("object2.json", FileMode.Create)) { |
| 201 | + // Write the CBOR object as JSON; here, a byte order |
| 202 | + // mark won't be added |
| 203 | + cbor.WriteJSONTo(stream); |
| 204 | +} |
| 205 | +// Version 1.2 now supports a third way to write |
| 206 | +// objects to JSON: the CBORObject.WriteJSON method |
| 207 | +using (var stream = new FileStream("object3.json", FileMode.Create)) { |
| 208 | + CBORObject.WriteJSON("some string", stream); |
| 209 | +} |
| 210 | +using (var stream = new FileStream("object4.json", FileMode.Create)) { |
| 211 | + CBORObject.WriteJSON(cbor, stream); |
| 212 | +} |
| 213 | +using (var stream = new FileStream("object5.json", FileMode.Create)) { |
| 214 | + CBORObject.WriteJSON(true, stream); |
| 215 | +} |
| 216 | +using (var stream = new FileStream("object6.json", FileMode.Create)) { |
| 217 | + CBORObject.WriteJSON(42, stream); |
| 218 | +} |
| 219 | +``` |
| 220 | + |
| 221 | + |
| 222 | + |
| 223 | +NOTE: All code samples in this section are released to the Public Domain, |
| 224 | +as explained in <http://creativecommons.org/publicdomain/zero/1.0/>. |
| 225 | + |
| 226 | +Source Code |
| 227 | +--------- |
| 228 | +Source code is available in the [project page](https://github.com/peteroupc/CBOR). |
| 229 | + |
| 230 | +About |
| 231 | +----------- |
| 232 | + |
| 233 | +Written in 2013-2014 by Peter O. |
| 234 | + |
| 235 | +Any copyright is dedicated to the Public Domain. |
| 236 | +http://creativecommons.org/publicdomain/zero/1.0/ |
| 237 | + |
| 238 | +If you like this, you should donate to Peter O. |
| 239 | +at: http://peteroupc.github.io/CBOR/ |
| 240 | + |
| 241 | +Clarifications |
| 242 | +------------------ |
| 243 | + |
| 244 | +The following are some clarifications to RFC 7049. |
| 245 | + |
| 246 | +* Section 2.4.2 doesn't specify what happens if a bignum's byte |
| 247 | + string has a length of 0. This implementation treats a positive |
| 248 | + bignum with length 0 as having a value of 0 and a negative |
| 249 | + bignum with length 0 as having a value of -1. |
| 250 | +* Section 2.4.1 specifies the number of seconds since the start of 1970. It is |
| 251 | + based on the POSIX definition of "seconds since the Epoch", which |
| 252 | + the RFC cites as a normative reference. This definition does not |
| 253 | + count leap seconds. When this implementation supports date |
| 254 | + conversion, it won't count leap seconds, either. This implementation |
| 255 | + treats values of infinity and NaN as invalid. |
| 256 | +* For tag 32, this implementation accepts strings that are valid |
| 257 | + Internationalized Resource Identifiers (IRIs) in addition to URIs. |
| 258 | + IRI are like URIs except that they also allow non-ASCII characters. |
| 259 | + |
| 260 | +Release Notes |
| 261 | +----------- |
| 262 | + |
| 263 | +In version 1.3: |
| 264 | + |
| 265 | +- Added a CompareToIgnoreTags method to CBORObject |
| 266 | +- The BigInteger constructor in the C# version is deprecated |
| 267 | +- Fixed bugs in converting from CBOR float and double to integers in some corner cases |
| 268 | +- Fixed a bug where CBORObject's OutermostTag returns 0 instead of the correct -1 for untagged objects |
| 269 | +- Fixed a bug where BigInteger's bitLength return value can be wrong in some corner cases |
| 270 | + |
| 271 | +In version 1.2: |
| 272 | + |
| 273 | +- The WriteJSON and WriteToJSON methods were added to CBORObject |
| 274 | +- Bugs were fixed in the Set and Add methods of CBORObject |
| 275 | + |
| 276 | +In version 1.1 there were many additions and bug fixes in arbitrary-precision |
| 277 | +arithmetic, including: |
| 278 | + |
| 279 | +- Added unchecked versions of intValue and longValue in BigInteger |
| 280 | +- Added more overloads for FromString in ExtendedDecimal and ExtendedFloat |
| 281 | +- Fixed bug where Pow doesn't compute the exact value in unlimited precision contexts |
| 282 | +- Much added documentation |
| 283 | + |
| 284 | +In version 1.0, the "adjust exponent" and "is precision in bits" flags were added to |
| 285 | +the arbitrary-precision arithmetic contexts, and a new Set method that is similar |
| 286 | +to Add but can replace a key's value in a CBOR map. Some bugs were also fixed. |
| 287 | + |
| 288 | +Version 0.23.0 has no new features of note. |
| 289 | + |
| 290 | +Version 0.22.0 adds CBOR support for decimal fractions and big floats with any |
| 291 | +exponent, even exponents higher than 65 bits, and implements well-formedness |
| 292 | +checking for tag 32 (URIs). Several bugs were also fixed. |
| 293 | + |
| 294 | +The [commit history](https://github.com/peteroupc/CBOR/commits/master) |
| 295 | +contains details on code changes in previous versions. |
| 296 | + |
| 297 | +Specifications |
| 298 | +----------- |
| 299 | +Here are specifications by this implementation's author on proposed |
| 300 | +CBOR tags: |
| 301 | + |
| 302 | +* Tag 30: [Rational numbers](http://peteroupc.github.io/CBOR/rational.html) |
| 303 | +* Tag 257: [Binary MIME messages](http://peteroupc.github.io/CBOR/binarymime.html) |
| 304 | +* Tag 38: [Language-tagged strings](http://peteroupc.github.io/CBOR/langtags.html) |
| 305 | +* Tag 264 and 265: [Arbitrary-exponent numbers](http://peteroupc.github.io/CBOR/bigfrac.html) |
| 306 | + |
| 307 | +Acknowledgments |
| 308 | +----------- |
| 309 | + |
| 310 | +* Carsten Bormann reviewed this library and gave helpful suggestions. |
| 311 | +* Anders Gustafsson converted this library to a Portable Class Library. |
0 commit comments