├── .gitattributes ├── .github └── workflows │ ├── codeql-analysis.yml │ └── maven.yml ├── .gitignore ├── LICENSE.md ├── README.md ├── api ├── Home.md ├── com.upokecenter.cbor.CBORDataUtilities.md ├── com.upokecenter.cbor.CBORDateConverter.ConversionType.md ├── com.upokecenter.cbor.CBORDateConverter.md ├── com.upokecenter.cbor.CBOREncodeOptions.md ├── com.upokecenter.cbor.CBORException.md ├── com.upokecenter.cbor.CBORNumber.NumberKind.md ├── com.upokecenter.cbor.CBORNumber.md ├── com.upokecenter.cbor.CBORObject.md ├── com.upokecenter.cbor.CBORType.md ├── com.upokecenter.cbor.CBORTypeMapper.md ├── com.upokecenter.cbor.ICBORConverter.md ├── com.upokecenter.cbor.ICBORToFromConverter.md ├── com.upokecenter.cbor.JSONOptions.ConversionMode.md ├── com.upokecenter.cbor.JSONOptions.md └── com.upokecenter.cbor.PODOptions.md ├── pom.xml └── src ├── main └── java │ └── com │ └── upokecenter │ └── cbor │ ├── Base64.java │ ├── CBORCanonical.java │ ├── CBORDataUtilities.java │ ├── CBORDataUtilitiesByteArrayString.java │ ├── CBORDataUtilitiesCharArrayString.java │ ├── CBORDataUtilitiesTextString.java │ ├── CBORDateConverter.java │ ├── CBORDoubleBits.java │ ├── CBOREInteger.java │ ├── CBOREncodeOptions.java │ ├── CBORException.java │ ├── CBORExtendedDecimal.java │ ├── CBORExtendedFloat.java │ ├── CBORExtendedRational.java │ ├── CBORInteger.java │ ├── CBORJson.java │ ├── CBORJson2.java │ ├── CBORJson3.java │ ├── CBORJsonWriter.java │ ├── CBORNumber.java │ ├── CBORObject.java │ ├── CBORReader.java │ ├── CBORType.java │ ├── CBORTypeMapper.java │ ├── CBORUriConverter.java │ ├── CBORUtilities.java │ ├── CBORUuidConverter.java │ ├── CharacterInputWithCount.java │ ├── CharacterReader.java │ ├── ICBORConverter.java │ ├── ICBORNumber.java │ ├── ICBORToFromConverter.java │ ├── ICharacterInput.java │ ├── JSONOptions.java │ ├── JSONPatch.java │ ├── JSONPointer.java │ ├── OptionsParser.java │ ├── PODOptions.java │ ├── PropertyMap.java │ ├── SharedRefs.java │ ├── StringOutput.java │ └── StringRefs.java └── test ├── java └── com │ └── upokecenter │ ├── test │ ├── AppResources.java │ ├── BEncoding.java │ ├── BEncodingTest.java │ ├── Base64.java │ ├── CBORDataUtilitiesTest.java │ ├── CBORExceptionTest.java │ ├── CBORGenerator.java │ ├── CBORNumberTest.java │ ├── CBORObjectTest.java │ ├── CBORPlistWriter.java │ ├── CBORSupplementTest.java │ ├── CBORTest.java │ ├── CBORTestCommon.java │ ├── CBORTypeMapperTest.java │ ├── CBORWriterHelper.java │ ├── CPOD.java │ ├── CPOD2.java │ ├── CPOD3.java │ ├── DateTest.java │ ├── FieldClass.java │ ├── JSONGenerator.java │ ├── JSONPatch.java │ ├── JSONPointer.java │ ├── JSONWithComments.java │ ├── JavaSpecificTest.java │ ├── LimitedMemoryStream.java │ ├── MiniCBOR.java │ ├── PODClass.java │ ├── RandomNumerics.java │ ├── RandomObjects.java │ ├── StringAndBigInt.java │ ├── StringOutput.java │ ├── TestCommon.java │ └── ToObjectTest.java │ └── util │ ├── IRandomGen.java │ ├── IRandomGenExtended.java │ ├── QueryStringHelper.java │ ├── QueryStringHelperCBOR.java │ ├── RandomGenerator.java │ └── XorShift128Plus.java └── resources └── Resources.properties /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | *.cs eol=lf 3 | *.java eol=lf 4 | *.js eol=lf 5 | *.rb eol=lf 6 | *.py eol=lf 7 | *.php eol=lf 8 | *.c eol=lf 9 | *.h eol=lf 10 | *.cc eol=lf 11 | *.hh eol=lf 12 | *.cpp eol=lf 13 | *.cxx eol=lf 14 | *.md eol=lf 15 | *.sln eol=lf 16 | *.config eol=lf 17 | *.csproj eol=lf 18 | *.vbproj eol=lf 19 | *.fsproj eol=lf 20 | *.dbproj eol=lf 21 | *.nuspec eol=lf 22 | *.html eol=lf 23 | *.htm eol=lf 24 | *.css eol=lf 25 | *.less eol=lf 26 | *.xml eol=lf 27 | *.ruleset eol=lf 28 | *.yml eol=lf 29 | .gitattributes eol=lf 30 | .gitignore eol=lf 31 | .npmignore eol=lf 32 | *.cs diff=csharp 33 | *.sln merge=union 34 | *.csproj merge=union 35 | *.vbproj merge=union 36 | *.fsproj merge=union 37 | *.dbproj merge=union 38 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ master ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ master ] 20 | schedule: 21 | - cron: '40 7 * * 0' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'java' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] 37 | # Learn more: 38 | # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed 39 | 40 | steps: 41 | - name: Checkout repository 42 | uses: actions/checkout@v2 43 | 44 | # Initializes the CodeQL tools for scanning. 45 | - name: Initialize CodeQL 46 | uses: github/codeql-action/init@v3 47 | with: 48 | languages: ${{ matrix.language }} 49 | # If you wish to specify custom queries, you can do so here or in a config file. 50 | # By default, queries listed here will override any specified in a config file. 51 | # Prefix the list here with "+" to use these queries and those in the config file. 52 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 53 | 54 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 55 | # If this step fails, then you should remove it and run the build manually (see later) 56 | - name: Autobuild 57 | uses: github/codeql-action/autobuild@v3 58 | 59 | # ℹ️ Command-line programs to run using the OS shell. 60 | # 📚 https://git.io/JvXDl 61 | 62 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 63 | # and modify them (or add more) to build your code if your project 64 | # uses a compiled language 65 | 66 | #- run: | 67 | # make bootstrap 68 | # make release 69 | 70 | - name: Perform CodeQL Analysis 71 | uses: github/codeql-action/analyze@v3 72 | -------------------------------------------------------------------------------- /.github/workflows/maven.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-maven 3 | 4 | # This workflow uses actions that are not certified by GitHub. 5 | # They are provided by a third-party and are governed by 6 | # separate terms of service, privacy policy, and support 7 | # documentation. 8 | 9 | name: Java CI with Maven 10 | 11 | on: 12 | push: 13 | branches: [ "master" ] 14 | pull_request: 15 | branches: [ "master" ] 16 | 17 | jobs: 18 | build: 19 | 20 | runs-on: ubuntu-latest 21 | 22 | steps: 23 | - uses: actions/checkout@v3 24 | - name: Set up JDK 17 25 | uses: actions/setup-java@v3 26 | with: 27 | java-version: '17' 28 | distribution: 'temurin' 29 | cache: maven 30 | - name: Build with Maven 31 | run: mvn -B package --file pom.xml 32 | 33 | permissions: 34 | contents: read 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.Cache 2 | *.Settings 3 | *.bat 4 | *.cache 5 | *.class 6 | *.jar 7 | *.log 8 | *.map 9 | *.nupkg 10 | *.pyc 11 | *.sdsettings 12 | *.shf* 13 | *.suo 14 | *.user 15 | *.userprefs 16 | *.versionsBackup 17 | .classpath 18 | .nuget/ 19 | .pmd 20 | .project 21 | .settings/ 22 | .vs/ 23 | CBORTest/OpenCover/ 24 | CBORTest/ProfilingSessions/ 25 | CBORTest/bin/ 26 | CBORTest/obj/ 27 | Help/ 28 | ProfilingSessions/ 29 | TestResults/ 30 | bin/ 31 | encoding/ 32 | encodingfldr/ 33 | js/*.ht* 34 | js/DecTest.* 35 | obj/ 36 | packages/ 37 | release.properties 38 | target/ 39 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. 4 | 5 | In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. 6 | 7 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CBOR 2 | 3 | [![Maven Central](https://img.shields.io/maven-central/v/com.upokecenter/cbor.svg?style=plastic)](https://search.maven.org/#search|ga|1|g%3A%22com.upokecenter%22%20AND%20a%3A%22cbor%22) 4 | 5 | --- 6 | 7 | A Java implementation of Concise Binary Object Representation, a general-purpose binary data format defined in RFC 8949. 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." 8 | 9 | This implementation was written by Peter O. and is released to the Public Domain under the [CC0 Declaration](https://creativecommons.org/publicdomain/zero/1.0/). 10 | 11 | This implementation also doubles as a reader and writer of JSON, and can convert data from JSON to CBOR and back. 12 | 13 | Finally, this implementation supports arbitrary-precision binary and decimal floating-point numbers and rational numbers with arbitrary-precision components. 14 | 15 | ## How to Install 16 | 17 | Starting with version 0.23.0, the Java implementation is available 18 | 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 19 | project, add the following to the `dependencies` section in your `pom.xml` file: 20 | 21 | ```xml 22 | 23 | com.upokecenter 24 | cbor 25 | 5.0.0-alpha2 26 | 27 | ``` 28 | 29 | In other Java-based environments, the library can be referred to by its 30 | group ID (`com.upokecenter`), artifact ID (`cbor`), and version, as given earlier. A nonrelease version of this library is `5.0.0-alpha` rather than the version number given earlier. 31 | 32 | ## Documentation 33 | 34 | This library defines one class, called CBORObject, that allows you to read and 35 | write CBOR objects to and from data streams and byte arrays, and to convert JSON 36 | text to CBOR objects and back. 37 | 38 | **See the [Java API documentation](https://peteroupc.github.io/CBOR/api/).** 39 | 40 | ## Examples 41 | 42 | Reading data from a file. 43 | 44 | ```java 45 | // Java 46 | // Open the file stream 47 | try (FileInputStream stream = new FileInputStream("object.cbor")) { 48 | // Read the CBOR object from the stream 49 | var cbor = CBORObject.Read(stream); 50 | // At this point, the object is read, but the file stream might 51 | // not have ended yet. Here, the code may choose to read another 52 | // CBOR object, check for the end of the stream, or just ignore the 53 | // rest of the file. The following is an example of checking for the 54 | // end of the stream. 55 | if (stream.getChannel().position() != stream.getChannel().size()) { 56 | // The end of the stream wasn't reached yet. 57 | } else { 58 | // The end of the stream was reached. 59 | } 60 | } 61 | ``` 62 | 63 | Writing multiple objects to a file, including arbitrary objects: 64 | 65 | ```java 66 | // Java 67 | // This example uses the "try-with-resources" statement from Java 7. 68 | // This example writes different kinds of objects in CBOR 69 | // format to the same file. 70 | try (FileOutputStream stream = new FileOutputStream("object.cbor")) { 71 | CBORObject.Write(true, stream); 72 | CBORObject.Write(422.5, stream); 73 | CBORObject.Write("some string", stream); 74 | CBORObject.Write(CBORObject.Undefined, stream); 75 | CBORObject.NewArray().Add(42).WriteTo(stream); 76 | } 77 | ``` 78 | 79 | NOTE: All code samples in this section are released to the Public Domain, 80 | as explained in . 81 | 82 | ## Source Code 83 | 84 | Source code is available in the [project page](https://github.com/peteroupc/CBOR-Java). 85 | 86 | ## About 87 | 88 | Written in 2013-2016 by Peter O. 89 | 90 | Any copyright to this work is released to the Public Domain. 91 | In case this is not possible, this work is also 92 | licensed under the Unlicense: [https://unlicense.org/](https://unlicense.org/) 93 | 94 | ## Signing Key 95 | 96 | Release versions, in the Central Repository, of the Java version of this library are signed with the following signing key. 97 | 98 | - ID: `Peter Occil (Maven key) ` 99 | - Fingerprint: 1A82D51407003717A4171AAC87522D618F2B2338 100 | 101 | ## Release Notes 102 | 103 | For release notes, see the [CBOR .NET repository](https://github.com/peteroupc/CBOR). 104 | 105 | The [commit history](https://github.com/peteroupc/CBOR-Java/commits/master) 106 | contains details on code changes in previous versions. 107 | 108 | ## Acknowledgments 109 | 110 | For acknowledgments, see the [CBOR .NET repository](https://github.com/peteroupc/CBOR). 111 | 112 | I thank all users who sent issues to this repository. 113 | -------------------------------------------------------------------------------- /api/Home.md: -------------------------------------------------------------------------------- 1 | # API Documentation 2 | -------------------------------------------------------------------------------- /api/com.upokecenter.cbor.CBORDateConverter.ConversionType.md: -------------------------------------------------------------------------------- 1 | # com.upokecenter.cbor.CBORDateConverter.ConversionType 2 | 3 | public static enum CBORDateConverter.ConversionType extends Enum 4 | 5 | Conversion type for date-time conversion. 6 | 7 | ## Nested Classes 8 | 9 | ## Enum Constants 10 | 11 | * `TaggedNumber `
12 | FromCBORObject accepts objects with tag 0 (date/time strings) and tag 1 13 | (number of seconds since the start of 1970), and ToCBORObject converts 14 | date/time objects to CBOR objects of tag 1. 15 | 16 | * `TaggedString `
17 | FromCBORObject accepts CBOR objects with tag 0 (date/time strings) and tag 1 18 | (number of seconds since the start of 1970), and ToCBORObject converts 19 | date/time objects to CBOR objects of tag 0. 20 | 21 | * `UntaggedNumber `
22 | FromCBORObject accepts untagged CBOR integer or CBOR floating-point objects 23 | that give the number of seconds since the start of 1970, and ToCBORObject 24 | converts date/time objects (java.util.Date in DotNet, and Date in Java) to such 25 | untagged CBOR objects. 26 | 27 | ## Methods 28 | 29 | * `static CBORDateConverter.ConversionType valueOf(String name)`
30 | Returns the enum constant of this class with the specified name. 31 | 32 | * `static CBORDateConverter.ConversionType[] values()`
33 | Returns an array containing the constants of this enum class, in 34 | the order they are declared. 35 | 36 | ## Method Details 37 | 38 | ### values 39 | 40 | public static CBORDateConverter.ConversionType[] values() 41 | 42 | ### valueOf 43 | 44 | public static CBORDateConverter.ConversionType valueOf(String name) 45 | -------------------------------------------------------------------------------- /api/com.upokecenter.cbor.CBORException.md: -------------------------------------------------------------------------------- 1 | # com.upokecenter.cbor.CBORException 2 | 3 | public final class CBORException extends RuntimeException 4 | 5 |

Exception thrown for errors involving CBOR data.

This library may 6 | throw exceptions of this type in certain cases, notably when errors occur, 7 | and may supply messages to those exceptions (the message can be accessed 8 | through the Message property in.NET or the getMessage() 9 | method in Java). These messages are intended to be read by humans to help 10 | diagnose the error (or other cause of the exception); they are not intended 11 | to be parsed by computer programs, and the exact text of the messages may 12 | change at any time between versions of this library.

13 | 14 | ## Constructors 15 | 16 | ## Methods 17 | -------------------------------------------------------------------------------- /api/com.upokecenter.cbor.CBORNumber.NumberKind.md: -------------------------------------------------------------------------------- 1 | # com.upokecenter.cbor.CBORNumber.NumberKind 2 | 3 | public static enum CBORNumber.NumberKind extends Enum 4 | 5 | Specifies the underlying form of this CBOR number object. 6 | 7 | ## Nested Classes 8 | 9 | ## Enum Constants 10 | 11 | * `Double `
12 | A 64-bit binary floating-point number. 13 | 14 | * `EDecimal `
15 | An arbitrary-precision decimal number. 16 | 17 | * `EFloat `
18 | An arbitrary-precision binary number. 19 | 20 | * `EInteger `
21 | An arbitrary-precision integer. 22 | 23 | * `ERational `
24 | An arbitrary-precision rational number. 25 | 26 | * `Integer `
27 | A 64-bit signed integer. 28 | 29 | ## Methods 30 | 31 | * `static CBORNumber.NumberKind valueOf(String name)`
32 | Returns the enum constant of this class with the specified name. 33 | 34 | * `static CBORNumber.NumberKind[] values()`
35 | Returns an array containing the constants of this enum class, in 36 | the order they are declared. 37 | 38 | ## Method Details 39 | 40 | ### values 41 | 42 | public static CBORNumber.NumberKind[] values() 43 | 44 | ### valueOf 45 | 46 | public static CBORNumber.NumberKind valueOf(String name) 47 | -------------------------------------------------------------------------------- /api/com.upokecenter.cbor.CBORType.md: -------------------------------------------------------------------------------- 1 | # com.upokecenter.cbor.CBORType 2 | 3 | public enum CBORType extends Enum 4 | 5 | Represents a type that a CBOR object can have. 6 | 7 | ## Nested Classes 8 | 9 | ## Enum Constants 10 | 11 | * `Array `
12 | An array of CBOR objects. 13 | 14 | * `Boolean `
15 | The simple values true and false. 16 | 17 | * `ByteString `
18 | An array of bytes. 19 | 20 | * `FloatingPoint `
21 | A 16-, 32-, or 64-bit binary floating-point number. 22 | 23 | * `Integer `
24 | An integer in the interval [-(2^64), 2^64 - 1], or an integer of major type 25 | 0 and 1. 26 | 27 | * `Map `
28 | A map of CBOR objects. 29 | 30 | * `Number `
31 | Deprecated. 32 | Since version 4.0, CBORObject.Type no longer returns this value for any 33 | CBOR Object - this is a breaking change from earlier 34 | versions. 35 | 36 | * `SimpleValue `
37 | A "simple value" other than floating point values, true, and false. 38 | 39 | * `TextString `
40 | A text string. 41 | 42 | ## Methods 43 | 44 | * `static CBORType valueOf(String name)`
45 | Returns the enum constant of this class with the specified name. 46 | 47 | * `static CBORType[] values()`
48 | Returns an array containing the constants of this enum class, in 49 | the order they are declared. 50 | 51 | ## Method Details 52 | 53 | ### values 54 | 55 | public static CBORType[] values() 56 | 57 | ### valueOf 58 | 59 | public static CBORType valueOf(String name) 60 | -------------------------------------------------------------------------------- /api/com.upokecenter.cbor.CBORTypeMapper.md: -------------------------------------------------------------------------------- 1 | # com.upokecenter.cbor.CBORTypeMapper 2 | 3 | public final class CBORTypeMapper extends Object 4 | 5 | Holds converters to customize the serialization and deserialization behavior 6 | of CBORObject.FromObject and CBORObject#ToObject, as well as 7 | type filters for ToObject. 8 | 9 | ## Constructors 10 | 11 | ## Methods 12 | 13 | * ` CBORTypeMapper AddConverter(Type type, 14 | ICBORConverter converter)`
15 | Registers an object that converts objects of a given type to CBOR objects 16 | (called a CBOR converter). 17 | 18 | * `CBORTypeMapper AddTypeName(String name)`
19 | Adds the fully qualified name of a Java or.NET type for use in type 20 | matching. 21 | 22 | * `CBORTypeMapper AddTypePrefix(String prefix)`
23 | Adds a prefix of a Java or.NET type for use in type matching. 24 | 25 | * `boolean FilterTypeName(String typeName)`
26 | Returns whether the specified Java or.NET type name fits the filters given 27 | in this mapper. 28 | 29 | ## Method Details 30 | 31 | ### AddConverter 32 | 33 | public CBORTypeMapper AddConverter(Type type, ICBORConverter converter) 34 | 35 | Registers an object that converts objects of a given type to CBOR objects 36 | (called a CBOR converter). If the CBOR converter converts to and from CBOR 37 | objects, it should implement the ICBORToFromConverter interface and provide 38 | ToCBORObject and FromCBORObject methods. If the CBOR converter only supports 39 | converting to (not from) CBOR objects, it should implement the 40 | ICBORConverter interface and provide a ToCBORObject method. 41 | 42 | **Type Parameters:** 43 | 44 | * T - Must be the same as the "type" parameter. 45 | 46 | **Parameters:** 47 | 48 | * type - A Type object specifying the type that the converter converts to 49 | CBOR objects. 50 | 51 | * converter - The parameter converter is an ICBORConverter 52 | object. 53 | 54 | **Returns:** 55 | 56 | * This object. 57 | 58 | **Throws:** 59 | 60 | * NullPointerException - The parameter type or 61 | converter is null. 62 | 63 | * IllegalArgumentException - Converter doesn't contain a proper ToCBORObject 64 | method". 65 | 66 | ### FilterTypeName 67 | 68 | public boolean FilterTypeName(String typeName) 69 | 70 | Returns whether the specified Java or.NET type name fits the filters given 71 | in this mapper. 72 | 73 | **Parameters:** 74 | 75 | * typeName - The fully qualified name of a Java or.NET class (for 76 | example, java.math.BigInteger or 77 | System.Globalization.CultureInfo). 78 | 79 | **Returns:** 80 | 81 | * Either true if the specified Java or.NET type name fits the 82 | filters given in this mapper, or false otherwise. 83 | 84 | ### AddTypePrefix 85 | 86 | public CBORTypeMapper AddTypePrefix(String prefix) 87 | 88 | Adds a prefix of a Java or.NET type for use in type matching. A type matches 89 | a prefix if its fully qualified name is or begins with that prefix, using 90 | codepoint-by-codepoint (case-sensitive) matching. 91 | 92 | **Parameters:** 93 | 94 | * prefix - The prefix of a Java or.NET type (for example, `java.math.` or 95 | `System.Globalization`). 96 | 97 | **Returns:** 98 | 99 | * This object. 100 | 101 | **Throws:** 102 | 103 | * NullPointerException - The parameter prefix is null. 104 | 105 | * IllegalArgumentException - The parameter prefix is empty. 106 | 107 | ### AddTypeName 108 | 109 | public CBORTypeMapper AddTypeName(String name) 110 | 111 | Adds the fully qualified name of a Java or.NET type for use in type 112 | matching. 113 | 114 | **Parameters:** 115 | 116 | * name - The fully qualified name of a Java or.NET class (for example, 117 | java.math.BigInteger or System.Globalization.CultureInfo). 118 | 119 | **Returns:** 120 | 121 | * This object. 122 | 123 | **Throws:** 124 | 125 | * NullPointerException - The parameter name is null. 126 | 127 | * IllegalArgumentException - The parameter name is empty. 128 | -------------------------------------------------------------------------------- /api/com.upokecenter.cbor.ICBORConverter.md: -------------------------------------------------------------------------------- 1 | # com.upokecenter.cbor.ICBORConverter 2 | 3 | public interface ICBORConverter 4 | 5 | Interface implemented by classes that convert objects of arbitrary types to 6 | CBOR objects. 7 | 8 | ## Methods 9 | 10 | * `CBORObject ToCBORObject(T obj)`
11 | Converts an object to a CBOR object. 12 | 13 | ## Method Details 14 | 15 | ### ToCBORObject 16 | 17 | CBORObject ToCBORObject(T obj) 18 | 19 | Converts an object to a CBOR object. 20 | 21 | **Parameters:** 22 | 23 | * obj - An object to convert to a CBOR object. 24 | 25 | **Returns:** 26 | 27 | * A CBOR object. 28 | -------------------------------------------------------------------------------- /api/com.upokecenter.cbor.ICBORToFromConverter.md: -------------------------------------------------------------------------------- 1 | # com.upokecenter.cbor.ICBORToFromConverter 2 | 3 | public interface ICBORToFromConverter extends ICBORConverter 4 | 5 | Classes that implement this interface can support conversions from CBOR 6 | objects to a custom type and back. 7 | 8 | ## Methods 9 | 10 | * `T FromCBORObject(CBORObject obj)`
11 | Converts a CBOR object to a custom type. 12 | 13 | ## Method Details 14 | 15 | ### FromCBORObject 16 | 17 | T FromCBORObject(CBORObject obj) 18 | 19 | Converts a CBOR object to a custom type. 20 | 21 | **Parameters:** 22 | 23 | * obj - A CBOR object to convert to the custom type. 24 | 25 | **Returns:** 26 | 27 | * An object of the custom type after conversion. 28 | -------------------------------------------------------------------------------- /api/com.upokecenter.cbor.JSONOptions.ConversionMode.md: -------------------------------------------------------------------------------- 1 | # com.upokecenter.cbor.JSONOptions.ConversionMode 2 | 3 | public static enum JSONOptions.ConversionMode extends Enum 4 | 5 | Specifies how JSON numbers are converted to CBOR objects when decoding JSON 6 | (such as via FromJSONString or ReadJSON). None of these 7 | conversion modes affects how CBOR objects are later encoded (such as via 8 | EncodeToBytes). 9 | 10 | ## Nested Classes 11 | 12 | ## Enum Constants 13 | 14 | * `Decimal128 `
15 | JSON numbers are decoded to CBOR as their closest-rounded approximation to 16 | an IEEE 854 decimal128 value, using the round-to-nearest/ties-to-even 17 | rounding mode and the rules for the EDecimal form of that approximation as 18 | given in the CBORObject.FromObject(EDecimal) method. 19 | 20 | * `Double `
21 | JSON numbers are decoded to CBOR as their closest-rounded approximation 22 | as 64-bit binary floating-point numbers (using the 23 | round-to-nearest/ties-to-even rounding mode). 24 | 25 | * `Full `
26 | JSON numbers are decoded to CBOR using the full precision given in the JSON 27 | text. 28 | 29 | * `IntOrFloat `
30 | A JSON number is decoded to CBOR objects either as a CBOR integer (major 31 | type 0 or 1) if the JSON number represents an integer at least -(2^53)+1 and 32 | less than 2^53, or as their closest-rounded approximation as 64-bit binary 33 | floating-point numbers (using the round-to-nearest/ties-to-even rounding 34 | mode) otherwise. 35 | 36 | * `IntOrFloatFromDouble `
37 | A JSON number is decoded to CBOR objects either as a CBOR integer (major 38 | type 0 or 1) if the number's closest-rounded approximation as a 64-bit 39 | binary floating-point number (using the round-to-nearest/ties-to-even 40 | rounding mode) represents an integer at least -(2^53)+1 and less than 2^53, 41 | or as that approximation otherwise. 42 | 43 | ## Methods 44 | 45 | * `static JSONOptions.ConversionMode valueOf(String name)`
46 | Returns the enum constant of this class with the specified name. 47 | 48 | * `static JSONOptions.ConversionMode[] values()`
49 | Returns an array containing the constants of this enum class, in 50 | the order they are declared. 51 | 52 | ## Method Details 53 | 54 | ### values 55 | 56 | public static JSONOptions.ConversionMode[] values() 57 | 58 | ### valueOf 59 | 60 | public static JSONOptions.ConversionMode valueOf(String name) 61 | -------------------------------------------------------------------------------- /api/com.upokecenter.cbor.JSONOptions.md: -------------------------------------------------------------------------------- 1 | # com.upokecenter.cbor.JSONOptions 2 | 3 | public final class JSONOptions extends Object 4 | 5 | Includes options to control how CBOR objects are converted to and from 6 | JavaScript object Notation (JSON). 7 | 8 | ## Nested Classes 9 | 10 | * `static enum  JSONOptions.ConversionMode`
11 | Specifies how JSON numbers are converted to CBOR objects when decoding JSON 12 | (such as via FromJSONString or ReadJSON). 13 | 14 | ## Fields 15 | 16 | * `static final JSONOptions Default`
17 | The default options for converting CBOR objects to JSON. 18 | 19 | ## Constructors 20 | 21 | ## Methods 22 | 23 | * `final boolean getAllowDuplicateKeys()`
24 | Gets a value indicating whether to allow duplicate keys when reading JSON. 25 | 26 | * `final boolean getKeepKeyOrder()`
27 | Gets a value indicating whether to preserve the order in which a map's keys 28 | appear when decoding JSON, by using maps created as though by 29 | CBORObject.NewOrderedMap. 30 | 31 | * `final JSONOptions.ConversionMode getNumberConversion()`
32 | Gets a value indicating how JSON numbers are decoded to CBOR objects. 33 | 34 | * `final boolean getPreserveNegativeZero()`
35 | Gets a value indicating whether the JSON decoder should preserve the 36 | distinction between positive zero and negative zero when the decoder decodes 37 | JSON to a floating-point number format that makes this distinction. 38 | 39 | * `final boolean getReplaceSurrogates()`
40 | Gets a value indicating whether surrogate code points not part of a 41 | surrogate pair (which consists of two consecutive char s forming one 42 | Unicode code point) are each replaced with a replacement character (U+FFFD). 43 | 44 | * `final boolean getWriteBasic()`
45 | Gets a value indicating whether JSON is written using only code points from 46 | the Basic Latin block (U+0000 to U+007F), also known as ASCII. 47 | 48 | * `String toString()`
49 | Gets the values of this options object's properties in text form. 50 | 51 | ## Field Details 52 | 53 | ### Default 54 | 55 | public static final JSONOptions Default 56 | 57 | The default options for converting CBOR objects to JSON. 58 | 59 | ## Method Details 60 | 61 | ### toString 62 | 63 | public String toString() 64 | 65 | Gets the values of this options object's properties in text form. 66 | 67 | **Overrides:** 68 | 69 | * toString in class Object 70 | 71 | **Returns:** 72 | 73 | * A text string containing the values of this options object's 74 | properties. The format of the string is the same as the one described in the 75 | string constructor for this class. 76 | 77 | ### getPreserveNegativeZero 78 | 79 | public final boolean getPreserveNegativeZero() 80 | 81 | Gets a value indicating whether the JSON decoder should preserve the 82 | distinction between positive zero and negative zero when the decoder decodes 83 | JSON to a floating-point number format that makes this distinction. For a 84 | value of false, if the result of parsing a JSON string would be a 85 | floating-point negative zero, that result is a positive zero instead. (Note 86 | that this property has no effect for conversion kind 87 | IntOrFloatFromDouble, where floating-point zeros are not possible.). 88 | 89 | **Returns:** 90 | 91 | * A value indicating whether to preserve the distinction between 92 | positive zero and negative zero when decoding JSON. The default is true. 93 | 94 | ### getNumberConversion 95 | 96 | public final JSONOptions.ConversionMode getNumberConversion() 97 | 98 | Gets a value indicating how JSON numbers are decoded to CBOR objects. None 99 | of the conversion modes affects how CBOR objects are later encoded (such as 100 | via EncodeToBytes). 101 | 102 | **Returns:** 103 | 104 | * A value indicating how JSON numbers are decoded to CBOR. The default 105 | is ConversionMode.Full. 106 | 107 | ### getWriteBasic 108 | 109 | public final boolean getWriteBasic() 110 | 111 | Gets a value indicating whether JSON is written using only code points from 112 | the Basic Latin block (U+0000 to U+007F), also known as ASCII. 113 | 114 | **Returns:** 115 | 116 | * A value indicating whether JSON is written using only code points 117 | from the Basic Latin block (U+0000 to U+007F), also known as ASCII. Default 118 | is false. 119 | 120 | ### getKeepKeyOrder 121 | 122 | public final boolean getKeepKeyOrder() 123 | 124 | Gets a value indicating whether to preserve the order in which a map's keys 125 | appear when decoding JSON, by using maps created as though by 126 | CBORObject.NewOrderedMap. If false, key order is not guaranteed to be 127 | preserved when decoding JSON. 128 | 129 | **Returns:** 130 | 131 | * A value indicating whether to preserve the order in which a CBOR 132 | map's keys appear when decoding JSON. The default is false. 133 | 134 | ### getAllowDuplicateKeys 135 | 136 | public final boolean getAllowDuplicateKeys() 137 | 138 | Gets a value indicating whether to allow duplicate keys when reading JSON. 139 | Used only when decoding JSON. If this property is true and a JSON 140 | object has two or more values with the same key, the last value of that key 141 | set forth in the JSON object is taken. 142 | 143 | **Returns:** 144 | 145 | * A value indicating whether to allow duplicate keys when reading 146 | JSON. The default is false. 147 | 148 | ### getReplaceSurrogates 149 | 150 | public final boolean getReplaceSurrogates() 151 | 152 | Gets a value indicating whether surrogate code points not part of a 153 | surrogate pair (which consists of two consecutive char s forming one 154 | Unicode code point) are each replaced with a replacement character (U+FFFD). 155 | If false, an exception is thrown when such code points are encountered. 156 | 157 | **Returns:** 158 | 159 | * True, if surrogate code points not part of a surrogate pair are each 160 | replaced with a replacement character, or false if an exception is thrown 161 | when such code points are encountered. The default is false. 162 | -------------------------------------------------------------------------------- /api/com.upokecenter.cbor.PODOptions.md: -------------------------------------------------------------------------------- 1 | # com.upokecenter.cbor.PODOptions 2 | 3 | public class PODOptions extends Object 4 | 5 | Options for controlling how certain DotNET or Java objects, such as 6 | so-called "plain old data" objects (better known as POCOs in DotNET or POJOs 7 | in Java), are converted to CBOR objects. 8 | 9 | ## Fields 10 | 11 | * `static final PODOptions Default`
12 | The default settings for "plain old data" options. 13 | 14 | ## Constructors 15 | 16 | ## Methods 17 | 18 | * `final boolean getUseCamelCase()`
19 | Gets a value indicating whether property, field, and method names are 20 | converted to camel case before they are used as keys. 21 | 22 | * `String toString()`
23 | Gets the values of this options object's properties in text form. 24 | 25 | ## Field Details 26 | 27 | ### Default 28 | 29 | public static final PODOptions Default 30 | 31 | The default settings for "plain old data" options. 32 | 33 | ## Method Details 34 | 35 | ### toString 36 | 37 | public String toString() 38 | 39 | Gets the values of this options object's properties in text form. 40 | 41 | **Overrides:** 42 | 43 | * toString in class Object 44 | 45 | **Returns:** 46 | 47 | * A text string containing the values of this options object's 48 | properties. The format of the string is the same as the one described in the 49 | string constructor for this class. 50 | 51 | ### getUseCamelCase 52 | 53 | public final boolean getUseCamelCase() 54 | 55 |

Gets a value indicating whether property, field, and method names are 56 | converted to camel case before they are used as keys. This option changes 57 | the behavior of key name serialization as follows. If "useCamelCase" is 58 | false :

  • In the .NET version, all key names are 59 | capitalized, meaning the first letter in the name is converted to a basic 60 | uppercase letter if it's a basic lowercase letter ("a" to "z"). (For 61 | example, "Name" and "IsName" both remain unchanged.)
  • In the Java 62 | version, all field names are capitalized, and for each eligible method name, 63 | the word "get" or "set" is removed from the name if the name starts with 64 | that word, then the name is capitalized. (For example, "getName" and 65 | "setName" both become "Name", and "isName" becomes "IsName".)
66 |

If "useCamelCase" is true :

  • In the .NET version, for 67 | each eligible property or field name, the word "Is" is removed from the name 68 | if the name starts with that word, then the name is converted to camel case, 69 | meaning the first letter in the name is converted to a basic lowercase 70 | letter if it's a basic uppercase letter ("A" to "Z"). (For example, "Name" 71 | and "IsName" both become "name", and "IsIsName" becomes 72 | "isName".)
  • In the Java version: For each eligible method name, the 73 | word "get", "set", or "is" is removed from the name if the name starts with 74 | that word, then the name is converted to camel case. (For example, 75 | "getName", "setName", and "isName" all become "name".) For each eligible 76 | field name, the word "is" is removed from the name if the name starts with 77 | that word, then the name is converted to camel case. (For example, "name" 78 | and "isName" both become "name".)

In the description above, a 79 | name "starts with" a word if that word begins the name and is followed by a 80 | character other than a basic digit or basic lowercase letter, that is, other 81 | than "a" to "z" or "0" to "9".

82 | 83 | **Returns:** 84 | 85 | * true If the names are converted to camel case; otherwise, 86 | false. This property is true by default. 87 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | com.upokecenter 5 | cbor 6 | jar 7 | 5.0.0-alpha2 8 | CBOR (Concise Binary Object Representation) 9 | A Java implementation of Concise Binary Object Representation (CBOR), a general-purpose binary data format defined in RFC 8949. 10 | https://github.com/peteroupc/CBOR-Java 11 | 12 | 13 | release 14 | 15 | 16 | 17 | org.apache.maven.plugins 18 | maven-gpg-plugin 19 | 1.5 20 | 21 | 22 | sign-artifacts 23 | verify 24 | 25 | sign 26 | 27 | 28 | 29 | 30 | 31 | org.apache.maven.plugins 32 | maven-javadoc-plugin 33 | 3.0.1 34 | 35 | CBOR for Java documentation, generated in {currentYear}. 36 | 37 | -html5 38 | 39 | 40 | 41 | 42 | 43 | attach-javadocs 44 | 45 | jar 46 | 47 | 48 | 49 | 50 | 51 | org.apache.maven.plugins 52 | maven-source-plugin 53 | 2.2.1 54 | 55 | 56 | attach-sources 57 | 58 | jar-no-fork 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | scm:git:https://github.com/peteroupc/CBOR-Java 69 | scm:git:https://github.com/peteroupc/CBOR-Java.git 70 | https://github.com/peteroupc/CBOR-Java 71 | 72 | 73 | 74 | Anders Gustaffson 75 | 76 | 77 | 78 | 79 | Peter Occil 80 | poccil14@gmail.com 81 | 82 | 83 | 84 | UTF-8 85 | 8 86 | 1.8 87 | 88 | 89 | 90 | Unlicense 91 | repo 92 | http://www.creativecommons.org/publicdomain/zero/1.0/ 93 | 94 | 95 | 96 | 97 | 98 | org.apache.maven.plugins 99 | maven-compiler-plugin 100 | 3.7.0 101 | 102 | 103 | -Xlint:all 104 | 105 | 106 | 107 | 108 | org.sonatype.plugins 109 | nexus-staging-maven-plugin 110 | true 111 | 1.6.13 112 | 113 | ossrh 114 | true 115 | https://oss.sonatype.org/ 116 | 117 | 118 | 119 | 120 | 121 | 122 | ossrh 123 | https://oss.sonatype.org/content/repositories/snapshots 124 | 125 | 126 | ossrh 127 | https://oss.sonatype.org/service/local/staging/deploy/maven2/ 128 | 129 | 130 | 131 | 132 | junit 133 | junit 134 | 4.13.1 135 | test 136 | 137 | 138 | com.github.peteroupc 139 | numbers 140 | 1.8.2 141 | 142 | 143 | com.github.peteroupc 144 | uriutility 145 | 1.0.1 146 | 147 | 148 | com.github.peteroupc 149 | datautilities 150 | 1.1.0 151 | 152 | 153 | 154 | 155 | -------------------------------------------------------------------------------- /src/main/java/com/upokecenter/cbor/Base64.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.cbor; 2 | /* 3 | Written by Peter O. 4 | Any copyright to this work is released to the Public Domain. 5 | In case this is not possible, this work is also 6 | licensed under the Unlicense: https://unlicense.org/ 7 | 8 | */ 9 | 10 | final class Base64 { 11 | private Base64() { 12 | } 13 | private static final String Base64URL = 14 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; 15 | 16 | private static final String Base64Classic = 17 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 18 | 19 | public static void WriteBase64( 20 | StringOutput writer, 21 | byte[] data, 22 | int offset, 23 | int count, 24 | boolean padding) throws java.io.IOException { 25 | WriteBase64(writer, data, offset, count, true, padding); 26 | } 27 | 28 | public static void WriteBase64URL( 29 | StringOutput writer, 30 | byte[] data, 31 | int offset, 32 | int count, 33 | boolean padding) throws java.io.IOException { 34 | WriteBase64(writer, data, offset, count, false, padding); 35 | } 36 | 37 | private static void WriteBase64( 38 | StringOutput writer, 39 | byte[] data, 40 | int offset, 41 | int count, 42 | boolean classic, 43 | boolean padding) throws java.io.IOException { 44 | if (writer == null) { 45 | throw new NullPointerException("writer"); 46 | } 47 | if (offset < 0) { 48 | throw new IllegalArgumentException("offset(" + offset + ") is less than " + 49 | "0 "); 50 | } 51 | if (offset > data.length) { 52 | throw new IllegalArgumentException("offset(" + offset + ") is more than " + 53 | data.length); 54 | } 55 | if (count < 0) { 56 | throw new IllegalArgumentException("count(" + count + ") is less than " + 57 | "0 "); 58 | } 59 | if (count > data.length) { 60 | throw new IllegalArgumentException("count(" + count + ") is more than " + 61 | data.length); 62 | } 63 | if (data.length - offset < count) { 64 | throw new IllegalArgumentException("data's length minus " + offset + "(" + 65 | (data.length - offset) + ") is less than " + count); 66 | } 67 | String alphabet = classic ? Base64Classic : Base64URL; 68 | int length = offset + count; 69 | byte[] buffer = new byte[32]; 70 | int bufferOffset = 0; 71 | int i; 72 | for (i = offset; i < (length - 2); i += 3) { 73 | if (bufferOffset >= buffer.length) { 74 | writer.WriteAscii(buffer, 0, bufferOffset); 75 | bufferOffset = 0; 76 | } 77 | buffer[bufferOffset++] = (byte)alphabet.charAt((data[i] >> 2) & 63); 78 | buffer[bufferOffset++] = (byte)alphabet.charAt(((data[i] & 3) << 4) + 79 | ((data[i + 1] >> 4) & 15)); 80 | buffer[bufferOffset++] = (byte)alphabet.charAt(((data[i + 1] & 15) << 2) + 81 | ((data[i + 2] >> 6) & 3)); 82 | buffer[bufferOffset++] = (byte)alphabet.charAt(data[i + 2] & 63); 83 | } 84 | int lenmod3 = count % 3; 85 | if (lenmod3 != 0) { 86 | if (bufferOffset >= buffer.length) { 87 | writer.WriteAscii(buffer, 0, bufferOffset); 88 | bufferOffset = 0; 89 | } 90 | i = length - lenmod3; 91 | buffer[bufferOffset++] = (byte)alphabet.charAt((data[i] >> 2) & 63); 92 | if (lenmod3 == 2) { 93 | buffer[bufferOffset++] = (byte)alphabet.charAt(((data[i] & 3) << 4) + 94 | ((data[i + 1] >> 4) & 15)); 95 | buffer[bufferOffset++] = (byte)alphabet.charAt((data[i + 1] & 15) << 2); 96 | if (padding) { 97 | buffer[bufferOffset++] = (byte)'='; 98 | } 99 | } else { 100 | buffer[bufferOffset++] = (byte)alphabet.charAt((data[i] & 3) << 4); 101 | if (padding) { 102 | buffer[bufferOffset++] = (byte)'='; 103 | buffer[bufferOffset++] = (byte)'='; 104 | } 105 | } 106 | } 107 | if (bufferOffset >= 0) { 108 | writer.WriteAscii(buffer, 0, bufferOffset); 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/main/java/com/upokecenter/cbor/CBORCanonical.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.cbor; 2 | 3 | import java.util.*; 4 | import java.io.*; 5 | 6 | final class CBORCanonical { 7 | private CBORCanonical() { 8 | } 9 | static final Comparator Comparer = 10 | new CtapComparer(); 11 | 12 | private static final Comparator> 13 | ByteComparer = new CtapByteComparer(); 14 | 15 | private static final class CtapByteComparer implements Comparator> 17 | { 18 | public int compare( 19 | Map.Entry kva, 20 | Map.Entry kvb) { 21 | byte[] bytesA = kva.getKey(); 22 | byte[] bytesB = kvb.getKey(); 23 | if (bytesA == null) { 24 | return bytesB == null ? 0 : -1; 25 | } 26 | if (bytesB == null) { 27 | return 1; 28 | } 29 | if (bytesA.length == 0) { 30 | return bytesB.length == 0 ? 0 : -1; 31 | } 32 | if (bytesB.length == 0) { 33 | return 1; 34 | } 35 | if (bytesA == bytesB) { 36 | // NOTE: Assumes reference equality of CBORObjects 37 | return 0; 38 | } 39 | // check major types 40 | if ((bytesA[0] & 0xe0) != (bytesB[0] & 0xe0)) { 41 | return (bytesA[0] & 0xe0) < (bytesB[0] & 0xe0) ? -1 : 1; 42 | } 43 | // check lengths 44 | if (bytesA.length != bytesB.length) { 45 | return bytesA.length < bytesB.length ? -1 : 1; 46 | } 47 | // check bytes 48 | for (int i = 0; i < bytesA.length; ++i) { 49 | if (bytesA[i] != bytesB[i]) { 50 | int ai = bytesA[i] & 0xff; 51 | int bi = bytesB[i] & 0xff; 52 | return (ai < bi) ? -1 : 1; 53 | } 54 | } 55 | return 0; 56 | } 57 | } 58 | 59 | private static final class CtapComparer implements Comparator 60 | { 61 | private static int MajorType(CBORObject a) { 62 | if (a.isTagged()) { 63 | return 6; 64 | } 65 | switch (a.getType()) { 66 | case Integer: 67 | return a.AsNumber().IsNegative() ? 1 : 0; 68 | case SimpleValue: 69 | case Boolean: 70 | case FloatingPoint: 71 | return 7; 72 | case ByteString: 73 | return 2; 74 | case TextString: 75 | return 3; 76 | case Array: 77 | return 4; 78 | case Map: 79 | return 5; 80 | default: throw new IllegalStateException(); 81 | } 82 | } 83 | 84 | public int compare(CBORObject a, CBORObject b) { 85 | if (a == null) { 86 | return b == null ? 0 : -1; 87 | } 88 | if (b == null) { 89 | return 1; 90 | } 91 | if (a == b) { 92 | // NOTE: Assumes reference equality of CBORObjects 93 | return 0; 94 | } 95 | a = a.Untag(); 96 | b = b.Untag(); 97 | byte[] abs; 98 | byte[] bbs; 99 | int amt = MajorType(a); 100 | int bmt = MajorType(b); 101 | if (amt != bmt) { 102 | return amt < bmt ? -1 : 1; 103 | } 104 | // System.out.println("a="+a); 105 | // System.out.println("b="+b); 106 | if (amt == 2) { 107 | // Both objects are byte strings 108 | abs = a.GetByteString(); 109 | bbs = b.GetByteString(); 110 | } else { 111 | // Might store arrays or maps, where 112 | // canonical encoding can fail due to too-deep 113 | // nesting 114 | abs = CtapCanonicalEncode(a); 115 | bbs = CtapCanonicalEncode(b); 116 | } 117 | if (abs.length != bbs.length) { 118 | // different lengths 119 | return abs.length < bbs.length ? -1 : 1; 120 | } 121 | for (int i = 0; i < abs.length; ++i) { 122 | if (abs[i] != bbs[i]) { 123 | int ai = abs[i] & 0xff; 124 | int bi = bbs[i] & 0xff; 125 | return (ai < bi) ? -1 : 1; 126 | } 127 | } 128 | return 0; 129 | } 130 | } 131 | 132 | private static boolean IsArrayOrMap(CBORObject a) { 133 | return a.getType() == CBORType.Array || a.getType() == CBORType.Map; 134 | } 135 | 136 | public static byte[] CtapCanonicalEncode(CBORObject a) { 137 | return CtapCanonicalEncode(a, 0); 138 | } 139 | 140 | private static boolean ByteArraysEqual(byte[] bytesA, byte[] bytesB) { 141 | if (bytesA == bytesB) { 142 | return true; 143 | } 144 | if (bytesA == null || bytesB == null) { 145 | return false; 146 | } 147 | if (bytesA.length == bytesB.length) { 148 | for (int j = 0; j < bytesA.length; ++j) { 149 | if (bytesA[j] != bytesB[j]) { 150 | return false; 151 | } 152 | } 153 | return true; 154 | } 155 | return false; 156 | } 157 | 158 | private static void CheckDepth(CBORObject cbor, int depth) { 159 | if (cbor.getType() == CBORType.Array) { 160 | for (int i = 0; i < cbor.size(); ++i) { 161 | if (depth >= 3 && IsArrayOrMap(cbor.get(i))) { 162 | throw new CBORException("Nesting level too deep"); 163 | } 164 | CheckDepth(cbor.get(i), depth + 1); 165 | } 166 | } else if (cbor.getType() == CBORType.Map) { 167 | for (CBORObject key : cbor.getKeys()) { 168 | if (depth >= 3 && (IsArrayOrMap(key) || IsArrayOrMap(cbor.get(key)))) { 169 | throw new CBORException("Nesting level too deep"); 170 | } 171 | CheckDepth(key, depth + 1); 172 | CheckDepth(cbor.get(key), depth + 1); 173 | } 174 | } 175 | } 176 | 177 | private static byte[] CtapCanonicalEncode(CBORObject a, int depth) { 178 | CBORObject cbor = a.Untag(); 179 | CBORType valueAType = cbor.getType(); 180 | try { 181 | if (valueAType == CBORType.Array) { 182 | { 183 | java.io.ByteArrayOutputStream ms = null; 184 | try { 185 | ms = new java.io.ByteArrayOutputStream(); 186 | 187 | CBORObject.WriteValue(ms, 4, cbor.size()); 188 | for (int i = 0; i < cbor.size(); ++i) { 189 | if (depth >= 3 && IsArrayOrMap(cbor.get(i))) { 190 | throw new CBORException("Nesting level too deep"); 191 | } 192 | byte[] bytes = CtapCanonicalEncode(cbor.get(i), depth + 1); 193 | ms.write(bytes, 0, bytes.length); 194 | } 195 | return ms.toByteArray(); 196 | } 197 | finally { 198 | try { if (ms != null) { ms.close(); } } catch (java.io.IOException ex) {} 199 | } 200 | } 201 | } else if (valueAType == CBORType.Map) { 202 | Map.Entry kv1; 203 | ArrayList> sortedKeys; 204 | sortedKeys = new ArrayList>(); 205 | for (CBORObject key : cbor.getKeys()) { 206 | if (depth >= 3 && (IsArrayOrMap(key) || IsArrayOrMap(cbor.get(key)))) { 207 | throw new CBORException("Nesting level too deep"); 208 | } 209 | CheckDepth(key, depth + 1); 210 | CheckDepth(cbor.get(key), depth + 1); 211 | // Check if key and value can be canonically encoded 212 | // (will throw an exception if they cannot) 213 | kv1 = new AbstractMap.SimpleImmutableEntry( 214 | CtapCanonicalEncode(key, depth + 1), 215 | CtapCanonicalEncode(cbor.get(key), depth + 1)); 216 | sortedKeys.add(kv1); 217 | } 218 | java.util.Collections.sort(sortedKeys, ByteComparer); 219 | { 220 | java.io.ByteArrayOutputStream ms = null; 221 | try { 222 | ms = new java.io.ByteArrayOutputStream(); 223 | 224 | CBORObject.WriteValue(ms, 5, cbor.size()); 225 | byte[] lastKey = null; 226 | for (int i = 0; i < sortedKeys.size(); ++i) { 227 | kv1 = sortedKeys.get(i); 228 | byte[] bytes = kv1.getKey(); 229 | if (lastKey != null && ByteArraysEqual(bytes, lastKey)) { 230 | throw new CBORException("duplicate canonical CBOR key"); 231 | } 232 | lastKey = bytes; 233 | ms.write(bytes, 0, bytes.length); 234 | bytes = kv1.getValue(); 235 | ms.write(bytes, 0, bytes.length); 236 | } 237 | return ms.toByteArray(); 238 | } 239 | finally { 240 | try { if (ms != null) { ms.close(); } } catch (java.io.IOException ex) {} 241 | } 242 | } 243 | } 244 | } catch (IOException ex) { 245 | throw new IllegalStateException(ex.toString(), ex); 246 | } 247 | if (valueAType == CBORType.SimpleValue || 248 | valueAType == CBORType.Boolean || valueAType == CBORType.ByteString || 249 | valueAType == CBORType.TextString) { 250 | return cbor.EncodeToBytes(CBOREncodeOptions.Default); 251 | } else if (valueAType == CBORType.FloatingPoint) { 252 | long bits = cbor.AsDoubleBits(); 253 | return new byte[] { 254 | (byte)0xfb, 255 | (byte)((bits >> 56) & 0xffL), 256 | (byte)((bits >> 48) & 0xffL), 257 | (byte)((bits >> 40) & 0xffL), 258 | (byte)((bits >> 32) & 0xffL), 259 | (byte)((bits >> 24) & 0xffL), 260 | (byte)((bits >> 16) & 0xffL), 261 | (byte)((bits >> 8) & 0xffL), 262 | (byte)(bits & 0xffL), 263 | }; 264 | } else { 265 | if (!(valueAType == CBORType.Integer)) { 266 | throw new IllegalArgumentException("Invalid CBOR type."); 267 | } 268 | return cbor.EncodeToBytes(CBOREncodeOptions.Default); 269 | } 270 | } 271 | } 272 | -------------------------------------------------------------------------------- /src/main/java/com/upokecenter/cbor/CBORDoubleBits.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.cbor; 2 | /* 3 | Written by Peter O. 4 | Any copyright to this work is released to the Public Domain. 5 | In case this is not possible, this work is also 6 | licensed under the Unlicense: https://unlicense.org/ 7 | 8 | */ 9 | 10 | import com.upokecenter.numbers.*; 11 | 12 | class CBORDoubleBits implements ICBORNumber { 13 | public boolean IsPositiveInfinity(Object obj) { 14 | return ((((Long)obj).longValue())) == (0x7ffL << 52); 15 | } 16 | 17 | public boolean IsInfinity(Object obj) { 18 | return (((((Long)obj).longValue())) & ~(1L << 63)) == (0x7ffL << 52); 19 | } 20 | 21 | public boolean IsNegativeInfinity(Object obj) { 22 | return ((((Long)obj).longValue())) == (0xfffL << 52); 23 | } 24 | 25 | public boolean IsNaN(Object obj) { 26 | return CBORUtilities.DoubleBitsNaN((((Long)obj).longValue())); 27 | } 28 | 29 | public double AsDouble(Object obj) { 30 | return CBORUtilities.Int64BitsToDouble((((Long)obj).longValue())); 31 | } 32 | 33 | public EDecimal AsEDecimal(Object obj) { 34 | return EDecimal.FromDoubleBits((((Long)obj).longValue())); 35 | } 36 | 37 | public EFloat AsEFloat(Object obj) { 38 | return EFloat.FromDoubleBits((((Long)obj).longValue())); 39 | } 40 | 41 | public float AsSingle(Object obj) { 42 | return CBORUtilities.Int32BitsToSingle( 43 | CBORUtilities.DoubleToRoundedSinglePrecision((((Long)obj).longValue()))); 44 | } 45 | 46 | public EInteger AsEInteger(Object obj) { 47 | return CBORUtilities.EIntegerFromDoubleBits((((Long)obj).longValue())); 48 | } 49 | 50 | public long AsInt64(Object obj) { 51 | if (this.IsNaN(obj) || this.IsInfinity(obj)) { 52 | throw new ArithmeticException("This Object's value is out of range"); 53 | } 54 | long b = DoubleBitsRoundDown((((Long)obj).longValue())); 55 | boolean neg = (b >> 63) != 0; 56 | b &= ~(1L << 63); 57 | if (b == 0) { 58 | return 0; 59 | } 60 | if (neg && b == (0x43eL << 52)) { 61 | return Long.MIN_VALUE; 62 | } 63 | if ((b >> 52) >= 0x43e) { 64 | throw new ArithmeticException("This Object's value is out of range"); 65 | } 66 | int exp = (int)(b >> 52); 67 | long mant = b & ((1L << 52) - 1); 68 | mant |= 1L << 52; 69 | int shift = 52 - (exp - 0x3ff); 70 | if (shift < 0) { 71 | mant <<= -shift; 72 | } else { 73 | mant >>= shift; 74 | } 75 | if (neg) { 76 | mant = -mant; 77 | } 78 | return mant; 79 | } 80 | 81 | public boolean CanFitInSingle(Object obj) { 82 | return this.IsNaN(obj) || 83 | CBORUtilities.DoubleRetainsSameValueInSingle((((Long)obj).longValue())); 84 | } 85 | 86 | public boolean CanFitInDouble(Object obj) { 87 | return true; 88 | } 89 | 90 | public boolean CanFitInInt32(Object obj) { 91 | return this.IsIntegral(obj) && this.CanTruncatedIntFitInInt32(obj); 92 | } 93 | 94 | public boolean CanFitInInt64(Object obj) { 95 | return this.IsIntegral(obj) && this.CanTruncatedIntFitInInt64(obj); 96 | } 97 | 98 | public boolean CanFitInUInt64(Object obj) { 99 | return this.IsIntegral(obj) && this.CanTruncatedIntFitInUInt64(obj); 100 | } 101 | 102 | private static long DoubleBitsRoundDown(long bits) { 103 | long origbits = bits; 104 | bits &= ~(1L << 63); 105 | if (bits == 0) { 106 | return origbits; 107 | } 108 | // Infinity and NaN 109 | if (bits >= (0x7ffL << 52)) { 110 | return origbits; 111 | } 112 | // Beyond noninteger range 113 | if ((bits >> 52) >= 0x433) { 114 | return origbits; 115 | } 116 | // Less than 1 117 | if ((bits >> 52) <= 0x3fe) { 118 | return (origbits >> 63) != 0 ? (1L << 63) : 0; 119 | } 120 | int exp = (int)(bits >> 52); 121 | long mant = bits & ((1L << 52) - 1); 122 | int shift = 52 - (exp - 0x3ff); 123 | return ((mant >> shift) << shift) | (origbits & (0xfffL << 52)); 124 | } 125 | 126 | public boolean CanTruncatedIntFitInInt64(Object obj) { 127 | if (this.IsNaN(obj) || this.IsInfinity(obj)) { 128 | return false; 129 | } 130 | long b = DoubleBitsRoundDown((((Long)obj).longValue())); 131 | boolean neg = (b >> 63) != 0; 132 | b &= ~(1L << 63); 133 | return (neg && b == (0x43eL << 52)) || ((b >> 52) < 0x43e); 134 | } 135 | 136 | public boolean CanTruncatedIntFitInUInt64(Object obj) { 137 | if (this.IsNaN(obj) || this.IsInfinity(obj)) { 138 | return false; 139 | } 140 | long b = DoubleBitsRoundDown((((Long)obj).longValue())); 141 | boolean neg = (b >> 63) != 0; 142 | b &= ~(1L << 63); 143 | return (neg && b == 0) || (!neg && (b >> 52) < 0x43f); 144 | } 145 | 146 | public boolean CanTruncatedIntFitInInt32(Object obj) { 147 | if (this.IsNaN(obj) || this.IsInfinity(obj)) { 148 | return false; 149 | } 150 | long b = DoubleBitsRoundDown((((Long)obj).longValue())); 151 | boolean neg = (b >> 63) != 0; 152 | b &= ~(1L << 63); 153 | return (neg && b == (0x41eL << 52)) || ((b >> 52) < 0x41e); 154 | } 155 | 156 | public int AsInt32(Object obj, int minValue, int maxValue) { 157 | if (this.IsNaN(obj) || this.IsInfinity(obj)) { 158 | throw new ArithmeticException("This Object's value is out of range"); 159 | } 160 | long b = DoubleBitsRoundDown((((Long)obj).longValue())); 161 | boolean neg = (b >> 63) != 0; 162 | b &= ~(1L << 63); 163 | if (b == 0) { 164 | return 0; 165 | } 166 | // Beyond noninteger range (thus beyond int32 range) 167 | if ((b >> 52) >= 0x433) { 168 | throw new ArithmeticException("This Object's value is out of range"); 169 | } 170 | int exp = (int)(b >> 52); 171 | long mant = b & ((1L << 52) - 1); 172 | mant |= 1L << 52; 173 | int shift = 52 - (exp - 0x3ff); 174 | mant >>= shift; 175 | if (neg) { 176 | mant = -mant; 177 | } 178 | if (mant < minValue || mant > maxValue) { 179 | throw new ArithmeticException("This Object's value is out of range"); 180 | } 181 | return (int)mant; 182 | } 183 | 184 | public boolean IsNumberZero(Object obj) { 185 | return (((((Long)obj).longValue())) & ~(1L << 63)) == 0; 186 | } 187 | 188 | public int Sign(Object obj) { 189 | return this.IsNaN(obj) ? (-2) : ((((((Long)obj).longValue())) >> 63) != 0 ? -1 : 1); 190 | } 191 | 192 | public boolean IsIntegral(Object obj) { 193 | return CBORUtilities.IsIntegerValue((((Long)obj).longValue())); 194 | } 195 | 196 | public Object Negate(Object obj) { 197 | return ((((Long)obj).longValue())) ^ (1L << 63); 198 | } 199 | 200 | public Object Abs(Object obj) { 201 | return ((((Long)obj).longValue())) & ~(1L << 63); 202 | } 203 | 204 | public ERational AsERational(Object obj) { 205 | return ERational.FromDoubleBits((((Long)obj).longValue())); 206 | } 207 | 208 | public boolean IsNegative(Object obj) { 209 | return (((((Long)obj).longValue())) >> 63) != 0; 210 | } 211 | } 212 | -------------------------------------------------------------------------------- /src/main/java/com/upokecenter/cbor/CBOREInteger.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.cbor; 2 | /* 3 | Written by Peter O. 4 | Any copyright to this work is released to the Public Domain. 5 | In case this is not possible, this work is also 6 | licensed under the Unlicense: https://unlicense.org/ 7 | 8 | */ 9 | 10 | import com.upokecenter.numbers.*; 11 | 12 | class CBOREInteger implements ICBORNumber { 13 | public boolean IsPositiveInfinity(Object obj) { 14 | return false; 15 | } 16 | 17 | public boolean IsInfinity(Object obj) { 18 | return false; 19 | } 20 | 21 | public boolean IsNegativeInfinity(Object obj) { 22 | return false; 23 | } 24 | 25 | public boolean IsNaN(Object obj) { 26 | return false; 27 | } 28 | 29 | public double AsDouble(Object obj) { 30 | return EFloat.FromEInteger((EInteger)obj).ToDouble(); 31 | } 32 | 33 | public EDecimal AsEDecimal(Object obj) { 34 | return EDecimal.FromEInteger((EInteger)obj); 35 | } 36 | 37 | public EFloat AsEFloat(Object obj) { 38 | return EFloat.FromEInteger((EInteger)obj); 39 | } 40 | 41 | public float AsSingle(Object obj) { 42 | return EFloat.FromEInteger((EInteger)obj).ToSingle(); 43 | } 44 | 45 | public EInteger AsEInteger(Object obj) { 46 | return (EInteger)obj; 47 | } 48 | 49 | public long AsInt64(Object obj) { 50 | EInteger bi = (EInteger)obj; 51 | if (!bi.CanFitInInt64()) { 52 | throw new ArithmeticException("This" + 53 | "\u0020object's value is out of range"); 54 | } 55 | return bi.ToInt64Checked(); 56 | } 57 | 58 | public boolean CanFitInSingle(Object obj) { 59 | EInteger bigintItem = (EInteger)obj; 60 | EFloat ef = EFloat.FromEInteger(bigintItem); 61 | EFloat ef2 = EFloat.FromSingle(ef.ToSingle()); 62 | return ef.compareTo(ef2) == 0; 63 | } 64 | 65 | public boolean CanFitInDouble(Object obj) { 66 | EInteger bigintItem = (EInteger)obj; 67 | EFloat ef = EFloat.FromEInteger(bigintItem); 68 | EFloat ef2 = EFloat.FromDouble(ef.ToDouble()); 69 | return ef.compareTo(ef2) == 0; 70 | } 71 | 72 | public boolean CanFitInInt32(Object obj) { 73 | EInteger bi = (EInteger)obj; 74 | return bi.CanFitInInt32(); 75 | } 76 | 77 | public boolean CanFitInInt64(Object obj) { 78 | EInteger bi = (EInteger)obj; 79 | return bi.CanFitInInt64(); 80 | } 81 | 82 | public boolean CanFitInUInt64(Object obj) { 83 | EInteger bi = (EInteger)obj; 84 | return bi.signum() >= 0 && bi.GetUnsignedBitLengthAsInt64() <= 64; 85 | } 86 | 87 | public boolean CanTruncatedIntFitInInt64(Object obj) { 88 | return this.CanFitInInt64(obj); 89 | } 90 | 91 | public boolean CanTruncatedIntFitInUInt64(Object obj) { 92 | return this.CanFitInUInt64(obj); 93 | } 94 | 95 | public boolean CanTruncatedIntFitInInt32(Object obj) { 96 | return this.CanFitInInt32(obj); 97 | } 98 | 99 | public boolean IsNumberZero(Object obj) { 100 | return ((EInteger)obj).isZero(); 101 | } 102 | 103 | public int Sign(Object obj) { 104 | return ((EInteger)obj).signum(); 105 | } 106 | 107 | public boolean IsIntegral(Object obj) { 108 | return true; 109 | } 110 | 111 | public int AsInt32(Object obj, int minValue, int maxValue) { 112 | EInteger bi = (EInteger)obj; 113 | if (bi.CanFitInInt32()) { 114 | int ret = bi.ToInt32Checked(); 115 | if (ret >= minValue && ret <= maxValue) { 116 | return ret; 117 | } 118 | } 119 | throw new ArithmeticException("This Object's value is out of range"); 120 | } 121 | 122 | public Object Negate(Object obj) { 123 | EInteger bigobj = (EInteger)obj; 124 | bigobj = bigobj.Negate(); 125 | return bigobj; 126 | } 127 | 128 | public Object Abs(Object obj) { 129 | return ((EInteger)obj).Abs(); 130 | } 131 | 132 | public ERational AsERational(Object obj) { 133 | return ERational.FromEInteger((EInteger)obj); 134 | } 135 | 136 | public boolean IsNegative(Object obj) { 137 | return ((EInteger)obj).signum() < 0; 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /src/main/java/com/upokecenter/cbor/CBORException.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.cbor; 2 | /* 3 | Any copyright to this work is released to the Public Domain. 4 | In case this is not possible, this work is also 5 | licensed under the Unlicense: https://unlicense.org/ 6 | 7 | */ 8 | 9 | /** 10 | *

Exception thrown for errors involving CBOR data.

This library may 11 | * throw exceptions of this type in certain cases, notably when errors occur, 12 | * and may supply messages to those exceptions (the message can be accessed 13 | * through the {@code Message} property in.NET or the {@code getMessage()} 14 | * method in Java). These messages are intended to be read by humans to help 15 | * diagnose the error (or other cause of the exception); they are not intended 16 | * to be parsed by computer programs, and the exact text of the messages may 17 | * change at any time between versions of this library.

18 | */ 19 | 20 | public final class CBORException extends RuntimeException { 21 | private static final long serialVersionUID = 1L; 22 | /** 23 | * Initializes a new instance of the {@link com.upokecenter.cbor.CBORException} 24 | * class. 25 | */ 26 | public CBORException() { 27 | } 28 | 29 | /** 30 | * Initializes a new instance of the {@link com.upokecenter.cbor.CBORException} 31 | * class. 32 | * @param message The parameter {@code message} is a text string. 33 | */ 34 | public CBORException(String message) { 35 | super(message); 36 | } 37 | 38 | /** 39 | * Initializes a new instance of the {@link com.upokecenter.cbor.CBORException} 40 | * class. Uses the specified message and inner exception. 41 | * @param message The parameter {@code message} is a text string. 42 | * @param innerException The parameter {@code innerException} is an Exception 43 | * object. 44 | */ 45 | public CBORException(String message, Throwable innerException) { 46 | super(message); 47 | initCause(innerException);; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/upokecenter/cbor/CBORExtendedDecimal.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.cbor; 2 | /* 3 | Written by Peter O. 4 | Any copyright to this work is released to the Public Domain. 5 | In case this is not possible, this work is also 6 | licensed under the Unlicense: https://unlicense.org/ 7 | 8 | */ 9 | 10 | import com.upokecenter.numbers.*; 11 | 12 | class CBORExtendedDecimal implements ICBORNumber { 13 | public boolean IsPositiveInfinity(Object obj) { 14 | EDecimal ed = (EDecimal)obj; 15 | return ed.IsPositiveInfinity(); 16 | } 17 | 18 | public boolean IsInfinity(Object obj) { 19 | EDecimal ed = (EDecimal)obj; 20 | return ed.IsInfinity(); 21 | } 22 | 23 | public boolean IsNegativeInfinity(Object obj) { 24 | EDecimal ed = (EDecimal)obj; 25 | return ed.IsNegativeInfinity(); 26 | } 27 | 28 | public boolean IsNaN(Object obj) { 29 | EDecimal ed = (EDecimal)obj; 30 | return ed.IsNaN(); 31 | } 32 | 33 | public double AsDouble(Object obj) { 34 | EDecimal ed = (EDecimal)obj; 35 | return ed.ToDouble(); 36 | } 37 | 38 | public EDecimal AsEDecimal(Object obj) { 39 | EDecimal ed = (EDecimal)obj; 40 | return ed; 41 | } 42 | 43 | public EFloat AsEFloat(Object obj) { 44 | EDecimal ed = (EDecimal)obj; 45 | return ed.ToEFloat(); 46 | } 47 | 48 | public float AsSingle(Object obj) { 49 | EDecimal ed = (EDecimal)obj; 50 | return ed.ToSingle(); 51 | } 52 | 53 | public EInteger AsEInteger(Object obj) { 54 | EDecimal ed = (EDecimal)obj; 55 | return ed.ToEInteger(); 56 | } 57 | 58 | public long AsInt64(Object obj) { 59 | EDecimal ef = (EDecimal)obj; 60 | if (this.CanTruncatedIntFitInInt64(obj)) { 61 | EInteger bi = ef.ToEInteger(); 62 | return bi.ToInt64Checked(); 63 | } 64 | throw new ArithmeticException("This Object's value is out of range"); 65 | } 66 | 67 | public boolean CanFitInSingle(Object obj) { 68 | EDecimal ef = (EDecimal)obj; 69 | return (!ef.isFinite()) || (ef.compareTo(EDecimal.FromSingle( 70 | ef.ToSingle())) == 0); 71 | } 72 | 73 | public boolean CanFitInDouble(Object obj) { 74 | EDecimal ef = (EDecimal)obj; 75 | return (!ef.isFinite()) || (ef.compareTo(EDecimal.FromDouble( 76 | ef.ToDouble())) == 0); 77 | } 78 | 79 | public boolean CanFitInInt32(Object obj) { 80 | return this.IsIntegral(obj) && this.CanTruncatedIntFitInInt32(obj); 81 | } 82 | 83 | public boolean CanFitInInt64(Object obj) { 84 | return this.IsIntegral(obj) && this.CanTruncatedIntFitInInt64(obj); 85 | } 86 | 87 | public boolean CanFitInUInt64(Object obj) { 88 | return this.IsIntegral(obj) && this.CanTruncatedIntFitInUInt64(obj); 89 | } 90 | 91 | public boolean CanTruncatedIntFitInInt64(Object obj) { 92 | EDecimal ef = (EDecimal)obj; 93 | if (!ef.isFinite()) { 94 | return false; 95 | } 96 | if (ef.isZero()) { 97 | return true; 98 | } 99 | if (ef.getExponent().compareTo(EInteger.FromInt64(21)) >= 0) { 100 | return false; 101 | } 102 | EInteger bi = ef.ToEInteger(); 103 | return bi.CanFitInInt64(); 104 | } 105 | 106 | public boolean CanTruncatedIntFitInUInt64(Object obj) { 107 | EDecimal ef = (EDecimal)obj; 108 | if (!ef.isFinite()) { 109 | return false; 110 | } 111 | if (ef.isZero()) { 112 | return true; 113 | } 114 | if (ef.getExponent().compareTo(EInteger.FromInt64(21)) >= 0) { 115 | return false; 116 | } 117 | EInteger bi = ef.ToEInteger(); 118 | return bi.signum() >= 0 && bi.GetUnsignedBitLengthAsInt64() <= 64; 119 | } 120 | 121 | public boolean CanTruncatedIntFitInInt32(Object obj) { 122 | EDecimal ef = (EDecimal)obj; 123 | if (!ef.isFinite()) { 124 | return false; 125 | } 126 | if (ef.isZero()) { 127 | return true; 128 | } 129 | if (ef.getExponent().compareTo(EInteger.FromInt64(11)) >= 0) { 130 | return false; 131 | } 132 | EInteger bi = ef.ToEInteger(); 133 | return bi.CanFitInInt32(); 134 | } 135 | 136 | public boolean IsNumberZero(Object obj) { 137 | EDecimal ed = (EDecimal)obj; 138 | return ed.isZero(); 139 | } 140 | 141 | public int Sign(Object obj) { 142 | EDecimal ed = (EDecimal)obj; 143 | return ed.IsNaN() ? 2 : ed.signum(); 144 | } 145 | 146 | public boolean IsIntegral(Object obj) { 147 | EDecimal ed = (EDecimal)obj; 148 | return ed.isFinite() && ((ed.getExponent().signum() >= 0) || 149 | (ed.compareTo(EDecimal.FromEInteger(ed.ToEInteger())) == 150 | 151 | 0)); 152 | } 153 | 154 | public int AsInt32(Object obj, int minValue, int maxValue) { 155 | EDecimal ef = (EDecimal)obj; 156 | if (this.CanTruncatedIntFitInInt32(obj)) { 157 | EInteger bi = ef.ToEInteger(); 158 | int ret = bi.ToInt32Checked(); 159 | if (ret >= minValue && ret <= maxValue) { 160 | return ret; 161 | } 162 | } 163 | throw new ArithmeticException("This Object's value is out of range"); 164 | } 165 | 166 | public Object Negate(Object obj) { 167 | EDecimal ed = (EDecimal)obj; 168 | return ed.Negate(); 169 | } 170 | 171 | public Object Abs(Object obj) { 172 | EDecimal ed = (EDecimal)obj; 173 | return ed.Abs(); 174 | } 175 | 176 | public ERational AsERational(Object obj) { 177 | return ERational.FromEDecimal((EDecimal)obj); 178 | } 179 | 180 | public boolean IsNegative(Object obj) { 181 | return ((EDecimal)obj).isNegative(); 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /src/main/java/com/upokecenter/cbor/CBORExtendedFloat.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.cbor; 2 | /* 3 | Written by Peter O. 4 | Any copyright to this work is released to the Public Domain. 5 | In case this is not possible, this work is also 6 | licensed under the Unlicense: https://unlicense.org/ 7 | 8 | */ 9 | 10 | import com.upokecenter.numbers.*; 11 | 12 | class CBORExtendedFloat implements ICBORNumber { 13 | public boolean IsPositiveInfinity(Object obj) { 14 | EFloat ef = (EFloat)obj; 15 | return ef.IsPositiveInfinity(); 16 | } 17 | 18 | public boolean IsInfinity(Object obj) { 19 | EFloat ef = (EFloat)obj; 20 | return ef.IsInfinity(); 21 | } 22 | 23 | public boolean IsNegativeInfinity(Object obj) { 24 | EFloat ef = (EFloat)obj; 25 | return ef.IsNegativeInfinity(); 26 | } 27 | 28 | public boolean IsNaN(Object obj) { 29 | EFloat ef = (EFloat)obj; 30 | return ef.IsNaN(); 31 | } 32 | 33 | public double AsDouble(Object obj) { 34 | EFloat ef = (EFloat)obj; 35 | return ef.ToDouble(); 36 | } 37 | 38 | public EDecimal AsEDecimal(Object obj) { 39 | EFloat ef = (EFloat)obj; 40 | return ef.ToEDecimal(); 41 | } 42 | 43 | public EFloat AsEFloat(Object obj) { 44 | EFloat ef = (EFloat)obj; 45 | return ef; 46 | } 47 | 48 | public float AsSingle(Object obj) { 49 | EFloat ef = (EFloat)obj; 50 | return ef.ToSingle(); 51 | } 52 | 53 | public EInteger AsEInteger(Object obj) { 54 | EFloat ef = (EFloat)obj; 55 | return ef.ToEInteger(); 56 | } 57 | 58 | public long AsInt64(Object obj) { 59 | EFloat ef = (EFloat)obj; 60 | if (this.CanTruncatedIntFitInInt64(obj)) { 61 | EInteger bi = ef.ToEInteger(); 62 | return bi.ToInt64Checked(); 63 | } 64 | throw new ArithmeticException("This Object's value is out of range"); 65 | } 66 | 67 | public boolean CanFitInSingle(Object obj) { 68 | EFloat ef = (EFloat)obj; 69 | return (!ef.isFinite()) || (ef.compareTo(EFloat.FromSingle( 70 | ef.ToSingle())) == 0); 71 | } 72 | 73 | public boolean CanFitInDouble(Object obj) { 74 | EFloat ef = (EFloat)obj; 75 | return (!ef.isFinite()) || (ef.compareTo(EFloat.FromDouble( 76 | ef.ToDouble())) == 0); 77 | } 78 | 79 | public boolean CanFitInInt32(Object obj) { 80 | return this.IsIntegral(obj) && this.CanTruncatedIntFitInInt32(obj); 81 | } 82 | 83 | public boolean CanFitInInt64(Object obj) { 84 | return this.IsIntegral(obj) && this.CanTruncatedIntFitInInt64(obj); 85 | } 86 | 87 | public boolean CanFitInUInt64(Object obj) { 88 | return this.IsIntegral(obj) && this.CanTruncatedIntFitInUInt64(obj); 89 | } 90 | 91 | public boolean CanTruncatedIntFitInInt64(Object obj) { 92 | EFloat ef = (EFloat)obj; 93 | if (!ef.isFinite()) { 94 | return false; 95 | } 96 | if (ef.isZero()) { 97 | return true; 98 | } 99 | if (ef.getExponent().compareTo(EInteger.FromInt64(65)) >= 0) { 100 | return false; 101 | } 102 | EInteger bi = ef.ToEInteger(); 103 | return bi.CanFitInInt64(); 104 | } 105 | 106 | public boolean CanTruncatedIntFitInUInt64(Object obj) { 107 | EFloat ef = (EFloat)obj; 108 | if (!ef.isFinite()) { 109 | return false; 110 | } 111 | if (ef.isZero()) { 112 | return true; 113 | } 114 | if (ef.getExponent().compareTo(EInteger.FromInt64(65)) >= 0) { 115 | return false; 116 | } 117 | EInteger bi = ef.ToEInteger(); 118 | return bi.signum() >= 0 && bi.GetUnsignedBitLengthAsInt64() <= 64; 119 | } 120 | 121 | public boolean CanTruncatedIntFitInInt32(Object obj) { 122 | EFloat ef = (EFloat)obj; 123 | if (!ef.isFinite()) { 124 | return false; 125 | } 126 | if (ef.isZero()) { 127 | return true; 128 | } 129 | if (ef.getExponent().compareTo(EInteger.FromInt64(33)) >= 0) { 130 | return false; 131 | } 132 | EInteger bi = ef.ToEInteger(); 133 | return bi.CanFitInInt32(); 134 | } 135 | 136 | public boolean IsNumberZero(Object obj) { 137 | EFloat ef = (EFloat)obj; 138 | return ef.isZero(); 139 | } 140 | 141 | public int Sign(Object obj) { 142 | EFloat ef = (EFloat)obj; 143 | return ef.IsNaN() ? 2 : ef.signum(); 144 | } 145 | 146 | public boolean IsIntegral(Object obj) { 147 | EFloat ef = (EFloat)obj; 148 | if (!ef.isFinite()) { 149 | return false; 150 | } 151 | if (ef.getExponent().signum() >= 0) { 152 | return true; 153 | } 154 | EFloat ef2 = EFloat.FromEInteger(ef.ToEInteger()); 155 | return ef2.compareTo(ef) == 0; 156 | } 157 | 158 | public int AsInt32(Object obj, int minValue, int maxValue) { 159 | EFloat ef = (EFloat)obj; 160 | if (this.CanTruncatedIntFitInInt32(obj)) { 161 | EInteger bi = ef.ToEInteger(); 162 | int ret = bi.ToInt32Checked(); 163 | if (ret >= minValue && ret <= maxValue) { 164 | return ret; 165 | } 166 | } 167 | throw new ArithmeticException("This Object's value is out of range"); 168 | } 169 | 170 | public Object Negate(Object obj) { 171 | EFloat ed = (EFloat)obj; 172 | return ed.Negate(); 173 | } 174 | 175 | public Object Abs(Object obj) { 176 | EFloat ed = (EFloat)obj; 177 | return ed.Abs(); 178 | } 179 | 180 | public ERational AsERational(Object obj) { 181 | return ERational.FromEFloat((EFloat)obj); 182 | } 183 | 184 | public boolean IsNegative(Object obj) { 185 | return ((EFloat)obj).isNegative(); 186 | } 187 | } 188 | -------------------------------------------------------------------------------- /src/main/java/com/upokecenter/cbor/CBORExtendedRational.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.cbor; 2 | /* 3 | Written by Peter O. 4 | Any copyright to this work is released to the Public Domain. 5 | In case this is not possible, this work is also 6 | licensed under the Unlicense: https://unlicense.org/ 7 | 8 | */ 9 | 10 | import com.upokecenter.numbers.*; 11 | 12 | class CBORExtendedRational implements ICBORNumber { 13 | public boolean IsPositiveInfinity(Object obj) { 14 | return ((ERational)obj).IsPositiveInfinity(); 15 | } 16 | 17 | public boolean IsInfinity(Object obj) { 18 | return ((ERational)obj).IsInfinity(); 19 | } 20 | 21 | public boolean IsNegativeInfinity(Object obj) { 22 | return ((ERational)obj).IsNegativeInfinity(); 23 | } 24 | 25 | public boolean IsNaN(Object obj) { 26 | return ((ERational)obj).IsNaN(); 27 | } 28 | 29 | public double AsDouble(Object obj) { 30 | ERational er = (ERational)obj; 31 | return er.ToDouble(); 32 | } 33 | 34 | public EDecimal AsEDecimal(Object obj) { 35 | ERational er = (ERational)obj; 36 | return 37 | 38 | er.ToEDecimalExactIfPossible( 39 | EContext.Decimal128.WithUnlimitedExponents()); 40 | } 41 | 42 | public EFloat AsEFloat(Object obj) { 43 | ERational er = (ERational)obj; 44 | return 45 | 46 | er.ToEFloatExactIfPossible( 47 | EContext.Binary128.WithUnlimitedExponents()); 48 | } 49 | 50 | public float AsSingle(Object obj) { 51 | ERational er = (ERational)obj; 52 | return er.ToSingle(); 53 | } 54 | 55 | public EInteger AsEInteger(Object obj) { 56 | ERational er = (ERational)obj; 57 | return er.ToEInteger(); 58 | } 59 | 60 | public long AsInt64(Object obj) { 61 | ERational ef = (ERational)obj; 62 | if (ef.isFinite()) { 63 | EInteger bi = ef.ToEInteger(); 64 | if (bi.CanFitInInt64()) { 65 | return bi.ToInt64Checked(); 66 | } 67 | } 68 | throw new ArithmeticException("This Object's value is out of range"); 69 | } 70 | 71 | public boolean CanFitInSingle(Object obj) { 72 | ERational ef = (ERational)obj; 73 | return (!ef.isFinite()) || (ef.compareTo(ERational.FromSingle( 74 | ef.ToSingle())) == 0); 75 | } 76 | 77 | public boolean CanFitInDouble(Object obj) { 78 | ERational ef = (ERational)obj; 79 | return (!ef.isFinite()) || (ef.compareTo(ERational.FromDouble( 80 | ef.ToDouble())) == 0); 81 | } 82 | 83 | public boolean CanFitInInt32(Object obj) { 84 | return this.IsIntegral(obj) && this.CanTruncatedIntFitInInt32(obj); 85 | } 86 | 87 | public boolean CanFitInInt64(Object obj) { 88 | return this.IsIntegral(obj) && this.CanTruncatedIntFitInInt64(obj); 89 | } 90 | 91 | public boolean CanFitInUInt64(Object obj) { 92 | return this.IsIntegral(obj) && this.CanTruncatedIntFitInUInt64(obj); 93 | } 94 | 95 | public boolean CanTruncatedIntFitInInt64(Object obj) { 96 | ERational ef = (ERational)obj; 97 | if (!ef.isFinite()) { 98 | return false; 99 | } 100 | EInteger bi = ef.ToEInteger(); 101 | return bi.CanFitInInt64(); 102 | } 103 | 104 | public boolean CanTruncatedIntFitInInt32(Object obj) { 105 | ERational ef = (ERational)obj; 106 | if (!ef.isFinite()) { 107 | return false; 108 | } 109 | EInteger bi = ef.ToEInteger(); 110 | return bi.CanFitInInt32(); 111 | } 112 | 113 | public boolean CanTruncatedIntFitInUInt64(Object obj) { 114 | ERational ef = (ERational)obj; 115 | if (!ef.isFinite()) { 116 | return false; 117 | } 118 | EInteger bi = ef.ToEInteger(); 119 | return bi.signum() >= 0 && bi.GetUnsignedBitLengthAsInt64() <= 64; 120 | } 121 | 122 | public boolean IsNumberZero(Object obj) { 123 | ERational ef = (ERational)obj; 124 | return ef.isZero(); 125 | } 126 | 127 | public int Sign(Object obj) { 128 | ERational ef = (ERational)obj; 129 | return ef.signum(); 130 | } 131 | 132 | public boolean IsIntegral(Object obj) { 133 | ERational ef = (ERational)obj; 134 | if (!ef.isFinite()) { 135 | return false; 136 | } 137 | if (ef.getDenominator().equals(EInteger.FromInt32(1))) { 138 | return true; 139 | } 140 | // A rational number is integral if the remainder 141 | // of the numerator divided by the denominator is 0 142 | EInteger denom = ef.getDenominator(); 143 | EInteger rem = ef.getNumerator().Remainder(denom); 144 | return rem.isZero(); 145 | } 146 | 147 | public int AsInt32(Object obj, int minValue, int maxValue) { 148 | ERational ef = (ERational)obj; 149 | if (ef.isFinite()) { 150 | EInteger bi = ef.ToEInteger(); 151 | if (bi.CanFitInInt32()) { 152 | int ret = bi.ToInt32Checked(); 153 | if (ret >= minValue && ret <= maxValue) { 154 | return ret; 155 | } 156 | } 157 | } 158 | throw new ArithmeticException("This Object's value is out of range"); 159 | } 160 | 161 | public Object Negate(Object obj) { 162 | ERational ed = (ERational)obj; 163 | return ed.Negate(); 164 | } 165 | 166 | public Object Abs(Object obj) { 167 | ERational ed = (ERational)obj; 168 | return ed.Abs(); 169 | } 170 | 171 | public ERational AsERational(Object obj) { 172 | return (ERational)obj; 173 | } 174 | 175 | public boolean IsNegative(Object obj) { 176 | return ((ERational)obj).isNegative(); 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /src/main/java/com/upokecenter/cbor/CBORInteger.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.cbor; 2 | /* 3 | Written by Peter O. 4 | Any copyright to this work is released to the Public Domain. 5 | In case this is not possible, this work is also 6 | licensed under the Unlicense: https://unlicense.org/ 7 | 8 | */ 9 | 10 | import com.upokecenter.numbers.*; 11 | 12 | class CBORInteger implements ICBORNumber { 13 | public Object Abs(Object obj) { 14 | long val = (((Long)obj).longValue()); 15 | return (val == Integer.MIN_VALUE) ? (EInteger.FromInt32(1).ShiftLeft(63)) : ((val < 0) ? 16 | -val : obj); 17 | } 18 | 19 | public EInteger AsEInteger(Object obj) { 20 | return EInteger.FromInt64((((Long)obj).longValue())); 21 | } 22 | 23 | public double AsDouble(Object obj) { 24 | return ((Long)obj).longValue(); 25 | } 26 | 27 | public EDecimal AsEDecimal(Object obj) { 28 | return EDecimal.FromInt64((((Long)obj).longValue())); 29 | } 30 | 31 | public EFloat AsEFloat(Object obj) { 32 | return EFloat.FromInt64((((Long)obj).longValue())); 33 | } 34 | 35 | public ERational AsERational(Object obj) { 36 | return ERational.FromInt64((((Long)obj).longValue())); 37 | } 38 | 39 | public int AsInt32(Object obj, int minValue, int maxValue) { 40 | long val = (((Long)obj).longValue()); 41 | if (!(val >= minValue && val <= maxValue)) { 42 | throw new ArithmeticException("This Object's value is out of range"); 43 | } 44 | return (int)val; 45 | } 46 | 47 | public long AsInt64(Object obj) { 48 | return ((Long)obj).longValue(); 49 | } 50 | 51 | public float AsSingle(Object obj) { 52 | return ((Long)obj).longValue(); 53 | } 54 | 55 | public boolean CanFitInDouble(Object obj) { 56 | long intItem = (((Long)obj).longValue()); 57 | if (intItem == Long.MIN_VALUE) { 58 | return true; 59 | } 60 | intItem = (intItem < 0) ? -intItem : intItem; 61 | while (intItem >= (1L << 53) && (intItem & 1) == 0) { 62 | intItem >>= 1; 63 | } 64 | return intItem < (1L << 53); 65 | } 66 | 67 | public boolean CanFitInInt32(Object obj) { 68 | long val = (((Long)obj).longValue()); 69 | return val >= Integer.MIN_VALUE && val <= Integer.MAX_VALUE; 70 | } 71 | 72 | public boolean CanFitInInt64(Object obj) { 73 | return true; 74 | } 75 | 76 | public boolean CanFitInSingle(Object obj) { 77 | long intItem = (((Long)obj).longValue()); 78 | if (intItem == Long.MIN_VALUE) { 79 | return true; 80 | } 81 | intItem = (intItem < 0) ? -intItem : intItem; 82 | while (intItem >= (1L << 24) && (intItem & 1) == 0) { 83 | intItem >>= 1; 84 | } 85 | return intItem < (1L << 24); 86 | } 87 | 88 | public boolean CanTruncatedIntFitInInt32(Object obj) { 89 | long val = (((Long)obj).longValue()); 90 | return val >= Integer.MIN_VALUE && val <= Integer.MAX_VALUE; 91 | } 92 | 93 | public boolean CanTruncatedIntFitInUInt64(Object obj) { 94 | long val = (((Long)obj).longValue()); 95 | return val >= 0; 96 | } 97 | 98 | public boolean CanFitInUInt64(Object obj) { 99 | long val = (((Long)obj).longValue()); 100 | return val >= 0; 101 | } 102 | 103 | public boolean CanTruncatedIntFitInInt64(Object obj) { 104 | return true; 105 | } 106 | 107 | public boolean IsInfinity(Object obj) { 108 | return false; 109 | } 110 | 111 | public boolean IsIntegral(Object obj) { 112 | return true; 113 | } 114 | 115 | public boolean IsNaN(Object obj) { 116 | return false; 117 | } 118 | 119 | public boolean IsNegative(Object obj) { 120 | return ((((Long)obj).longValue())) < 0; 121 | } 122 | 123 | public boolean IsNegativeInfinity(Object obj) { 124 | return false; 125 | } 126 | 127 | public boolean IsPositiveInfinity(Object obj) { 128 | return false; 129 | } 130 | 131 | public boolean IsNumberZero(Object obj) { 132 | return ((((Long)obj).longValue())) == 0; 133 | } 134 | 135 | public Object Negate(Object obj) { 136 | return (((((Long)obj).longValue())) == Long.MIN_VALUE) ? (EInteger.FromInt32(1).ShiftLeft(63)) : 137 | (-(((Long)obj).longValue())); 138 | } 139 | 140 | public int Sign(Object obj) { 141 | long val = (((Long)obj).longValue()); 142 | return (val == 0) ? 0 : ((val < 0) ? -1 : 1); 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /src/main/java/com/upokecenter/cbor/CBORType.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.cbor; 2 | /* 3 | Written by Peter O. 4 | Any copyright to this work is released to the Public Domain. 5 | In case this is not possible, this work is also 6 | licensed under the Unlicense: https://unlicense.org/ 7 | 8 | */ 9 | 10 | /** 11 | * Represents a type that a CBOR object can have. 12 | */ 13 | public enum CBORType 14 | { 15 | /** 16 | * This property is no longer used. 17 | * @deprecated Since version 4.0, CBORObject.Type no longer returns this\u0020value for any 18 | * CBOR Object - this is a breaking change from earlier 19 | * versions.\u0020Instead, use the IsNumber property of CBORObject to 20 | * determine whether a CBOR Object represents a number, or use the two new 21 | * CBORType values instead. CBORType.Integer covers CBOR objects 22 | * representing\u0020integers of\u0020major type 0 and 1. 23 | * CBORType.FloatingPoint covers CBOR objects representing 16-, 32-, and 24 | * 64-bit floating-point numbers. CBORType.Number may be removed in version 25 | * 5.0 or later. 26 | */ 27 | @Deprecated 28 | Number, 29 | 30 | /** 31 | * The simple values true and false. 32 | */ 33 | Boolean, 34 | 35 | /** 36 | * A "simple value" other than floating point values, true, and false. 37 | */ 38 | SimpleValue, 39 | 40 | /** 41 | * An array of bytes. 42 | */ 43 | ByteString, 44 | 45 | /** 46 | * A text string. 47 | */ 48 | TextString, 49 | 50 | /** 51 | * An array of CBOR objects. 52 | */ 53 | Array, 54 | 55 | /** 56 | * A map of CBOR objects. 57 | */ 58 | Map, 59 | 60 | /** 61 | * An integer in the interval [-(2^64), 2^64 - 1], or an integer of major type 62 | * 0 and 1. 63 | */ 64 | Integer, 65 | 66 | /** 67 | * A 16-, 32-, or 64-bit binary floating-point number. 68 | */ 69 | FloatingPoint, 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/com/upokecenter/cbor/CBORTypeMapper.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.cbor; 2 | 3 | import java.util.*; 4 | 5 | /** 6 | * Holds converters to customize the serialization and deserialization behavior 7 | * of {@code CBORObject.FromObject} and {@code CBORObject#ToObject}, as well as 8 | * type filters for {@code ToObject}. 9 | */ 10 | public final class CBORTypeMapper { 11 | private final List typePrefixes; 12 | private final List typeNames; 13 | private final Map 14 | converters; 15 | 16 | /** 17 | * Initializes a new instance of the {@link 18 | * com.upokecenter.cbor.CBORTypeMapper} class. 19 | */ 20 | public CBORTypeMapper() { 21 | this.typePrefixes = new ArrayList(); 22 | this.typeNames = new ArrayList(); 23 | this.converters = new HashMap(); 24 | } 25 | 26 | /** 27 | * Registers an object that converts objects of a given type to CBOR objects 28 | * (called a CBOR converter). If the CBOR converter converts to and from CBOR 29 | * objects, it should implement the ICBORToFromConverter interface and provide 30 | * ToCBORObject and FromCBORObject methods. If the CBOR converter only supports 31 | * converting to (not from) CBOR objects, it should implement the 32 | * ICBORConverter interface and provide a ToCBORObject method. 33 | * @param type A Type object specifying the type that the converter converts to 34 | * CBOR objects. 35 | * @param converter The parameter {@code converter} is an ICBORConverter 36 | * object. 37 | * @param Must be the same as the "type" parameter. 38 | * @return This object. 39 | * @throws NullPointerException The parameter {@code type} or {@code 40 | * converter} is null. 41 | * @throws IllegalArgumentException Converter doesn't contain a proper ToCBORObject 42 | * method". 43 | */ 44 | 45 | public CBORTypeMapper AddConverter(java.lang.reflect.Type type, 46 | ICBORConverter converter) { 47 | if (type == null) { 48 | throw new NullPointerException("type"); 49 | } 50 | if (converter == null) { 51 | throw new NullPointerException("converter"); 52 | } 53 | ConverterInfo ci = new ConverterInfo(); 54 | ci.setConverter(converter); 55 | ci.setToObject(PropertyMap.FindOneArgumentMethod( 56 | converter.getClass(), 57 | "ToCBORObject", 58 | type));; 59 | if (ci.getToObject() == null) { 60 | throw new IllegalArgumentException( 61 | "Converter doesn't contain a proper ToCBORObject method"); 62 | } 63 | ci.setFromObject(PropertyMap.FindOneArgumentMethod( 64 | converter.getClass(), 65 | "FromCBORObject", 66 | CBORObject.class)); 67 | this.converters.put(type, ci); 68 | return this; 69 | } 70 | 71 | @SuppressWarnings("unchecked") 72 | T ConvertBackWithConverter( 73 | CBORObject cbor, 74 | java.lang.reflect.Type type) { 75 | ConverterInfo convinfo = PropertyMap.GetOrDefault( 76 | this.converters, 77 | type, 78 | null); 79 | return (T)(convinfo == null ? null : (convinfo.getFromObject() == null) ? null : 80 | PropertyMap.CallFromObject(convinfo, cbor)); 81 | } 82 | 83 | CBORObject ConvertWithConverter(Object obj) { 84 | Object type = obj.getClass(); 85 | ConverterInfo convinfo = PropertyMap.GetOrDefault( 86 | this.converters, 87 | type, 88 | null); 89 | return (convinfo == null) ? null : 90 | PropertyMap.CallToObject(convinfo, obj); 91 | } 92 | 93 | /** 94 | * Returns whether the specified Java or.NET type name fits the filters given 95 | * in this mapper. 96 | * @param typeName The fully qualified name of a Java or.NET class (for 97 | * example, {@code java.math.BigInteger} or {@code 98 | * System.Globalization.CultureInfo}). 99 | * @return Either {@code true} if the specified Java or.NET type name fits the 100 | * filters given in this mapper, or {@code false} otherwise. 101 | */ 102 | public boolean FilterTypeName(String typeName) { 103 | if (((typeName) == null || (typeName).length() == 0)) { 104 | return false; 105 | } 106 | for (String prefix : this.typePrefixes) { 107 | if (typeName.length() >= prefix.length() && 108 | typeName.substring(0, prefix.length()).equals(prefix)) { 109 | return true; 110 | } 111 | } 112 | for (String name : this.typeNames) { 113 | if (typeName.equals(name)) { 114 | return true; 115 | } 116 | } 117 | return false; 118 | } 119 | 120 | /** 121 | * Adds a prefix of a Java or.NET type for use in type matching. A type matches 122 | * a prefix if its fully qualified name is or begins with that prefix, using 123 | * codepoint-by-codepoint (case-sensitive) matching. 124 | * @param prefix The prefix of a Java or.NET type (for example, `java.math.` or 125 | * `System.Globalization`). 126 | * @return This object. 127 | * @throws NullPointerException The parameter {@code prefix} is null. 128 | * @throws IllegalArgumentException The parameter {@code prefix} is empty. 129 | */ 130 | public CBORTypeMapper AddTypePrefix(String prefix) { 131 | if (prefix == null) { 132 | throw new NullPointerException("prefix"); 133 | } 134 | if (prefix.length() == 0) { 135 | throw new IllegalArgumentException("prefix" + " is empty."); 136 | } 137 | this.typePrefixes.add(prefix); 138 | return this; 139 | } 140 | 141 | /** 142 | * Adds the fully qualified name of a Java or.NET type for use in type 143 | * matching. 144 | * @param name The fully qualified name of a Java or.NET class (for example, 145 | * {@code java.math.BigInteger} or {@code System.Globalization.CultureInfo}). 146 | * @return This object. 147 | * @throws NullPointerException The parameter {@code name} is null. 148 | * @throws IllegalArgumentException The parameter {@code name} is empty. 149 | */ 150 | public CBORTypeMapper AddTypeName(String name) { 151 | if (name == null) { 152 | throw new NullPointerException("name"); 153 | } 154 | if (name.length() == 0) { 155 | throw new IllegalArgumentException("name" + " is empty."); 156 | } 157 | this.typeNames.add(name); 158 | return this; 159 | } 160 | 161 | static final class ConverterInfo { 162 | public final Object getToObject() { return propVartoobject; } 163 | public final void setToObject(Object value) { propVartoobject = value; } 164 | private Object propVartoobject; 165 | 166 | public final Object getFromObject() { return propVarfromobject; } 167 | public final void setFromObject(Object value) { propVarfromobject = value; } 168 | private Object propVarfromobject; 169 | 170 | public final Object getConverter() { return propVarconverter; } 171 | public final void setConverter(Object value) { propVarconverter = value; } 172 | private Object propVarconverter; 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /src/main/java/com/upokecenter/cbor/CBORUriConverter.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.cbor; 2 | /* 3 | Written by Peter O. 4 | Any copyright to this work is released to the Public Domain. 5 | In case this is not possible, this work is also 6 | licensed under the Unlicense: https://unlicense.org/ 7 | 8 | */ 9 | 10 | import com.upokecenter.util.*; 11 | 12 | class CBORUriConverter implements ICBORToFromConverter { 13 | private static CBORObject ValidateObject(CBORObject obj) { 14 | if (obj.getType() != CBORType.TextString) { 15 | throw new CBORException("URI/IRI must be a text String"); 16 | } 17 | boolean isiri = obj.HasMostOuterTag(266); 18 | boolean isiriref = obj.HasMostOuterTag(267); 19 | if (isiriref && !URIUtility.IsValidIRI( 20 | obj.AsString(), 21 | com.upokecenter.util.URIUtility.ParseMode.IRIStrict)) { 22 | throw new CBORException("String is not a valid IRI Reference"); 23 | } 24 | if (isiri && (!URIUtility.IsValidIRI( 25 | obj.AsString(), 26 | com.upokecenter.util.URIUtility.ParseMode.IRIStrict) || 27 | !URIUtility.HasScheme(obj.AsString()))) { 28 | throw new CBORException("String is not a valid IRI"); 29 | } 30 | if (!URIUtility.IsValidIRI( 31 | obj.AsString(), 32 | com.upokecenter.util.URIUtility.ParseMode.URIStrict) || 33 | !URIUtility.HasScheme(obj.AsString())) { 34 | throw new CBORException("String is not a valid URI"); 35 | } 36 | return obj; 37 | } 38 | 39 | public java.net.URI FromCBORObject(CBORObject obj) { 40 | if (obj.HasMostOuterTag(32) || 41 | obj.HasMostOuterTag(266) || 42 | obj.HasMostOuterTag(267)) { 43 | ValidateObject(obj); 44 | try { 45 | return new java.net.URI(obj.AsString()); 46 | } catch (Exception ex) { 47 | throw new CBORException(ex.getMessage(), ex); 48 | } 49 | } 50 | throw new CBORException(); 51 | } 52 | 53 | public CBORObject ToCBORObject(java.net.URI uri) { 54 | if (uri == null) { 55 | throw new NullPointerException("uri"); 56 | } 57 | String uriString = uri.toString(); 58 | boolean nonascii = false; 59 | for (int i = 0; i < uriString.length(); ++i) { 60 | nonascii |= uriString.charAt(i) >= 0x80; 61 | } 62 | int tag = nonascii ? 266 : 32; 63 | if (!URIUtility.HasScheme(uriString)) { 64 | tag = 267; 65 | } 66 | return CBORObject.FromString(uriString).WithTag(tag); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/com/upokecenter/cbor/CBORUuidConverter.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.cbor; 2 | /* 3 | Written by Peter O. 4 | Any copyright to this work is released to the Public Domain. 5 | In case this is not possible, this work is also 6 | licensed under the Unlicense: https://unlicense.org/ 7 | 8 | */ 9 | 10 | class CBORUuidConverter implements ICBORToFromConverter { 11 | private static CBORObject ValidateObject(CBORObject obj) { 12 | if (obj.getType() != CBORType.ByteString) { 13 | throw new CBORException("UUID must be a byte String"); 14 | } 15 | byte[] bytes = obj.GetByteString(); 16 | if (bytes.length != 16) { 17 | throw new CBORException("UUID must be 16" + 18 | "\u0020bytes long"); 19 | } 20 | return obj; 21 | } 22 | 23 | /** 24 | * Internal API. 25 | * @param obj The parameter {@code obj} is an internal parameter. 26 | * @return A CBORObject object. 27 | */ 28 | public CBORObject ToCBORObject(java.util.UUID obj) { 29 | byte[] bytes = PropertyMap.UUIDToBytes(obj); 30 | return CBORObject.FromByteArray(bytes).WithTag(37); 31 | } 32 | 33 | public java.util.UUID FromCBORObject(CBORObject obj) { 34 | if (!obj.HasMostOuterTag(37)) { 35 | throw new CBORException("Must have outermost tag 37"); 36 | } 37 | ValidateObject(obj); 38 | byte[] bytes = obj.GetByteString(); 39 | char[] guidChars = new char[36]; 40 | String hex = "0123456789abcdef"; 41 | int index = 0; 42 | for (int i = 0; i < 16; ++i) { 43 | if (i == 4 || i == 6 || i == 8 || i == 10) { 44 | guidChars[index++] = '-'; 45 | } 46 | guidChars[index++] = hex.charAt((bytes[i] >> 4) & 15); 47 | guidChars[index++] = hex.charAt(bytes[i] & 15); 48 | } 49 | String guidString = new String(guidChars); 50 | // NOTE: Don't use the byte[] constructor of the DotNet java.util.UUID class, 51 | // since the bytes may have to be rearranged in order to generate a 52 | // java.util.UUID from a UUID; thus the exact java.util.UUID generated from a byte String 53 | // by that constructor may differ between little-endian and big-endian 54 | // computers, but I don't have access to a big-endian machine to test 55 | // this hypothesis. 56 | return java.util.UUID.fromString(guidString); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/com/upokecenter/cbor/CharacterInputWithCount.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.cbor; 2 | 3 | class CharacterInputWithCount implements ICharacterInput { 4 | private final ICharacterInput ci; 5 | private int offset; 6 | 7 | public CharacterInputWithCount(ICharacterInput ci) { 8 | this.ci = ci; 9 | } 10 | 11 | public int GetOffset() { 12 | return this.offset; 13 | } 14 | 15 | public void RaiseError(String str) { 16 | throw new CBORException(this.NewErrorString(str)); 17 | } 18 | 19 | public void RaiseError(Exception ex) { 20 | if (ex.getCause() == null) { 21 | throw new CBORException( 22 | this.NewErrorString(ex.getMessage()), 23 | ex); 24 | } else { 25 | throw new CBORException( 26 | this.NewErrorString(ex.getMessage()), 27 | ex.getCause()); 28 | } 29 | } 30 | 31 | public int Read(int[] chars, int index, int length) { 32 | if (chars == null) { 33 | throw new NullPointerException("chars"); 34 | } 35 | if (index < 0) { 36 | throw new IllegalArgumentException("index(" + index + 37 | ") is less than 0"); 38 | } 39 | if (index > chars.length) { 40 | throw new IllegalArgumentException("index(" + index + 41 | ") is more than " + chars.length); 42 | } 43 | if (length < 0) { 44 | throw new IllegalArgumentException("length(" + length + 45 | ") is less than 0"); 46 | } 47 | if (length > chars.length) { 48 | throw new IllegalArgumentException("length(" + length + 49 | ") is more than " + chars.length); 50 | } 51 | if (chars.length - index < length) { 52 | throw new IllegalArgumentException("chars's length minus " + index + "(" + 53 | (chars.length - index) + ") is less than " + length); 54 | } 55 | int ret = this.ci.Read(chars, index, length); 56 | if (ret > 0) { 57 | this.offset += ret; 58 | } 59 | return ret; 60 | } 61 | 62 | public int ReadChar() { 63 | int c = -1; 64 | try { 65 | c = this.ci.ReadChar(); 66 | } catch (IllegalStateException ex) { 67 | this.RaiseError(ex); 68 | } 69 | if (c >= 0) { 70 | ++this.offset; 71 | } 72 | return c; 73 | } 74 | 75 | private String NewErrorString(String str) { 76 | return str + " (offset " + this.GetOffset() + ")"; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/com/upokecenter/cbor/ICBORConverter.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.cbor; 2 | /* 3 | Written by Peter O. 4 | Any copyright to this work is released to the Public Domain. 5 | In case this is not possible, this work is also 6 | licensed under the Unlicense: https://unlicense.org/ 7 | 8 | */ 9 | 10 | /** 11 | * Interface implemented by classes that convert objects of arbitrary types to 12 | * CBOR objects. 13 | * @param Type to convert to a CBOR object. 14 | */ 15 | public interface ICBORConverter { 16 | /** 17 | * Converts an object to a CBOR object. 18 | * @param obj An object to convert to a CBOR object. 19 | * @return A CBOR object. 20 | */ 21 | CBORObject ToCBORObject(T obj); 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/upokecenter/cbor/ICBORNumber.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.cbor; 2 | /* 3 | Written by Peter O. 4 | Any copyright to this work is released to the Public Domain. 5 | In case this is not possible, this work is also 6 | licensed under the Unlicense: https://unlicense.org/ 7 | 8 | */ 9 | import com.upokecenter.numbers.*; 10 | 11 | /** 12 | * This is an internal API. 13 | */ 14 | interface ICBORNumber { 15 | /** 16 | * This is an internal API. 17 | * @param obj The parameter {@code obj} is an arbitrary object. 18 | * @return The return value is an internal value. 19 | */ 20 | boolean IsPositiveInfinity(Object obj); 21 | 22 | /** 23 | * This is an internal API. 24 | * @param obj The parameter {@code obj} is an arbitrary object. 25 | * @return The return value is an internal value. 26 | */ 27 | boolean IsInfinity(Object obj); 28 | 29 | /** 30 | * This is an internal API. 31 | * @param obj The parameter {@code obj} is an arbitrary object. 32 | * @return The return value is an internal value. 33 | */ 34 | boolean IsNegativeInfinity(Object obj); 35 | 36 | /** 37 | * This is an internal API. 38 | * @param obj The parameter {@code obj} is an arbitrary object. 39 | * @return The return value is an internal value. 40 | */ 41 | boolean IsNaN(Object obj); 42 | 43 | /** 44 | * This is an internal API. 45 | * @param obj The parameter {@code obj} is an arbitrary object. 46 | * @return The return value is an internal value. 47 | */ 48 | boolean IsNegative(Object obj); 49 | 50 | /** 51 | * This is an internal API. 52 | * @param obj The parameter {@code obj} is an arbitrary object. 53 | * @return The return value is an internal value. 54 | */ 55 | double AsDouble(Object obj); 56 | 57 | /** 58 | * This is an internal API. 59 | * @param obj The parameter {@code obj} is an arbitrary object. 60 | * @return The return value is an internal value. 61 | */ 62 | Object Negate(Object obj); 63 | 64 | /** 65 | * This is an internal API. 66 | * @param obj The parameter {@code obj} is an arbitrary object. 67 | * @return The return value is an internal value. 68 | */ 69 | Object Abs(Object obj); 70 | 71 | /** 72 | * This is an internal API. 73 | * @param obj The parameter {@code obj} is an arbitrary object. 74 | * @return The return value is an internal value. 75 | */ 76 | EDecimal AsEDecimal(Object obj); 77 | 78 | /** 79 | * This is an internal API. 80 | * @param obj The parameter {@code obj} is an arbitrary object. 81 | * @return The return value is an internal value. 82 | */ 83 | EFloat AsEFloat(Object obj); 84 | 85 | /** 86 | * This is an internal API. 87 | * @param obj The parameter {@code obj} is an arbitrary object. 88 | * @return The return value is an internal value. 89 | */ 90 | ERational AsERational(Object obj); 91 | 92 | /** 93 | * This is an internal API. 94 | * @param obj The parameter {@code obj} is an arbitrary object. 95 | * @return The return value is an internal value. 96 | */ 97 | float AsSingle(Object obj); 98 | 99 | /** 100 | * This is an internal API. 101 | * @param obj The parameter {@code obj} is an arbitrary object. 102 | * @return The return value is an internal value. 103 | */ 104 | EInteger AsEInteger(Object obj); 105 | 106 | /** 107 | * This is an internal API. 108 | * @param obj The parameter {@code obj} is an arbitrary object. 109 | * @return The return value is an internal value. 110 | */ 111 | long AsInt64(Object obj); 112 | 113 | /** 114 | * This is an internal API. 115 | * @param obj The parameter {@code obj} is an arbitrary object. 116 | * @return The return value is an internal value. 117 | */ 118 | boolean CanFitInSingle(Object obj); 119 | 120 | /** 121 | * This is an internal API. 122 | * @param obj The parameter {@code obj} is an arbitrary object. 123 | * @return The return value is an internal value. 124 | */ 125 | boolean CanFitInDouble(Object obj); 126 | 127 | /** 128 | * This is an internal API. 129 | * @param obj The parameter {@code obj} is an arbitrary object. 130 | * @return The return value is an internal value. 131 | */ 132 | boolean CanFitInInt32(Object obj); 133 | 134 | /** 135 | * This is an internal API. 136 | * @param obj The parameter {@code obj} is an arbitrary object. 137 | * @return The return value is an internal value. 138 | */ 139 | boolean CanFitInInt64(Object obj); 140 | 141 | boolean CanFitInUInt64(Object obj); 142 | 143 | /** 144 | * This is an internal API. 145 | * @param obj The parameter {@code obj} is an arbitrary object. 146 | * @return The return value is an internal value. 147 | */ 148 | boolean CanTruncatedIntFitInInt64(Object obj); 149 | 150 | /** 151 | * This is an internal API. 152 | * @param obj The parameter {@code obj} is an arbitrary object. 153 | * @return The return value is an internal value. 154 | */ 155 | boolean CanTruncatedIntFitInUInt64(Object obj); 156 | 157 | /** 158 | * This is an internal API. 159 | * @param obj The parameter {@code obj} is an arbitrary object. 160 | * @return The return value is an internal value. 161 | */ 162 | boolean CanTruncatedIntFitInInt32(Object obj); 163 | 164 | /** 165 | * This is an internal API. 166 | * @return The return value is an internal value. 167 | */ 168 | int AsInt32(Object obj, int minValue, int maxValue); 169 | 170 | /** 171 | * This is an internal API. 172 | * @param obj The parameter {@code obj} is an arbitrary object. 173 | * @return The return value is an internal value. 174 | */ 175 | boolean IsNumberZero(Object obj); 176 | 177 | /** 178 | * This is an internal API. 179 | * @param obj The parameter {@code obj} is an arbitrary object. 180 | * @return The return value is an internal value. 181 | */ 182 | int Sign(Object obj); 183 | 184 | /** 185 | * This is an internal API. 186 | * @param obj The parameter {@code obj} is an arbitrary object. 187 | * @return The return value is an internal value. 188 | */ 189 | boolean IsIntegral(Object obj); 190 | } 191 | -------------------------------------------------------------------------------- /src/main/java/com/upokecenter/cbor/ICBORToFromConverter.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.cbor; 2 | /* 3 | Written by Peter O. 4 | Any copyright to this work is released to the Public Domain. 5 | In case this is not possible, this work is also 6 | licensed under the Unlicense: https://unlicense.org/ 7 | 8 | */ 9 | 10 | /** 11 | * Classes that implement this interface can support conversions from CBOR 12 | * objects to a custom type and back. 13 | * @param Type of objects to convert to and from CBOR objects. 14 | */ 15 | public interface ICBORToFromConverter extends ICBORConverter { 16 | /** 17 | * Converts a CBOR object to a custom type. 18 | * @param obj A CBOR object to convert to the custom type. 19 | * @return An object of the custom type after conversion. 20 | */ 21 | T FromCBORObject(CBORObject obj); 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/upokecenter/cbor/ICharacterInput.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.cbor; 2 | 3 | /** 4 | * An interface for reading Unicode characters from a data source. 5 | */ 6 | interface ICharacterInput { 7 | /** 8 | * Reads a Unicode character from a data source. 9 | * @return Either a Unicode code point (from 0-0xd7ff or from 0xe000 to 10 | * 0x10ffff), or the value -1 indicating the end of the source. 11 | */ 12 | int ReadChar(); 13 | 14 | /** 15 | * Reads a sequence of Unicode code points from a data source. 16 | * @param chars Output buffer. 17 | * @param index Index in the output buffer to start writing to. 18 | * @param length Maximum number of code points to write. 19 | * @return Either a Unicode code point (from 0-0xd7ff or from 0xe000 to 20 | * 0x10ffff), or the value -1 indicating the end of the source. 21 | * @throws IllegalArgumentException Either "index" or "length" is less than 0 or 22 | * greater than "chars"'s length, or "chars"'s length minus "index" is less 23 | * than "length". 24 | * @throws NullPointerException The parameter {@code chars} is null. 25 | */ 26 | int Read(int[] chars, int index, int length); 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/upokecenter/cbor/JSONPatch.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.cbor; 2 | /* 3 | Written in 2013 by Peter Occil. 4 | Any copyright to this work is released to the Public Domain. 5 | In case this is not possible, this work is also 6 | licensed under the Unlicense: https://unlicense.org/ 7 | 8 | */ 9 | 10 | final class JSONPatch { 11 | private JSONPatch() { 12 | } 13 | private static CBORObject AddOperation( 14 | CBORObject o, 15 | String valueOpStr, 16 | String path, 17 | CBORObject value) { 18 | if (path == null) { 19 | throw new CBORException("Patch " + valueOpStr); 20 | } 21 | if (path.length() == 0) { 22 | o = value; 23 | } else { 24 | // System.out.println("pointer--->"+path); 25 | JSONPointer pointer = JSONPointer.FromPointer(o, path); 26 | CBORObject parent = pointer.GetParent(); 27 | // System.out.println("addop pointer "+path+" ["+parent+"]"); 28 | if (pointer.GetParent().getType() == CBORType.Array) { 29 | int index = pointer.GetIndex(); 30 | // System.out.println("index "+index); 31 | if (index < 0) { 32 | throw new CBORException("Patch " + valueOpStr + " path"); 33 | } 34 | // System.out.println("before "+parent+""); 35 | parent.Insert(index, value); 36 | // System.out.println("after "+parent+""); 37 | } else if (pointer.GetParent().getType() == CBORType.Map) { 38 | String key = pointer.GetKey(); 39 | parent.Set(CBORObject.FromString(key), value); 40 | } else { 41 | throw new CBORException("Patch " + valueOpStr + " path"); 42 | } 43 | } 44 | return o; 45 | } 46 | 47 | private static CBORObject CloneCbor(CBORObject o) { 48 | switch (o.getType()) { 49 | case ByteString: 50 | case Map: 51 | case Array: 52 | return CBORObject.DecodeFromBytes(o.EncodeToBytes()); 53 | default: return o; 54 | } 55 | } 56 | 57 | private static String GetString(CBORObject o, String str) { 58 | CBORObject co = o.GetOrDefault(str, null); 59 | if (co == null) { 60 | throw new CBORException(str + " not found"); 61 | } 62 | if (co.getType() != CBORType.TextString) { 63 | throw new CBORException("Not a" + 64 | "\u0020text String type"); 65 | } 66 | return co.AsString(); 67 | } 68 | 69 | public static CBORObject Patch(CBORObject o, CBORObject ptch) { 70 | // clone the Object in case of failure 71 | if (o == null) { 72 | throw new CBORException("Object is null"); 73 | } 74 | if (ptch == null) { 75 | throw new CBORException("patch is null"); 76 | } 77 | if (ptch.getType() != CBORType.Array) { 78 | throw new CBORException("patch is not an array"); 79 | } 80 | o = CloneCbor(o); 81 | for (int i = 0; i < ptch.size(); ++i) { 82 | CBORObject patchOp = ptch.get(i); 83 | 84 | // NOTE: This algorithm requires "op" to exist 85 | // only once; the CBORObject, however, does not 86 | // allow duplicates 87 | String valueOpStr = GetString(patchOp, "op"); 88 | if ("add".equals(valueOpStr)) { 89 | // operation 90 | CBORObject value = patchOp.GetOrDefault("value", null); 91 | if (value == null) { 92 | throw new CBORException("Patch " + valueOpStr + " value"); 93 | } 94 | value = patchOp.get("value"); 95 | o = AddOperation( 96 | o, 97 | valueOpStr, 98 | GetString(patchOp, "path"), 99 | value); 100 | } else if ("replace".equals(valueOpStr)) { 101 | // operation 102 | CBORObject value = patchOp.GetOrDefault("value", null); 103 | if (value == null) { 104 | throw new CBORException("Patch " + valueOpStr + " value"); 105 | } 106 | 107 | o = ReplaceOperation( 108 | o, 109 | valueOpStr, 110 | GetString(patchOp, "path"), 111 | CloneCbor(value)); 112 | } else if ("remove".equals(valueOpStr)) { 113 | // Remove operation 114 | String path = GetString(patchOp, "path"); 115 | if (path == null) { 116 | throw new CBORException("Patch " + valueOpStr + " path"); 117 | } 118 | if (path.length() == 0) { 119 | o = null; 120 | } else { 121 | RemoveOperation(o, valueOpStr, GetString(patchOp, "path")); 122 | } 123 | } else if ("move".equals(valueOpStr)) { 124 | String path = GetString(patchOp, "path"); 125 | if (path == null) { 126 | throw new CBORException("Patch " + valueOpStr + " path"); 127 | } 128 | String fromPath = GetString(patchOp, "from"); 129 | if (fromPath == null) { 130 | throw new CBORException("Patch " + valueOpStr + " from"); 131 | } 132 | if (path.equals(fromPath)) { 133 | JSONPointer pointer = JSONPointer.FromPointer(o, path); 134 | if (pointer.Exists()) { 135 | // Moving to the same path, so return 136 | return o; 137 | } 138 | } 139 | // if (path.startsWith(fromPath)) { 140 | // throw new CBORException("Patch " + valueOpStr + ": startsWith failed " + 141 | // "[" + path + "] [" + fromPath + "]"); 142 | // } 143 | CBORObject movedObj = RemoveOperation(o, valueOpStr, fromPath); 144 | o = AddOperation(o, valueOpStr, path, CloneCbor(movedObj)); 145 | } else if ("copy".equals(valueOpStr)) { 146 | String path = GetString(patchOp, "path"); 147 | String fromPath = GetString(patchOp, "from"); 148 | if (path == null) { 149 | throw new CBORException("Patch " + valueOpStr + " path"); 150 | } 151 | if (fromPath == null) { 152 | throw new CBORException("Patch " + valueOpStr + " from"); 153 | } 154 | JSONPointer pointer = JSONPointer.FromPointer(o, fromPath); 155 | if (!pointer.Exists()) { 156 | throw new CBORException("Patch " + valueOpStr + " " + fromPath); 157 | } 158 | CBORObject copiedObj = pointer.GetValue(); 159 | o = AddOperation( 160 | o, 161 | valueOpStr, 162 | path, 163 | CloneCbor(copiedObj)); 164 | } else if ("test".equals(valueOpStr)) { 165 | String path = GetString(patchOp, "path"); 166 | if (path == null) { 167 | throw new CBORException("Patch " + valueOpStr + " path"); 168 | } 169 | CBORObject value = null; 170 | if (!patchOp.ContainsKey("value")) { 171 | throw new CBORException("Patch " + valueOpStr + " value"); 172 | } 173 | value = patchOp.get("value"); 174 | JSONPointer pointer = JSONPointer.FromPointer(o, path); 175 | if (!pointer.Exists()) { 176 | throw new CBORException("Patch " + valueOpStr + " " + path); 177 | } 178 | Object testedObj = pointer.GetValue(); 179 | if ((testedObj == null) ? (value != null) : 180 | !testedObj.equals(value)) { 181 | throw new CBORException("Patch " + valueOpStr); 182 | } 183 | } else { 184 | throw new CBORException("Unrecognized op"); 185 | } 186 | } 187 | return (o == null) ? (CBORObject.Null) : o; 188 | } 189 | 190 | private static CBORObject RemoveOperation( 191 | CBORObject o, 192 | String valueOpStr, 193 | String path) { 194 | if (path == null) { 195 | throw new CBORException("Patch " + valueOpStr); 196 | } 197 | if (path.length() == 0) { 198 | return o; 199 | } else { 200 | JSONPointer pointer = JSONPointer.FromPointer(o, path); 201 | if (!pointer.Exists()) { 202 | throw new CBORException("Patch " + valueOpStr + " " + path); 203 | } 204 | o = pointer.GetValue(); 205 | if (pointer.GetParent().getType() == CBORType.Array) { 206 | pointer.GetParent().RemoveAt(pointer.GetIndex()); 207 | } else if (pointer.GetParent().getType() == CBORType.Map) { 208 | pointer.GetParent().Remove( 209 | CBORObject.FromString(pointer.GetKey())); 210 | } 211 | return o; 212 | } 213 | } 214 | 215 | private static CBORObject ReplaceOperation( 216 | CBORObject o, 217 | String valueOpStr, 218 | String path, 219 | CBORObject value) { 220 | if (path == null) { 221 | throw new CBORException("Patch " + valueOpStr); 222 | } 223 | 224 | if (path.length() == 0) { 225 | o = value; 226 | } else { 227 | JSONPointer pointer = JSONPointer.FromPointer(o, path); 228 | if (!pointer.Exists()) { 229 | throw new CBORException("Patch " + valueOpStr + " " + path); 230 | } 231 | if (pointer.GetParent().getType() == CBORType.Array) { 232 | int index = pointer.GetIndex(); 233 | if (index < 0) { 234 | throw new CBORException("Patch " + valueOpStr + " path"); 235 | } 236 | pointer.GetParent().Set(index, value); 237 | } else if (pointer.GetParent().getType() == CBORType.Map) { 238 | String key = pointer.GetKey(); 239 | pointer.GetParent().Set(CBORObject.FromString(key), value); 240 | } else { 241 | throw new CBORException("Patch " + valueOpStr + " path"); 242 | } 243 | } 244 | return o; 245 | } 246 | } 247 | -------------------------------------------------------------------------------- /src/main/java/com/upokecenter/cbor/OptionsParser.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.cbor; 2 | 3 | import java.util.*; 4 | 5 | final class OptionsParser { 6 | private final Map dict = new 7 | HashMap(); 8 | 9 | private static String[] SplitAt(String str, String delimiter) { 10 | if (delimiter == null) { 11 | throw new NullPointerException("delimiter"); 12 | } 13 | if (delimiter.length() == 0) { 14 | throw new IllegalArgumentException("delimiter is empty."); 15 | } 16 | if (((str) == null || (str).length() == 0)) { 17 | return new String[] { "" }; 18 | } 19 | int index = 0; 20 | boolean first = true; 21 | ArrayList strings = null; 22 | int delimLength = delimiter.length(); 23 | while (true) { 24 | int index2 = str.indexOf( 25 | delimiter, index); 26 | if (index2 < 0) { 27 | if (first) { 28 | String[] strret = new String[1]; 29 | strret[0] = str; 30 | return strret; 31 | } 32 | strings = (strings == null) ? (new ArrayList()) : strings; 33 | strings.add(str.substring(index)); 34 | break; 35 | } else { 36 | first = false; 37 | String newstr = str.substring(index, (index)+(index2 - index)); 38 | strings = (strings == null) ? (new ArrayList()) : strings; 39 | strings.add(newstr); 40 | index = index2 + delimLength; 41 | } 42 | } 43 | return strings.toArray(new String[] { }); 44 | } 45 | 46 | public OptionsParser(String options) { 47 | if (options == null) { 48 | throw new NullPointerException("options"); 49 | } 50 | if (options.length() > 0) { 51 | String[] optionsArray = SplitAt(options, ";"); 52 | for (String opt : optionsArray) { 53 | int index = opt.indexOf('='); 54 | if (index < 0) { 55 | throw new IllegalArgumentException("Invalid options String: " + 56 | options); 57 | } 58 | String key = com.upokecenter.util.DataUtilities.ToLowerCaseAscii(opt.substring(0, index)); 59 | String value = opt.substring(index + 1); 60 | this.dict.put(key, value); 61 | } 62 | } 63 | } 64 | 65 | public String GetLCString(String key, String defaultValue) { 66 | String lckey = com.upokecenter.util.DataUtilities.ToLowerCaseAscii(key); 67 | String val = null; if ((val = this.dict.getOrDefault(lckey, null)) != null) { 68 | String lcvalue = com.upokecenter.util.DataUtilities.ToLowerCaseAscii(val); 69 | return lcvalue; 70 | } 71 | return defaultValue; 72 | } 73 | 74 | public boolean GetBoolean(String key, boolean defaultValue) { 75 | String lckey = com.upokecenter.util.DataUtilities.ToLowerCaseAscii(key); 76 | String val = null; if ((val = this.dict.getOrDefault(lckey, null)) != null) { 77 | String lcvalue = com.upokecenter.util.DataUtilities.ToLowerCaseAscii(val); 78 | return lcvalue.equals("1") || 79 | lcvalue.equals("yes") || 80 | lcvalue.equals("on") || 81 | lcvalue.equals("true"); 82 | } 83 | return defaultValue; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/com/upokecenter/cbor/PODOptions.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.cbor; 2 | 3 | /** 4 | * Options for controlling how certain DotNET or Java objects, such as 5 | * so-called "plain old data" objects (better known as POCOs in DotNET or POJOs 6 | * in Java), are converted to CBOR objects. 7 | */ 8 | public class PODOptions { 9 | /** 10 | * Initializes a new instance of the {@link com.upokecenter.cbor.PODOptions} 11 | * class with all the default options. 12 | */ 13 | public PODOptions() { 14 | this(""); 15 | } 16 | 17 | /** 18 | * Initializes a new instance of the {@link com.upokecenter.cbor.PODOptions} 19 | * class. 20 | * @param removeIsPrefix The parameter is not used. 21 | * @param useCamelCase The value of the "UseCamelCase" property. 22 | * @deprecated Use the more readable String constructor instead. 23 | */ 24 | @Deprecated 25 | public PODOptions(boolean removeIsPrefix, boolean useCamelCase) { 26 | this.propVarusecamelcase = useCamelCase; 27 | } 28 | 29 | /** 30 | * Initializes a new instance of the {@link com.upokecenter.cbor.PODOptions} 31 | * class. 32 | * @param paramString A string setting forth the options to use. This is a 33 | * semicolon-separated list of options, each of which has a key and a value 34 | * separated by an equal sign ("="). Whitespace and line separators are not 35 | * allowed to appear between the semicolons or between the equal signs, nor may 36 | * the string begin or end with whitespace. The string can be empty, but cannot 37 | * be null. The following is an example of this parameter: {@code 38 | * usecamelcase = true}. The key can be any one of the following where the 39 | * letters can be any combination of basic uppercase and basic lowercase 40 | * letters: {@code usecamelcase}. Other keys are ignored in this version of the 41 | * CBOR library. (Keys are compared using a basic case-insensitive comparison, 42 | * in which two strings are equal if they match after converting the basic 43 | * uppercase letters A to Z (U+0041 to U+005A) in both strings to basic 44 | * lowercase letters.) If two or more key/value pairs have equal keys (in a 45 | * basic case-insensitive comparison), the value given for the last such key is 46 | * used. The key just given can have a value of {@code 1}, {@code true}, {@code 47 | * yes}, or {@code on} (where the letters can be any combination of basic 48 | * uppercase and basic lowercase letters), which means true, and any other 49 | * value meaning false. For example, {@code usecamelcase = Yes} and {@code 50 | * usecamelcase = 1} both set the {@code UseCamelCase} property to true. In the 51 | * future, this class may allow other keys to store other kinds of values, not 52 | * just true or false. 53 | * @throws NullPointerException The parameter {@code paramString} is null. 54 | */ 55 | public PODOptions(String paramString) { 56 | if (paramString == null) { 57 | throw new NullPointerException("paramString"); 58 | } 59 | OptionsParser parser = new OptionsParser(paramString); 60 | this.propVarusecamelcase = parser.GetBoolean("usecamelcase", true); 61 | } 62 | 63 | /** 64 | * Gets the values of this options object's properties in text form. 65 | * @return A text string containing the values of this options object's 66 | * properties. The format of the string is the same as the one described in the 67 | * string constructor for this class. 68 | */ 69 | @Override public String toString() { 70 | return new StringBuilder() 71 | .append("usecamelcase=").append(this.getUseCamelCase() ? "true" : 72 | "false").toString(); 73 | } 74 | 75 | /** 76 | * The default settings for "plain old data" options. 77 | */ 78 | public static final PODOptions Default = new PODOptions(); 79 | 80 | /** 81 | *

Gets a value indicating whether property, field, and method names are 82 | * converted to camel case before they are used as keys. This option changes 83 | * the behavior of key name serialization as follows. If "useCamelCase" is 84 | * {@code false} :

  • In the .NET version, all key names are 85 | * capitalized, meaning the first letter in the name is converted to a basic 86 | * uppercase letter if it's a basic lowercase letter ("a" to "z"). (For 87 | * example, "Name" and "IsName" both remain unchanged.)
  • In the Java 88 | * version, all field names are capitalized, and for each eligible method name, 89 | * the word "get" or "set" is removed from the name if the name starts with 90 | * that word, then the name is capitalized. (For example, "getName" and 91 | * "setName" both become "Name", and "isName" becomes "IsName".)
92 | *

If "useCamelCase" is {@code true} :

  • In the .NET version, for 93 | * each eligible property or field name, the word "Is" is removed from the name 94 | * if the name starts with that word, then the name is converted to camel case, 95 | * meaning the first letter in the name is converted to a basic lowercase 96 | * letter if it's a basic uppercase letter ("A" to "Z"). (For example, "Name" 97 | * and "IsName" both become "name", and "IsIsName" becomes 98 | * "isName".)
  • In the Java version: For each eligible method name, the 99 | * word "get", "set", or "is" is removed from the name if the name starts with 100 | * that word, then the name is converted to camel case. (For example, 101 | * "getName", "setName", and "isName" all become "name".) For each eligible 102 | * field name, the word "is" is removed from the name if the name starts with 103 | * that word, then the name is converted to camel case. (For example, "name" 104 | * and "isName" both become "name".)

In the description above, a 105 | * name "starts with" a word if that word begins the name and is followed by a 106 | * character other than a basic digit or basic lowercase letter, that is, other 107 | * than "a" to "z" or "0" to "9".

108 | * @return {@code true} If the names are converted to camel case; otherwise, 109 | * {@code false}. This property is {@code true} by default. 110 | */ 111 | public final boolean getUseCamelCase() { return propVarusecamelcase; } 112 | private final boolean propVarusecamelcase; 113 | } 114 | -------------------------------------------------------------------------------- /src/main/java/com/upokecenter/cbor/SharedRefs.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.cbor; 2 | /* 3 | Written by Peter O. 4 | Any copyright to this work is released to the Public Domain. 5 | In case this is not possible, this work is also 6 | licensed under the Unlicense: https://unlicense.org/ 7 | 8 | */ 9 | 10 | import java.util.*; 11 | import com.upokecenter.numbers.*; 12 | 13 | class SharedRefs { 14 | private final List sharedObjects; 15 | 16 | public SharedRefs() { 17 | this.sharedObjects = new ArrayList(); 18 | } 19 | 20 | public void AddObject(CBORObject obj) { 21 | this.sharedObjects.add(obj); 22 | } 23 | 24 | public CBORObject GetObject(long smallIndex) { 25 | if (smallIndex < 0) { 26 | throw new CBORException("Unexpected index"); 27 | } 28 | if (smallIndex > Integer.MAX_VALUE) { 29 | throw new CBORException("Index " + smallIndex + 30 | " is bigger than supported "); 31 | } 32 | int index = (int)smallIndex; 33 | if (index >= this.sharedObjects.size()) { 34 | throw new CBORException("Index " + index + " is not valid"); 35 | } 36 | return this.sharedObjects.get(index); 37 | } 38 | 39 | public CBORObject GetObject(EInteger bigIndex) { 40 | if (bigIndex.signum() < 0) { 41 | throw new CBORException("Unexpected index"); 42 | } 43 | if (!bigIndex.CanFitInInt32()) { 44 | throw new CBORException("Index " + bigIndex + 45 | " is bigger than supported "); 46 | } 47 | int index = bigIndex.ToInt32Checked(); 48 | if (index >= this.sharedObjects.size()) { 49 | throw new CBORException("Index " + index + " is not valid"); 50 | } 51 | return this.sharedObjects.get(index); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/upokecenter/cbor/StringOutput.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.cbor; 2 | /* 3 | Written by Peter O. 4 | Any copyright to this work is released to the Public Domain. 5 | In case this is not possible, this work is also 6 | licensed under the Unlicense: https://unlicense.org/ 7 | 8 | */ 9 | 10 | import java.io.*; 11 | 12 | final class StringOutput { 13 | private final StringBuilder builder; 14 | private final OutputStream outputStream; 15 | 16 | public StringOutput(StringBuilder builder) { 17 | this.builder = builder; 18 | this.outputStream = null; 19 | } 20 | 21 | public StringOutput(OutputStream outputStream) { 22 | this.outputStream = outputStream; 23 | this.builder = null; 24 | } 25 | 26 | public void WriteString(String str) throws java.io.IOException { 27 | if (this.outputStream != null) { 28 | if (str.length() == 1) { 29 | this.WriteCodePoint(str.charAt(0)); 30 | } else { 31 | if (com.upokecenter.util.DataUtilities.WriteUtf8( 32 | str, 33 | 0, 34 | str.length(), 35 | this.outputStream, 36 | false) < 0) { 37 | throw new IllegalArgumentException("str has an unpaired surrogate"); 38 | } 39 | } 40 | } else { 41 | this.builder.append(str); 42 | } 43 | } 44 | 45 | public void WriteString(String str, int index, int length) throws java.io.IOException { 46 | if (this.outputStream == null) { 47 | this.builder.append(str, index, (index)+(length)); 48 | } else { 49 | if (length == 1) { 50 | this.WriteCodePoint(str.charAt(index)); 51 | } else { 52 | if ( 53 | com.upokecenter.util.DataUtilities.WriteUtf8( 54 | str, 55 | index, 56 | length, 57 | this.outputStream, 58 | false) < 0) { 59 | throw new IllegalArgumentException("str has an unpaired surrogate"); 60 | } 61 | } 62 | } 63 | } 64 | 65 | public void WriteAscii(byte[] bytes, int index, int length) throws java.io.IOException { 66 | if (bytes == null) { 67 | throw new NullPointerException("bytes"); 68 | } 69 | if (index < 0) { 70 | throw new IllegalArgumentException("\"index\" (" + index + ") is not" + 71 | "\u0020greater or equal to 0"); 72 | } 73 | if (index > bytes.length) { 74 | throw new IllegalArgumentException("\"index\" (" + index + ") is not less" + 75 | "\u0020or equal to " + bytes.length); 76 | } 77 | if (length < 0) { 78 | throw new IllegalArgumentException(" (" + length + ") is not greater or" + 79 | "\u0020equal to 0"); 80 | } 81 | if (length > bytes.length) { 82 | throw new IllegalArgumentException(" (" + length + ") is not less or equal" + 83 | "\u0020to " + bytes.length); 84 | } 85 | if (bytes.length - index < length) { 86 | throw new IllegalArgumentException("\"bytes\" + \"'s length minus \" +" + 87 | "\u0020index (" + (bytes.length - index) + ") is not greater or" + 88 | "\u0020 equal to " + length); 89 | } 90 | if (this.outputStream == null) { 91 | com.upokecenter.util.DataUtilities.ReadUtf8FromBytes( 92 | bytes, 93 | index, 94 | length, 95 | this.builder, 96 | false); 97 | } else { 98 | for (int i = 0; i < length; ++i) { 99 | byte b = bytes[i + index]; 100 | if ((b & 0x7f) != b) { 101 | throw new IllegalArgumentException("str is non-ASCII"); 102 | } 103 | } 104 | this.outputStream.write(bytes, index, length); 105 | } 106 | } 107 | 108 | public void WriteCodePoint(int codePoint) throws java.io.IOException { 109 | if ((codePoint >> 7) == 0) { 110 | // Code point is in the Basic Latin range (U+0000 to U+007F) 111 | if (this.outputStream == null) { 112 | this.builder.append((char)codePoint); 113 | } else { 114 | this.outputStream.write((byte)codePoint); 115 | } 116 | return; 117 | } 118 | if (codePoint < 0) { 119 | throw new IllegalArgumentException("codePoint(" + codePoint + 120 | ") is less than 0"); 121 | } 122 | if (codePoint > 0x10ffff) { 123 | throw new IllegalArgumentException("codePoint(" + codePoint + 124 | ") is more than " + 0x10ffff); 125 | } 126 | if (this.outputStream != null) { 127 | if (codePoint < 0x80) { 128 | this.outputStream.write((byte)codePoint); 129 | } else if (codePoint <= 0x7ff) { 130 | this.outputStream.write((byte)(0xc0 | ((codePoint >> 6) & 131 | 0x1f))); 132 | this.outputStream.write((byte)(0x80 | (codePoint & 0x3f))); 133 | } else if (codePoint <= 0xffff) { 134 | if ((codePoint & 0xf800) == 0xd800) { 135 | throw new IllegalArgumentException("ch is a surrogate"); 136 | } 137 | this.outputStream.write((byte)(0xe0 | ((codePoint >> 12) & 138 | 0x0f))); 139 | this.outputStream.write((byte)(0x80 | ((codePoint >> 6) & 140 | 0x3f))); 141 | this.outputStream.write((byte)(0x80 | (codePoint & 0x3f))); 142 | } else { 143 | this.outputStream.write((byte)(0xf0 | ((codePoint >> 18) & 144 | 0x07))); 145 | this.outputStream.write((byte)(0x80 | ((codePoint >> 12) & 146 | 0x3f))); 147 | this.outputStream.write((byte)(0x80 | ((codePoint >> 6) & 148 | 0x3f))); 149 | this.outputStream.write((byte)(0x80 | (codePoint & 0x3f))); 150 | } 151 | } else { 152 | if ((codePoint & 0xfff800) == 0xd800) { 153 | throw new IllegalArgumentException("ch is a surrogate"); 154 | } 155 | if (codePoint <= 0xffff) { 156 | { 157 | this.builder.append((char)codePoint); 158 | } 159 | } else if (codePoint <= 0x10ffff) { 160 | this.builder.append((char)((((codePoint - 0x10000) >> 10) & 161 | 0x3ff) | 0xd800)); 162 | this.builder.append((char)(((codePoint - 0x10000) & 0x3ff) | 163 | 0xdc00)); 164 | } 165 | } 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /src/main/java/com/upokecenter/cbor/StringRefs.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.cbor; 2 | /* 3 | Written by Peter O. 4 | Any copyright to this work is released to the Public Domain. 5 | In case this is not possible, this work is also 6 | licensed under the Unlicense: https://unlicense.org/ 7 | 8 | */ 9 | 10 | import java.util.*; 11 | import com.upokecenter.numbers.*; 12 | 13 | /** 14 | * Implements CBOR string references, described at {@code 15 | * http://cbor.schmorp.de/stringref}. 16 | */ 17 | class StringRefs { 18 | private final ArrayList> stack; 19 | 20 | public StringRefs() { 21 | this.stack = new ArrayList>(); 22 | ArrayList firstItem = new ArrayList(); 23 | this.stack.add(firstItem); 24 | } 25 | 26 | public void Push() { 27 | ArrayList firstItem = new ArrayList(); 28 | this.stack.add(firstItem); 29 | } 30 | 31 | public void Pop() { 32 | this.stack.remove(this.stack.size() - 1); 33 | } 34 | 35 | public void AddStringIfNeeded(CBORObject str, int lengthHint) { 36 | boolean addStr = false; 37 | ArrayList lastList = this.stack.get(this.stack.size() - 1); 38 | if (lastList.size() < 24) { 39 | addStr |= lengthHint >= 3; 40 | } else if (lastList.size() < 256) { 41 | addStr |= lengthHint >= 4; 42 | } else if (lastList.size() < 65536) { 43 | addStr |= lengthHint >= 5; 44 | } else { 45 | // NOTE: lastList's size can't be higher than (2^64)-1 46 | addStr |= lengthHint >= 7; 47 | } 48 | // NOTE: An additional branch, with lengthHint >= 11, would 49 | // be needed if the size could be higher than (2^64)-1 50 | if (addStr) { 51 | lastList.add(str); 52 | } 53 | } 54 | 55 | public CBORObject GetString(long smallIndex) { 56 | if (smallIndex < 0) { 57 | throw new CBORException("Unexpected index"); 58 | } 59 | if (smallIndex > Integer.MAX_VALUE) { 60 | throw new CBORException("Index " + smallIndex + 61 | " is bigger than supported "); 62 | } 63 | int index = (int)smallIndex; 64 | ArrayList lastList = this.stack.get(this.stack.size() - 1); 65 | if (index >= lastList.size()) { 66 | throw new CBORException("Index " + index + " is not valid"); 67 | } 68 | CBORObject ret = lastList.get(index); 69 | // Byte strings are mutable, so make a copy 70 | return (ret.getType() == CBORType.ByteString) ? 71 | CBORObject.FromByteArray(ret.GetByteString()) : ret; 72 | } 73 | 74 | public CBORObject GetString(EInteger bigIndex) { 75 | if (bigIndex.signum() < 0) { 76 | throw new CBORException("Unexpected index"); 77 | } 78 | if (!bigIndex.CanFitInInt32()) { 79 | throw new CBORException("Index " + bigIndex + 80 | " is bigger than supported "); 81 | } 82 | int index = bigIndex.ToInt32Checked(); 83 | ArrayList lastList = this.stack.get(this.stack.size() - 1); 84 | if (index >= lastList.size()) { 85 | throw new CBORException("Index " + index + " is not valid"); 86 | } 87 | CBORObject ret = lastList.get(index); 88 | // Byte strings are mutable, so make a copy 89 | return (ret.getType() == CBORType.ByteString) ? 90 | CBORObject.FromByteArray(ret.GetByteString()) : ret; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/test/java/com/upokecenter/test/AppResources.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.test; 2 | 3 | import java.util.*; 4 | import com.upokecenter.cbor.CBORObject; 5 | 6 | final class AppResources { 7 | 8 | ResourceBundle mgr; 9 | 10 | public AppResources(String name) { 11 | mgr = ResourceBundle.getBundle(name); 12 | } 13 | 14 | public CBORObject GetJSON(String name) { 15 | return CBORObject.FromJSONString(GetString(name)); 16 | } 17 | 18 | public String GetString(String name) { 19 | return mgr.getString(name); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/test/java/com/upokecenter/test/BEncodingTest.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.test; 2 | 3 | import java.io.*; 4 | import org.junit.Assert; 5 | import org.junit.Test; 6 | import com.upokecenter.util.*; 7 | import com.upokecenter.cbor.*; 8 | 9 | public class BEncodingTest { 10 | private static CBORObject EncodingFromBytes(byte[] b) { 11 | try { 12 | java.io.ByteArrayInputStream s = null; 13 | try { 14 | s = new java.io.ByteArrayInputStream(b); 15 | 16 | return BEncoding.Read(s); 17 | } 18 | finally { 19 | try { if (s != null) { s.close(); } } catch (java.io.IOException ex) {} 20 | } 21 | } catch (IOException ex) { 22 | throw new CBORException("", ex); 23 | } 24 | } 25 | 26 | private static byte[] EncodingToBytes(CBORObject b) { 27 | try { 28 | java.io.ByteArrayOutputStream ms = null; 29 | try { 30 | ms = new java.io.ByteArrayOutputStream(); 31 | 32 | BEncoding.Write(b, ms); 33 | return ms.toByteArray(); 34 | } 35 | finally { 36 | try { if (ms != null) { ms.close(); } } catch (java.io.IOException ex) {} 37 | } 38 | } catch (IOException ex) { 39 | throw new CBORException("", ex); 40 | } 41 | } 42 | 43 | public static void DoTestLong(long value) { 44 | String b = "i" + TestCommon.LongToString(value) + "e"; 45 | CBORObject beo = EncodingFromBytes(com.upokecenter.util.DataUtilities.GetUtf8Bytes(b, 46 | false)); 47 | Assert.assertEquals(value, beo.AsNumber().ToInt64Checked()); 48 | String newb = com.upokecenter.util.DataUtilities.GetUtf8String(EncodingToBytes(beo), false); 49 | Assert.assertEquals(b, newb); 50 | } 51 | 52 | public static void DoTestString(String value) { 53 | String b = com.upokecenter.util.DataUtilities.GetUtf8Length(value, false) + ":" + value; 54 | CBORObject beo = EncodingFromBytes(com.upokecenter.util.DataUtilities.GetUtf8Bytes(b, 55 | false)); 56 | Assert.assertEquals(value, beo.AsString()); 57 | String newb = com.upokecenter.util.DataUtilities.GetUtf8String(EncodingToBytes(beo), false); 58 | Assert.assertEquals(b, newb); 59 | } 60 | 61 | @Test(timeout = 30000) 62 | public void TestLong() { 63 | DoTestLong(0); 64 | DoTestLong(-1); 65 | DoTestLong(Integer.MIN_VALUE); 66 | DoTestLong(Integer.MAX_VALUE); 67 | DoTestLong(Long.MIN_VALUE); 68 | DoTestLong(Long.MAX_VALUE); 69 | } 70 | 71 | @Test(timeout = 30000) 72 | public void TestList() { 73 | CBORObject beo = CBORObject.NewArray(); 74 | beo.Add(ToObjectTest.TestToFromObjectRoundTrip(1)); 75 | beo.Add(ToObjectTest.TestToFromObjectRoundTrip("two")); 76 | beo.Add(ToObjectTest.TestToFromObjectRoundTrip(3)); 77 | beo.Add(ToObjectTest.TestToFromObjectRoundTrip("four")); 78 | Assert.assertEquals(4, beo.size()); 79 | Assert.assertEquals(1, beo.get(0).AsNumber().ToInt64Checked()); 80 | { 81 | String stringTemp = beo.get(1).AsString(); 82 | Assert.assertEquals( 83 | "two", 84 | stringTemp); 85 | } 86 | Assert.assertEquals(3, beo.get(2).AsNumber().ToInt64Checked()); 87 | { 88 | String stringTemp = beo.get(3).AsString(); 89 | Assert.assertEquals( 90 | "four", 91 | stringTemp); 92 | } 93 | byte[] b = EncodingToBytes(beo); 94 | beo = EncodingFromBytes(b); 95 | Assert.assertEquals(4, beo.size()); 96 | Assert.assertEquals(1, beo.get(0).AsNumber().ToInt64Checked()); 97 | { 98 | String stringTemp = beo.get(1).AsString(); 99 | Assert.assertEquals( 100 | "two", 101 | stringTemp); 102 | } 103 | Assert.assertEquals(3, beo.get(2).AsNumber().ToInt64Checked()); 104 | { 105 | String stringTemp = beo.get(3).AsString(); 106 | Assert.assertEquals( 107 | "four", 108 | stringTemp); 109 | } 110 | } 111 | 112 | @Test(timeout = 30000) 113 | public void TestDictionary() { 114 | CBORObject beo = CBORObject.NewMap(); 115 | beo.set("zero",ToObjectTest.TestToFromObjectRoundTrip(1)); 116 | beo.set("one",ToObjectTest.TestToFromObjectRoundTrip("two")); 117 | beo.set("two",ToObjectTest.TestToFromObjectRoundTrip(3)); 118 | beo.set("three",ToObjectTest.TestToFromObjectRoundTrip("four")); 119 | Assert.assertEquals(4, beo.size()); 120 | Assert.assertEquals(1, beo.get("zero").AsNumber().ToInt64Checked()); 121 | { 122 | String stringTemp = beo.get("one").AsString(); 123 | Assert.assertEquals( 124 | "two", 125 | stringTemp); 126 | } 127 | Assert.assertEquals(3, beo.get("two").AsNumber().ToInt64Checked()); 128 | { 129 | String stringTemp = beo.get("three").AsString(); 130 | Assert.assertEquals( 131 | "four", 132 | stringTemp); 133 | } 134 | byte[] b = EncodingToBytes(beo); 135 | beo = EncodingFromBytes(b); 136 | Assert.assertEquals(4, beo.size()); 137 | Assert.assertEquals(1, beo.get("zero").AsNumber().ToInt64Checked()); 138 | { 139 | String stringTemp = beo.get("one").AsString(); 140 | Assert.assertEquals( 141 | "two", 142 | stringTemp); 143 | } 144 | Assert.assertEquals(3, beo.get("two").AsNumber().ToInt64Checked()); 145 | { 146 | String stringTemp = beo.get("three").AsString(); 147 | Assert.assertEquals( 148 | "four", 149 | stringTemp); 150 | } 151 | } 152 | 153 | @Test(timeout = 30000) 154 | public void TestString() { 155 | DoTestString(""); 156 | DoTestString(" "); 157 | DoTestString("test"); 158 | 159 | DoTestString( 160 | TestCommon.Repeat("three", 15)); 161 | DoTestString("te\u007fst"); 162 | DoTestString("te\u0080st"); 163 | DoTestString("te\u3000st"); 164 | DoTestString("te\u07ffst"); 165 | DoTestString("te\u0800st"); 166 | DoTestString("te\uffffst"); 167 | DoTestString("te\ud7ffst"); 168 | DoTestString("te\ue000st"); 169 | DoTestString("te\ud800\udc00st"); 170 | DoTestString("te\udbff\udc00st"); 171 | DoTestString("te\ud800\udfffst"); 172 | DoTestString("te\udbff\udfffst"); 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /src/test/java/com/upokecenter/test/Base64.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.test; 2 | /* 3 | Written by Peter O. 4 | Any copyright to this work is released to the Public Domain. 5 | In case this is not possible, this work is also 6 | licensed under the Unlicense: https://unlicense.org/ 7 | 8 | */ 9 | 10 | final class Base64 { 11 | private Base64() { 12 | } 13 | private static final String Base64URL = 14 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; 15 | 16 | private static final String Base64Classic = 17 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 18 | 19 | public static void WriteBase64( 20 | StringOutput writer, 21 | byte[] data, 22 | int offset, 23 | int count, 24 | boolean padding) throws java.io.IOException { 25 | WriteBase64(writer, data, offset, count, true, padding); 26 | } 27 | 28 | public static void WriteBase64URL( 29 | StringOutput writer, 30 | byte[] data, 31 | int offset, 32 | int count, 33 | boolean padding) throws java.io.IOException { 34 | WriteBase64(writer, data, offset, count, false, padding); 35 | } 36 | 37 | private static void WriteBase64( 38 | StringOutput writer, 39 | byte[] data, 40 | int offset, 41 | int count, 42 | boolean classic, 43 | boolean padding) throws java.io.IOException { 44 | if (writer == null) { 45 | throw new NullPointerException("writer"); 46 | } 47 | if (offset < 0) { 48 | throw new IllegalArgumentException("offset(" + offset + ") is less than " + 49 | "0 "); 50 | } 51 | if (offset > data.length) { 52 | throw new IllegalArgumentException("offset(" + offset + ") is more than " + 53 | data.length); 54 | } 55 | if (count < 0) { 56 | throw new IllegalArgumentException("count(" + count + ") is less than " + 57 | "0 "); 58 | } 59 | if (count > data.length) { 60 | throw new IllegalArgumentException("count(" + count + ") is more than " + 61 | data.length); 62 | } 63 | if (data.length - offset < count) { 64 | throw new IllegalArgumentException("data's length minus " + offset + "(" + 65 | (data.length - offset) + ") is less than " + count); 66 | } 67 | String alphabet = classic ? Base64Classic : Base64URL; 68 | int length = offset + count; 69 | byte[] buffer = new byte[32]; 70 | int bufferOffset = 0; 71 | int i; 72 | for (i = offset; i < (length - 2); i += 3) { 73 | if (bufferOffset >= buffer.length) { 74 | writer.WriteAscii(buffer, 0, bufferOffset); 75 | bufferOffset = 0; 76 | } 77 | buffer[bufferOffset++] = (byte)alphabet.charAt((data[i] >> 2) & 63); 78 | buffer[bufferOffset++] = (byte)alphabet.charAt(((data[i] & 3) << 4) + 79 | ((data[i + 1] >> 4) & 15)); 80 | buffer[bufferOffset++] = (byte)alphabet.charAt(((data[i + 1] & 15) << 2) + 81 | ((data[i + 2] >> 6) & 3)); 82 | buffer[bufferOffset++] = (byte)alphabet.charAt(data[i + 2] & 63); 83 | } 84 | int lenmod3 = count % 3; 85 | if (lenmod3 != 0) { 86 | if (bufferOffset >= buffer.length) { 87 | writer.WriteAscii(buffer, 0, bufferOffset); 88 | bufferOffset = 0; 89 | } 90 | i = length - lenmod3; 91 | buffer[bufferOffset++] = (byte)alphabet.charAt((data[i] >> 2) & 63); 92 | if (lenmod3 == 2) { 93 | buffer[bufferOffset++] = (byte)alphabet.charAt(((data[i] & 3) << 4) + 94 | ((data[i + 1] >> 4) & 15)); 95 | buffer[bufferOffset++] = (byte)alphabet.charAt((data[i + 1] & 15) << 2); 96 | if (padding) { 97 | buffer[bufferOffset++] = (byte)'='; 98 | } 99 | } else { 100 | buffer[bufferOffset++] = (byte)alphabet.charAt((data[i] & 3) << 4); 101 | if (padding) { 102 | buffer[bufferOffset++] = (byte)'='; 103 | buffer[bufferOffset++] = (byte)'='; 104 | } 105 | } 106 | } 107 | if (bufferOffset >= 0) { 108 | writer.WriteAscii(buffer, 0, bufferOffset); 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/test/java/com/upokecenter/test/CBORDataUtilitiesTest.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.test; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | import com.upokecenter.cbor.*; 6 | import com.upokecenter.numbers.*; 7 | 8 | public class CBORDataUtilitiesTest { 9 | private static void AssertNegative(CBORObject obj) { 10 | if (!(obj.AsNumber().IsNegative())) { 11 | Assert.fail(); 12 | } 13 | CBORTestCommon.AssertRoundTrip(obj); 14 | } 15 | 16 | @Test(timeout = 30000) 17 | public void TestPreserveNegativeZero() { 18 | CBORObject cbor; 19 | JSONOptions pnz = new JSONOptions("numberconversion=full;preservenegativezero=true"); 20 | cbor = CBORDataUtilities.ParseJSONNumber("-0", pnz); 21 | { 22 | String stringTemp = cbor.ToObject(EDecimal.class).toString(); 23 | Assert.assertEquals( 24 | "-0", 25 | stringTemp); 26 | } 27 | cbor = CBORDataUtilities.ParseJSONNumber("-0e-1", pnz); 28 | { 29 | String stringTemp = cbor.ToObject(EDecimal.class).toString(); 30 | Assert.assertEquals( 31 | "-0.0", 32 | stringTemp); 33 | } 34 | cbor = CBORDataUtilities.ParseJSONNumber("-0e1", pnz); 35 | { 36 | String stringTemp = cbor.ToObject(EDecimal.class).toString(); 37 | Assert.assertEquals( 38 | "-0E+1", 39 | stringTemp); 40 | } 41 | cbor = CBORDataUtilities.ParseJSONNumber("-0.0e1", pnz); 42 | { 43 | String stringTemp = cbor.ToObject(EDecimal.class).toString(); 44 | Assert.assertEquals( 45 | "-0", 46 | stringTemp); 47 | } 48 | cbor = CBORDataUtilities.ParseJSONNumber("-0.0", pnz); 49 | { 50 | String stringTemp = cbor.ToObject(EDecimal.class).toString(); 51 | Assert.assertEquals( 52 | "-0.0", 53 | stringTemp); 54 | } 55 | String[] assertNegatives = new String[] { 56 | "-0", 57 | "-0.0", 58 | "-0.0000", 59 | "-0e0", 60 | "-0e+1", 61 | "-0e-1", 62 | "-0e+999999999999", 63 | "-0e-999999999999", 64 | "-0.0e0", 65 | "-0.0e+1", 66 | "-0.0e-1", 67 | "-0.0e+999999999999", 68 | "-0.0e-999999999999", 69 | "-0.000e0", 70 | "-0.000e+0", 71 | "-0.000e-0", 72 | "-0.000e1", 73 | "-0.000e+1", 74 | "-0.000e-1", 75 | "-0.000e+999999999999", 76 | "-0.000e-999999999999", 77 | }; 78 | for (String str : assertNegatives) { 79 | cbor = CBORDataUtilities.ParseJSONNumber(str, pnz); 80 | AssertNegative(cbor); 81 | } 82 | } 83 | 84 | // testing obsolete method 85 | @Test(timeout = 30000) 86 | public void TestParseJSONNumberSubstring() { 87 | String tstr = 88 | 89 | "-3.00931381333368754713014659613049757554804012787921371662913692598770508705049030832574634419795955864174175076186656951904296875000E-49"; 90 | try { 91 | CBORDataUtilities.ParseJSONNumber( 92 | "xyzxyz" + tstr, 93 | 6, 94 | tstr.length(), 95 | new JSONOptions("numberconversion=full")); 96 | } catch (Exception ex) { 97 | Assert.fail(ex.toString()); 98 | throw new IllegalStateException("", ex); 99 | } 100 | } 101 | 102 | @Test(timeout = 30000) 103 | public void TestParseJSONNumberNegativeZero() { 104 | String[] strings = new String[] { 105 | "-0", "0", "-0E+0", "0", "-0E-0", "0", "-0E-1", "0.0", 106 | "-0.00", "0.00", "-0.00E+0", "0.00", "-0.00E-0", "0.00", 107 | "-0.00E-1", "0.000", 108 | }; 109 | for (int i = 0; i < strings.length; i += 2) { 110 | EDecimal jsonDecimal = (EDecimal)CBORDataUtilities 111 | .ParseJSONNumber(strings[i], new 112 | 113 | JSONOptions("numberconversion=full;preservenegativezero=false")).ToObject( 114 | EDecimal.class); 115 | Assert.assertEquals( 116 | strings[i + 1], 117 | jsonDecimal.toString()); 118 | } 119 | } 120 | 121 | private static final String[] GoodJsonNumbers = { 122 | "5.2", "5e+1", "-5.2", "-5e+1", 123 | "5.2", "5e+01", "-5.2", "-5e+01", 124 | "5.20000", "5.000e+01", "-5.2000", "-5e+01", 125 | "5.000e-01", "-5e-01", 126 | "5.000e01", "-5e01", 127 | }; 128 | 129 | private static final String[] BadJsonNumbers = { 130 | null, "100.", "-100.", "100.e+20", "-100.e+20", 131 | "100.e20", "+0.1", "0.", "-0.", "+0", 132 | "=0g.1", "0g.1", "0.e+20", "-0.e20", "-0.e+20", 133 | "0.e20", "", "xyz", "Infinity", "-Infinity", 134 | "true", ".1", ".01", "-.1", "-.01", "-xyz", "-true", 135 | "0..1", "-0..1", "0xyz", "-0xyz", 136 | "0.1xyz", "0.xyz", "0.5exyz", "0.5q+88", 137 | "0.5ee88", "-5e", "5e", "88ee99", 138 | "-5e-2x", "-5e+2x", "5e-2x", "5e+2x", 139 | "0.5e+xyz", "0.5e+88xyz", 140 | "00000", "00.5e+2", "00.5", "00.5e-2", "00.5e-999", "00.5e999", 141 | "00000", "00.5E+2", "00.5", "00.5E-2", "00.5E-999", "00.5e999", 142 | "00001", "01.5e+2", "01.5", "01.5e-2", "01.5e-999", "01.5e999", 143 | "00001", "01.5E+2", "01.5", "01.5E-2", "01.5E-999", "01.5e999", 144 | "--1", "--0", "--1.5E+2", "--1.5", "--1.5E-2", "--1.5E-999", 145 | "--1.5E999", 146 | "-00000", "-00.5e+2", "-00.5", "-00.5e-2", "-00.5e-999", "-00.5e999", 147 | "-00000", "-00.5E+2", "-00.5", "-00.5E-2", "-00.5E-999", "-00.5E999", 148 | "-00001", "-01.5e+2", "-01.5", "-01.5e-2", "-01.5e-999", "-01.5e999", 149 | "-00001", "-01.5E+2", "-01.5", "-01.5E-2", "-01.5E-999", "-01.5E999", 150 | "0x1", "0xf", "0x20", "0x01", ".2", ".05", 151 | "-0x1", "-0xf", "-0x20", "-0x01", "-.2", "-.05", 152 | "23.", "23.e-2", "23.e0", "23.e1", "0.", 153 | }; 154 | 155 | @Test(timeout = 30000) 156 | public void TestParseJSONNumber() { 157 | for (String str : BadJsonNumbers) { 158 | if (CBORDataUtilities.ParseJSONNumber(str) != null) { 159 | Assert.fail(str); 160 | } 161 | if (CBORDataUtilities.ParseJSONNumber(str, 162 | new JSONOptions("numberconversion=full")) != null) { 163 | Assert.fail(str); 164 | } 165 | if (CBORDataUtilities.ParseJSONNumber(str, new 166 | JSONOptions("numberconversion=full;preservenegativezero=true")) != 167 | null) { 168 | Assert.fail(str); 169 | } 170 | if (CBORDataUtilities.ParseJSONNumber(str, new 171 | JSONOptions("numberconversion=full;preservenegativezero=false")) != 172 | null) { 173 | Assert.fail(str); 174 | } 175 | } 176 | CBORObject cbor = CBORDataUtilities.ParseJSONNumber("2e-2147483648", 177 | new JSONOptions("numberconversion=full")); 178 | CBORTestCommon.AssertJSONSer(cbor, "2E-2147483648"); 179 | for (String str : GoodJsonNumbers) { 180 | if (CBORDataUtilities.ParseJSONNumber(str) == null) { 181 | Assert.fail(str); 182 | } 183 | if (CBORDataUtilities.ParseJSONNumber(str, new 184 | JSONOptions("numberconversion=full;preservenegativezero=true")) == 185 | null) { 186 | Assert.fail(str); 187 | } 188 | if (CBORDataUtilities.ParseJSONNumber(str, new 189 | JSONOptions("numberconversion=full;preservenegativezero=false")) == 190 | null) { 191 | Assert.fail(str); 192 | } 193 | } 194 | { 195 | CBORNumber objectTemp = 196 | ToObjectTest.TestToFromObjectRoundTrip(230).AsNumber(); 197 | CBORNumber objectTemp2 = CBORDataUtilities.ParseJSONNumber("23.0e01", 198 | new JSONOptions("numberconversion=full")).AsNumber(); 199 | TestCommon.CompareTestEqual(objectTemp, objectTemp2); 200 | } 201 | { 202 | CBORNumber objectTemp = 203 | ToObjectTest.TestToFromObjectRoundTrip(23).AsNumber(); 204 | CBORNumber objectTemp2 = 205 | CBORDataUtilities.ParseJSONNumber("23.0e00", new 206 | JSONOptions("numberconversion=full")).AsNumber(); 207 | TestCommon.CompareTestEqual(objectTemp, objectTemp2); 208 | } 209 | cbor = CBORDataUtilities.ParseJSONNumber( 210 | "1e+99999999999999999999999999", 211 | new JSONOptions("numberconversion=full")); 212 | if (!(cbor != null)) { 213 | Assert.fail(); 214 | } 215 | if (cbor.AsNumber().CanFitInDouble()) { 216 | Assert.fail(); 217 | } 218 | CBORTestCommon.AssertRoundTrip(cbor); 219 | } 220 | } 221 | -------------------------------------------------------------------------------- /src/test/java/com/upokecenter/test/CBORExceptionTest.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.test; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | import com.upokecenter.cbor.*; 6 | 7 | public class CBORExceptionTest { 8 | @Test(timeout = 30000) 9 | public void TestConstructor() { 10 | try { 11 | throw new CBORException("Test exception"); 12 | } catch (CBORException ex) { 13 | // NOTE: Intentionally empty 14 | } catch (Exception ex) { 15 | Assert.fail(ex.toString()); 16 | throw new IllegalStateException("", ex); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/test/java/com/upokecenter/test/CBORGenerator.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.test; 2 | 3 | import com.upokecenter.util.*; 4 | 5 | public final class CBORGenerator { 6 | private static final class ByteWriter { 7 | private byte[] bytes = new byte[64]; 8 | 9 | public ByteWriter Write(int b) { 10 | if (this.getByteLength() < this.bytes.length) { 11 | this.bytes[this.getByteLength()] = (byte)b; 12 | this.setByteLength(1 + this.getByteLength()); 13 | } else { 14 | byte[] newbytes = new byte[this.bytes.length * 2]; 15 | System.arraycopy(this.bytes, 0, newbytes, 0, this.bytes.length); 16 | this.bytes = newbytes; 17 | this.bytes[this.getByteLength()] = (byte)b; 18 | this.setByteLength(1 + this.getByteLength()); 19 | } 20 | return this; 21 | } 22 | 23 | public final int getByteLength() { return propVarbytelength; } 24 | public final void setByteLength(int value) { propVarbytelength = value; } 25 | private int propVarbytelength; 26 | 27 | public byte[] ToBytes() { 28 | byte[] newbytes = new byte[this.getByteLength()]; 29 | System.arraycopy(this.bytes, 0, newbytes, 0, this.getByteLength()); 30 | return newbytes; 31 | } 32 | } 33 | 34 | private static void GenerateArgument( 35 | IRandomGenExtended r, 36 | int majorType, 37 | int len, 38 | ByteWriter bs) { 39 | int maxArg = 4; 40 | int minArg = (len < 0x18) ? 0 : ((len <= 0xff) ? 1 : 41 | ((len <= 0xffff) ? 2 : 3)); 42 | int arg = minArg + r.GetInt32(maxArg - minArg + 1); 43 | int sh; 44 | switch (arg) { 45 | case 0: 46 | bs.Write((majorType * 0x20) + len); 47 | break; 48 | case 1: 49 | bs.Write((majorType * 0x20) + 0x18); 50 | bs.Write(len & 0xff); 51 | break; 52 | case 2: 53 | bs.Write((majorType * 0x20) + 0x19); 54 | sh = 8; 55 | for (int i = 0; i < 2; ++i) { 56 | bs.Write((len >> sh) & 0xff); 57 | sh -= 8; 58 | } 59 | break; 60 | case 3: 61 | bs.Write((majorType * 0x20) + 0x1a); 62 | sh = 24; 63 | for (int i = 0; i < 4; ++i) { 64 | bs.Write((len >> sh) & 0xff); 65 | sh -= 8; 66 | } 67 | break; 68 | case 4: 69 | bs.Write((majorType * 0x20) + 0x1b); 70 | for (int i = 0; i < 4; ++i) { 71 | bs.Write(0); 72 | } 73 | sh = 24; 74 | for (int i = 0; i < 4; ++i) { 75 | bs.Write((len >> sh) & 0xff); 76 | sh -= 8; 77 | } 78 | break; 79 | } 80 | } 81 | 82 | private static final int[] 83 | ValueMajorTypes = { 84 | 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 85 | 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 6, 6, 7, 7, 7, 7, 7, 7, 86 | }; 87 | 88 | private static final int[] 89 | ValueMajorTypesHighDepth = { 90 | 0, 1, 2, 3, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 91 | 5, 5, 5, 5, 5, 5, 6, 7, 92 | }; 93 | 94 | private static final int[] ValueMajorTypesHighLength = { 95 | 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 6, 96 | 6, 7, 7, 7, 7, 7, 7, 97 | }; 98 | 99 | private static void GenerateUtf8(IRandomGenExtended ra, ByteWriter bs, int 100 | length) { 101 | for (int i = 0; i < length;) { 102 | int r = ra.GetInt32(10); 103 | if (r > 0) { 104 | bs.Write(ra.GetInt32(128)); 105 | ++i; 106 | } else { 107 | r = ra.GetInt32(3); 108 | if (r == 0 && length - i >= 2) { 109 | r = 0xc2 + ra.GetInt32(0xdf - 0xc2 + 1); 110 | bs.Write(r); 111 | bs.Write(0x80 + ra.GetInt32(0x40)); 112 | i += 2; 113 | } else if (r == 1 && length - i >= 3) { 114 | r = 0xe0 + ra.GetInt32(16); 115 | bs.Write(r); 116 | int lower = (r == 0xe0) ? 0xa0 : 0x80; 117 | int upper = (r == 0xed) ? 0x9f : 0xbf; 118 | r = lower + ra.GetInt32(upper - lower + 1); 119 | bs.Write(r); 120 | bs.Write(0x80 + ra.GetInt32(0x40)); 121 | i += 3; 122 | } else if (r == 2 && length - i >= 4) { 123 | r = 0xf0 + ra.GetInt32(5); 124 | bs.Write(r); 125 | int lower = (r == 0xf0) ? 0x90 : 0x80; 126 | int upper = (r == 0xf4) ? 0x8f : 0xbf; 127 | r = lower + ra.GetInt32(upper - lower + 1); 128 | bs.Write(r); 129 | bs.Write(0x80 + ra.GetInt32(0x40)); 130 | bs.Write(0x80 + ra.GetInt32(0x40)); 131 | i += 4; 132 | } 133 | } 134 | } 135 | } 136 | 137 | private void GenerateSmall(IRandomGenExtended r, int depth, ByteWriter bs) { 138 | int v = r.GetInt32(100); 139 | if (v < 25) { 140 | GenerateArgument(r, 0, r.GetInt32(100), bs); 141 | } else if (v < 35) { 142 | bs.Write(0x41); 143 | bs.Write(0x20); 144 | } else if (v < 45) { 145 | bs.Write(0x41); 146 | bs.Write(0x20); 147 | } else if (v < 50) { 148 | bs.Write(0x81); 149 | this.GenerateSmall(r, depth + 1, bs); 150 | } else if (v < 53) { 151 | bs.Write(0xa2); 152 | bs.Write(0xf7); 153 | bs.Write(0xf6); 154 | this.GenerateSmall(r, depth + 1, bs); 155 | bs.Write(0xf5); 156 | } else if (v < 80) { 157 | bs.Write(0x40); 158 | } else if (v < 100) { 159 | bs.Write(0x60); 160 | } 161 | } 162 | private void Generate(IRandomGenExtended r, int depth, ByteWriter bs) { 163 | int majorType = ValueMajorTypes[r.GetInt32(ValueMajorTypes.length)]; 164 | if (depth > 6) { 165 | majorType = ValueMajorTypesHighDepth[r.GetInt32( 166 | ValueMajorTypesHighDepth.length)]; 167 | } 168 | if (bs.getByteLength() > 2000000) { 169 | majorType = ValueMajorTypesHighLength[r.GetInt32( 170 | ValueMajorTypesHighLength.length)]; 171 | } 172 | if (majorType == 3 || majorType == 2) { // Byte and text strings 173 | int len = r.GetInt32(1000); 174 | if (r.GetInt32(50) == 0 && depth < 2) { 175 | long v = (long)r.GetInt32(100000) * r.GetInt32(100000); 176 | len = (int)(v / 100000); 177 | } else if (depth > 6) { 178 | len = r.GetInt32(100) == 0 ? 1 : 0; 179 | } else if (depth > 2) { 180 | len = r.GetInt32(16) + 1; 181 | } 182 | // TODO: Ensure key uniqueness 183 | if (r.GetInt32(2) == 0) { 184 | // Indefinite length 185 | bs.Write(0x1f + (majorType * 0x20)); 186 | while (len > 0) { 187 | int sublen = r.GetInt32(len + 1); 188 | GenerateArgument(r, majorType, sublen, bs); 189 | if (majorType == 3) { 190 | GenerateUtf8(r, bs, sublen); 191 | } else { 192 | for (int i = 0; i < sublen; ++i) { 193 | bs.Write(r.GetInt32(256)); 194 | } 195 | } 196 | len -= sublen; 197 | } 198 | bs.Write(0xff); 199 | } else { 200 | // Definite length 201 | GenerateArgument(r, majorType, len, bs); 202 | if (majorType == 3) { 203 | GenerateUtf8(r, bs, len); 204 | } else { 205 | for (int i = 0; i < len; ++i) { 206 | bs.Write(r.GetInt32(256)); 207 | } 208 | } 209 | } 210 | return; 211 | } else if (majorType == 4 || majorType == 5) { // Arrays and maps 212 | int len = r.GetInt32(8); 213 | if (r.GetInt32(50) == 0 && depth < 2) { 214 | long v = (long)r.GetInt32(1000) * r.GetInt32(1000); 215 | len = (int)(v / 1000); 216 | } else if (depth > 6) { 217 | len = r.GetInt32(100) == 0 ? 1 : 0; 218 | } else if (depth > 2) { 219 | len = r.GetInt32(3) + 1; 220 | } 221 | if (depth > 6) { 222 | len = r.GetInt32(100) < 50 ? 1 : (r.GetInt32(100) < 10 ? 2 : 0); 223 | } 224 | boolean indefiniteLength = r.GetInt32(2) == 0; 225 | if (indefiniteLength) { 226 | bs.Write(0x1f + (majorType * 0x20)); 227 | } else { 228 | GenerateArgument(r, majorType, len, bs); 229 | } 230 | for (int i = 0; i < len; ++i) { 231 | if (depth > 6) { 232 | this.GenerateSmall(r, depth + 1, bs); 233 | } else { 234 | this.Generate(r, depth + 1, bs); 235 | } 236 | if (majorType == 5) { 237 | this.Generate(r, depth + 1, bs); 238 | } 239 | } 240 | if (indefiniteLength) { 241 | bs.Write(0xff); 242 | } 243 | return; 244 | } 245 | int arg = r.GetInt32(5); 246 | switch (arg) { 247 | case 0: 248 | bs.Write((majorType * 0x20) + r.GetInt32(0x18)); 249 | break; 250 | case 1: 251 | bs.Write((majorType * 0x20) + 0x18); 252 | if (majorType == 7) { 253 | bs.Write(32 + r.GetInt32(224)); 254 | } else { 255 | bs.Write(r.GetInt32(256)); 256 | } 257 | break; 258 | case 2: 259 | bs.Write((majorType * 0x20) + 0x19); 260 | for (int i = 0; i < 2; ++i) { 261 | bs.Write(r.GetInt32(256)); 262 | } 263 | break; 264 | case 3: 265 | bs.Write((majorType * 0x20) + 0x1a); 266 | for (int i = 0; i < 4; ++i) { 267 | bs.Write(r.GetInt32(256)); 268 | } 269 | break; 270 | case 4: 271 | bs.Write((majorType * 0x20) + 0x1b); 272 | for (int i = 0; i < 8; ++i) { 273 | bs.Write(r.GetInt32(256)); 274 | } 275 | break; 276 | } 277 | if (majorType == 6) { // Tags 278 | this.Generate(r, depth + 1, bs); 279 | } 280 | } 281 | 282 | public byte[] Generate(IRandomGenExtended random) { 283 | ByteWriter bs = new ByteWriter(); 284 | if (random == null) { 285 | throw new NullPointerException("random"); 286 | } 287 | this.Generate(random, 0, bs); 288 | byte[] ret = bs.ToBytes(); 289 | return ret; 290 | } 291 | } 292 | -------------------------------------------------------------------------------- /src/test/java/com/upokecenter/test/CBORTypeMapperTest.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.test; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | import com.upokecenter.cbor.*; 6 | 7 | public class CBORTypeMapperTest { 8 | @Test(timeout = 30000) 9 | public void TestAddTypeName() { 10 | CBORTypeMapper tm = new CBORTypeMapper(); 11 | try { 12 | tm.AddTypeName(null); 13 | Assert.fail("Should have failed"); 14 | } catch (NullPointerException ex) { 15 | // NOTE: Intentionally empty 16 | } catch (Exception ex) { 17 | Assert.fail(ex.toString()); 18 | throw new IllegalStateException("", ex); 19 | } 20 | try { 21 | tm.AddTypeName(""); 22 | Assert.fail("Should have failed"); 23 | } catch (IllegalArgumentException ex) { 24 | // NOTE: Intentionally empty 25 | } catch (Exception ex) { 26 | Assert.fail(ex.toString()); 27 | throw new IllegalStateException("", ex); 28 | } 29 | try { 30 | tm.AddTypeName("java.net.URI"); 31 | } catch (Exception ex) { 32 | Assert.fail(ex.toString()); 33 | throw new IllegalStateException("", ex); 34 | } 35 | } 36 | 37 | @Test(timeout = 30000) 38 | public void TestAddTypePrefix() { 39 | CBORTypeMapper tm = new CBORTypeMapper(); 40 | try { 41 | tm.AddTypePrefix(null); 42 | Assert.fail("Should have failed"); 43 | } catch (NullPointerException ex) { 44 | // NOTE: Intentionally empty 45 | } catch (Exception ex) { 46 | Assert.fail(ex.toString()); 47 | throw new IllegalStateException("", ex); 48 | } 49 | try { 50 | tm.AddTypePrefix(""); 51 | Assert.fail("Should have failed"); 52 | } catch (IllegalArgumentException ex) { 53 | // NOTE: Intentionally empty 54 | } catch (Exception ex) { 55 | Assert.fail(ex.toString()); 56 | throw new IllegalStateException("", ex); 57 | } 58 | try { 59 | tm.AddTypePrefix("java.net.URI"); 60 | } catch (Exception ex) { 61 | Assert.fail(ex.toString()); 62 | throw new IllegalStateException("", ex); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/test/java/com/upokecenter/test/CBORWriterHelper.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.test; 2 | import java.io.*; 3 | import com.upokecenter.cbor.*; 4 | 5 | /** 6 | * Helper class to write CBOR objects using a "fluent" interface. Inspired by 7 | * suggestions by GitHub user "sbernard31". 8 | */ 9 | public final class CBORWriterHelper { 10 | private final OutputStream outputStream; 11 | 12 | /** 13 | * Initializes a new instance of the {@link CBORWriterHelper} class. 14 | * @param outputStream 15 | */ 16 | public CBORWriterHelper(OutputStream outputStream) { 17 | this.outputStream = outputStream; 18 | } 19 | 20 | public CBORWriterHelper WriteStartArray(int size) throws java.io.IOException { 21 | CBORObject.WriteValue(this.outputStream, 4, size); 22 | return this; 23 | } 24 | 25 | public CBORWriterHelper WriteStartMap(int size) throws java.io.IOException { 26 | CBORObject.WriteValue(this.outputStream, 5, size); 27 | return this; 28 | } 29 | 30 | public CBORWriterHelper WriteStartArray(long size) throws java.io.IOException { 31 | CBORObject.WriteValue(this.outputStream, 4, size); 32 | return this; 33 | } 34 | 35 | public CBORWriterHelper WriteStartMap(long size) throws java.io.IOException { 36 | CBORObject.WriteValue(this.outputStream, 5, size); 37 | return this; 38 | } 39 | 40 | public CBORWriterHelper WriteStartArray() throws java.io.IOException { 41 | this.outputStream.write(0x9f); 42 | return this; 43 | } 44 | 45 | public CBORWriterHelper WriteStartMap() throws java.io.IOException { 46 | this.outputStream.write(0xbf); 47 | return this; 48 | } 49 | 50 | public CBORWriterHelper WriteEndArray() throws java.io.IOException { 51 | this.outputStream.write(0xff); 52 | return this; 53 | } 54 | 55 | public CBORWriterHelper WriteEndMap() throws java.io.IOException { 56 | this.outputStream.write(0xff); 57 | return this; 58 | } 59 | 60 | public CBORWriterHelper Write(Object key, Object value) throws java.io.IOException { 61 | CBORObject.Write(key, this.outputStream); 62 | CBORObject.Write(value, this.outputStream); 63 | return this; 64 | } 65 | 66 | public CBORWriterHelper Write(Object value) throws java.io.IOException { 67 | CBORObject.Write(value, this.outputStream); 68 | return this; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/test/java/com/upokecenter/test/CPOD.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.test; 2 | /* 3 | Written by Peter O. 4 | Any copyright to this work is released to the Public Domain. 5 | In case this is not possible, this work is also 6 | licensed under the Unlicense: https://unlicense.org/ 7 | 8 | */ 9 | 10 | public final class CPOD { 11 | public final String getAa() { return propVaraa; } 12 | public final void setAa(String value) { propVaraa = value; } 13 | private String propVaraa; 14 | 15 | private final String getBb() { return propVarbb; } 16 | private final void setBb(String value) { propVarbb = value; } 17 | private String propVarbb; 18 | } 19 | -------------------------------------------------------------------------------- /src/test/java/com/upokecenter/test/CPOD2.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.test; 2 | 3 | public final class CPOD2 { 4 | public final String getAa() { return propVaraa; } 5 | public final void setAa(String value) { propVaraa = value; } 6 | private String propVaraa; 7 | 8 | public final boolean isAa() { return propVarisaa; } 9 | public final void setAa(boolean value) { propVarisaa = value; } 10 | private boolean propVarisaa; 11 | } 12 | -------------------------------------------------------------------------------- /src/test/java/com/upokecenter/test/CPOD3.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.test; 2 | 3 | public class CPOD3 { 4 | public final String getAa() { return propVaraa; } 5 | public final void setAa(String value) { propVaraa = value; } 6 | private String propVaraa; 7 | public final String getBb() { return propVarbb; } 8 | public final void setBb(String value) { propVarbb = value; } 9 | private String propVarbb; 10 | public final String getCc() { return propVarcc; } 11 | public final void setCc(String value) { propVarcc = value; } 12 | private String propVarcc; 13 | } 14 | -------------------------------------------------------------------------------- /src/test/java/com/upokecenter/test/DateTest.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.test; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | import com.upokecenter.util.*; 6 | import com.upokecenter.cbor.*; 7 | import com.upokecenter.numbers.*; 8 | 9 | public class DateTest { 10 | public static void DateConverterRoundTripOne( 11 | CBORDateConverter dtc, 12 | int smallYear, 13 | int[] lesserFields) { 14 | DateConverterRoundTripOne( 15 | dtc, 16 | EInteger.FromInt32(smallYear), 17 | lesserFields); 18 | } 19 | 20 | public static void DateConverterRoundTripOne( 21 | CBORDateConverter dtc, 22 | EInteger year, 23 | int[] lesserFields) { 24 | if (lesserFields == null) { 25 | throw new NullPointerException("lesserFields"); 26 | } 27 | if (year == null) { 28 | throw new NullPointerException("year"); 29 | } 30 | String yearString = year.toString(); 31 | String fieldsString = yearString + "," + lesserFields[0] + "," + 32 | lesserFields[1] + "," + lesserFields[2] + "," + lesserFields[3] + "," + 33 | lesserFields[4] + "," + lesserFields[5] + "," + lesserFields[6]; 34 | try { 35 | if (dtc == null) { 36 | throw new NullPointerException("dtc"); 37 | } 38 | CBORObject obj = dtc.DateTimeFieldsToCBORObject(year, lesserFields); 39 | fieldsString += "\n" + obj.toString(); 40 | EInteger[] newYear = new EInteger[1]; 41 | int[] newLesserFields = new int[7]; 42 | if (dtc.TryGetDateTimeFields(obj, newYear, newLesserFields)) { 43 | for (int i = 0; i < lesserFields.length; ++i) { 44 | Assert.assertEquals(fieldsString, lesserFields[i], newLesserFields[i]); 45 | } 46 | Assert.assertEquals("year\n" + fieldsString,year,newYear[0]); 47 | } else { 48 | Assert.fail(fieldsString); 49 | } 50 | } catch (Exception ex) { 51 | throw new IllegalStateException( 52 | ex.getMessage() + "\n" + fieldsString, 53 | ex); 54 | } 55 | } 56 | 57 | private static EInteger RandomYear(IRandomGenExtended irg) { 58 | return EInteger.FromInt32(irg.GetInt32(9998) + 1); 59 | } 60 | 61 | private static EInteger RandomExpandedYear(IRandomGenExtended irg) { 62 | return EInteger.FromInt32(irg.GetInt32(1000000) - 500000); 63 | } 64 | 65 | private static boolean IsLeapYear(EInteger bigYear) { 66 | bigYear = bigYear.Remainder(400); 67 | if (bigYear.signum() < 0) { 68 | bigYear = bigYear.Add(400); 69 | } 70 | return ((bigYear.Remainder(4).signum() == 0) && 71 | (bigYear.Remainder(100).signum() != 0)) || 72 | (bigYear.Remainder(400).signum() == 0); 73 | } 74 | 75 | private static final int[] ValueNormalDays = { 76 | 0, 31, 28, 31, 30, 31, 30, 77 | 31, 31, 30, 78 | 31, 30, 31, 79 | }; 80 | 81 | private static final int[] ValueLeapDays = { 82 | 0, 31, 29, 31, 30, 31, 30, 83 | 31, 31, 30, 84 | 31, 30, 31, 85 | }; 86 | 87 | private static int[] RandomLesserFields(IRandomGenExtended irg, EInteger 88 | year) { 89 | int month = irg.GetInt32(12) + 1; 90 | int days = IsLeapYear(year) ? ValueLeapDays[month] : 91 | ValueNormalDays[month]; 92 | return new int[] { 93 | month, 94 | irg.GetInt32(days) + 1, 95 | irg.GetInt32(24), 96 | irg.GetInt32(60), 97 | irg.GetInt32(60), 98 | irg.GetInt32(1000000000), 99 | 0, 100 | }; 101 | } 102 | 103 | @Test(timeout = 30000) 104 | public void DateConverterRoundTrip() { 105 | CBORDateConverter[] dtcs = new CBORDateConverter[] { 106 | CBORDateConverter.TaggedString, 107 | }; 108 | int[] lesserFields; 109 | RandomGenerator rg = new RandomGenerator(); 110 | for (int i = 0; i < 10000; ++i) { 111 | EInteger year = RandomYear(rg); 112 | lesserFields = RandomLesserFields(rg, year); 113 | for (int j = 0; j < dtcs.length; ++j) { 114 | DateConverterRoundTripOne(dtcs[j], year, lesserFields); 115 | } 116 | } 117 | dtcs = new CBORDateConverter[] { 118 | CBORDateConverter.TaggedNumber, 119 | CBORDateConverter.UntaggedNumber, 120 | }; 121 | for (int i = 0; i < 30000; ++i) { 122 | EInteger year = RandomExpandedYear(rg); 123 | lesserFields = RandomLesserFields(rg, year); 124 | // Don't check fractional seconds because conversion is lossy 125 | lesserFields[5] = 0; 126 | for (int j = 0; j < dtcs.length; ++j) { 127 | DateConverterRoundTripOne(dtcs[j], year, lesserFields); 128 | } 129 | } 130 | lesserFields = new int[] { 131 | 2, 132 | 11, 133 | 7, 134 | 59, 135 | 3, 136 | 0, 137 | 0, 138 | }; 139 | DateConverterRoundTripOne( 140 | CBORDateConverter.TaggedString, 141 | 9328, 142 | lesserFields); 143 | DateConverterRoundTripOne( 144 | CBORDateConverter.UntaggedNumber, 145 | 9328, 146 | lesserFields); 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /src/test/java/com/upokecenter/test/FieldClass.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.test; 2 | 3 | public final class FieldClass { 4 | private static final int ConstFieldA = 55; 5 | private static final byte[] StaticFieldA = new byte[2]; 6 | public final int ReadonlyFieldA = 33; 7 | private final int privateFieldB = 44; 8 | public int publicFieldA = 66; 9 | private final int privateFieldA = 67; 10 | } 11 | -------------------------------------------------------------------------------- /src/test/java/com/upokecenter/test/JSONPatch.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.test; 2 | /* 3 | Written in 2013 by Peter Occil. 4 | Any copyright to this work is released to the Public Domain. 5 | In case this is not possible, this work is also 6 | licensed under the Unlicense: https://unlicense.org/ 7 | 8 | */ 9 | 10 | import java.util.*; 11 | import com.upokecenter.cbor.*; 12 | 13 | public final class JSONPatch { 14 | private JSONPatch() { 15 | } 16 | private static CBORObject AddOperation( 17 | CBORObject o, 18 | String valueOpStr, 19 | String path, 20 | CBORObject value) { 21 | if (path == null) { 22 | throw new IllegalArgumentException("Patch " + valueOpStr); 23 | } 24 | if (path.length() == 0) { 25 | o = value; 26 | } else { 27 | JSONPointer pointer = JSONPointer.FromPointer(o, path); 28 | if (pointer.GetParent().getType() == CBORType.Array) { 29 | int index = pointer.GetIndex(); 30 | if (index < 0) { 31 | throw new IllegalArgumentException("Patch " + valueOpStr + " path"); 32 | } 33 | ((CBORObject)pointer.GetParent()).Insert(index, value); 34 | } else if (pointer.GetParent().getType() == CBORType.Map) { 35 | String key = pointer.GetKey(); 36 | ((CBORObject)pointer.GetParent()).Set(key, value); 37 | } else { 38 | throw new IllegalArgumentException("Patch " + valueOpStr + " path"); 39 | } 40 | } 41 | return o; 42 | } 43 | 44 | private static CBORObject CloneCbor(CBORObject o) { 45 | return CBORObject.FromJSONString(o.ToJSONString()); 46 | } 47 | 48 | private static String GetString(CBORObject o, String key) { 49 | return o.ContainsKey(key) ? o.get(key).AsString() : null; 50 | } 51 | 52 | public static CBORObject Patch(CBORObject o, CBORObject ptch) { 53 | // clone the Object in case of failure 54 | if (o == null) { 55 | throw new NullPointerException("o"); 56 | } 57 | o = CloneCbor(o); 58 | if (ptch == null) { 59 | throw new NullPointerException("ptch"); 60 | } 61 | for (int i = 0; i < ptch.size(); ++i) { 62 | CBORObject patchOp = ptch.get(i); 63 | // NOTE: This algorithm requires "op" to exist 64 | // only once; the CBORObject, however, does not 65 | // allow duplicates 66 | String valueOpStr = GetString(patchOp, "op"); 67 | if (valueOpStr == null) { 68 | throw new IllegalArgumentException("Patch"); 69 | } 70 | if ("add".equals(valueOpStr)) { 71 | // operation 72 | CBORObject value = null; 73 | if (!patchOp.ContainsKey("value")) { 74 | throw new IllegalArgumentException("Patch " + valueOpStr + " value"); 75 | } 76 | value = patchOp.get("value"); 77 | o = AddOperation(o, valueOpStr, GetString(patchOp, "path"), value); 78 | } else if ("replace".equals(valueOpStr)) { 79 | // operation 80 | CBORObject value = null; 81 | if (!patchOp.ContainsKey("value")) { 82 | throw new IllegalArgumentException("Patch " + valueOpStr + " value"); 83 | } 84 | value = patchOp.get("value"); 85 | o = ReplaceOperation( 86 | o, 87 | valueOpStr, 88 | GetString(patchOp, "path"), 89 | value); 90 | } else if ("remove".equals(valueOpStr)) { 91 | // Remove operation 92 | String path = patchOp.get("path").AsString(); 93 | if (path == null) { 94 | throw new IllegalArgumentException("Patch " + valueOpStr + " path"); 95 | } 96 | if (path.length() == 0) { 97 | o = null; 98 | } else { 99 | RemoveOperation(o, valueOpStr, GetString(patchOp, "path")); 100 | } 101 | } else if ("move".equals(valueOpStr)) { 102 | String path = patchOp.get("path").AsString(); 103 | if (path == null) { 104 | throw new IllegalArgumentException("Patch " + valueOpStr + " path"); 105 | } 106 | String fromPath = patchOp.get("from").AsString(); 107 | if (fromPath == null) { 108 | throw new IllegalArgumentException("Patch " + valueOpStr + " from"); 109 | } 110 | if (path.startsWith(fromPath)) { 111 | throw new IllegalArgumentException("Patch " + valueOpStr); 112 | } 113 | CBORObject movedObj = RemoveOperation(o, valueOpStr, fromPath); 114 | o = AddOperation(o, valueOpStr, path, CloneCbor(movedObj)); 115 | } else if ("copy".equals(valueOpStr)) { 116 | String path = patchOp.get("path").AsString(); 117 | String fromPath = patchOp.get("from").AsString(); 118 | if (path == null) { 119 | throw new IllegalArgumentException("Patch " + valueOpStr + " path"); 120 | } 121 | if (fromPath == null) { 122 | throw new IllegalArgumentException("Patch " + valueOpStr + " from"); 123 | } 124 | JSONPointer pointer = JSONPointer.FromPointer(o, path); 125 | if (!pointer.Exists()) { 126 | throw new NoSuchElementException("Patch " + 127 | valueOpStr + " " + fromPath); 128 | } 129 | CBORObject copiedObj = pointer.GetValue(); 130 | o = AddOperation( 131 | o, 132 | valueOpStr, 133 | path, 134 | CloneCbor(copiedObj)); 135 | } else if ("test".equals(valueOpStr)) { 136 | String path = patchOp.get("path").AsString(); 137 | if (path == null) { 138 | throw new IllegalArgumentException("Patch " + valueOpStr + " path"); 139 | } 140 | CBORObject value = null; 141 | if (!patchOp.ContainsKey("value")) { 142 | throw new IllegalArgumentException("Patch " + valueOpStr + " value"); 143 | } 144 | value = patchOp.get("value"); 145 | JSONPointer pointer = JSONPointer.FromPointer(o, path); 146 | if (!pointer.Exists()) { 147 | throw new IllegalArgumentException("Patch " + 148 | valueOpStr + " " + path); 149 | } 150 | Object testedObj = pointer.GetValue(); 151 | if ((testedObj == null) ? (value != null) : 152 | !testedObj.equals(value)) { 153 | throw new IllegalStateException("Patch " + valueOpStr); 154 | } 155 | } 156 | } 157 | return (o == null) ? CBORObject.Null : o; 158 | } 159 | 160 | private static CBORObject RemoveOperation( 161 | CBORObject o, 162 | String valueOpStr, 163 | String path) { 164 | if (path == null) { 165 | throw new IllegalArgumentException("Patch " + valueOpStr); 166 | } 167 | if (path.length() == 0) { 168 | return o; 169 | } else { 170 | JSONPointer pointer = JSONPointer.FromPointer(o, path); 171 | if (!pointer.Exists()) { 172 | throw new NoSuchElementException("Patch " + 173 | valueOpStr + " " + path); 174 | } 175 | o = pointer.GetValue(); 176 | if (pointer.GetParent().getType() == CBORType.Array) { 177 | ((CBORObject)pointer.GetParent()).RemoveAt(pointer.GetIndex()); 178 | } else if (pointer.GetParent().getType() == CBORType.Map) { 179 | ((CBORObject)pointer.GetParent()).Remove( 180 | CBORObject.FromObject(pointer.GetKey())); 181 | } 182 | return o; 183 | } 184 | } 185 | 186 | private static CBORObject ReplaceOperation( 187 | CBORObject o, 188 | String valueOpStr, 189 | String path, 190 | CBORObject value) { 191 | if (path == null) { 192 | throw new IllegalArgumentException("Patch " + valueOpStr); 193 | } 194 | if (path.length() == 0) { 195 | o = value; 196 | } else { 197 | JSONPointer pointer = JSONPointer.FromPointer(o, path); 198 | if (!pointer.Exists()) { 199 | throw new NoSuchElementException("Patch " + 200 | valueOpStr + " " + path); 201 | } 202 | if (pointer.GetParent().getType() == CBORType.Array) { 203 | int index = pointer.GetIndex(); 204 | if (index < 0) { 205 | throw new IllegalArgumentException("Patch " + valueOpStr + " path"); 206 | } 207 | ((CBORObject)pointer.GetParent()).Set(index, value); 208 | } else if (pointer.GetParent().getType() == CBORType.Map) { 209 | String key = pointer.GetKey(); 210 | ((CBORObject)pointer.GetParent()).Set(key, value); 211 | } else { 212 | throw new IllegalArgumentException("Patch " + valueOpStr + " path"); 213 | } 214 | } 215 | return o; 216 | } 217 | } 218 | -------------------------------------------------------------------------------- /src/test/java/com/upokecenter/test/LimitedMemoryStream.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.test; 2 | import java.io.ByteArrayOutputStream; 3 | import java.io.IOException; 4 | import java.io.OutputStream; 5 | 6 | public final class LimitedMemoryStream extends OutputStream { 7 | private final ByteArrayOutputStream ms; 8 | private final int maxSize; 9 | private int pos; 10 | public LimitedMemoryStream(int maxSize) { 11 | if(maxSize<0)throw new IllegalArgumentException("maxSize"); 12 | this.ms=new ByteArrayOutputStream(); 13 | this.maxSize=maxSize; 14 | this.pos=0; 15 | } 16 | public void close() throws IOException { 17 | ms.close(); 18 | } 19 | public void flush() throws IOException { 20 | ms.flush(); 21 | } 22 | public void write(int b) throws IOException { 23 | if(pos>=maxSize)throw new UnsupportedOperationException(); 24 | pos++; ms.write(b); 25 | } 26 | public void write(byte[] bytes) throws IOException { 27 | write(bytes, 0, bytes.length); 28 | } 29 | public void write(byte[] bytes, int offset, int length) throws IOException { 30 | if((long)pos + length > maxSize)throw new UnsupportedOperationException(); 31 | pos+=length; ms.write(bytes, offset, length); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/test/java/com/upokecenter/test/PODClass.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.test; 2 | 3 | // One property returns an array for testing purposes 4 | 5 | public final class PODClass { 6 | /** 7 | * Initializes a new instance of the {@link PODClass} class. 8 | */ 9 | public PODClass() { 10 | this.setPropA(0); 11 | this.setPropB(1); 12 | this.setPropC(false); 13 | this.propVarprivatepropa = 2; 14 | this.setFloatProp(0); 15 | this.setDoubleProp(0); 16 | this.setStringProp(""); 17 | this.setStringArray(null); 18 | } 19 | 20 | public boolean HasGoodPrivateProp() { 21 | int ppa = this.getPrivatePropA(); 22 | return ppa == 2; 23 | } 24 | 25 | private final int getPrivatePropA() { return propVarprivatepropa; } 26 | private final int propVarprivatepropa; 27 | 28 | public static int getStaticPropA() { return propVarstaticpropa; } 29 | public static void setStaticPropA(int value) { propVarstaticpropa = value; } 30 | private static int propVarstaticpropa; 31 | 32 | public final int getPropA() { return propVarpropa; } 33 | public final void setPropA(int value) { propVarpropa = value; } 34 | private int propVarpropa; 35 | 36 | public final int getPropB() { return propVarpropb; } 37 | public final void setPropB(int value) { propVarpropb = value; } 38 | private int propVarpropb; 39 | 40 | public final boolean isPropC() { return propVarispropc; } 41 | public final void setPropC(boolean value) { propVarispropc = value; } 42 | private boolean propVarispropc; 43 | 44 | public final float getFloatProp() { return propVarfloatprop; } 45 | public final void setFloatProp(float value) { propVarfloatprop = value; } 46 | private float propVarfloatprop; 47 | 48 | public final double getDoubleProp() { return propVardoubleprop; } 49 | public final void setDoubleProp(double value) { propVardoubleprop = value; } 50 | private double propVardoubleprop; 51 | 52 | public final String getStringProp() { return propVarstringprop; } 53 | public final void setStringProp(String value) { propVarstringprop = value; } 54 | private String propVarstringprop; 55 | 56 | public final String[] getStringArray() { return propVarstringarray; } 57 | public final void setStringArray(String[] value) { propVarstringarray = value; } 58 | private String[] propVarstringarray; 59 | } 60 | -------------------------------------------------------------------------------- /src/test/java/com/upokecenter/test/RandomNumerics.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.test; 2 | /* 3 | Written by Peter O. 4 | Any copyright to this work is released to the Public Domain. 5 | In case this is not possible, this work is also 6 | licensed under the Unlicense: https://unlicense.org/ 7 | 8 | */ 9 | 10 | import com.upokecenter.util.*; 11 | import com.upokecenter.numbers.*; 12 | 13 | /** 14 | * Generates random objects of various kinds for purposes of testing code that 15 | * uses them. The methods will not necessarily sample uniformly from all 16 | * objects of a particular kind. 17 | */ 18 | public final class RandomNumerics { 19 | private RandomNumerics() { 20 | } 21 | private static final int MaxExclusiveStringLength = 0x2000; 22 | private static final int MaxExclusiveShortStringLength = 50; 23 | private static final int MaxNumberLength = 50000; 24 | private static final int MaxShortNumberLength = 40; 25 | 26 | public static ERational RandomERational(IRandomGenExtended rand) { 27 | EInteger bigintA = RandomEInteger(rand); 28 | EInteger bigintB = RandomEInteger(rand); 29 | if (bigintB.isZero()) { 30 | bigintB = EInteger.FromInt32(1); 31 | } 32 | return ERational.Create(bigintA, bigintB); 33 | } 34 | 35 | public static EDecimal GenerateEDecimalSmall(IRandomGenExtended wrapper) { 36 | if (wrapper == null) { 37 | throw new NullPointerException("wrapper"); 38 | } 39 | if (wrapper.GetInt32(2) == 0) { 40 | EInteger eix = EInteger.FromBytes( 41 | RandomObjects.RandomByteString(wrapper, 1 + wrapper.GetInt32(36)), 42 | true); 43 | int exp = wrapper.GetInt32(25) - 12; 44 | return EDecimal.Create(eix, exp); 45 | } 46 | return 47 | EDecimal.FromString(RandomObjects.RandomDecimalStringShort(wrapper, false)); 48 | } 49 | 50 | public static EDecimal RandomEDecimal(IRandomGenExtended r) { 51 | return RandomEDecimal(r, null); 52 | } 53 | 54 | public static EDecimal RandomEDecimal(IRandomGenExtended r, String[] 55 | decimalString) { 56 | if (r == null) { 57 | throw new NullPointerException("r"); 58 | } 59 | if (r.GetInt32(100) == 0) { 60 | int x = r.GetInt32(3); 61 | if (x == 0) { 62 | if (decimalString != null) { 63 | decimalString[0] = "Infinity"; 64 | } 65 | return EDecimal.PositiveInfinity; 66 | } 67 | if (x == 1) { 68 | if (decimalString != null) { 69 | decimalString[0] = "-Infinity"; 70 | } 71 | return EDecimal.NegativeInfinity; 72 | } 73 | if (x == 2) { 74 | if (decimalString != null) { 75 | decimalString[0] = "NaN"; 76 | } 77 | return EDecimal.NaN; 78 | } 79 | // Signaling NaN currently not generated because 80 | // it doesn't round-trip as well 81 | } 82 | if (r.GetInt32(100) < 30) { 83 | String str = RandomObjects.RandomDecimalString(r); 84 | if (str.length() < 500) { 85 | if (decimalString != null) { 86 | decimalString[0] = str; 87 | } 88 | return EDecimal.FromString(str); 89 | } 90 | } 91 | EInteger emant = RandomEInteger(r); 92 | EInteger eexp; 93 | if (r.GetInt32(100) < 95) { 94 | int exp = (r.GetInt32(100) < 80) ? (r.GetInt32(50) - 25) : 95 | (r.GetInt32(5000) - 2500); 96 | eexp = EInteger.FromInt32(exp); 97 | } else { 98 | eexp = RandomEInteger(r); 99 | } 100 | EDecimal ed = EDecimal.Create(emant, eexp); 101 | if (decimalString != null) { 102 | decimalString[0] = emant.toString() + "E" + eexp.toString(); 103 | } 104 | return ed; 105 | } 106 | 107 | private static EInteger BitHeavyEInteger(IRandomGenExtended rg, int count) { 108 | StringBuilder sb = new StringBuilder(); 109 | int[] oneChances = { 110 | 999, 1, 980, 20, 750, 250, 980, 111 | 20, 980, 20, 980, 20, 750, 250, 112 | }; 113 | int oneChance = oneChances[rg.GetInt32(oneChances.length)]; 114 | for (int i = 0; i < count; ++i) { 115 | sb.append((rg.GetInt32(1000) >= oneChance) ? '0' : '1'); 116 | } 117 | return EInteger.FromRadixString(sb.toString(), 2); 118 | } 119 | 120 | private static EInteger DigitHeavyEInteger(IRandomGenExtended rg, int 121 | count) { 122 | StringBuilder sb = new StringBuilder(); 123 | int[] oneChances = { 124 | 999, 1, 980, 20, 750, 250, 980, 125 | 20, 980, 20, 980, 20, 750, 250, 126 | }; 127 | int oneChance = oneChances[rg.GetInt32(oneChances.length)]; 128 | for (int i = 0; i < count; ++i) { 129 | sb.append((rg.GetInt32(1000) >= oneChance) ? '0' : '9'); 130 | } 131 | return EInteger.FromRadixString(sb.toString(), 10); 132 | } 133 | 134 | public static EInteger RandomEInteger(IRandomGenExtended r) { 135 | if (r == null) { 136 | throw new NullPointerException("r"); 137 | } 138 | int selection = r.GetInt32(100); 139 | if (selection < 10) { 140 | int count = r.GetInt32(MaxNumberLength); 141 | count = (int)((long)count * r.GetInt32(MaxNumberLength) / 142 | MaxNumberLength); 143 | count = (int)((long)count * r.GetInt32(MaxNumberLength) / 144 | MaxNumberLength); 145 | count = Math.max(count, 1); 146 | if (selection == 0 || selection == 1) { 147 | return BitHeavyEInteger(r, count); 148 | } else if ((selection == 2 || selection == 3) && count < 500) { 149 | return DigitHeavyEInteger(r, count); 150 | } 151 | byte[] bytes = RandomObjects.RandomByteString(r, count); 152 | return EInteger.FromBytes(bytes, true); 153 | } else { 154 | byte[] bytes = RandomObjects.RandomByteString( 155 | r, 156 | r.GetInt32(MaxShortNumberLength) + 1); 157 | return EInteger.FromBytes(bytes, true); 158 | } 159 | } 160 | 161 | public static EInteger RandomEIntegerSmall(IRandomGenExtended r) { 162 | if (r == null) { 163 | throw new NullPointerException("r"); 164 | } 165 | byte[] bytes = RandomObjects.RandomByteString( 166 | r, 167 | r.GetInt32(MaxShortNumberLength) + 1); 168 | return EInteger.FromBytes(bytes, true); 169 | } 170 | 171 | private static int IntInRange(IRandomGenExtended rg, int minInc, int 172 | maxExc) { 173 | return minInc + rg.GetInt32(maxExc - minInc); 174 | } 175 | 176 | public static EFloat CloseToPowerOfTwo(IRandomGenExtended rg) { 177 | if (rg == null) { 178 | throw new NullPointerException("rg"); 179 | } 180 | int pwr = (rg.GetInt32(100) < 80) ? IntInRange(rg, -20, 20) : 181 | IntInRange(rg, -300, 300); 182 | int pwr2 = pwr - (rg.GetInt32(100) < 80 ? IntInRange(rg, 51, 61) : 183 | IntInRange(rg, 2, 300)); 184 | EFloat ef = rg.GetInt32(2) == 0 ? EFloat.Create(1, 185 | pwr).Add(EFloat.Create(1, pwr2)) : EFloat.Create(1, 186 | pwr).Subtract(EFloat.Create(1, pwr2)); 187 | if (rg.GetInt32(10) == 0) { 188 | pwr2 = pwr - (rg.GetInt32(100) < 80 ? IntInRange(rg, 51, 61) : 189 | IntInRange(rg, 2, 300)); 190 | ef = (rg.GetInt32(2) == 0) ? ef.Add(EFloat.Create(1, pwr2)) : 191 | ef.Subtract(EFloat.Create(1, pwr2)); 192 | } 193 | return ef; 194 | } 195 | 196 | public static EFloat RandomEFloat(IRandomGenExtended r) { 197 | if (r == null) { 198 | throw new NullPointerException("r"); 199 | } 200 | if (r.GetInt32(100) == 0) { 201 | int x = r.GetInt32(3); 202 | if (x == 0) { 203 | return EFloat.PositiveInfinity; 204 | } 205 | if (x == 1) { 206 | return EFloat.NegativeInfinity; 207 | } 208 | if (x == 2) { 209 | return EFloat.NaN; 210 | } 211 | } 212 | return r.GetInt32(100) == 3 ? 213 | CloseToPowerOfTwo(r) : EFloat.Create( 214 | RandomEInteger(r), 215 | EInteger.FromInt64(r.GetInt32(400) - 200)); 216 | } 217 | 218 | public static EInteger RandomSmallIntegral(IRandomGenExtended r) { 219 | return EInteger.FromString(RandomObjects.RandomSmallIntegralString(r)); 220 | } 221 | } 222 | -------------------------------------------------------------------------------- /src/test/java/com/upokecenter/test/StringAndBigInt.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.test; 2 | 3 | import com.upokecenter.util.*; 4 | import com.upokecenter.numbers.*; 5 | 6 | final class StringAndBigInt { 7 | private static final String ValueDigits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 8 | 9 | private static final String ValueDigitsLower = 10 | "0123456789abcdefghijklmnopqrstuvwxyz"; 11 | 12 | public final String getStringValue() { return propVarstringvalue; } 13 | private final String propVarstringvalue; 14 | 15 | public final EInteger getBigIntValue() { return propVarbigintvalue; } 16 | private final EInteger propVarbigintvalue; 17 | 18 | private StringAndBigInt(String sv, EInteger biv) { 19 | this.propVarstringvalue = sv; 20 | this.propVarbigintvalue = biv; 21 | } 22 | 23 | public static StringAndBigInt Generate(IRandomGenExtended rand, int radix) { 24 | return Generate(rand, radix, 50); 25 | } 26 | 27 | public static StringAndBigInt Generate( 28 | IRandomGenExtended rand, 29 | int radix, 30 | int maxNumDigits) { 31 | if (radix < 2) { 32 | throw new IllegalArgumentException("radix(" + radix + 33 | ") is less than 2"); 34 | } 35 | if (radix > 36) { 36 | throw new IllegalArgumentException("radix(" + radix + 37 | ") is more than 36"); 38 | } 39 | EInteger bv = EInteger.FromInt32(0); 40 | int numDigits = 1 + rand.GetInt32(maxNumDigits); 41 | boolean negative = false; 42 | StringBuilder builder = new StringBuilder(); 43 | if (rand.GetInt32(2) == 0) { 44 | builder.append('-'); 45 | negative = true; 46 | } 47 | int radixpowint = radix * radix * radix * radix; 48 | EInteger radixpow4 = EInteger.FromInt32(radixpowint); 49 | EInteger radixpow1 = EInteger.FromInt32(radix); 50 | int count = 0; 51 | for (int i = 0; i < numDigits - 4; i += 4) { 52 | int digitvalues = rand.GetInt32(radixpowint); 53 | int digit = digitvalues % radix; 54 | digitvalues /= radix; 55 | int digit2 = digitvalues % radix; 56 | digitvalues /= radix; 57 | int digit3 = digitvalues % radix; 58 | digitvalues /= radix; 59 | int digit4 = digitvalues % radix; 60 | count += 4; 61 | int bits = rand.GetInt32(16); 62 | builder = (bits & 0x01) == 0 ? builder.append(ValueDigits.charAt(digit)) : 63 | builder.append(ValueDigitsLower.charAt(digit)); 64 | builder = (bits & 0x02) == 0 ? builder.append(ValueDigits.charAt(digit2)) : 65 | builder.append(ValueDigitsLower.charAt(digit2)); 66 | builder = (bits & 0x04) == 0 ? builder.append(ValueDigits.charAt(digit3)) : 67 | builder.append(ValueDigitsLower.charAt(digit3)); 68 | builder = (bits & 0x08) == 0 ? builder.append(ValueDigits.charAt(digit4)) : 69 | builder.append(ValueDigitsLower.charAt(digit4)); 70 | int digits = (((((digit * radix) + digit2) * 71 | radix) + digit3) * radix) + digit4; 72 | bv = bv.Multiply(radixpow4); 73 | EInteger bigintTmp = EInteger.FromInt32(digits); 74 | bv = bv.Add(bigintTmp); 75 | } 76 | for (int i = count; i < numDigits; ++i) { 77 | int digit = rand.GetInt32(radix); 78 | builder = rand.GetInt32(2) == 0 ? builder.append(ValueDigits.charAt(digit)) : 79 | builder.append(ValueDigitsLower.charAt(digit)); 80 | bv = bv.Multiply(radixpow1); 81 | EInteger bigintTmp = EInteger.FromInt32(digit); 82 | bv = bv.Add(bigintTmp); 83 | } 84 | if (negative) { 85 | bv = bv.Negate(); 86 | } 87 | return new StringAndBigInt(builder.toString(), bv); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/test/java/com/upokecenter/test/StringOutput.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.test; 2 | /* 3 | Written by Peter O. 4 | Any copyright to this work is released to the Public Domain. 5 | In case this is not possible, this work is also 6 | licensed under the Unlicense: https://unlicense.org/ 7 | 8 | */ 9 | 10 | import java.io.*; 11 | 12 | import com.upokecenter.util.*; 13 | 14 | final class StringOutput { 15 | private final StringBuilder builder; 16 | private final OutputStream outputStream; 17 | 18 | public StringOutput(StringBuilder builder) { 19 | this.builder = builder; 20 | this.outputStream = null; 21 | } 22 | 23 | public StringOutput(OutputStream outputStream) { 24 | this.outputStream = outputStream; 25 | this.builder = null; 26 | } 27 | 28 | public void WriteString(String str) throws java.io.IOException { 29 | if (this.outputStream != null) { 30 | if (str.length() == 1) { 31 | this.WriteCodePoint(str.charAt(0)); 32 | } else { 33 | if (com.upokecenter.util.DataUtilities.WriteUtf8( 34 | str, 35 | 0, 36 | str.length(), 37 | this.outputStream, 38 | false) < 0) { 39 | throw new IllegalArgumentException("str has an unpaired surrogate"); 40 | } 41 | } 42 | } else { 43 | this.builder.append(str); 44 | } 45 | } 46 | 47 | public void WriteString(String str, int index, int length) throws java.io.IOException { 48 | if (this.outputStream == null) { 49 | this.builder.append(str, index, (index)+(length)); 50 | } else { 51 | if (length == 1) { 52 | this.WriteCodePoint(str.charAt(index)); 53 | } else { 54 | if ( 55 | com.upokecenter.util.DataUtilities.WriteUtf8( 56 | str, 57 | index, 58 | length, 59 | this.outputStream, 60 | false) < 0) { 61 | throw new IllegalArgumentException("str has an unpaired surrogate"); 62 | } 63 | } 64 | } 65 | } 66 | 67 | public void WriteAscii(byte[] bytes, int index, int length) throws java.io.IOException { 68 | if (bytes == null) { 69 | throw new NullPointerException("bytes"); 70 | } 71 | if (index < 0) { 72 | throw new IllegalArgumentException("\"index\" (" + index + ") is not" + 73 | "\u0020greater or equal to 0"); 74 | } 75 | if (index > bytes.length) { 76 | throw new IllegalArgumentException("\"index\" (" + index + ") is not less" + 77 | "\u0020or equal to " + bytes.length); 78 | } 79 | if (length < 0) { 80 | throw new IllegalArgumentException(" (" + length + ") is not greater or" + 81 | "\u0020equal to 0"); 82 | } 83 | if (length > bytes.length) { 84 | throw new IllegalArgumentException(" (" + length + ") is not less or equal" + 85 | "\u0020to " + bytes.length); 86 | } 87 | if (bytes.length - index < length) { 88 | throw new IllegalArgumentException("\"bytes\" + \"'s length minus \" +" + 89 | "\u0020index (" + (bytes.length - index) + ") is not greater or" + 90 | "\u0020 equal to " + length); 91 | } 92 | if (this.outputStream == null) { 93 | com.upokecenter.util.DataUtilities.ReadUtf8FromBytes( 94 | bytes, 95 | index, 96 | length, 97 | this.builder, 98 | false); 99 | } else { 100 | for (int i = 0; i < length; ++i) { 101 | byte b = bytes[i + index]; 102 | if ((b & 0x7f) != b) { 103 | throw new IllegalArgumentException("str is non-ASCII"); 104 | } 105 | } 106 | this.outputStream.write(bytes, index, length); 107 | } 108 | } 109 | 110 | public void WriteCodePoint(int codePoint) throws java.io.IOException { 111 | if ((codePoint >> 7) == 0) { 112 | // Code point is in the Basic Latin range (U+0000 to U+007F) 113 | if (this.outputStream == null) { 114 | this.builder.append((char)codePoint); 115 | } else { 116 | this.outputStream.write((byte)codePoint); 117 | } 118 | return; 119 | } 120 | if (codePoint < 0) { 121 | throw new IllegalArgumentException("codePoint(" + codePoint + 122 | ") is less than 0"); 123 | } 124 | if (codePoint > 0x10ffff) { 125 | throw new IllegalArgumentException("codePoint(" + codePoint + 126 | ") is more than " + 0x10ffff); 127 | } 128 | if (this.outputStream != null) { 129 | if (codePoint < 0x80) { 130 | this.outputStream.write((byte)codePoint); 131 | } else if (codePoint <= 0x7ff) { 132 | this.outputStream.write((byte)(0xc0 | ((codePoint >> 6) & 133 | 0x1f))); 134 | this.outputStream.write((byte)(0x80 | (codePoint & 0x3f))); 135 | } else if (codePoint <= 0xffff) { 136 | if ((codePoint & 0xf800) == 0xd800) { 137 | throw new IllegalArgumentException("ch is a surrogate"); 138 | } 139 | this.outputStream.write((byte)(0xe0 | ((codePoint >> 12) & 140 | 0x0f))); 141 | this.outputStream.write((byte)(0x80 | ((codePoint >> 6) & 142 | 0x3f))); 143 | this.outputStream.write((byte)(0x80 | (codePoint & 0x3f))); 144 | } else { 145 | this.outputStream.write((byte)(0xf0 | ((codePoint >> 18) & 146 | 0x07))); 147 | this.outputStream.write((byte)(0x80 | ((codePoint >> 12) & 148 | 0x3f))); 149 | this.outputStream.write((byte)(0x80 | ((codePoint >> 6) & 150 | 0x3f))); 151 | this.outputStream.write((byte)(0x80 | (codePoint & 0x3f))); 152 | } 153 | } else { 154 | if ((codePoint & 0xfff800) == 0xd800) { 155 | throw new IllegalArgumentException("ch is a surrogate"); 156 | } 157 | if (codePoint <= 0xffff) { 158 | { 159 | this.builder.append((char)codePoint); 160 | } 161 | } else if (codePoint <= 0x10ffff) { 162 | this.builder.append((char)((((codePoint - 0x10000) >> 10) & 163 | 0x3ff) | 0xd800)); 164 | this.builder.append((char)(((codePoint - 0x10000) & 0x3ff) | 165 | 0xdc00)); 166 | } 167 | } 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /src/test/java/com/upokecenter/util/IRandomGen.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.util; 2 | 3 | /** 4 | * Interface for random-number generators. 5 | */ 6 | public interface IRandomGen { 7 | /** 8 | * Randomly generates a set of bytes. 9 | * @param bytes Byte buffer to store the random bytes. 10 | * @param offset A zero-based index showing where the desired portion of {@code 11 | * bytes} begins. 12 | * @param length The length, in bytes, of the desired portion of {@code bytes} 13 | * (but not more than {@code bytes} 's length). 14 | * @return Number of bytes returned. 15 | */ 16 | int GetBytes(byte[] bytes, int offset, int length); 17 | } 18 | -------------------------------------------------------------------------------- /src/test/java/com/upokecenter/util/IRandomGenExtended.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.util; 2 | 3 | public interface IRandomGenExtended extends IRandomGen { 4 | int GetInt32(int maxExclusive); 5 | 6 | long GetInt64(long maxExclusive); 7 | } 8 | -------------------------------------------------------------------------------- /src/test/java/com/upokecenter/util/QueryStringHelperCBOR.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.util; 2 | // Written by Peter O. 3 | // Any copyright to this work is released to the Public Domain. 4 | // In case this is not possible, this work is also 5 | // licensed under the Unlicense: https://unlicense.org/ 6 | 7 | import java.util.*; 8 | 9 | import com.upokecenter.cbor.*; 10 | 11 | public final class QueryStringHelperCBOR { 12 | private QueryStringHelperCBOR() { 13 | } 14 | @SuppressWarnings("unchecked") 15 | private static CBORObject ConvertListsToCBOR(List dict) { 16 | CBORObject cbor = CBORObject.NewArray(); 17 | for (int i = 0; i < dict.size(); ++i) { 18 | Object di = dict.get(i); 19 | Map value = ((di instanceof Map) ? (Map)di : null); 20 | // A list contains only integer indices, 21 | // with no gaps. 22 | if (QueryStringHelper.IsList(value)) { 23 | List newList = QueryStringHelper.ConvertToList(value); 24 | cbor.Add(ConvertListsToCBOR(newList)); 25 | } else if (value != null) { 26 | // Convert the list's descendents 27 | // if they are lists 28 | cbor.Add(ConvertListsToCBOR(value)); 29 | } else { 30 | cbor.Add(dict.get(i)); 31 | } 32 | } 33 | return cbor; 34 | } 35 | 36 | @SuppressWarnings("unchecked") 37 | private static CBORObject ConvertListsToCBOR(Map 38 | dict) { 39 | CBORObject cbor = CBORObject.NewMap(); 40 | for (String key : new ArrayList(dict.keySet())) { 41 | Object di = dict.get(key); 42 | Map value = ((di instanceof Map) ? (Map)di : null); 43 | // A list contains only integer indices, 44 | // with no gaps. 45 | if (QueryStringHelper.IsList(value)) { 46 | List newList = QueryStringHelper.ConvertToList(value); 47 | cbor.Add(key, ConvertListsToCBOR(newList)); 48 | } else if (value != null) { 49 | // Convert the dictionary's descendents 50 | // if they are lists 51 | cbor.Add(key, ConvertListsToCBOR(value)); 52 | } else { 53 | cbor.Add(key, dict.get(key)); 54 | } 55 | } 56 | return cbor; 57 | } 58 | 59 | public static CBORObject QueryStringToCBOR(String query) { 60 | return QueryStringToCBOR(query, "&"); 61 | } 62 | public static CBORObject QueryStringToCBOR(String query, 63 | String delimiter) { 64 | // Convert array-like dictionaries to ILists 65 | return 66 | ConvertListsToCBOR(QueryStringHelper.QueryStringToDictInternal(query, 67 | delimiter)); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/test/java/com/upokecenter/util/XorShift128Plus.java: -------------------------------------------------------------------------------- 1 | package com.upokecenter.util; 2 | 3 | /** 4 | *

A class that implements a statistically-random byte generator, using 5 | * Sebastiano Vigna's xorshift128+ RNG as 7 | * the underlying implementation. This class is safe for concurrent use among 8 | * multiple threads.

9 | */ 10 | public class XorShift128Plus implements IRandomGen { 11 | private final long[] s = new long[2]; 12 | private final Object syncRoot = new Object(); 13 | 14 | /** 15 | * Initializes a new instance of the {@link XorShift128Plus} class. 16 | */ 17 | public XorShift128Plus() { 18 | this.Seed(); 19 | } 20 | 21 | /** 22 | * @param bytes Not documented yet. 23 | * @param offset Not documented yet. 24 | * @param length Not documented yet. 25 | * @throws NullPointerException The parameter {@code bytes} is null. 26 | */ 27 | public int GetBytes(byte[] bytes, int offset, int length) { 28 | if (bytes == null) { 29 | throw new NullPointerException("bytes"); 30 | } 31 | if (offset < 0) { 32 | throw new IllegalArgumentException("offset(" + offset + 33 | ") is less than 0"); 34 | } 35 | if (offset > bytes.length) { 36 | throw new IllegalArgumentException("offset(" + offset + 37 | ") is more than " + bytes.length); 38 | } 39 | if (length < 0) { 40 | throw new IllegalArgumentException("length(" + length + 41 | ") is less than 0"); 42 | } 43 | if (length > bytes.length) { 44 | throw new IllegalArgumentException("length(" + length + 45 | ") is more than " + bytes.length); 46 | } 47 | if (bytes.length - offset < length) { 48 | throw new IllegalArgumentException("bytes's length minus " + offset + "(" + 49 | (bytes.length - offset) + ") is less than " + length); 50 | } 51 | int count = length; 52 | synchronized (this.syncRoot) { 53 | while (length >= 8) { 54 | long nv = this.NextValue(); 55 | bytes[offset++] = ((byte)nv); 56 | nv >>= 8; 57 | bytes[offset++] = ((byte)nv); 58 | nv >>= 8; 59 | bytes[offset++] = ((byte)nv); 60 | nv >>= 8; 61 | bytes[offset++] = ((byte)nv); 62 | nv >>= 8; 63 | bytes[offset++] = ((byte)nv); 64 | nv >>= 8; 65 | bytes[offset++] = ((byte)nv); 66 | nv >>= 8; 67 | bytes[offset++] = ((byte)nv); 68 | nv >>= 8; 69 | bytes[offset++] = ((byte)nv); 70 | length -= 8; 71 | } 72 | if (length != 0) { 73 | long nv = this.NextValue(); 74 | while (length > 0) { 75 | bytes[offset++] = ((byte)nv); 76 | nv >>= 8; 77 | --length; 78 | } 79 | } 80 | } 81 | return count; 82 | } 83 | 84 | // xorshift128 + generator 85 | // http://xorshift.di.unimi.it/xorshift128plus.c 86 | private long NextValue() { 87 | long s1 = this.s[0]; 88 | long s0 = this.s[1]; 89 | this.s[0] = s0; 90 | s1 ^= s1 << 23; 91 | long t1 = s1 >> 18; 92 | t1 &= 0x3fffffffffffL; 93 | long t0 = s0 >> 5; 94 | t0 &= 0x7ffffffffffffffL; 95 | this.s[1] = s1 ^ s0 ^ t1 ^ t0; 96 | return this.s[1] + s0; 97 | } 98 | 99 | private void Seed() { 100 | long lb = System.currentTimeMillis() & 0xffffffffffL; 101 | this.s[0] = lb; 102 | lb = 0L; 103 | this.s[1] = lb; 104 | if ((this.s[0] | this.s[1]) == 0) { 105 | ++this.s[0]; 106 | } 107 | } 108 | } 109 | --------------------------------------------------------------------------------