├── .circleci ├── config.yml └── maven-release-settings.xml ├── .gitignore ├── ChangeLog.md ├── LICENSE ├── README.md ├── pom.xml └── src ├── main └── java │ └── com │ └── arangodb │ └── velocypack │ ├── ArrayIterator.java │ ├── ObjectIterator.java │ ├── SliceIterator.java │ ├── VPackAttributeTranslator.java │ ├── VPackBuilder.java │ ├── VPackSlice.java │ ├── VPackStringSlice.java │ ├── ValueType.java │ ├── exception │ ├── VPackBuilderException.java │ ├── VPackBuilderKeyAlreadyWrittenException.java │ ├── VPackBuilderNeedOpenCompoundException.java │ ├── VPackBuilderNeedOpenObjectException.java │ ├── VPackBuilderNumberOutOfRangeException.java │ ├── VPackBuilderUnexpectedValueException.java │ ├── VPackException.java │ ├── VPackKeyTypeException.java │ ├── VPackNeedAttributeTranslatorException.java │ ├── VPackParserException.java │ └── VPackValueTypeException.java │ └── internal │ ├── DefaultVPackBuilderOptions.java │ ├── VPackAttributeTranslatorImpl.java │ ├── Value.java │ └── util │ ├── BinaryUtil.java │ ├── DateUtil.java │ ├── NumberUtil.java │ ├── ObjectArrayUtil.java │ ├── ValueLengthUtil.java │ └── ValueTypeUtil.java └── test ├── java └── com │ └── arangodb │ └── velocypack │ ├── VPackBuilderTest.java │ ├── VPackSliceTest.java │ ├── VPackUtil.java │ └── util │ ├── DateUtilTest.java │ ├── SliceIteratorTest.java │ └── ValueTest.java └── resources └── logback-test.xml /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | 3 | commands: 4 | timeout: 5 | parameters: 6 | duration: 7 | default: '5m' 8 | type: 'string' 9 | steps: 10 | - run: 11 | name: Cancel job after <> 12 | background: true 13 | command: | 14 | sleep <> 15 | echo "Cancelling job as <> has elapsed" 16 | curl --fail -X POST -H "Circle-Token: ${CIRCLE_TOKEN}" "https://circleci.com/api/v1.1/project/github/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}/${CIRCLE_BUILD_NUM}/cancel" 17 | report: 18 | parameters: 19 | working_directory: 20 | type: 'string' 21 | default: '.' 22 | steps: 23 | - run: 24 | name: Create reports 25 | command: mvn surefire-report:report-only 26 | working_directory: <> 27 | - store_artifacts: 28 | path: <>/target/site 29 | load_cache: 30 | steps: 31 | - run: 32 | name: Generate Cache Checksum 33 | command: find . -name 'pom.xml' | sort | xargs cat > /tmp/maven_cache_seed 34 | - restore_cache: 35 | key: maven-{{ .Environment.CIRCLE_JOB }}-{{ checksum "/tmp/maven_cache_seed" }} 36 | store_cache: 37 | steps: 38 | - save_cache: 39 | key: maven-{{ .Environment.CIRCLE_JOB }}-{{ checksum "/tmp/maven_cache_seed" }} 40 | paths: 41 | - ~/.m2/repository 42 | config_gpg: 43 | steps: 44 | - run: 45 | name: Configure GPG 46 | command: echo $GPG_PRIVATE_KEY | base64 --decode | gpg --batch --no-tty --import --yes 47 | deploy: 48 | steps: 49 | - run: 50 | name: Deploy to Apache Maven Central 51 | command: mvn -s .circleci/maven-release-settings.xml -Dmaven.test.skip=true deploy 52 | release: 53 | steps: 54 | - run: 55 | name: Release to Apache Maven Central 56 | command: mvn -s .circleci/maven-release-settings.xml -Dmaven.test.skip=true nexus-staging:release 57 | environment: 58 | MAVEN_OPTS: "--add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.lang.reflect=ALL-UNNAMED --add-opens=java.base/java.text=ALL-UNNAMED --add-opens=java.desktop/java.awt.font=ALL-UNNAMED" 59 | 60 | executors: 61 | j8: 62 | docker: 63 | - image: 'cimg/openjdk:8.0' 64 | j11: 65 | docker: 66 | - image: 'cimg/openjdk:11.0' 67 | j17: 68 | docker: 69 | - image: 'cimg/openjdk:17.0' 70 | j21: 71 | docker: 72 | - image: 'cimg/openjdk:21.0' 73 | 74 | jobs: 75 | 76 | test: 77 | parameters: 78 | jdk: 79 | type: 'string' 80 | default: 'j21' 81 | executor: <> 82 | steps: 83 | - timeout 84 | - checkout 85 | - setup_remote_docker 86 | - load_cache 87 | - run: 88 | name: mvn version 89 | command: mvn --version 90 | - run: 91 | name: mvn dependency:tree 92 | command: mvn dependency:tree 93 | - run: 94 | name: Test 95 | command: mvn test 96 | - report 97 | - store_cache 98 | 99 | deploy: 100 | executor: 'j17' 101 | steps: 102 | - timeout 103 | - checkout 104 | - load_cache 105 | - config_gpg 106 | - deploy 107 | - store_cache 108 | 109 | release: 110 | executor: 'j17' 111 | steps: 112 | - timeout 113 | - checkout 114 | - load_cache 115 | - config_gpg 116 | - deploy 117 | - release 118 | - store_cache 119 | 120 | workflows: 121 | test-jdk: 122 | jobs: 123 | - test: 124 | name: test-<> 125 | matrix: 126 | parameters: 127 | jdk: 128 | - 'j8' 129 | - 'j11' 130 | - 'j17' 131 | - 'j21' 132 | deploy: 133 | jobs: 134 | - deploy: 135 | context: java-release 136 | filters: 137 | tags: 138 | only: /^deploy.*/ 139 | branches: 140 | ignore: /.*/ 141 | release: 142 | jobs: 143 | - release: 144 | context: java-release 145 | filters: 146 | tags: 147 | only: /^release.*/ 148 | branches: 149 | ignore: /.*/ 150 | -------------------------------------------------------------------------------- /.circleci/maven-release-settings.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | ossrh 7 | 8 | true 9 | 10 | 11 | ${env.GPG_KEYNAME} 12 | ${env.GPG_PASSPHRASE} 13 | 14 | 15 | 16 | 17 | 18 | 19 | ossrh 20 | ${env.OSSRH_USERNAME} 21 | ${env.OSSRH_PASSWORD} 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.classpath 2 | /.project 3 | /.settings 4 | /target 5 | /.idea 6 | /*.iml 7 | *.jfr 8 | /.gradle 9 | /bin 10 | /build 11 | dependency-reduced-pom.xml 12 | -------------------------------------------------------------------------------- /ChangeLog.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). 6 | 7 | ## [Unreleased] 8 | 9 | ## [3.1.0] - 2024-09-20 10 | 11 | - fixed memory consumption issue in dates serialization 12 | - explicit JPMS module name `com.arangodb.velocypack` 13 | 14 | ## [3.0.0] - 2022-11-30 15 | 16 | - removed all databind capabilities (#31), which are now provided by [jackson-dataformat-velocypack](https://github.com/arangodb/jackson-dataformat-velocypack). 17 | 18 | ## [2.5.4] - 2021-08-24 19 | 20 | - fixed escaping in JSON string generation (#29) 21 | 22 | ## [2.5.3] - 2021-04-23 23 | 24 | - improved performances of `VPackParser.toJson()` 25 | - added `VPackSlice.getSchemaDescription()` to return a printable schema description of the VPack slice 26 | 27 | ## [2.5.2] - 2021-03-23 28 | 29 | - fixed start offset of byte array copy in `VPackSlice.toByteArray` 30 | 31 | ## [2.5.1] - 2020-12-21 32 | 33 | - fixed getting attribute from VPackSlice with `null` key ([spring-data#210](https://github.com/arangodb/spring-data/issues/210)) 34 | 35 | ## [2.5.0] - 2020-10-12 36 | 37 | - support deserializing ints as BigDecimals 38 | - removed escaping forward slash in `VPackParser` 39 | 40 | ## [2.4.1] - 2020-08-14 41 | 42 | - fixed base64 encoding for Java version >= 9 43 | 44 | ## [2.4.0] - 2020-07-29 45 | 46 | - added useTypeHints option to VPack.Builder 47 | 48 | ## [2.3.1] - 2020-05-05 49 | 50 | - shaded jackson dependency 51 | 52 | ## [2.3.0] - 2020-04-28 53 | 54 | - bugfix serialization unindexed singleton arrays 55 | - added `add(Byte)`, `is(Byte)`, `getAsByte()` to VPackBuilder and VPackSlice 56 | - use custom VPackBuilder in VPackParser 57 | 58 | ## [2.2.1] - 2020-03-25 59 | 60 | - improved array iteration performances 61 | 62 | ## [2.2.0] - 2020-03-05 63 | 64 | - deserialization support for wildcard types 65 | - deserialization support for java.lang.Iterable 66 | - raised the minimum JVM source and target version to 8 67 | - All-Arguments constructor deserialization 68 | - Static Factory Method deserialization 69 | - Support for Kotlin data classes and Scala case classes 70 | - Builder deserialization 71 | 72 | ## [2.1.1] - 2020-01-20 73 | 74 | - fixed tagging bugs 75 | - fixed custom types byte size 76 | - fixed BCD byte size 77 | - Map and Set VPackInstanceCreators preserve collections entries order (based on `LinkedHashSet` and `LinkedHashMap`) 78 | 79 | ## [2.1.0] - 2019-12-20 80 | 81 | - added [tags support](https://github.com/arangodb/velocypack/blob/master/VelocyPack.md#tagging) 82 | 83 | ## [2.0.0] - 2019-12-19 84 | 85 | - performance improvements 86 | - raised minimum supported Java version to Java 7 87 | 88 | ## [1.4.3] - 2019-10-22 89 | 90 | - jackson v2.9.10 91 | 92 | ## [1.4.2] - 2019-07-29 93 | 94 | - properly (always) close the builder object 95 | 96 | ## [1.4.1] - 2018-09-18 97 | 98 | ### Fixed 99 | 100 | - fixed handling of additional fields 101 | 102 | ## [1.4.0] - 2018-09-18 103 | 104 | ### Added 105 | 106 | - added support for generic types (issue #1, #3) 107 | 108 | Serialize the class name in a field `_class` when necessary. Field name can be configured through `VPack.Builder#typeKey(String)` 109 | 110 | ## [1.3.0] - 2018-08-02 111 | 112 | ### Changed 113 | 114 | - `VPackDeserializationContext#deserialize(VPackSlice, Class)` to `VPackDeserializationContext#deserialize(VPackSlice, java.lang.reflect.Type)` 115 | 116 | ## [1.2.0] - 2018-06-08 117 | 118 | ### Changed 119 | 120 | - replaced dependency json-simple with jackson 121 | 122 | ## [1.1.0] - 2018-04-19 123 | 124 | ### Added 125 | 126 | - added support for deserializing `BigInteger`/`BigDecimal` from String 127 | 128 | ### Changed 129 | 130 | - changed serializing `BigInteger`/`BigDecimal` to String 131 | 132 | ## [1.0.15] - 2017-04-17 133 | 134 | ### Fixed 135 | 136 | - fixed `DateUtil` does incorrect conversion of UTC time (issue #6) 137 | 138 | ## [1.0.14] - 2017-11-27 139 | 140 | ### Fixed 141 | 142 | - fixed Json parsing of negative long 143 | 144 | ## [1.0.13] - 2017-11-03 145 | 146 | ### Fixed 147 | 148 | - fixed deserialization of BigDecimal 149 | 150 | ## [1.0.12] - 2017-10-23 151 | 152 | ### Changed 153 | 154 | - exclude junit dependency of json-simple 155 | 156 | ### Fixed 157 | 158 | - fixed VPack to JSON parsing of negative `int` 159 | - fixed serialization of negative `int`/`long` value (issue #5) 160 | 161 | ## [1.0.11] - 2017-07-31 162 | 163 | ### Fixed 164 | 165 | - fixed `DateUtil` (thread-safe) 166 | 167 | ## [1.0.10] - 2017-07-20 168 | 169 | ### Fixed 170 | 171 | - fixed Json parsing of null within Objects (issue #2) 172 | 173 | ## [1.0.9] - 2017-06-20 174 | 175 | ### Fixed 176 | 177 | - fixed deserializing of internal field `_id` 178 | 179 | ## [1.0.8] - 2017-06-13 180 | 181 | ### Added 182 | 183 | - added `VPackSetupContext#registerDeserializer(Type, VPackDeserializer, boolean)` 184 | - added `VPackSetupContext#registerDeserializer(String, Type, VPackDeserializer, boolean)` 185 | 186 | ## [1.0.7] - 2017-06-09 187 | 188 | ### Added 189 | 190 | - added `VPackSetupContext#registerKeyMapAdapter(type, adapter)` 191 | 192 | ## [1.0.6] - 2017-06-09 193 | 194 | ### Added 195 | 196 | - added `VPack.Builder#registerKeyMapAdapter(type, adapter)` 197 | - added `VPack#serialize(Object, SerializeOptions)` 198 | 199 | ## [1.0.5] - 2017-04-13 200 | 201 | ### Fixed 202 | 203 | - fixed VPackSlice float/double bug 204 | 205 | ## [1.0.4] - 2017-04-11 206 | 207 | ### Changed 208 | 209 | - optimize `VPack.Builder` and `VPackParser.Builder` (thread-safe) 210 | 211 | ## [1.0.3] - 2017-03-23 212 | 213 | ### Fixed 214 | 215 | - fixed serialization for parameterized types 216 | 217 | ## [1.0.2] - 2017-03-22 218 | 219 | ### Added 220 | 221 | - added support for deserializing parameterized types 222 | 223 | ## [1.0.1] - 2017-03-17 224 | 225 | ### Added 226 | 227 | - added support for registering modules on `VPack`,`VPackParser` 228 | 229 | [unreleased]: https://github.com/arangodb/java-velocypack/compare/1.4.1...HEAD 230 | [1.4.1]: https://github.com/arangodb/java-velocypack/compare/1.4.0...1.4.1 231 | [1.4.0]: https://github.com/arangodb/java-velocypack/compare/1.3.0...1.4.0 232 | [1.3.0]: https://github.com/arangodb/java-velocypack/compare/2.3.1...1.3.0 233 | [1.2.0]: https://github.com/arangodb/java-velocypack/compare/1.1.0...1.2.0 234 | [1.1.0]: https://github.com/arangodb/java-velocypack/compare/1.0.15...1.1.0 235 | [1.0.15]: https://github.com/arangodb/java-velocypack/compare/1.0.14...1.0.15 236 | [1.0.14]: https://github.com/arangodb/java-velocypack/compare/1.0.13...1.0.14 237 | [1.0.13]: https://github.com/arangodb/java-velocypack/compare/1.0.12...1.0.13 238 | [1.0.12]: https://github.com/arangodb/java-velocypack/compare/1.0.11...1.0.12 239 | [1.0.11]: https://github.com/arangodb/java-velocypack/compare/1.0.10...1.0.11 240 | [1.0.10]: https://github.com/arangodb/java-velocypack/compare/1.0.9...1.0.10 241 | [1.0.9]: https://github.com/arangodb/java-velocypack/compare/1.0.8...1.0.9 242 | [1.0.8]: https://github.com/arangodb/java-velocypack/compare/1.0.7...1.0.8 243 | [1.0.7]: https://github.com/arangodb/java-velocypack/compare/1.0.6...1.0.7 244 | [1.0.6]: https://github.com/arangodb/java-velocypack/compare/1.0.5...1.0.6 245 | [1.0.5]: https://github.com/arangodb/java-velocypack/compare/1.0.4...1.0.5 246 | [1.0.4]: https://github.com/arangodb/java-velocypack/compare/1.0.3...1.0.4 247 | [1.0.3]: https://github.com/arangodb/java-velocypack/compare/1.0.2...1.0.3 248 | [1.0.2]: https://github.com/arangodb/java-velocypack/compare/1.0.1...1.0.2 249 | [1.0.1]: https://github.com/arangodb/java-velocypack/compare/1.0.1 250 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2016 ArangoDB GmbH 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![ArangoDB-Logo](https://user-images.githubusercontent.com/3998723/207981337-79d49127-48fc-4c7c-9411-8a688edca1dd.png) 2 | 3 | # ArangoDB VelocyPack Java 4 | 5 | [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.arangodb/velocypack/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.arangodb/velocypack) 6 | [![CircleCI](https://dl.circleci.com/status-badge/img/gh/arangodb/java-velocypack/tree/main.svg?style=svg)](https://dl.circleci.com/status-badge/redirect/gh/arangodb/java-velocypack/tree/main) 7 | 8 | Java implementation for [VelocyPack](https://github.com/arangodb/velocypack). 9 | 10 | ## Maven 11 | 12 | To add the dependency to your project with maven, add the following code to your pom.xml: 13 | 14 | ```XML 15 | 16 | 17 | com.arangodb 18 | velocypack 19 | x.y.z 20 | 21 | 22 | ``` 23 | 24 | ## Compile 25 | 26 | ``` 27 | mvn clean install -DskipTests=true -Dgpg.skip=true -Dmaven.javadoc.skip=true -B 28 | ``` 29 | 30 | # Usage 31 | 32 | ## build VelocyPack - Object 33 | 34 | ```Java 35 | VPackBuilder builder = new VPackBuilder(); 36 | builder.add(ValueType.OBJECT); // object start 37 | builder.add("foo", "bar"); // add field "foo" with value "bar" 38 | builder.close(); // object end 39 | 40 | VPackSlice slice = builder.slice(); // create slice 41 | ``` 42 | 43 | ## working with VPackSlice - Object 44 | 45 | ```Java 46 | VPackSlice slice = ... 47 | int size = slice.size(); // number of fields 48 | VPackSlice foo = slice.get("foo"); // get field "foo" 49 | String value = foo.getAsString(); // get value from "foo" 50 | 51 | // iterate over the fields 52 | for (final Iterator> iterator = slice.objectIterator(); iterator.hasNext();) { 53 | Entry field = iterator.next(); 54 | ... 55 | } 56 | ``` 57 | 58 | ## build VelocyPack - Array 59 | 60 | ```Java 61 | VPackBuilder builder = new VPackBuilder(); 62 | builder.add(ValueType.ARRAY); // array start 63 | builder.add(1); // add value 1 64 | builder.add(2); // add value 2 65 | builder.add(3); // add value 3 66 | builder.close(); // array end 67 | 68 | VPackSlice slice = builder.slice(); // create slice 69 | ``` 70 | 71 | ## working with VPackSlice - Array 72 | 73 | ```Java 74 | VPackSlice slice = ... 75 | int size = slice.size(); // number of values 76 | 77 | // iterate over values 78 | for (int i = 0; i < slice.size(); i++) { 79 | VPackSlice value = slice.get(i); 80 | ... 81 | } 82 | 83 | // iterate over values with Iterator 84 | for (final Iterator iterator = slice.arrayIterator(); iterator.hasNext();) { 85 | VPackSlice value = iterator.next(); 86 | ... 87 | } 88 | ``` 89 | 90 | ## build VelocyPack - nested Objects 91 | 92 | ```Java 93 | VPackBuilder builder = new VPackBuilder(); 94 | builder.add(ValueType.OBJECT); // object start 95 | builder.add("foo", ValueType.OBJECT); // add object in field "foo" 96 | builder.add("bar", 1); // add field "bar" with value 1 to object "foo" 97 | builder.close(); // object "foo" end 98 | builder.close(); // object end 99 | 100 | VPackSlice slice = builder.slice(); // create slice 101 | ``` 102 | 103 | 104 | # Learn more 105 | 106 | - [ArangoDB](https://www.arangodb.com/) 107 | - [ChangeLog](ChangeLog.md) 108 | - [JavaDoc](https://www.javadoc.io/doc/com.arangodb/velocypack/latest/index.html) 109 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | com.arangodb 6 | velocypack 7 | 3.1.0 8 | 2017 9 | jar 10 | 11 | ArangoDB Velocypack 12 | ArangoDB Velocypack for Java 13 | http://maven.apache.org 14 | 15 | 16 | 17 | Apache License 2.0 18 | http://www.apache.org/licenses/LICENSE-2.0 19 | repo 20 | 21 | 22 | 23 | 24 | UTF-8 25 | 26 | 27 | 28 | 29 | mpv1989 30 | Mark Vollmary 31 | https://github.com/mpv1989 32 | 33 | 34 | 35 | 36 | 37 | ossrh 38 | https://oss.sonatype.org/content/repositories/snapshots 39 | 40 | 41 | ossrh 42 | https://oss.sonatype.org/service/local/staging/deploy/maven2/ 43 | 44 | 45 | 46 | 47 | 48 | doclint-java8-disable 49 | 50 | [1.8,) 51 | 52 | 53 | -Xdoclint:none 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | org.sonatype.plugins 62 | nexus-staging-maven-plugin 63 | 1.6.13 64 | true 65 | 66 | ossrh 67 | https://oss.sonatype.org/ 68 | 84aff6e87e214c 69 | false 70 | 71 | 72 | 73 | 74 | org.apache.maven.plugins 75 | maven-jar-plugin 76 | 77 | 78 | 79 | com.arangodb.velocypack 80 | 81 | 82 | 83 | 84 | 85 | 86 | org.apache.maven.plugins 87 | maven-assembly-plugin 88 | 2.4.1 89 | 90 | 91 | assembly 92 | package 93 | 94 | single 95 | 96 | 97 | 98 | 99 | 100 | ${project.artifactId}-${project.version}-standalone 101 | 102 | false 103 | false 104 | 105 | jar-with-dependencies 106 | 107 | 108 | 109 | 110 | 111 | org.apache.maven.plugins 112 | maven-compiler-plugin 113 | 3.2 114 | 115 | 8 116 | 8 117 | 118 | 119 | 120 | 121 | org.apache.maven.plugins 122 | maven-resources-plugin 123 | 2.7 124 | 125 | UTF-8 126 | 127 | 128 | 129 | 130 | org.apache.maven.plugins 131 | maven-source-plugin 132 | 2.4 133 | 134 | 135 | 136 | jar 137 | 138 | 139 | 140 | 141 | 142 | 143 | org.apache.maven.plugins 144 | maven-javadoc-plugin 145 | 2.9.1 146 | 147 | 148 | attach-javadocs 149 | 150 | jar 151 | 152 | 153 | ${javadoc.opts} 154 | 155 | 156 | 157 | 158 | 159 | 160 | maven-surefire-plugin 161 | 2.19.1 162 | 163 | -Dfile.encoding=UTF-8 164 | 165 | **/*Test.java 166 | **/*Example.java 167 | 168 | 169 | 170 | 171 | 172 | maven-deploy-plugin 173 | 3.1.1 174 | 175 | 10 176 | 177 | 178 | 179 | 180 | org.apache.maven.plugins 181 | maven-gpg-plugin 182 | 3.0.1 183 | 184 | 185 | --pinentry-mode 186 | loopback 187 | 188 | 189 | 190 | 191 | sign-artifacts 192 | verify 193 | 194 | sign 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | org.slf4j 207 | slf4j-api 208 | 1.7.30 209 | 210 | 211 | ch.qos.logback 212 | logback-classic 213 | 1.2.13 214 | test 215 | 216 | 217 | junit 218 | junit 219 | 4.13.2 220 | test 221 | 222 | 223 | org.hamcrest 224 | hamcrest-all 225 | 1.3 226 | test 227 | 228 | 229 | 230 | 231 | https://github.com/arangodb/java-velocypack 232 | scm:git:git://github.com/arangodb/java-velocypack.git 233 | scm:git:git://github.com/arangodb/java-velocypack.git 234 | 235 | 236 | 237 | ArangoDB GmbH 238 | https://www.arangodb.com 239 | 240 | 241 | 242 | -------------------------------------------------------------------------------- /src/main/java/com/arangodb/velocypack/ArrayIterator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DISCLAIMER 3 | * 4 | * Copyright 2016 ArangoDB GmbH, Cologne, Germany 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * Copyright holder is ArangoDB GmbH, Cologne, Germany 19 | */ 20 | 21 | package com.arangodb.velocypack; 22 | 23 | import java.util.NoSuchElementException; 24 | 25 | import com.arangodb.velocypack.exception.VPackValueTypeException; 26 | 27 | /** 28 | * @author Mark Vollmary 29 | * 30 | */ 31 | public class ArrayIterator extends SliceIterator { 32 | 33 | public ArrayIterator(final VPackSlice slice) throws VPackValueTypeException { 34 | super(slice); 35 | if (!slice.isArray()) { 36 | throw new VPackValueTypeException(ValueType.ARRAY); 37 | } 38 | if (size > 0) { 39 | current = slice.getNth(0).getStart(); 40 | } 41 | } 42 | 43 | @Override 44 | public VPackSlice next() { 45 | if (hasNext()) { 46 | final VPackSlice next = getCurrent(); 47 | position++; 48 | current += next.getByteSize(); 49 | return next; 50 | } else { 51 | throw new NoSuchElementException(); 52 | } 53 | } 54 | 55 | @Override 56 | public void remove() { 57 | throw new UnsupportedOperationException(); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/arangodb/velocypack/ObjectIterator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DISCLAIMER 3 | * 4 | * Copyright 2016 ArangoDB GmbH, Cologne, Germany 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * Copyright holder is ArangoDB GmbH, Cologne, Germany 19 | */ 20 | 21 | package com.arangodb.velocypack; 22 | 23 | import java.util.Map.Entry; 24 | import java.util.NoSuchElementException; 25 | 26 | import com.arangodb.velocypack.exception.VPackKeyTypeException; 27 | import com.arangodb.velocypack.exception.VPackNeedAttributeTranslatorException; 28 | import com.arangodb.velocypack.exception.VPackValueTypeException; 29 | 30 | /** 31 | * @author Mark Vollmary 32 | * 33 | */ 34 | public class ObjectIterator extends SliceIterator> { 35 | 36 | public ObjectIterator(final VPackSlice slice) throws VPackValueTypeException { 37 | super(slice); 38 | if (!slice.isObject()) { 39 | throw new VPackValueTypeException(ValueType.OBJECT); 40 | } 41 | if (size > 0) { 42 | final byte head = slice.head(); 43 | if (head == 0x14) { 44 | current = slice.keyAt(0).getStart(); 45 | } else { 46 | current = slice.getStart() + slice.findDataOffset(); 47 | } 48 | } 49 | } 50 | 51 | @Override 52 | public Entry next() { 53 | if (position++ > 0) { 54 | if (position <= size && current != 0) { 55 | // skip over key 56 | current += getCurrent().getByteSize(); 57 | // skip over value 58 | current += getCurrent().getByteSize(); 59 | } else { 60 | throw new NoSuchElementException(); 61 | } 62 | } 63 | final VPackSlice currentField = getCurrent(); 64 | return new Entry() { 65 | @Override 66 | public VPackSlice setValue(final VPackSlice value) { 67 | throw new UnsupportedOperationException(); 68 | } 69 | 70 | @Override 71 | public VPackSlice getValue() { 72 | return new VPackSlice(currentField.getBuffer(), currentField.getStart() + currentField.getByteSize()); 73 | } 74 | 75 | @Override 76 | public String getKey() { 77 | try { 78 | return currentField.makeKey().getAsString(); 79 | } catch (final VPackKeyTypeException | VPackNeedAttributeTranslatorException e) { 80 | throw new NoSuchElementException(); 81 | } 82 | } 83 | }; 84 | } 85 | 86 | @Override 87 | public void remove() { 88 | throw new UnsupportedOperationException(); 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /src/main/java/com/arangodb/velocypack/SliceIterator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DISCLAIMER 3 | * 4 | * Copyright 2016 ArangoDB GmbH, Cologne, Germany 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * Copyright holder is ArangoDB GmbH, Cologne, Germany 19 | */ 20 | 21 | package com.arangodb.velocypack; 22 | 23 | import java.util.Iterator; 24 | 25 | import com.arangodb.velocypack.exception.VPackValueTypeException; 26 | 27 | /** 28 | * @author Mark Vollmary 29 | * 30 | */ 31 | public abstract class SliceIterator implements Iterator { 32 | 33 | protected final VPackSlice slice; 34 | protected final long size; 35 | protected long position; 36 | protected long current; 37 | 38 | protected SliceIterator(final VPackSlice slice) throws VPackValueTypeException { 39 | super(); 40 | this.slice = slice; 41 | size = slice.getLength(); 42 | position = 0; 43 | } 44 | 45 | @Override 46 | public boolean hasNext() { 47 | return position < size; 48 | } 49 | 50 | protected VPackSlice getCurrent() { 51 | return new VPackSlice(slice.getBuffer(), (int) current); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/arangodb/velocypack/VPackAttributeTranslator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DISCLAIMER 3 | * 4 | * Copyright 2016 ArangoDB GmbH, Cologne, Germany 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * Copyright holder is ArangoDB GmbH, Cologne, Germany 19 | */ 20 | 21 | package com.arangodb.velocypack; 22 | 23 | import com.arangodb.velocypack.exception.VPackException; 24 | 25 | /** 26 | * @author Mark Vollmary 27 | * 28 | */ 29 | public interface VPackAttributeTranslator { 30 | 31 | void add(String attribute, int key) throws VPackException; 32 | 33 | void seal() throws VPackException; 34 | 35 | VPackSlice translate(String attribute); 36 | 37 | VPackSlice translate(int key); 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/arangodb/velocypack/VPackBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DISCLAIMER 3 | * 4 | * Copyright 2016 ArangoDB GmbH, Cologne, Germany 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * Copyright holder is ArangoDB GmbH, Cologne, Germany 19 | */ 20 | 21 | package com.arangodb.velocypack; 22 | 23 | import java.math.BigDecimal; 24 | import java.math.BigInteger; 25 | import java.nio.charset.StandardCharsets; 26 | import java.sql.Timestamp; 27 | import java.util.ArrayList; 28 | import java.util.Arrays; 29 | import java.util.Collection; 30 | import java.util.Comparator; 31 | import java.util.Date; 32 | import java.util.List; 33 | 34 | import com.arangodb.velocypack.exception.VPackBuilderException; 35 | import com.arangodb.velocypack.exception.VPackBuilderKeyAlreadyWrittenException; 36 | import com.arangodb.velocypack.exception.VPackBuilderNeedOpenCompoundException; 37 | import com.arangodb.velocypack.exception.VPackBuilderNeedOpenObjectException; 38 | import com.arangodb.velocypack.exception.VPackBuilderNumberOutOfRangeException; 39 | import com.arangodb.velocypack.exception.VPackBuilderUnexpectedValueException; 40 | import com.arangodb.velocypack.exception.VPackKeyTypeException; 41 | import com.arangodb.velocypack.exception.VPackNeedAttributeTranslatorException; 42 | import com.arangodb.velocypack.exception.VPackValueTypeException; 43 | import com.arangodb.velocypack.internal.DefaultVPackBuilderOptions; 44 | import com.arangodb.velocypack.internal.Value; 45 | import com.arangodb.velocypack.internal.util.NumberUtil; 46 | 47 | /** 48 | * @author Mark Vollmary 49 | * 50 | */ 51 | public class VPackBuilder { 52 | 53 | private static final int INTEGER_BYTES = Integer.SIZE / Byte.SIZE; 54 | private static final int LONG_BYTES = Long.SIZE / Byte.SIZE; 55 | private static final int DOUBLE_BYTES = Double.SIZE / Byte.SIZE; 56 | 57 | public interface BuilderOptions { 58 | boolean isBuildUnindexedArrays(); 59 | 60 | void setBuildUnindexedArrays(boolean buildUnindexedArrays); 61 | 62 | boolean isBuildUnindexedObjects(); 63 | 64 | void setBuildUnindexedObjects(boolean buildUnindexedObjects); 65 | } 66 | 67 | public interface Appender { 68 | void append(VPackBuilder builder, T value) throws VPackBuilderException; 69 | } 70 | 71 | private static final Appender VALUE = new Appender() { 72 | @Override 73 | public void append(final VPackBuilder builder, final Value value) throws VPackBuilderException { 74 | builder.set(value); 75 | } 76 | }; 77 | private static final Appender VALUE_TYPE = new Appender() { 78 | @Override 79 | public void append(final VPackBuilder builder, final ValueType value) throws VPackBuilderException { 80 | switch (value) { 81 | case NULL: 82 | builder.appendNull(); 83 | break; 84 | case ARRAY: 85 | builder.addArray(false); 86 | break; 87 | case OBJECT: 88 | builder.addObject(false); 89 | break; 90 | default: 91 | throw new VPackValueTypeException(ValueType.ARRAY, ValueType.OBJECT, ValueType.NULL); 92 | } 93 | } 94 | }; 95 | private static final Appender BOOLEAN = new Appender() { 96 | @Override 97 | public void append(final VPackBuilder builder, final Boolean value) throws VPackBuilderException { 98 | builder.appendBoolean(value); 99 | } 100 | }; 101 | private static final Appender DOUBLE = new Appender() { 102 | @Override 103 | public void append(final VPackBuilder builder, final Double value) throws VPackBuilderException { 104 | builder.appendDouble(value); 105 | } 106 | }; 107 | private static final Appender FLOAT = new Appender() { 108 | @Override 109 | public void append(final VPackBuilder builder, final Float value) throws VPackBuilderException { 110 | builder.appendDouble(value); 111 | } 112 | }; 113 | private static final Appender BIG_DECIMAL = new Appender() { 114 | @Override 115 | public void append(final VPackBuilder builder, final BigDecimal value) throws VPackBuilderException { 116 | builder.appendString(value.toString()); 117 | } 118 | }; 119 | private static final Appender LONG = new Appender() { 120 | @Override 121 | public void append(final VPackBuilder builder, final Long value) throws VPackBuilderException { 122 | if (value <= 9 && value >= -6) { 123 | builder.appendSmallInt(value); 124 | } else { 125 | builder.add((byte) 0x27); 126 | builder.append(value, LONG_BYTES); 127 | } 128 | } 129 | }; 130 | private static final Appender INTEGER = new Appender() { 131 | @Override 132 | public void append(final VPackBuilder builder, final Integer value) throws VPackBuilderException { 133 | if (value <= 9 && value >= -6) { 134 | builder.appendSmallInt(value); 135 | } else { 136 | builder.add((byte) 0x23); 137 | builder.append(value, INTEGER_BYTES); 138 | } 139 | } 140 | }; 141 | private static final Appender SHORT = new Appender() { 142 | @Override 143 | public void append(final VPackBuilder builder, final Short value) throws VPackBuilderException { 144 | if (value <= 9 && value >= -6) { 145 | builder.appendSmallInt(value); 146 | } else { 147 | builder.add((byte) 0x23); 148 | builder.append(value, INTEGER_BYTES); 149 | } 150 | } 151 | }; 152 | private static final Appender BYTE = new Appender() { 153 | @Override 154 | public void append(final VPackBuilder builder, final Byte value) { 155 | if (value <= 9 && value >= -6) { 156 | builder.appendSmallInt(value); 157 | } else { 158 | builder.add((byte) 0x23); 159 | builder.append(value, INTEGER_BYTES); 160 | } 161 | } 162 | }; 163 | private static final Appender BIG_INTEGER = new Appender() { 164 | @Override 165 | public void append(final VPackBuilder builder, final BigInteger value) throws VPackBuilderException { 166 | builder.appendString(value.toString()); 167 | } 168 | }; 169 | private static final Appender DATE = new Appender() { 170 | @Override 171 | public void append(final VPackBuilder builder, final Date value) throws VPackBuilderException { 172 | builder.appendDate(value); 173 | } 174 | }; 175 | private static final Appender SQL_DATE = new Appender() { 176 | @Override 177 | public void append(final VPackBuilder builder, final java.sql.Date value) throws VPackBuilderException { 178 | builder.appendSQLDate(value); 179 | } 180 | }; 181 | private static final Appender SQL_TIMESTAMP = new Appender() { 182 | @Override 183 | public void append(final VPackBuilder builder, final Timestamp value) throws VPackBuilderException { 184 | builder.appendSQLTimestamp(value); 185 | } 186 | }; 187 | private static final Appender STRING = new Appender() { 188 | @Override 189 | public void append(final VPackBuilder builder, final String value) throws VPackBuilderException { 190 | builder.appendString(value); 191 | } 192 | }; 193 | private static final Appender CHARACTER = new Appender() { 194 | @Override 195 | public void append(final VPackBuilder builder, final Character value) throws VPackBuilderException { 196 | builder.appendString(String.valueOf(value)); 197 | } 198 | }; 199 | private static final Appender BYTE_ARRAY = new Appender() { 200 | @Override 201 | public void append(final VPackBuilder builder, final byte[] value) throws VPackBuilderException { 202 | builder.appendBinary(value); 203 | } 204 | }; 205 | private static final Appender VPACK = new Appender() { 206 | @Override 207 | public void append(final VPackBuilder builder, final VPackSlice value) throws VPackBuilderException { 208 | builder.appendVPack(value); 209 | } 210 | }; 211 | 212 | private byte[] buffer; // Here we collect the result 213 | private int size; 214 | private final List stack; // Start positions of open 215 | // objects/arrays 216 | private final List> index; // Indices for starts 217 | // of 218 | // subindex 219 | private boolean keyWritten; // indicates that in the current object the key 220 | // has been written but the value not yet 221 | private final BuilderOptions options; 222 | 223 | public VPackBuilder() { 224 | this(new DefaultVPackBuilderOptions()); 225 | } 226 | 227 | public VPackBuilder(final BuilderOptions options) { 228 | super(); 229 | this.options = options; 230 | size = 0; 231 | buffer = new byte[10]; 232 | stack = new ArrayList<>(); 233 | index = new ArrayList<>(4); 234 | } 235 | 236 | public BuilderOptions getOptions() { 237 | return options; 238 | } 239 | 240 | private void add(final byte b) { 241 | ensureCapacity(size + 1); 242 | buffer[size++] = b; 243 | } 244 | 245 | private void addUnchecked(final byte b) { 246 | buffer[size++] = b; 247 | } 248 | 249 | private void remove(final int index) { 250 | final int numMoved = size - index - 1; 251 | if (numMoved > 0) { 252 | System.arraycopy(buffer, index + 1, buffer, index, numMoved); 253 | } 254 | buffer[--size] = 0; 255 | } 256 | 257 | private void ensureCapacity(final int minCapacity) { 258 | final int oldCapacity = buffer.length; 259 | if (minCapacity > oldCapacity) { 260 | final byte[] oldData = buffer; 261 | int newCapacity = (oldCapacity * 3) / 2 + 1; 262 | if (newCapacity < minCapacity) { 263 | newCapacity = minCapacity; 264 | } 265 | buffer = Arrays.copyOf(oldData, newCapacity); 266 | } 267 | } 268 | 269 | private void appendTag(long tag) { 270 | if(tag <= 255) { 271 | ensureCapacity(size + 1 + 1); 272 | addUnchecked((byte) 0xee); 273 | append(tag, 1); 274 | } else { 275 | ensureCapacity(size + 1 + 8); 276 | addUnchecked((byte) 0xef); 277 | append(tag, LONG_BYTES); 278 | } 279 | } 280 | 281 | public VPackBuilder add(final ValueType value) throws VPackBuilderException { 282 | return addInternal(VALUE_TYPE, value); 283 | } 284 | 285 | public VPackBuilder add(final ValueType value, final boolean unindexed) throws VPackBuilderException { 286 | return addInternal(VALUE, new Value(value, unindexed)); 287 | } 288 | 289 | public VPackBuilder add(final Boolean value) throws VPackBuilderException { 290 | return addInternal(BOOLEAN, value); 291 | } 292 | 293 | public VPackBuilder add(final Double value) throws VPackBuilderException { 294 | return addInternal(DOUBLE, value); 295 | } 296 | 297 | public VPackBuilder add(final Float value) throws VPackBuilderException { 298 | return addInternal(FLOAT, value); 299 | } 300 | 301 | public VPackBuilder add(final BigDecimal value) throws VPackBuilderException { 302 | return addInternal(BIG_DECIMAL, value); 303 | } 304 | 305 | public VPackBuilder add(final Long value) throws VPackBuilderException { 306 | return addInternal(LONG, value); 307 | } 308 | 309 | public VPackBuilder add(final Long value, final ValueType type) throws VPackBuilderException { 310 | return addInternal(VALUE, new Value(value, type)); 311 | } 312 | 313 | public VPackBuilder add(final Integer value) throws VPackBuilderException { 314 | return addInternal(INTEGER, value); 315 | } 316 | 317 | public VPackBuilder add(final Short value) throws VPackBuilderException { 318 | return addInternal(SHORT, value); 319 | } 320 | 321 | public VPackBuilder add(final Byte value) throws VPackBuilderException { 322 | return addInternal(BYTE, value); 323 | } 324 | 325 | public VPackBuilder add(final BigInteger value) throws VPackBuilderException { 326 | return addInternal(BIG_INTEGER, value); 327 | } 328 | 329 | public VPackBuilder add(final BigInteger value, final ValueType type) throws VPackBuilderException { 330 | return addInternal(VALUE, new Value(value, type)); 331 | } 332 | 333 | public VPackBuilder add(final Date value) throws VPackBuilderException { 334 | return addInternal(DATE, value); 335 | } 336 | 337 | public VPackBuilder add(final java.sql.Date value) throws VPackBuilderException { 338 | return addInternal(SQL_DATE, value); 339 | } 340 | 341 | public VPackBuilder add(final java.sql.Timestamp value) throws VPackBuilderException { 342 | return addInternal(SQL_TIMESTAMP, value); 343 | } 344 | 345 | public VPackBuilder add(final String value) throws VPackBuilderException { 346 | return addInternal(STRING, value); 347 | } 348 | 349 | public VPackBuilder add(final Character value) throws VPackBuilderException { 350 | return addInternal(CHARACTER, value); 351 | } 352 | 353 | public VPackBuilder add(final byte[] value) throws VPackBuilderException { 354 | return addInternal(BYTE_ARRAY, value); 355 | } 356 | 357 | public VPackBuilder add(final VPackSlice value) throws VPackBuilderException { 358 | return addInternal(VPACK, value); 359 | } 360 | 361 | public VPackBuilder add(final String attribute, final ValueType value) throws VPackBuilderException { 362 | return addInternal(attribute, VALUE_TYPE, value); 363 | } 364 | 365 | public VPackBuilder add(final String attribute, final ValueType value, final boolean unindexed) 366 | throws VPackBuilderException { 367 | return addInternal(attribute, VALUE, new Value(value, unindexed)); 368 | } 369 | 370 | public VPackBuilder add(final String attribute, final Boolean value) throws VPackBuilderException { 371 | return addInternal(attribute, BOOLEAN, value); 372 | } 373 | 374 | public VPackBuilder add(final String attribute, final Double value) throws VPackBuilderException { 375 | return addInternal(attribute, DOUBLE, value); 376 | } 377 | 378 | public VPackBuilder add(final String attribute, final Float value) throws VPackBuilderException { 379 | return addInternal(attribute, FLOAT, value); 380 | } 381 | 382 | public VPackBuilder add(final String attribute, final BigDecimal value) throws VPackBuilderException { 383 | return addInternal(attribute, BIG_DECIMAL, value); 384 | } 385 | 386 | public VPackBuilder add(final String attribute, final Long value) throws VPackBuilderException { 387 | return addInternal(attribute, LONG, value); 388 | } 389 | 390 | public VPackBuilder add(final String attribute, final Long value, final ValueType type) 391 | throws VPackBuilderException { 392 | return addInternal(attribute, VALUE, new Value(value, type)); 393 | } 394 | 395 | public VPackBuilder add(final String attribute, final Integer value) throws VPackBuilderException { 396 | return addInternal(attribute, INTEGER, value); 397 | } 398 | 399 | public VPackBuilder add(final String attribute, final Short value) throws VPackBuilderException { 400 | return addInternal(attribute, SHORT, value); 401 | } 402 | 403 | public VPackBuilder add(final String attribute, final Byte value) throws VPackBuilderException { 404 | return addInternal(attribute, BYTE, value); 405 | } 406 | 407 | public VPackBuilder add(final String attribute, final BigInteger value) throws VPackBuilderException { 408 | return addInternal(attribute, BIG_INTEGER, value); 409 | } 410 | 411 | public VPackBuilder add(final String attribute, final BigInteger value, final ValueType type) 412 | throws VPackBuilderException { 413 | return addInternal(attribute, VALUE, new Value(value, type)); 414 | } 415 | 416 | public VPackBuilder add(final String attribute, final String value) throws VPackBuilderException { 417 | return addInternal(attribute, STRING, value); 418 | } 419 | 420 | public VPackBuilder add(final String attribute, final Character value) throws VPackBuilderException { 421 | return addInternal(attribute, CHARACTER, value); 422 | } 423 | 424 | public VPackBuilder add(final String attribute, final Date value) throws VPackBuilderException { 425 | return addInternal(attribute, DATE, value); 426 | } 427 | 428 | public VPackBuilder add(final String attribute, final java.sql.Date value) throws VPackBuilderException { 429 | return addInternal(attribute, SQL_DATE, value); 430 | } 431 | 432 | public VPackBuilder add(final String attribute, final java.sql.Timestamp value) throws VPackBuilderException { 433 | return addInternal(attribute, SQL_TIMESTAMP, value); 434 | } 435 | 436 | public VPackBuilder add(final String attribute, final byte[] value) throws VPackBuilderException { 437 | return addInternal(attribute, BYTE_ARRAY, value); 438 | } 439 | 440 | public VPackBuilder add(final String attribute, final VPackSlice value) throws VPackBuilderException { 441 | return addInternal(attribute, VPACK, value); 442 | } 443 | 444 | public VPackBuilder addTagged(final long tag, final ValueType value) throws VPackBuilderException { 445 | return addInternal(tag, VALUE_TYPE, value); 446 | } 447 | 448 | public VPackBuilder addTagged(final long tag, final ValueType value, final boolean unindexed) throws VPackBuilderException { 449 | return addInternal(tag, VALUE, new Value(value, unindexed)); 450 | } 451 | 452 | public VPackBuilder addTagged(final long tag, final Boolean value) throws VPackBuilderException { 453 | return addInternal(tag, BOOLEAN, value); 454 | } 455 | 456 | public VPackBuilder addTagged(final long tag, final Double value) throws VPackBuilderException { 457 | return addInternal(tag, DOUBLE, value); 458 | } 459 | 460 | public VPackBuilder addTagged(final long tag, final Float value) throws VPackBuilderException { 461 | return addInternal(tag, FLOAT, value); 462 | } 463 | 464 | public VPackBuilder addTagged(final long tag, final BigDecimal value) throws VPackBuilderException { 465 | return addInternal(tag, BIG_DECIMAL, value); 466 | } 467 | 468 | public VPackBuilder addTagged(final long tag, final Long value) throws VPackBuilderException { 469 | return addInternal(tag, LONG, value); 470 | } 471 | 472 | public VPackBuilder addTagged(final long tag, final Long value, final ValueType type) throws VPackBuilderException { 473 | return addInternal(tag, VALUE, new Value(value, type)); 474 | } 475 | 476 | public VPackBuilder addTagged(final long tag, final Integer value) throws VPackBuilderException { 477 | return addInternal(tag, INTEGER, value); 478 | } 479 | 480 | public VPackBuilder addTagged(final long tag, final Short value) throws VPackBuilderException { 481 | return addInternal(tag, SHORT, value); 482 | } 483 | 484 | public VPackBuilder addTagged(final long tag, final Byte value) throws VPackBuilderException { 485 | return addInternal(tag, BYTE, value); 486 | } 487 | 488 | public VPackBuilder addTagged(final long tag, final BigInteger value) throws VPackBuilderException { 489 | return addInternal(tag, BIG_INTEGER, value); 490 | } 491 | 492 | public VPackBuilder addTagged(final long tag, final BigInteger value, final ValueType type) throws VPackBuilderException { 493 | return addInternal(tag, VALUE, new Value(value, type)); 494 | } 495 | 496 | public VPackBuilder addTagged(final long tag, final Date value) throws VPackBuilderException { 497 | return addInternal(tag, DATE, value); 498 | } 499 | 500 | public VPackBuilder addTagged(final long tag, final java.sql.Date value) throws VPackBuilderException { 501 | return addInternal(tag, SQL_DATE, value); 502 | } 503 | 504 | public VPackBuilder addTagged(final long tag, final java.sql.Timestamp value) throws VPackBuilderException { 505 | return addInternal(tag, SQL_TIMESTAMP, value); 506 | } 507 | 508 | public VPackBuilder addTagged(final long tag, final String value) throws VPackBuilderException { 509 | return addInternal(tag, STRING, value); 510 | } 511 | 512 | public VPackBuilder addTagged(final long tag, final Character value) throws VPackBuilderException { 513 | return addInternal(tag, CHARACTER, value); 514 | } 515 | 516 | public VPackBuilder addTagged(final long tag, final byte[] value) throws VPackBuilderException { 517 | return addInternal(tag, BYTE_ARRAY, value); 518 | } 519 | 520 | public VPackBuilder addTagged(final long tag, final VPackSlice value) throws VPackBuilderException { 521 | return addInternal(tag, VPACK, value); 522 | } 523 | 524 | public VPackBuilder addTagged(final String attribute, final long tag, final ValueType value) throws VPackBuilderException { 525 | return addInternal(attribute, tag, VALUE_TYPE, value); 526 | } 527 | 528 | public VPackBuilder addTagged(final String attribute, final long tag, final ValueType value, final boolean unindexed) 529 | throws VPackBuilderException { 530 | return addInternal(attribute, tag, VALUE, new Value(value, unindexed)); 531 | } 532 | 533 | public VPackBuilder addTagged(final String attribute, final long tag, final Boolean value) throws VPackBuilderException { 534 | return addInternal(attribute, tag, BOOLEAN, value); 535 | } 536 | 537 | public VPackBuilder addTagged(final String attribute, final long tag, final Double value) throws VPackBuilderException { 538 | return addInternal(attribute, tag, DOUBLE, value); 539 | } 540 | 541 | public VPackBuilder addTagged(final String attribute, final long tag, final Float value) throws VPackBuilderException { 542 | return addInternal(attribute, tag, FLOAT, value); 543 | } 544 | 545 | public VPackBuilder addTagged(final String attribute, final long tag, final BigDecimal value) throws VPackBuilderException { 546 | return addInternal(attribute, tag, BIG_DECIMAL, value); 547 | } 548 | 549 | public VPackBuilder addTagged(final String attribute, final long tag, final Long value) throws VPackBuilderException { 550 | return addInternal(attribute, tag, LONG, value); 551 | } 552 | 553 | public VPackBuilder addTagged(final String attribute, final long tag, final Long value, final ValueType type) 554 | throws VPackBuilderException { 555 | return addInternal(attribute, tag, VALUE, new Value(value, type)); 556 | } 557 | 558 | public VPackBuilder addTagged(final String attribute, final long tag, final Integer value) throws VPackBuilderException { 559 | return addInternal(attribute, tag, INTEGER, value); 560 | } 561 | 562 | public VPackBuilder addTagged(final String attribute, final long tag, final Short value) throws VPackBuilderException { 563 | return addInternal(attribute, tag, SHORT, value); 564 | } 565 | 566 | public VPackBuilder addTagged(final String attribute, final long tag, final Byte value) throws VPackBuilderException { 567 | return addInternal(attribute, tag, BYTE, value); 568 | } 569 | 570 | public VPackBuilder addTagged(final String attribute, final long tag, final BigInteger value) throws VPackBuilderException { 571 | return addInternal(attribute, tag, BIG_INTEGER, value); 572 | } 573 | 574 | public VPackBuilder addTagged(final String attribute, final long tag, final BigInteger value, final ValueType type) 575 | throws VPackBuilderException { 576 | return addInternal(attribute, tag, VALUE, new Value(value, type)); 577 | } 578 | 579 | public VPackBuilder addTagged(final String attribute, final long tag, final String value) throws VPackBuilderException { 580 | return addInternal(attribute, tag, STRING, value); 581 | } 582 | 583 | public VPackBuilder addTagged(final String attribute, final long tag, final Character value) throws VPackBuilderException { 584 | return addInternal(attribute, tag, CHARACTER, value); 585 | } 586 | 587 | public VPackBuilder addTagged(final String attribute, final long tag, final Date value) throws VPackBuilderException { 588 | return addInternal(attribute, tag, DATE, value); 589 | } 590 | 591 | public VPackBuilder addTagged(final String attribute, final long tag, final java.sql.Date value) throws VPackBuilderException { 592 | return addInternal(attribute, tag, SQL_DATE, value); 593 | } 594 | 595 | public VPackBuilder addTagged(final String attribute, final long tag, final java.sql.Timestamp value) throws VPackBuilderException { 596 | return addInternal(attribute, tag, SQL_TIMESTAMP, value); 597 | } 598 | 599 | public VPackBuilder addTagged(final String attribute, final long tag, final byte[] value) throws VPackBuilderException { 600 | return addInternal(attribute, tag, BYTE_ARRAY, value); 601 | } 602 | 603 | public VPackBuilder addTagged(final String attribute, final long tag, final VPackSlice value) throws VPackBuilderException { 604 | return addInternal(attribute, tag, VPACK, value); 605 | } 606 | 607 | private VPackBuilder addInternal(final Appender appender, final T value) throws VPackBuilderException { 608 | return addInternal(0, appender, value); 609 | } 610 | 611 | private VPackBuilder addInternal(final long tag, final Appender appender, final T value) throws VPackBuilderException { 612 | boolean haveReported = false; 613 | if (!stack.isEmpty() && !keyWritten) { 614 | reportAdd(); 615 | haveReported = true; 616 | } 617 | 618 | if (tag != 0) { 619 | appendTag(tag); 620 | } 621 | 622 | try { 623 | if (value == null) { 624 | appendNull(); 625 | } else { 626 | appender.append(this, value); 627 | } 628 | } catch (final VPackBuilderException e) { 629 | // clean up in case of an exception 630 | if (haveReported) { 631 | cleanupAdd(); 632 | } 633 | throw e; 634 | } 635 | return this; 636 | } 637 | 638 | private VPackBuilder addInternal(final String attribute, final Appender appender, final T value) 639 | throws VPackBuilderException { 640 | return addInternal(attribute, 0, appender, value); 641 | } 642 | 643 | private VPackBuilder addInternal(final String attribute, final long tag, final Appender appender, final T value) 644 | throws VPackBuilderException { 645 | if (attribute != null) { 646 | boolean haveReported = false; 647 | if (!stack.isEmpty()) { 648 | final byte head = head(); 649 | if (head != 0x0b && head != 0x14) { 650 | throw new VPackBuilderNeedOpenObjectException(); 651 | } 652 | if (keyWritten) { 653 | throw new VPackBuilderKeyAlreadyWrittenException(); 654 | } 655 | reportAdd(); 656 | haveReported = true; 657 | } 658 | try { 659 | if (VPackSlice.attributeTranslator != null) { 660 | final VPackSlice translate = VPackSlice.attributeTranslator.translate(attribute); 661 | if (translate != null) { 662 | final byte[] trValue = translate.getBuffer(); 663 | int trValueLength = translate.getByteSize(); 664 | int trValueStart = translate.getStart(); 665 | ensureCapacity(size + trValueLength); 666 | for (int i = 0; i < trValueLength; i++) { 667 | addUnchecked(trValue[i+trValueStart]); 668 | } 669 | keyWritten = true; 670 | if (value == null) { 671 | appendNull(); 672 | } else { 673 | appender.append(this, value); 674 | } 675 | return this; 676 | } 677 | // otherwise fall through to regular behavior 678 | } 679 | STRING.append(this, attribute); 680 | keyWritten = true; 681 | 682 | if (tag != 0) { 683 | appendTag(tag); 684 | } 685 | 686 | if (value == null) { 687 | appendNull(); 688 | } else { 689 | appender.append(this, value); 690 | } 691 | } catch (final VPackBuilderException e) { 692 | // clean up in case of an exception 693 | if (haveReported) { 694 | cleanupAdd(); 695 | } 696 | throw e; 697 | } finally { 698 | keyWritten = false; 699 | } 700 | } else { 701 | addInternal(tag, appender, value); 702 | } 703 | return this; 704 | } 705 | 706 | private void set(final Value item) throws VPackBuilderException { 707 | final Class clazz = item.getClazz(); 708 | switch (item.getType()) { 709 | case NULL: 710 | appendNull(); 711 | break; 712 | case ARRAY: 713 | addArray(item.isUnindexed()); 714 | break; 715 | case OBJECT: 716 | addObject(item.isUnindexed()); 717 | break; 718 | case SMALLINT: 719 | final long vSmallInt = item.getNumber().longValue(); 720 | if (vSmallInt < -6 || vSmallInt > 9) { 721 | throw new VPackBuilderNumberOutOfRangeException(ValueType.SMALLINT); 722 | } 723 | appendSmallInt(vSmallInt); 724 | break; 725 | case INT: 726 | final int length; 727 | if (clazz == Long.class || clazz == BigInteger.class) { 728 | add((byte) 0x27); 729 | length = LONG_BYTES; 730 | } else { 731 | throw new VPackBuilderUnexpectedValueException(ValueType.INT, Long.class, Integer.class, 732 | BigInteger.class, Short.class); 733 | } 734 | append(item.getNumber().longValue(), length); 735 | break; 736 | case UINT: 737 | final BigInteger vUInt; 738 | if (clazz == Long.class) { 739 | vUInt = BigInteger.valueOf(item.getLong()); 740 | } else if (clazz == BigInteger.class) { 741 | vUInt = item.getBigInteger(); 742 | } else { 743 | throw new VPackBuilderUnexpectedValueException(ValueType.UINT, Long.class, Integer.class, 744 | BigInteger.class); 745 | } 746 | if (vUInt.compareTo(BigInteger.ZERO) < 0) { 747 | throw new VPackBuilderUnexpectedValueException(ValueType.UINT, "non-negative", Long.class, 748 | Integer.class, BigInteger.class); 749 | } 750 | appendUInt(vUInt); 751 | break; 752 | default: 753 | break; 754 | } 755 | } 756 | 757 | private void appendNull() { 758 | add((byte) 0x18); 759 | } 760 | 761 | private void appendBoolean(final boolean value) { 762 | if (value) { 763 | add((byte) 0x1a); 764 | } else { 765 | add((byte) 0x19); 766 | } 767 | } 768 | 769 | private void appendDouble(final double value) { 770 | add((byte) 0x1b); 771 | append(value); 772 | } 773 | 774 | private void append(final double value) { 775 | append(Double.doubleToRawLongBits(value), DOUBLE_BYTES); 776 | } 777 | 778 | private void appendSmallInt(final long value) { 779 | if (value >= 0) { 780 | add((byte) (value + 0x30)); 781 | } else { 782 | add((byte) (value + 0x40)); 783 | } 784 | } 785 | 786 | private void appendUInt(final BigInteger value) { 787 | add((byte) 0x2f); 788 | append(value); 789 | } 790 | 791 | private void append(final long value, final int length) { 792 | ensureCapacity(size + length); 793 | for (int i = length - 1; i >= 0; i--) { 794 | addUnchecked((byte) (value >> (length - i - 1 << 3))); 795 | } 796 | } 797 | 798 | private void append(final BigInteger value) { 799 | ensureCapacity(size + VPackBuilder.LONG_BYTES); 800 | for (int i = VPackBuilder.LONG_BYTES - 1; i >= 0; i--) { 801 | addUnchecked(value.shiftRight(VPackBuilder.LONG_BYTES - i - 1 << 3).byteValue()); 802 | } 803 | } 804 | 805 | private void appendDate(final Date value) { 806 | add((byte) 0x1c); 807 | append(value.getTime(), LONG_BYTES); 808 | } 809 | 810 | private void appendSQLDate(final java.sql.Date value) { 811 | add((byte) 0x1c); 812 | append(value.getTime(), LONG_BYTES); 813 | } 814 | 815 | private void appendSQLTimestamp(final Timestamp value) { 816 | add((byte) 0x1c); 817 | append(value.getTime(), LONG_BYTES); 818 | } 819 | 820 | private void appendString(final String value) { 821 | final byte[] bytes = value.getBytes(StandardCharsets.UTF_8); 822 | final int length = bytes.length; 823 | if (length <= 126) { 824 | // short string 825 | add((byte) (0x40 + length)); 826 | } else { 827 | // long string 828 | add((byte) 0xbf); 829 | appendLength(length); 830 | } 831 | appendString(bytes); 832 | } 833 | 834 | private void appendString(final byte[] bytes) { 835 | ensureCapacity(size + bytes.length); 836 | System.arraycopy(bytes, 0, buffer, size, bytes.length); 837 | size += bytes.length; 838 | } 839 | 840 | private void appendBinary(final byte[] value) { 841 | add((byte) 0xc3); 842 | append(value.length, INTEGER_BYTES); 843 | ensureCapacity(size + value.length); 844 | System.arraycopy(value, 0, buffer, size, value.length); 845 | size += value.length; 846 | } 847 | 848 | private void appendVPack(final VPackSlice value) { 849 | final byte[] vpack = value.getBuffer(); 850 | int length = value.getByteSize(); 851 | ensureCapacity(size + length); 852 | System.arraycopy(vpack, value.getStart(), buffer, size, length); 853 | size += length; 854 | } 855 | 856 | private void addArray(final boolean unindexed) { 857 | addCompoundValue((byte) (unindexed ? 0x13 : 0x06)); 858 | } 859 | 860 | private void addObject(final boolean unindexed) { 861 | addCompoundValue((byte) (unindexed ? 0x14 : 0x0b)); 862 | } 863 | 864 | private void addCompoundValue(final byte head) { 865 | // an Array or Object is started: 866 | stack.add(size); 867 | index.add(stack.size() - 1, new ArrayList()); 868 | add(head); 869 | // Will be filled later with bytelength and nr subs 870 | size += 8; 871 | ensureCapacity(size); 872 | } 873 | 874 | private void appendLength(final long length) { 875 | append(length, LONG_BYTES); 876 | } 877 | 878 | private void reportAdd() { 879 | final Collection depth = index.get(stack.size() - 1); 880 | depth.add(size - stack.get(stack.size() - 1)); 881 | } 882 | 883 | private void cleanupAdd() { 884 | final List depth = index.get(stack.size() - 1); 885 | depth.remove(depth.size() - 1); 886 | } 887 | 888 | public VPackBuilder close() throws VPackBuilderException { 889 | try { 890 | return close(true); 891 | } catch (final VPackKeyTypeException | VPackNeedAttributeTranslatorException e) { 892 | throw new VPackBuilderException(e); 893 | } 894 | } 895 | 896 | protected VPackBuilder close(final boolean sort) 897 | throws VPackBuilderNeedOpenCompoundException, VPackKeyTypeException, VPackNeedAttributeTranslatorException { 898 | if (isClosed()) { 899 | throw new VPackBuilderNeedOpenCompoundException(); 900 | } 901 | final byte head = head(); 902 | final boolean isArray = head == 0x06 || head == 0x13; 903 | final List in = index.get(stack.size() - 1); 904 | final int tos = stack.get(stack.size() - 1); 905 | if (in.isEmpty()) { 906 | return closeEmptyArrayOrObject(tos, isArray); 907 | } 908 | if (head == 0x13 || head == 0x14 || (head == 0x06 && options.isBuildUnindexedArrays()) 909 | || head == 0x0b && (options.isBuildUnindexedObjects() || in.size() == 1)) { 910 | if (closeCompactArrayOrObject(tos, isArray, in)) { 911 | return this; 912 | } 913 | // This might fall through, if closeCompactArrayOrObject gave up! 914 | } 915 | if (isArray) { 916 | return closeArray(tos, in); 917 | } 918 | // fix head byte in case a compact Array / Object was originally 919 | // requested 920 | buffer[tos] = (byte) 0x0b; 921 | 922 | // First determine byte length and its format: 923 | final int offsetSize; 924 | // can be 1, 2, 4 or 8 for the byte width of the offsets, 925 | // the byte length and the number of subvalues: 926 | if (size - tos + in.size() - 6 <= 0xff) { 927 | // We have so far used _pos - tos bytes, including the reserved 8 928 | // bytes for byte length and number of subvalues. In the 1-byte 929 | // number 930 | // case we would win back 6 bytes but would need one byte per 931 | // subvalue 932 | // for the index table 933 | offsetSize = 1; 934 | } else if ((size - tos) + 2 * in.size() <= 0xffff) { 935 | offsetSize = 2; 936 | } else { 937 | offsetSize = 4; 938 | } 939 | // Maybe we need to move down data 940 | if (offsetSize == 1) { 941 | final int targetPos = 3; 942 | if ((size - 1) > (tos + 9)) { 943 | for (int i = tos + targetPos; i < tos + 9; i++) { 944 | remove(tos + targetPos); 945 | } 946 | } 947 | final int diff = 9 - targetPos; 948 | final int n = in.size(); 949 | for (int i = 0; i < n; i++) { 950 | in.set(i, in.get(i) - diff); 951 | } 952 | } 953 | // One could move down things in the offsetSize == 2 case as well, 954 | // since we only need 4 bytes in the beginning. However, saving these 955 | // 4 bytes has been sacrificed on the Altar of Performance. 956 | 957 | // Now build the table: 958 | if (sort && in.size() >= 2) { 959 | // Object 960 | sortObjectIndex(tos, in); 961 | } 962 | // final int tableBase = size; 963 | for (long x : in) { 964 | ensureCapacity(size + offsetSize); 965 | for (int j = 0; j < offsetSize; j++) { 966 | addUnchecked(/* tableBase + offsetSize * i + j, */ (byte) (x & 0xff)); 967 | x >>= 8; 968 | } 969 | } 970 | // Finally fix the byte width in the type byte: 971 | if (offsetSize > 1) { 972 | if (offsetSize == 2) { 973 | buffer[tos] = (byte) (buffer[tos] + 1); 974 | } else { 975 | buffer[tos] = (byte) (buffer[tos] + 2); 976 | } 977 | } 978 | // Fix the byte length in the beginning 979 | long x = size - tos; 980 | for (int i = 1; i <= offsetSize; i++) { 981 | buffer[tos + i] = (byte) (x & 0xff); 982 | x >>= 8; 983 | } 984 | // set the number of items in the beginning 985 | x = in.size(); 986 | for (int i = offsetSize + 1; i <= 2 * offsetSize; i++) { 987 | buffer[tos + i] = (byte) (x & 0xff); 988 | x >>= 8; 989 | } 990 | stack.remove(stack.size() - 1); 991 | return this; 992 | } 993 | 994 | private VPackBuilder closeEmptyArrayOrObject(final int tos, final boolean isArray) { 995 | // empty Array or Object 996 | buffer[tos] = (byte) (isArray ? 0x01 : 0x0a); 997 | // no bytelength and number subvalues needed 998 | for (int i = 1; i <= 8; i++) { 999 | remove(tos + 1); 1000 | } 1001 | stack.remove(stack.size() - 1); 1002 | return this; 1003 | } 1004 | 1005 | private boolean closeCompactArrayOrObject(final int tos, final boolean isArray, final List in) { 1006 | // use the compact Array / Object format 1007 | final long nLen = NumberUtil.getVariableValueLength(in.size()); 1008 | long byteSize = size - (tos + 8) + nLen; 1009 | long bLen = NumberUtil.getVariableValueLength(byteSize); 1010 | byteSize += bLen; 1011 | if (NumberUtil.getVariableValueLength(byteSize) != bLen) { 1012 | byteSize += 1; 1013 | bLen += 1; 1014 | } 1015 | if (bLen < 9) { 1016 | // can only use compact notation if total byte length is at most 1017 | // 8 bytes long 1018 | buffer[tos] = (byte) (isArray ? 0x13 : 0x14); 1019 | final int targetPos = (int) (1 + bLen); 1020 | if (size - 1 >= (tos + 9)) { 1021 | for (int i = tos + targetPos; i < tos + 9; i++) { 1022 | remove(tos + targetPos); 1023 | } 1024 | } 1025 | // store byte length 1026 | storeVariableValueLength(tos, byteSize, false); 1027 | // need additional memory for storing the number of values 1028 | if (nLen > 8 - bLen) { 1029 | ensureCapacity((int) (size + nLen)); 1030 | } 1031 | // store number of values 1032 | storeVariableValueLength((int) (tos + byteSize), in.size(), true); 1033 | size += nLen; 1034 | stack.remove(stack.size() - 1); 1035 | return true; 1036 | } 1037 | return false; 1038 | } 1039 | 1040 | private void storeVariableValueLength(final int offset, final long value, final boolean reverse) { 1041 | int i = offset; 1042 | long val = value; 1043 | if (reverse) { 1044 | while (val >= 0x80) { 1045 | buffer[--i] = (byte) ((byte) (val & 0x7f) | (byte) 0x80); 1046 | val >>= 7; 1047 | } 1048 | buffer[--i] = (byte) (val & 0x7f); 1049 | } else { 1050 | while (val >= 0x80) { 1051 | buffer[++i] = (byte) ((byte) (val & 0x7f) | (byte) 0x80); 1052 | val >>= 7; 1053 | } 1054 | buffer[++i] = (byte) (val & 0x7f); 1055 | } 1056 | } 1057 | 1058 | private VPackBuilder closeArray(final int tos, final List in) { 1059 | // fix head byte in case a compact Array was originally 1060 | // requested 1061 | buffer[tos] = (byte) 0x06; 1062 | 1063 | boolean needIndexTable = true; 1064 | boolean needNrSubs = true; 1065 | final int n = in.size(); 1066 | if (n == 1) { 1067 | needIndexTable = false; 1068 | needNrSubs = false; 1069 | } else if ((size - tos) - in.get(0) == n * (in.get(1) - in.get(0))) { 1070 | // In this case it could be that all entries have the same length 1071 | // and we do not need an offset table at all: 1072 | boolean noTable = true; 1073 | final int subLen = in.get(1) - in.get(0); 1074 | if ((size - tos) - in.get(n - 1) != subLen) { 1075 | noTable = false; 1076 | } else { 1077 | for (int i = 1; i < n - 1; i++) { 1078 | if (in.get(i + 1) - in.get(i) != subLen) { 1079 | noTable = false; 1080 | break; 1081 | } 1082 | } 1083 | } 1084 | if (noTable) { 1085 | needIndexTable = false; 1086 | needNrSubs = false; 1087 | } 1088 | } 1089 | 1090 | // First determine byte length and its format: 1091 | final int offsetSize; 1092 | // can be 1, 2, 4 or 8 for the byte width of the offsets, 1093 | // the byte length and the number of subvalues: 1094 | if ((size - tos) + (needIndexTable ? n : 0) - (needNrSubs ? 6 : 7) <= 0xff) { 1095 | // We have so far used _pos - tos bytes, including the reserved 8 1096 | // bytes for byte length and number of subvalues. In the 1-byte 1097 | // number 1098 | // case we would win back 6 bytes but would need one byte per 1099 | // subvalue 1100 | // for the index table 1101 | offsetSize = 1; 1102 | } else if ((size - tos) + (needIndexTable ? 2 * n : 0) <= 0xffff) { 1103 | offsetSize = 2; 1104 | } else { 1105 | offsetSize = 4; 1106 | } 1107 | // Maybe we need to move down data 1108 | if (offsetSize == 1) { 1109 | int targetPos = 3; 1110 | if (!needIndexTable) { 1111 | targetPos = 2; 1112 | } 1113 | if ((size - 1) > (tos + 9)) { 1114 | for (int i = tos + targetPos; i < tos + 9; i++) { 1115 | remove(tos + targetPos); 1116 | } 1117 | } 1118 | final int diff = 9 - targetPos; 1119 | if (needIndexTable) { 1120 | for (int i = 0; i < n; i++) { 1121 | in.set(i, in.get(i) - diff); 1122 | } 1123 | } // Note: if !needIndexTable the index is now wrong! 1124 | } 1125 | // One could move down things in the offsetSize == 2 case as well, 1126 | // since we only need 4 bytes in the beginning. However, saving these 1127 | // 4 bytes has been sacrificed on the Altar of Performance. 1128 | 1129 | // Now build the table: 1130 | if (needIndexTable) { 1131 | // final int tableBase = size; 1132 | for (long x : in) { 1133 | ensureCapacity(size + offsetSize); 1134 | for (int j = 0; j < offsetSize; j++) { 1135 | addUnchecked(/* tableBase + offsetSize * i + j, */ (byte) (x & 0xff)); 1136 | x >>= 8; 1137 | } 1138 | } 1139 | } else { // no index table 1140 | buffer[tos] = (byte) 0x02; 1141 | } 1142 | // Finally fix the byte width in the type byte: 1143 | if (offsetSize > 1) { 1144 | if (offsetSize == 2) { 1145 | buffer[tos] = (byte) (buffer[tos] + 1); 1146 | } else { 1147 | buffer[tos] = (byte) (buffer[tos] + 2); 1148 | } 1149 | } 1150 | // Fix the byte length in the beginning 1151 | long x = size - tos; 1152 | for (int i = 1; i <= offsetSize; i++) { 1153 | buffer[tos + i] = (byte) (x & 0xff); 1154 | x >>= 8; 1155 | } 1156 | // set the number of items in the beginning 1157 | if (needNrSubs) { 1158 | x = n; 1159 | for (int i = offsetSize + 1; i <= 2 * offsetSize; i++) { 1160 | buffer[tos + i] = (byte) (x & 0xff); 1161 | x >>= 8; 1162 | } 1163 | } 1164 | stack.remove(stack.size() - 1); 1165 | return this; 1166 | } 1167 | 1168 | private static class SortEntry { 1169 | private final VPackStringSlice slice; 1170 | private final int offset; 1171 | 1172 | public SortEntry(final VPackStringSlice slice, final int offset) { 1173 | super(); 1174 | this.slice = slice; 1175 | this.offset = offset; 1176 | } 1177 | } 1178 | 1179 | private void sortObjectIndex(final int start, final List offsets) 1180 | throws VPackKeyTypeException, VPackNeedAttributeTranslatorException { 1181 | VPackBuilder.SortEntry[] attributes = new VPackBuilder.SortEntry[offsets.size()]; 1182 | for (int i = 0; i < offsets.size(); i++) { 1183 | Integer offset = offsets.get(i); 1184 | attributes[i] = new SortEntry(new VPackSlice(buffer, start + offset).makeKey().getAsStringSlice(), offset); 1185 | } 1186 | final Comparator comparator = new Comparator() { 1187 | @Override 1188 | public int compare(final SortEntry o1, final SortEntry o2) { 1189 | return o1.slice.compareTo(o2.slice); 1190 | } 1191 | }; 1192 | Arrays.sort(attributes, comparator); 1193 | offsets.clear(); 1194 | for (final SortEntry sortEntry : attributes) { 1195 | offsets.add(sortEntry.offset); 1196 | } 1197 | } 1198 | 1199 | public static int compareTo( 1200 | final byte[] b1, 1201 | final int b1Index, 1202 | final int b1Length, 1203 | final byte[] b2, 1204 | final int b2Index, 1205 | final int b2Length) { 1206 | final int commonLength = Math.min(b1Length, b2Length); 1207 | for (int i = 0; i < commonLength; i++) { 1208 | final byte byte1 = b1[b1Index + i]; 1209 | final byte byte2 = b2[b2Index + i]; 1210 | if (byte1 != byte2) { 1211 | return (byte1 < byte2) ? -1 : 1; 1212 | } 1213 | } 1214 | if (b1Length != b2Length) { 1215 | return (b1Length < b2Length) ? -2 : 2; 1216 | } 1217 | return 0; 1218 | } 1219 | 1220 | private boolean isClosed() { 1221 | return stack.isEmpty(); 1222 | } 1223 | 1224 | private byte head() { 1225 | final Integer in = stack.get(stack.size() - 1); 1226 | return buffer[in]; 1227 | } 1228 | 1229 | public VPackSlice slice() { 1230 | return new VPackSlice(buffer); 1231 | } 1232 | 1233 | public int getVpackSize() { 1234 | return size; 1235 | } 1236 | 1237 | } 1238 | -------------------------------------------------------------------------------- /src/main/java/com/arangodb/velocypack/VPackSlice.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DISCLAIMER 3 | * 4 | * Copyright 2016 ArangoDB GmbH, Cologne, Germany 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * Copyright holder is ArangoDB GmbH, Cologne, Germany 19 | */ 20 | 21 | package com.arangodb.velocypack; 22 | 23 | import com.arangodb.velocypack.exception.VPackException; 24 | import com.arangodb.velocypack.exception.VPackKeyTypeException; 25 | import com.arangodb.velocypack.exception.VPackNeedAttributeTranslatorException; 26 | import com.arangodb.velocypack.exception.VPackValueTypeException; 27 | import com.arangodb.velocypack.internal.VPackAttributeTranslatorImpl; 28 | import com.arangodb.velocypack.internal.util.BinaryUtil; 29 | import com.arangodb.velocypack.internal.util.DateUtil; 30 | import com.arangodb.velocypack.internal.util.NumberUtil; 31 | import com.arangodb.velocypack.internal.util.ObjectArrayUtil; 32 | import com.arangodb.velocypack.internal.util.ValueLengthUtil; 33 | import com.arangodb.velocypack.internal.util.ValueTypeUtil; 34 | 35 | import java.io.Serializable; 36 | import java.math.BigDecimal; 37 | import java.math.BigInteger; 38 | import java.nio.charset.StandardCharsets; 39 | import java.util.ArrayList; 40 | import java.util.Arrays; 41 | import java.util.Collections; 42 | import java.util.Date; 43 | import java.util.Iterator; 44 | import java.util.List; 45 | import java.util.Map; 46 | import java.util.Map.Entry; 47 | 48 | /** 49 | * @author Mark Vollmary 50 | * 51 | */ 52 | public class VPackSlice implements Serializable { 53 | 54 | private static final long serialVersionUID = -3452953589283603980L; 55 | 56 | private static final byte[] NONE_SLICE_DATA = new byte[] { 0x00 }; 57 | public static final VPackSlice NONE_SLICE = new VPackSlice(); 58 | 59 | public static final VPackAttributeTranslator attributeTranslator = new VPackAttributeTranslatorImpl(); 60 | 61 | private final byte[] vpack; 62 | private final int start; 63 | 64 | protected VPackSlice() { 65 | this(NONE_SLICE_DATA, 0); 66 | } 67 | 68 | public VPackSlice(final byte[] vpack) { 69 | this(vpack, 0); 70 | } 71 | 72 | public VPackSlice(final byte[] vpack, final int start) { 73 | super(); 74 | this.vpack = vpack; 75 | this.start = start; 76 | } 77 | 78 | public byte head() { 79 | return vpack[start]; 80 | } 81 | 82 | public byte[] getBuffer() { 83 | return vpack; 84 | } 85 | 86 | /** 87 | * @return VPackSlice buffer without trailing zeros 88 | */ 89 | public byte[] toByteArray() { 90 | return Arrays.copyOfRange(vpack, start, start + getByteSize()); 91 | } 92 | 93 | public int getStart() { 94 | return start; 95 | } 96 | 97 | public int getValueStart() { 98 | return start + tagsOffset(start); 99 | } 100 | 101 | public VPackSlice value() { 102 | return isTagged() ? new VPackSlice(vpack, getValueStart()) : this; 103 | } 104 | 105 | public ValueType getType() { 106 | return ValueTypeUtil.get(head()); 107 | } 108 | 109 | private int length() { 110 | return ValueLengthUtil.get(head()) - 1; 111 | } 112 | 113 | public boolean isType(final ValueType type) { 114 | return getType() == type; 115 | } 116 | 117 | public boolean isNone() { 118 | return isType(ValueType.NONE); 119 | } 120 | 121 | public boolean isNull() { 122 | return isType(ValueType.NULL); 123 | } 124 | 125 | public boolean isIllegal() { 126 | return isType(ValueType.ILLEGAL); 127 | } 128 | 129 | public boolean isBoolean() { 130 | return isType(ValueType.BOOL); 131 | } 132 | 133 | public boolean isTrue() { 134 | return head() == 0x1a; 135 | } 136 | 137 | public boolean isFalse() { 138 | return head() == 0x19; 139 | } 140 | 141 | public boolean isArray() { 142 | return isType(ValueType.ARRAY); 143 | } 144 | 145 | public boolean isObject() { 146 | return isType(ValueType.OBJECT); 147 | } 148 | 149 | public boolean isDouble() { 150 | return isType(ValueType.DOUBLE); 151 | } 152 | 153 | public boolean isDate() { 154 | return isType(ValueType.UTC_DATE); 155 | } 156 | 157 | public boolean isExternal() { 158 | return isType(ValueType.EXTERNAL); 159 | } 160 | 161 | public boolean isMinKey() { 162 | return isType(ValueType.MIN_KEY); 163 | } 164 | 165 | public boolean isMaxKey() { 166 | return isType(ValueType.MAX_KEY); 167 | } 168 | 169 | public boolean isInt() { 170 | return isType(ValueType.INT); 171 | } 172 | 173 | public boolean isUInt() { 174 | return isType(ValueType.UINT); 175 | } 176 | 177 | public boolean isSmallInt() { 178 | return isType(ValueType.SMALLINT); 179 | } 180 | 181 | public boolean isInteger() { 182 | return isInt() || isUInt() || isSmallInt(); 183 | } 184 | 185 | public boolean isByte() { 186 | return isInteger(); 187 | } 188 | 189 | public boolean isNumber() { 190 | return isInteger() || isDouble(); 191 | } 192 | 193 | public boolean isString() { 194 | return isType(ValueType.STRING); 195 | } 196 | 197 | public boolean isBinary() { 198 | return isType(ValueType.BINARY); 199 | } 200 | 201 | public boolean isBCD() { 202 | return isType(ValueType.BCD); 203 | } 204 | 205 | public boolean isCustom() { 206 | return isType(ValueType.CUSTOM); 207 | } 208 | 209 | public boolean isTagged() { 210 | return isType(ValueType.TAGGED); 211 | } 212 | 213 | public long getFirstTag() { 214 | if(isTagged()) { 215 | if(vpack[start] == (byte)0xee) { 216 | return NumberUtil.toLong(vpack, start+1, 1, false); 217 | } else if(vpack[start] == (byte)0xef) { 218 | return NumberUtil.toLong(vpack, start+1, 8, false); 219 | } else { 220 | throw new IllegalStateException("Invalid tag type ID"); 221 | } 222 | } 223 | 224 | return 0; 225 | } 226 | 227 | public List getTags() { 228 | if(!isTagged()) { 229 | return Collections.emptyList(); 230 | } 231 | 232 | List ret = new ArrayList<>(); 233 | int start = this.start; 234 | 235 | while(ValueTypeUtil.get(vpack[start]) == ValueType.TAGGED) { 236 | int offset; 237 | long tag; 238 | 239 | if(vpack[start] == (byte)0xee) { 240 | tag = NumberUtil.toLong(vpack, start+1, 1, false); 241 | offset = 2; 242 | } else if(vpack[start] == (byte)0xef) { 243 | tag = NumberUtil.toLong(vpack, start+1, 8, false); 244 | offset = 9; 245 | } else { 246 | throw new IllegalStateException("Invalid tag type ID"); 247 | } 248 | 249 | ret.add(tag); 250 | start += offset; 251 | } 252 | 253 | return ret; 254 | } 255 | 256 | public boolean hasTag(long tagId) { 257 | int start = this.start; 258 | 259 | while(ValueTypeUtil.get(vpack[start]) == ValueType.TAGGED) { 260 | int offset; 261 | long tag; 262 | 263 | if(vpack[start] == (byte)0xee) { 264 | tag = NumberUtil.toLong(vpack, start+1, 1, false); 265 | offset = 2; 266 | } else if(vpack[start] == (byte)0xef) { 267 | tag = NumberUtil.toLong(vpack, start+1, 8, false); 268 | offset = 9; 269 | } else { 270 | throw new IllegalStateException("Invalid tag type ID"); 271 | } 272 | 273 | if(tag == tagId) { 274 | return true; 275 | } 276 | 277 | start += offset; 278 | } 279 | 280 | return false; 281 | } 282 | 283 | public boolean getAsBoolean() { 284 | if (!isBoolean()) { 285 | throw new VPackValueTypeException(ValueType.BOOL); 286 | } 287 | return isTrue(); 288 | } 289 | 290 | public double getAsDouble() { 291 | return getAsNumber().doubleValue(); 292 | } 293 | 294 | private double getAsDoubleUnchecked() { 295 | return NumberUtil.toDouble(vpack, start + 1, length()); 296 | } 297 | 298 | public BigDecimal getAsBigDecimal() { 299 | if (isString()) { 300 | return new BigDecimal(getAsString()); 301 | } else if (isDouble()) { 302 | return BigDecimal.valueOf(getAsDouble()); 303 | } else if (isSmallInt() || isInt()) { 304 | return BigDecimal.valueOf(getAsLong()); 305 | } else if (isUInt()) { 306 | return new BigDecimal(NumberUtil.toBigInteger(vpack, start + 1, length())); 307 | } else { 308 | throw new VPackValueTypeException(ValueType.STRING, ValueType.DOUBLE); 309 | } 310 | } 311 | 312 | private long getSmallInt() { 313 | final byte head = head(); 314 | final long smallInt; 315 | if (head >= 0x30 && head <= 0x39) { 316 | smallInt = head - 0x30; 317 | } else /* if (head >= 0x3a && head <= 0x3f) */ { 318 | smallInt = head - 0x3a - 6; 319 | } 320 | return smallInt; 321 | } 322 | 323 | private long getInt() { 324 | return NumberUtil.toLong(vpack, start + 1, length(), true); 325 | } 326 | 327 | private long getUInt() { 328 | return NumberUtil.toLong(vpack, start + 1, length()); 329 | } 330 | 331 | public Number getAsNumber() { 332 | final Number result; 333 | if (isSmallInt()) { 334 | result = getSmallInt(); 335 | } else if (isInt()) { 336 | result = getInt(); 337 | } else if (isUInt()) { 338 | result = getUInt(); 339 | } else if (isDouble()) { 340 | result = getAsDoubleUnchecked(); 341 | } else { 342 | throw new VPackValueTypeException(ValueType.INT, ValueType.UINT, ValueType.SMALLINT); 343 | } 344 | return result; 345 | } 346 | 347 | public long getAsLong() { 348 | return getAsNumber().longValue(); 349 | } 350 | 351 | public int getAsInt() { 352 | return getAsNumber().intValue(); 353 | } 354 | 355 | public float getAsFloat() { 356 | return getAsNumber().floatValue(); 357 | } 358 | 359 | public short getAsShort() { 360 | return getAsNumber().shortValue(); 361 | } 362 | 363 | public byte getAsByte() { 364 | return getAsNumber().byteValue(); 365 | } 366 | 367 | public BigInteger getAsBigInteger() { 368 | if (isString()) { 369 | return new BigInteger(getAsString()); 370 | } else if (isSmallInt() || isInt()) { 371 | return BigInteger.valueOf(getAsLong()); 372 | } else if (isUInt()) { 373 | return NumberUtil.toBigInteger(vpack, start + 1, length()); 374 | } else { 375 | throw new VPackValueTypeException(ValueType.STRING, ValueType.INT, ValueType.UINT, ValueType.SMALLINT); 376 | } 377 | } 378 | 379 | public Date getAsDate() { 380 | if (!isDate()) { 381 | throw new VPackValueTypeException(ValueType.UTC_DATE); 382 | } 383 | return DateUtil.toDate(vpack, start + 1, length()); 384 | } 385 | 386 | public java.sql.Date getAsSQLDate() { 387 | if (!isDate()) { 388 | throw new VPackValueTypeException(ValueType.UTC_DATE); 389 | } 390 | return DateUtil.toSQLDate(vpack, start + 1, length()); 391 | } 392 | 393 | public java.sql.Timestamp getAsSQLTimestamp() { 394 | if (!isDate()) { 395 | throw new VPackValueTypeException(ValueType.UTC_DATE); 396 | } 397 | return DateUtil.toSQLTimestamp(vpack, start + 1, length()); 398 | } 399 | 400 | public String getAsString() { 401 | return getAsStringSlice().toString(); 402 | } 403 | 404 | public VPackStringSlice getAsStringSlice() { 405 | if (!isString()) { 406 | throw new VPackValueTypeException(ValueType.STRING); 407 | } 408 | return isLongString() ? getLongString() : getShortString(); 409 | } 410 | 411 | public char getAsChar() { 412 | return getAsString().charAt(0); 413 | } 414 | 415 | private boolean isLongString() { 416 | return head() == (byte) 0xbf; 417 | } 418 | 419 | private VPackStringSlice getShortString() { 420 | return new VPackStringSlice(vpack, start + 1, length()); 421 | } 422 | 423 | private VPackStringSlice getLongString() { 424 | return new VPackStringSlice(vpack, start + 9, getLongStringLength()); 425 | } 426 | 427 | private int getLongStringLength() { 428 | return (int) NumberUtil.toLong(vpack, start + 1, 8); 429 | } 430 | 431 | private int getStringLength() { 432 | return isLongString() ? getLongStringLength() : head() - 0x40; 433 | } 434 | 435 | public byte[] getAsBinary() { 436 | if (!isBinary()) { 437 | throw new VPackValueTypeException(ValueType.BINARY); 438 | } 439 | return BinaryUtil.toBinary(vpack, start + 1 + head() - ((byte) 0xbf), getBinaryLength()); 440 | } 441 | 442 | public int getBinaryLength() { 443 | if (!isBinary()) { 444 | throw new VPackValueTypeException(ValueType.BINARY); 445 | } 446 | return getBinaryLengthUnchecked(); 447 | } 448 | 449 | private int getBinaryLengthUnchecked() { 450 | return (int) NumberUtil.toLong(vpack, start + 1, head() - ((byte) 0xbf)); 451 | } 452 | 453 | /** 454 | * @return the number of members for an Array, Object or String 455 | */ 456 | public int getLength() { 457 | final long length; 458 | if (isString()) { 459 | length = getStringLength(); 460 | } else if (!isArray() && !isObject()) { 461 | throw new VPackValueTypeException(ValueType.ARRAY, ValueType.OBJECT, ValueType.STRING); 462 | } else { 463 | final byte head = head(); 464 | if (head == 0x01 || head == 0x0a) { 465 | // empty 466 | length = 0; 467 | } else if (head == 0x13 || head == 0x14) { 468 | // compact array or object 469 | final long end = NumberUtil.readVariableValueLength(vpack, start + 1, false); 470 | length = NumberUtil.readVariableValueLength(vpack, (int) (start + end - 1), true); 471 | } else { 472 | final int offsetsize = ObjectArrayUtil.getOffsetSize(head); 473 | final long end = NumberUtil.toLong(vpack, start + 1, offsetsize); 474 | if (head <= 0x05) { 475 | // array with no offset table or length 476 | final int dataOffset = findDataOffset(); 477 | final VPackSlice first = new VPackSlice(vpack, start + dataOffset); 478 | length = (end - dataOffset) / first.getByteSize(); 479 | } else if (offsetsize < 8) { 480 | length = NumberUtil.toLong(vpack, start + 1 + offsetsize, offsetsize); 481 | } else { 482 | length = NumberUtil.toLong(vpack, (int) (start + end - offsetsize), offsetsize); 483 | } 484 | } 485 | } 486 | return (int) length; 487 | } 488 | 489 | public int size() { 490 | return getLength(); 491 | } 492 | 493 | /** 494 | * Must be called for a nonempty array or object at start(): 495 | */ 496 | protected int findDataOffset() { 497 | final int fsm = ObjectArrayUtil.getFirstSubMap(head()); 498 | final int offset; 499 | if (fsm <= 2 && vpack[start + 2] != 0) { 500 | offset = 2; 501 | } else if (fsm <= 3 && vpack[start + 3] != 0) { 502 | offset = 3; 503 | } else if (fsm <= 5 && vpack[start + 6] != 0) { 504 | offset = 5; 505 | } else { 506 | offset = 9; 507 | } 508 | return offset; 509 | } 510 | 511 | public int getByteSize() { 512 | return getByteSize(start); 513 | } 514 | 515 | private int getByteSize(int start) { 516 | long size; 517 | final byte head = vpack[start]; 518 | final int valueLength = ValueLengthUtil.get(head); 519 | if (valueLength != 0) { 520 | size = valueLength; 521 | } else { 522 | switch (ValueTypeUtil.get(head)) { 523 | case ARRAY: 524 | case OBJECT: 525 | if (head == 0x13 || head == 0x14) { 526 | // compact Array or Object 527 | size = NumberUtil.readVariableValueLength(vpack, start + 1, false); 528 | } else /* if (head <= 0x14) */ { 529 | size = NumberUtil.toLong(vpack, start + 1, ObjectArrayUtil.getOffsetSize(head)); 530 | } 531 | break; 532 | case STRING: 533 | // long UTF-8 String 534 | size = NumberUtil.toLong(vpack, start + 1, 8) + 1 + 8; 535 | break; 536 | case BINARY: 537 | size = 1 + head - ((byte) 0xbf) + NumberUtil.toLong(vpack, start + 1, head - ((byte) 0xbf)); 538 | break; 539 | case BCD: 540 | if (head <= (byte) 0xcf) { 541 | size = 1 + head - ((byte) 0xc7) + NumberUtil.toLong(vpack, start + 1, head - ((byte) 0xc7)) + 4; 542 | } else { 543 | size = 1 + head - ((byte) 0xcf) + NumberUtil.toLong(vpack, start + 1, head - ((byte) 0xcf)) + 4; 544 | } 545 | break; 546 | case TAGGED: 547 | int offset = tagsOffset(start); 548 | size = getByteSize(start + offset) + offset; 549 | break; 550 | case CUSTOM: 551 | if (head == (byte) 0xf4 || head == (byte) 0xf5 || head == (byte) 0xf6) { 552 | size = 2 + NumberUtil.toLong(vpack, start + 1, 1); 553 | } else if (head == (byte) 0xf7 || head == (byte) 0xf8 || head == (byte) 0xf9) { 554 | size = 3 + NumberUtil.toLong(vpack, start + 1, 2); 555 | } else if (head == (byte) 0xfa || head == (byte) 0xfb || head == (byte) 0xfc) { 556 | size = 5 + NumberUtil.toLong(vpack, start + 1, 4); 557 | } else /* if (head == 0xfd || head == 0xfe || head == 0xff) */ { 558 | size = 9 + NumberUtil.toLong(vpack, start + 1, 8); 559 | } 560 | break; 561 | default: 562 | // TODO 563 | throw new IllegalStateException("Invalid type for byteSize()"); 564 | } 565 | } 566 | return (int) size; 567 | } 568 | 569 | private int tagOffset(int start) { 570 | byte v = vpack[start]; 571 | 572 | if(ValueTypeUtil.get(v) == ValueType.TAGGED) { 573 | if(v == (byte)0xee) { 574 | return 2; 575 | } else if(v == (byte)0xef) { 576 | return 9; 577 | } else { 578 | throw new IllegalStateException("Invalid tag type ID"); 579 | } 580 | } 581 | 582 | return 0; 583 | } 584 | 585 | private int tagsOffset(int start) { 586 | int ret = 0; 587 | 588 | while(ValueTypeUtil.get(vpack[start]) == ValueType.TAGGED) { 589 | int offset = tagOffset(start); 590 | ret += offset; 591 | start += offset; 592 | } 593 | 594 | return ret; 595 | } 596 | 597 | /** 598 | * @return array value at the specified index 599 | * @throws VPackValueTypeException 600 | */ 601 | public VPackSlice get(final int index) { 602 | if (!isArray()) { 603 | throw new VPackValueTypeException(ValueType.ARRAY); 604 | } 605 | return getNth(index); 606 | } 607 | 608 | public VPackSlice get(final String attribute) throws VPackException { 609 | if (!isObject()) { 610 | throw new VPackValueTypeException(ValueType.OBJECT); 611 | } 612 | final byte head = head(); 613 | VPackSlice result; 614 | if (attribute == null) { 615 | result = NONE_SLICE; 616 | } else if (head == 0x0a) { 617 | // special case, empty object 618 | result = NONE_SLICE; 619 | } else if (head == 0x14) { 620 | // compact Object 621 | result = getFromCompactObject(attribute); 622 | } else { 623 | final int offsetsize = ObjectArrayUtil.getOffsetSize(head); 624 | final long end = NumberUtil.toLong(vpack, start + 1, offsetsize); 625 | final long n; 626 | if (offsetsize < 8) { 627 | n = NumberUtil.toLong(vpack, start + 1 + offsetsize, offsetsize); 628 | } else { 629 | n = NumberUtil.toLong(vpack, (int) (start + end - offsetsize), offsetsize); 630 | } 631 | if (n == 1) { 632 | // Just one attribute, there is no index table! 633 | final VPackSlice key = new VPackSlice(vpack, start + findDataOffset()); 634 | 635 | if (key.isString()) { 636 | if (key.isEqualString(attribute)) { 637 | result = new VPackSlice(vpack, key.start + key.getByteSize()); 638 | } else { 639 | // no match 640 | result = NONE_SLICE; 641 | } 642 | } else if (key.isInteger()) { 643 | // translate key 644 | if (key.translateUnchecked().isEqualString(attribute)) { 645 | result = new VPackSlice(vpack, key.start + key.getByteSize()); 646 | } else { 647 | // no match 648 | result = NONE_SLICE; 649 | } 650 | } else { 651 | // no match 652 | result = NONE_SLICE; 653 | } 654 | } else { 655 | final long ieBase = end - n * offsetsize - (offsetsize == 8 ? 8 : 0); 656 | 657 | // only use binary search for attributes if we have at least 658 | // this many entries 659 | // otherwise we'll always use the linear search 660 | final long sortedSearchEntriesThreshold = 4; 661 | 662 | final boolean sorted = head >= 0x0b && head <= 0x0e; 663 | if (sorted && n >= sortedSearchEntriesThreshold) { 664 | // This means, we have to handle the special case n == 1 665 | // only in the linear search! 666 | result = searchObjectKeyBinary(attribute, ieBase, offsetsize, n); 667 | } else { 668 | result = searchObjectKeyLinear(attribute, ieBase, offsetsize, n); 669 | } 670 | } 671 | } 672 | return result; 673 | } 674 | 675 | /** 676 | * translates an integer key into a string, without checks 677 | */ 678 | protected VPackSlice translateUnchecked() { 679 | final VPackSlice result = attributeTranslator.translate(getAsInt()); 680 | return result != null ? result : NONE_SLICE; 681 | } 682 | 683 | protected VPackSlice makeKey() throws VPackKeyTypeException, VPackNeedAttributeTranslatorException { 684 | if (isString()) { 685 | return this; 686 | } 687 | if (isInteger()) { 688 | return translateUnchecked(); 689 | } 690 | throw new VPackKeyTypeException("Cannot translate key of this type"); 691 | } 692 | 693 | private VPackSlice getFromCompactObject(final String attribute) 694 | throws VPackKeyTypeException, VPackNeedAttributeTranslatorException { 695 | for (final Iterator> iterator = objectIterator(); iterator.hasNext();) { 696 | final Entry next = iterator.next(); 697 | if (next.getKey().equals(attribute)) { 698 | return next.getValue(); 699 | } 700 | } 701 | // not found 702 | return NONE_SLICE; 703 | } 704 | 705 | private VPackSlice searchObjectKeyBinary( 706 | final String attribute, 707 | final long ieBase, 708 | final int offsetsize, 709 | final long n) throws VPackValueTypeException, VPackNeedAttributeTranslatorException { 710 | 711 | VPackSlice result; 712 | long l = 0; 713 | long r = n - 1; 714 | 715 | byte[] attributeBytes = attribute.getBytes(StandardCharsets.UTF_8); 716 | for (;;) { 717 | // midpoint 718 | final long index = l + ((r - l) / 2); 719 | final long offset = ieBase + index * offsetsize; 720 | final long keyIndex = NumberUtil.toLong(vpack, (int) (start + offset), offsetsize); 721 | final VPackSlice key = new VPackSlice(vpack, (int) (start + keyIndex)); 722 | int res; 723 | if (key.isString()) { 724 | res = key.getAsStringSlice().compareToBytes(attributeBytes); 725 | } else if (key.isInteger()) { 726 | // translate key 727 | res = key.translateUnchecked().getAsStringSlice().compareToBytes(attributeBytes); 728 | } else { 729 | // invalid key 730 | result = NONE_SLICE; 731 | break; 732 | } 733 | if (res == 0) { 734 | // found 735 | result = new VPackSlice(vpack, key.start + key.getByteSize()); 736 | break; 737 | } 738 | if (res > 0) { 739 | if (index == 0) { 740 | result = NONE_SLICE; 741 | break; 742 | } 743 | r = index - 1; 744 | } else { 745 | l = index + 1; 746 | } 747 | if (r < l) { 748 | result = NONE_SLICE; 749 | break; 750 | } 751 | } 752 | return result; 753 | } 754 | 755 | private VPackSlice searchObjectKeyLinear( 756 | final String attribute, 757 | final long ieBase, 758 | final int offsetsize, 759 | final long n) throws VPackValueTypeException, VPackNeedAttributeTranslatorException { 760 | 761 | VPackSlice result = NONE_SLICE; 762 | for (long index = 0; index < n; index++) { 763 | final long offset = ieBase + index * offsetsize; 764 | final long keyIndex = NumberUtil.toLong(vpack, (int) (start + offset), offsetsize); 765 | final VPackSlice key = new VPackSlice(vpack, (int) (start + keyIndex)); 766 | if (key.isString()) { 767 | if (!key.isEqualString(attribute)) { 768 | continue; 769 | } 770 | } else if (key.isInteger()) { 771 | // translate key 772 | if (!key.translateUnchecked().isEqualString(attribute)) { 773 | continue; 774 | } 775 | } else { 776 | // invalid key type 777 | result = NONE_SLICE; 778 | break; 779 | } 780 | // key is identical. now return value 781 | result = new VPackSlice(vpack, key.start + key.getByteSize()); 782 | break; 783 | } 784 | return result; 785 | 786 | } 787 | 788 | public VPackSlice keyAt(final int index) { 789 | if (!isObject()) { 790 | throw new VPackValueTypeException(ValueType.OBJECT); 791 | } 792 | return getNthKey(index); 793 | } 794 | 795 | public VPackSlice valueAt(final int index) { 796 | if (!isObject()) { 797 | throw new VPackValueTypeException(ValueType.OBJECT); 798 | } 799 | final VPackSlice key = getNthKey(index); 800 | return new VPackSlice(vpack, key.start + key.getByteSize()); 801 | } 802 | 803 | private VPackSlice getNthKey(final int index) { 804 | return new VPackSlice(vpack, start + getNthOffset(index)); 805 | } 806 | 807 | public VPackSlice getNth(final int index) { 808 | return new VPackSlice(vpack, start + getNthOffset(index)); 809 | } 810 | 811 | /** 812 | * 813 | * @return the offset for the nth member from an Array or Object type 814 | */ 815 | private int getNthOffset(final int index) { 816 | final int offset; 817 | final byte head = head(); 818 | if (head == 0x13 || head == 0x14) { 819 | // compact Array or Object 820 | offset = getNthOffsetFromCompact(index); 821 | } else if (head == 0x01 || head == 0x0a) { 822 | // special case: empty Array or empty Object 823 | throw new IndexOutOfBoundsException(); 824 | } else { 825 | final long n; 826 | final int offsetsize = ObjectArrayUtil.getOffsetSize(head); 827 | final long end = NumberUtil.toLong(vpack, start + 1, offsetsize); 828 | int dataOffset = findDataOffset(); 829 | if (head <= 0x05) { 830 | // array with no offset table or length 831 | final VPackSlice first = new VPackSlice(vpack, start + dataOffset); 832 | n = (end - dataOffset) / first.getByteSize(); 833 | } else if (offsetsize < 8) { 834 | n = NumberUtil.toLong(vpack, start + 1 + offsetsize, offsetsize); 835 | } else { 836 | n = NumberUtil.toLong(vpack, (int) (start + end - offsetsize), offsetsize); 837 | } 838 | if (index >= n) { 839 | throw new IndexOutOfBoundsException(); 840 | } 841 | if (head <= 0x05 || n == 1) { 842 | // no index table, but all array items have the same length 843 | // or only one item is in the array 844 | // now fetch first item and determine its length 845 | if (dataOffset == 0) { 846 | dataOffset = findDataOffset(); 847 | } 848 | offset = dataOffset + index * new VPackSlice(vpack, start + dataOffset).getByteSize(); 849 | } else { 850 | final long ieBase = end - n * offsetsize + index * offsetsize - (offsetsize == 8 ? 8 : 0); 851 | offset = (int) NumberUtil.toLong(vpack, (int) (start + ieBase), offsetsize); 852 | } 853 | } 854 | return offset; 855 | } 856 | 857 | /** 858 | * @return the offset for the nth member from a compact Array or Object type 859 | */ 860 | private int getNthOffsetFromCompact(final int index) { 861 | final long end = NumberUtil.readVariableValueLength(vpack, start + 1, false); 862 | final long n = NumberUtil.readVariableValueLength(vpack, (int) (start + end - 1), true); 863 | if (index >= n) { 864 | throw new IndexOutOfBoundsException(); 865 | } 866 | final byte head = head(); 867 | long offset = 1 + NumberUtil.getVariableValueLength(end); 868 | long current = 0; 869 | while (current != index) { 870 | final long byteSize = new VPackSlice(vpack, (int) (start + offset)).getByteSize(); 871 | offset += byteSize; 872 | if (head == 0x14) { 873 | offset += byteSize; 874 | } 875 | ++current; 876 | } 877 | return (int) offset; 878 | } 879 | 880 | private boolean isEqualString(final String s) { 881 | final String string = getAsString(); 882 | return string.equals(s); 883 | } 884 | 885 | private int compareString(final String s) { 886 | final String string = getAsString(); 887 | return string.compareTo(s); 888 | } 889 | 890 | public Iterator arrayIterator() { 891 | if (isArray()) { 892 | return new ArrayIterator(this); 893 | } else { 894 | throw new VPackValueTypeException(ValueType.ARRAY); 895 | } 896 | } 897 | 898 | public Iterator> objectIterator() { 899 | if (isObject()) { 900 | return new ObjectIterator(this); 901 | } else { 902 | throw new VPackValueTypeException(ValueType.OBJECT); 903 | } 904 | } 905 | 906 | /** 907 | * @return a pretty-printable schema of the VPackSlice, for debug purposes only 908 | */ 909 | public String getSchemaDescription() { 910 | StringBuilder sb = new StringBuilder(); 911 | doGetSchemaDescription(sb, 0); 912 | return sb.toString(); 913 | } 914 | 915 | private void doGetSchemaDescription(StringBuilder sb, int level) { 916 | ValueType type = getType(); 917 | sb.append(" "); 918 | sb.append(type); 919 | 920 | if (type == ValueType.OBJECT) { 921 | level++; 922 | Iterator> it = objectIterator(); 923 | while (it.hasNext()) { 924 | Map.Entry f = it.next(); 925 | sb.append("\n"); 926 | for (int i = 0; i < level; i++) { 927 | sb.append(" |----"); 928 | } 929 | sb.append(" "); 930 | sb.append(f.getKey()); 931 | f.getValue().doGetSchemaDescription(sb, level); 932 | } 933 | } else if (type == ValueType.ARRAY) { 934 | // only print the schema of the first element of the array 935 | Iterator ai = arrayIterator(); 936 | if (ai.hasNext()) { 937 | level++; 938 | VPackSlice firstValue = ai.next(); 939 | firstValue.doGetSchemaDescription(sb, level); 940 | } 941 | } 942 | } 943 | 944 | @Override 945 | public int hashCode() { 946 | final int prime = 31; 947 | int result = 1; 948 | result = prime * result + start; 949 | 950 | int arrayHash = 1; 951 | for (int i = start, max = getByteSize(); i < max; i++) 952 | arrayHash = 31 * arrayHash + vpack[i]; 953 | 954 | result = prime * result + arrayHash; 955 | return result; 956 | } 957 | 958 | @Override 959 | public boolean equals(final Object obj) { 960 | if (this == obj) { 961 | return true; 962 | } 963 | if (obj == null) { 964 | return false; 965 | } 966 | if (getClass() != obj.getClass()) { 967 | return false; 968 | } 969 | final VPackSlice other = (VPackSlice) obj; 970 | 971 | int byteSize = getByteSize(); 972 | int otherByteSize = other.getByteSize(); 973 | 974 | if(byteSize != otherByteSize) { 975 | return false; 976 | } 977 | 978 | for(int i = 0; i < byteSize; i++) { 979 | if(vpack[i+start] != other.vpack[i+other.start]) { 980 | return false; 981 | } 982 | } 983 | 984 | return true; 985 | } 986 | 987 | 988 | } 989 | -------------------------------------------------------------------------------- /src/main/java/com/arangodb/velocypack/VPackStringSlice.java: -------------------------------------------------------------------------------- 1 | package com.arangodb.velocypack; 2 | 3 | import java.nio.charset.StandardCharsets; 4 | 5 | /** 6 | * Wrapper around a {@link ValueType#STRING} supporting fast bytewise comparison. 7 | * 8 | * @see VelocyPack Objects 9 | */ 10 | public class VPackStringSlice implements Comparable { 11 | private final byte[] vpack; 12 | /** 13 | * Index of the string bytes within {@link this#vpack}, 14 | * i.e. tag byte and length are somewhere before this index. 15 | */ 16 | private final int start; 17 | private final int length; 18 | 19 | public VPackStringSlice(byte[] vpack, int start, int length) { 20 | this.vpack = vpack; 21 | this.start = start; 22 | this.length = length; 23 | } 24 | 25 | @Override 26 | public int compareTo(VPackStringSlice o) { 27 | return compareToBytes(o.vpack, o.start, o.length); 28 | } 29 | 30 | public int compareToBytes(byte[] other) { 31 | return compareToBytes(other, 0, other.length); 32 | } 33 | 34 | public int compareToBytes(byte[] other, int off, int oLen) { 35 | for (int i = 0; i < length && i < oLen; i++) { 36 | int c = (vpack[start + i] & 0xff) - (other[off + i] & 0xff); 37 | if (c != 0) return c; 38 | } 39 | return length - oLen; 40 | } 41 | 42 | @Override 43 | public String toString() { 44 | return new String(vpack, start, length, StandardCharsets.UTF_8); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/arangodb/velocypack/ValueType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DISCLAIMER 3 | * 4 | * Copyright 2016 ArangoDB GmbH, Cologne, Germany 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * Copyright holder is ArangoDB GmbH, Cologne, Germany 19 | */ 20 | 21 | package com.arangodb.velocypack; 22 | 23 | /** 24 | * @author Mark Vollmary 25 | * 26 | */ 27 | public enum ValueType { 28 | NONE, // not yet initialized 29 | ILLEGAL, // illegal value 30 | NULL, // JSON null 31 | BOOL, 32 | ARRAY, 33 | OBJECT, 34 | DOUBLE, 35 | UTC_DATE, // UTC Date 36 | EXTERNAL, 37 | MIN_KEY, 38 | MAX_KEY, 39 | INT, 40 | UINT, 41 | SMALLINT, 42 | STRING, 43 | BINARY, 44 | BCD, 45 | CUSTOM, 46 | TAGGED, 47 | VPACK 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/arangodb/velocypack/exception/VPackBuilderException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DISCLAIMER 3 | * 4 | * Copyright 2016 ArangoDB GmbH, Cologne, Germany 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * Copyright holder is ArangoDB GmbH, Cologne, Germany 19 | */ 20 | 21 | package com.arangodb.velocypack.exception; 22 | 23 | /** 24 | * @author Mark Vollmary 25 | * 26 | */ 27 | public class VPackBuilderException extends VPackException { 28 | 29 | private static final long serialVersionUID = -8439245715363257017L; 30 | 31 | public VPackBuilderException() { 32 | super(); 33 | } 34 | 35 | public VPackBuilderException(final String message) { 36 | super(message); 37 | } 38 | 39 | public VPackBuilderException(final Throwable cause) { 40 | super(cause); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/arangodb/velocypack/exception/VPackBuilderKeyAlreadyWrittenException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DISCLAIMER 3 | * 4 | * Copyright 2016 ArangoDB GmbH, Cologne, Germany 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * Copyright holder is ArangoDB GmbH, Cologne, Germany 19 | */ 20 | 21 | package com.arangodb.velocypack.exception; 22 | 23 | /** 24 | * @author Mark Vollmary 25 | * 26 | */ 27 | public class VPackBuilderKeyAlreadyWrittenException extends VPackBuilderException { 28 | 29 | private static final long serialVersionUID = -1958878757748616132L; 30 | 31 | public VPackBuilderKeyAlreadyWrittenException() { 32 | super(); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/arangodb/velocypack/exception/VPackBuilderNeedOpenCompoundException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DISCLAIMER 3 | * 4 | * Copyright 2016 ArangoDB GmbH, Cologne, Germany 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * Copyright holder is ArangoDB GmbH, Cologne, Germany 19 | */ 20 | 21 | package com.arangodb.velocypack.exception; 22 | 23 | /** 24 | * @author Mark Vollmary 25 | * 26 | */ 27 | public class VPackBuilderNeedOpenCompoundException extends VPackBuilderException { 28 | 29 | private static final long serialVersionUID = 7985444459377106986L; 30 | 31 | public VPackBuilderNeedOpenCompoundException() { 32 | super(); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/arangodb/velocypack/exception/VPackBuilderNeedOpenObjectException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DISCLAIMER 3 | * 4 | * Copyright 2016 ArangoDB GmbH, Cologne, Germany 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * Copyright holder is ArangoDB GmbH, Cologne, Germany 19 | */ 20 | 21 | /* 22 | * DISCLAIMER 23 | * 24 | * Copyright 2016 ArangoDB GmbH, Cologne, Germany 25 | * 26 | * Licensed under the Apache License, Version 2.0 (the "License"); 27 | * you may not use this file except in compliance with the License. 28 | * You may obtain a copy of the License at 29 | * 30 | * http://www.apache.org/licenses/LICENSE-2.0 31 | * 32 | * Unless required by applicable law or agreed to in writing, software 33 | * distributed under the License is distributed on an "AS IS" BASIS, 34 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 35 | * See the License for the specific language governing permissions and 36 | * limitations under the License. 37 | * 38 | * Copyright holder is ArangoDB GmbH, Cologne, Germany 39 | */ 40 | 41 | package com.arangodb.velocypack.exception; 42 | 43 | /** 44 | * @author Mark Vollmary 45 | * 46 | */ 47 | public class VPackBuilderNeedOpenObjectException extends VPackBuilderNeedOpenCompoundException { 48 | 49 | private static final long serialVersionUID = 7005556054918252752L; 50 | 51 | public VPackBuilderNeedOpenObjectException() { 52 | super(); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/com/arangodb/velocypack/exception/VPackBuilderNumberOutOfRangeException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DISCLAIMER 3 | * 4 | * Copyright 2016 ArangoDB GmbH, Cologne, Germany 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * Copyright holder is ArangoDB GmbH, Cologne, Germany 19 | */ 20 | 21 | package com.arangodb.velocypack.exception; 22 | 23 | import com.arangodb.velocypack.ValueType; 24 | 25 | /** 26 | * @author Mark Vollmary 27 | * 28 | */ 29 | public class VPackBuilderNumberOutOfRangeException extends VPackBuilderException { 30 | 31 | private static final long serialVersionUID = 7173727199390076286L; 32 | 33 | public VPackBuilderNumberOutOfRangeException(final ValueType type) { 34 | super(String.format("Number out of range of %s.%s", type.getClass().getSimpleName(), type.name())); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/arangodb/velocypack/exception/VPackBuilderUnexpectedValueException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DISCLAIMER 3 | * 4 | * Copyright 2016 ArangoDB GmbH, Cologne, Germany 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * Copyright holder is ArangoDB GmbH, Cologne, Germany 19 | */ 20 | 21 | package com.arangodb.velocypack.exception; 22 | 23 | import com.arangodb.velocypack.ValueType; 24 | 25 | /** 26 | * @author Mark Vollmary 27 | * 28 | */ 29 | public class VPackBuilderUnexpectedValueException extends VPackBuilderException { 30 | 31 | private static final long serialVersionUID = -7365305871886897353L; 32 | 33 | public VPackBuilderUnexpectedValueException(final ValueType type, final Class... classes) { 34 | super(createMessage(type, null, classes)); 35 | } 36 | 37 | public VPackBuilderUnexpectedValueException(final ValueType type, final String specify, final Class... classes) { 38 | super(createMessage(type, specify, classes)); 39 | } 40 | 41 | private static String createMessage(final ValueType type, final String specify, final Class... classes) { 42 | final StringBuilder sb = new StringBuilder(); 43 | sb.append("Must give "); 44 | if (specify != null) { 45 | sb.append(specify); 46 | sb.append(" "); 47 | } 48 | for (int i = 0; i < classes.length; i++) { 49 | if (i > 0) { 50 | sb.append(" or "); 51 | } 52 | sb.append(classes[i].getSimpleName()); 53 | } 54 | sb.append(" for "); 55 | sb.append(type.getClass().getSimpleName()); 56 | sb.append("."); 57 | sb.append(type.name()); 58 | return sb.toString(); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/com/arangodb/velocypack/exception/VPackException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DISCLAIMER 3 | * 4 | * Copyright 2016 ArangoDB GmbH, Cologne, Germany 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * Copyright holder is ArangoDB GmbH, Cologne, Germany 19 | */ 20 | 21 | package com.arangodb.velocypack.exception; 22 | 23 | /** 24 | * @author Mark Vollmary 25 | * 26 | */ 27 | public abstract class VPackException extends RuntimeException { 28 | 29 | private static final long serialVersionUID = 3547943271830879415L; 30 | 31 | protected VPackException() { 32 | super(); 33 | } 34 | 35 | protected VPackException(final String message) { 36 | super(message); 37 | } 38 | 39 | protected VPackException(final Throwable cause) { 40 | super(cause); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/arangodb/velocypack/exception/VPackKeyTypeException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DISCLAIMER 3 | * 4 | * Copyright 2016 ArangoDB GmbH, Cologne, Germany 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * Copyright holder is ArangoDB GmbH, Cologne, Germany 19 | */ 20 | 21 | package com.arangodb.velocypack.exception; 22 | 23 | /** 24 | * @author Mark Vollmary 25 | * 26 | */ 27 | public class VPackKeyTypeException extends VPackException { 28 | 29 | private static final long serialVersionUID = 1328826711387001473L; 30 | 31 | public VPackKeyTypeException(final String message) { 32 | super(message); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/arangodb/velocypack/exception/VPackNeedAttributeTranslatorException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DISCLAIMER 3 | * 4 | * Copyright 2016 ArangoDB GmbH, Cologne, Germany 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * Copyright holder is ArangoDB GmbH, Cologne, Germany 19 | */ 20 | 21 | package com.arangodb.velocypack.exception; 22 | 23 | /** 24 | * @author Mark Vollmary 25 | * 26 | */ 27 | public class VPackNeedAttributeTranslatorException extends VPackException { 28 | 29 | private static final long serialVersionUID = -676583112112943083L; 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/arangodb/velocypack/exception/VPackParserException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DISCLAIMER 3 | * 4 | * Copyright 2016 ArangoDB GmbH, Cologne, Germany 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * Copyright holder is ArangoDB GmbH, Cologne, Germany 19 | */ 20 | 21 | package com.arangodb.velocypack.exception; 22 | 23 | /** 24 | * @author Mark Vollmary 25 | * 26 | */ 27 | public class VPackParserException extends VPackException { 28 | 29 | private static final long serialVersionUID = 2374233320699603759L; 30 | 31 | public VPackParserException(final Throwable cause) { 32 | super(cause); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/arangodb/velocypack/exception/VPackValueTypeException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DISCLAIMER 3 | * 4 | * Copyright 2016 ArangoDB GmbH, Cologne, Germany 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * Copyright holder is ArangoDB GmbH, Cologne, Germany 19 | */ 20 | 21 | package com.arangodb.velocypack.exception; 22 | 23 | import com.arangodb.velocypack.ValueType; 24 | 25 | /** 26 | * @author Mark Vollmary 27 | * 28 | */ 29 | public class VPackValueTypeException extends VPackException { 30 | 31 | private static final long serialVersionUID = 8128171173539033177L; 32 | 33 | public VPackValueTypeException(final ValueType... types) { 34 | super(createMessage(types)); 35 | } 36 | 37 | private static String createMessage(final ValueType... types) { 38 | final StringBuilder sb = new StringBuilder(); 39 | sb.append("Expecting type "); 40 | for (int i = 0; i < types.length; i++) { 41 | if (i > 0) { 42 | sb.append(" or "); 43 | } 44 | sb.append(types[i].name()); 45 | } 46 | return sb.toString(); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/arangodb/velocypack/internal/DefaultVPackBuilderOptions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DISCLAIMER 3 | * 4 | * Copyright 2016 ArangoDB GmbH, Cologne, Germany 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * Copyright holder is ArangoDB GmbH, Cologne, Germany 19 | */ 20 | 21 | package com.arangodb.velocypack.internal; 22 | 23 | import com.arangodb.velocypack.VPackBuilder.BuilderOptions; 24 | 25 | /** 26 | * @author Mark Vollmary 27 | * 28 | */ 29 | public class DefaultVPackBuilderOptions implements BuilderOptions { 30 | 31 | private boolean buildUnindexedArrays; 32 | private boolean buildUnindexedObjects; 33 | 34 | public DefaultVPackBuilderOptions() { 35 | super(); 36 | buildUnindexedArrays = false; 37 | buildUnindexedObjects = false; 38 | } 39 | 40 | @Override 41 | public boolean isBuildUnindexedArrays() { 42 | return buildUnindexedArrays; 43 | } 44 | 45 | @Override 46 | public void setBuildUnindexedArrays(final boolean buildUnindexedArrays) { 47 | this.buildUnindexedArrays = buildUnindexedArrays; 48 | } 49 | 50 | @Override 51 | public boolean isBuildUnindexedObjects() { 52 | return buildUnindexedObjects; 53 | } 54 | 55 | @Override 56 | public void setBuildUnindexedObjects(final boolean buildUnindexedObjects) { 57 | this.buildUnindexedObjects = buildUnindexedObjects; 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/arangodb/velocypack/internal/VPackAttributeTranslatorImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DISCLAIMER 3 | * 4 | * Copyright 2016 ArangoDB GmbH, Cologne, Germany 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * Copyright holder is ArangoDB GmbH, Cologne, Germany 19 | */ 20 | 21 | package com.arangodb.velocypack.internal; 22 | 23 | import java.util.HashMap; 24 | import java.util.Map; 25 | 26 | import com.arangodb.velocypack.VPackAttributeTranslator; 27 | import com.arangodb.velocypack.VPackBuilder; 28 | import com.arangodb.velocypack.VPackSlice; 29 | import com.arangodb.velocypack.ValueType; 30 | import com.arangodb.velocypack.exception.VPackException; 31 | 32 | /** 33 | * @author Mark Vollmary 34 | * 35 | */ 36 | public class VPackAttributeTranslatorImpl implements VPackAttributeTranslator { 37 | 38 | private static final String KEY = "_key"; 39 | private static final String REV = "_rev"; 40 | private static final String ID = "_id"; 41 | private static final String FROM = "_from"; 42 | private static final String TO = "_to"; 43 | 44 | private static final byte KEY_ATTRIBUTE = 0x31; 45 | private static final byte REV_ATTRIBUTE = 0x32; 46 | private static final byte ID_ATTRIBUTE = 0x33; 47 | private static final byte FROM_ATTRIBUTE = 0x34; 48 | private static final byte TO_ATTRIBUTE = 0x35; 49 | private static final byte ATTRIBUTE_BASE = 0x30; 50 | 51 | private VPackBuilder builder; 52 | private final Map attributeToKey; 53 | private final Map keyToAttribute; 54 | 55 | public VPackAttributeTranslatorImpl() { 56 | super(); 57 | builder = null; 58 | attributeToKey = new HashMap<>(); 59 | keyToAttribute = new HashMap<>(); 60 | try { 61 | add(KEY, KEY_ATTRIBUTE - ATTRIBUTE_BASE); 62 | add(REV, REV_ATTRIBUTE - ATTRIBUTE_BASE); 63 | add(ID, ID_ATTRIBUTE - ATTRIBUTE_BASE); 64 | add(FROM, FROM_ATTRIBUTE - ATTRIBUTE_BASE); 65 | add(TO, TO_ATTRIBUTE - ATTRIBUTE_BASE); 66 | seal(); 67 | } catch (final VPackException e) { 68 | throw new RuntimeException(e); 69 | } 70 | } 71 | 72 | @Override 73 | public void add(final String attribute, final int key) throws VPackException { 74 | if (builder == null) { 75 | builder = new VPackBuilder(); 76 | builder.add(ValueType.OBJECT); 77 | } 78 | builder.add(attribute, key); 79 | } 80 | 81 | @Override 82 | public void seal() throws VPackException { 83 | if (builder == null) { 84 | return; 85 | } 86 | builder.close(); 87 | final VPackSlice slice = builder.slice(); 88 | for (int i = 0; i < slice.getLength(); i++) { 89 | final VPackSlice key = slice.keyAt(i); 90 | final VPackSlice value = slice.valueAt(i); 91 | attributeToKey.put(key.getAsString(), value); 92 | keyToAttribute.put(value.getAsInt(), key); 93 | } 94 | } 95 | 96 | @Override 97 | public VPackSlice translate(final String attribute) { 98 | return attributeToKey.get(attribute); 99 | } 100 | 101 | @Override 102 | public VPackSlice translate(final int key) { 103 | return keyToAttribute.get(key); 104 | } 105 | 106 | } 107 | -------------------------------------------------------------------------------- /src/main/java/com/arangodb/velocypack/internal/Value.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DISCLAIMER 3 | * 4 | * Copyright 2016 ArangoDB GmbH, Cologne, Germany 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * Copyright holder is ArangoDB GmbH, Cologne, Germany 19 | */ 20 | 21 | package com.arangodb.velocypack.internal; 22 | 23 | import java.math.BigInteger; 24 | 25 | import com.arangodb.velocypack.ValueType; 26 | import com.arangodb.velocypack.exception.VPackValueTypeException; 27 | 28 | /** 29 | * @author Mark Vollmary 30 | * 31 | */ 32 | public class Value { 33 | 34 | private final Object value; 35 | 36 | private final ValueType type; 37 | private final Class clazz; 38 | private final boolean unindexed; 39 | 40 | private Value(final Object value, final ValueType type, final Class clazz) { 41 | this(value, type, clazz, false); 42 | } 43 | 44 | private Value(final Object value, final ValueType type, final Class clazz, final boolean unindexed) { 45 | super(); 46 | this.value = value; 47 | this.type = type; 48 | this.clazz = clazz; 49 | this.unindexed = unindexed; 50 | } 51 | 52 | public Value(final ValueType type) { 53 | this(type, false); 54 | } 55 | 56 | public Value(final ValueType type, final boolean unindexed) throws VPackValueTypeException { 57 | this(null, type, null, unindexed); 58 | if (type != ValueType.ARRAY && type != ValueType.OBJECT && type != ValueType.NULL) { 59 | throw new VPackValueTypeException(ValueType.ARRAY, ValueType.OBJECT, ValueType.NULL); 60 | } 61 | } 62 | 63 | public Value(final Long value, final ValueType type) throws VPackValueTypeException { 64 | this(value, type, Long.class); 65 | if (type != ValueType.INT && type != ValueType.UINT && type != ValueType.SMALLINT) { 66 | throw new VPackValueTypeException(ValueType.INT, ValueType.UINT, ValueType.SMALLINT); 67 | } 68 | } 69 | 70 | public Value(final BigInteger value, final ValueType type) throws VPackValueTypeException { 71 | this(value, type, BigInteger.class); 72 | if (type != ValueType.INT && type != ValueType.UINT && type != ValueType.SMALLINT) { 73 | throw new VPackValueTypeException(ValueType.INT, ValueType.UINT, ValueType.SMALLINT); 74 | } 75 | } 76 | 77 | public ValueType getType() { 78 | return type; 79 | } 80 | 81 | public Class getClazz() { 82 | return clazz; 83 | } 84 | 85 | public boolean isUnindexed() { 86 | return unindexed; 87 | } 88 | 89 | public Number getNumber() { 90 | return (Number) value; 91 | } 92 | 93 | public Long getLong() { 94 | return (Long) value; 95 | } 96 | 97 | public BigInteger getBigInteger() { 98 | return (BigInteger) value; 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /src/main/java/com/arangodb/velocypack/internal/util/BinaryUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DISCLAIMER 3 | * 4 | * Copyright 2016 ArangoDB GmbH, Cologne, Germany 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * Copyright holder is ArangoDB GmbH, Cologne, Germany 19 | */ 20 | 21 | package com.arangodb.velocypack.internal.util; 22 | 23 | /** 24 | * @author Mark Vollmary 25 | * 26 | */ 27 | public class BinaryUtil { 28 | 29 | private BinaryUtil() { 30 | super(); 31 | } 32 | 33 | public static byte[] toBinary(final byte[] array, final int offset, final int length) { 34 | final byte[] result = new byte[length]; 35 | for (int i = offset, j = 0; j < length; i++, j++) { 36 | result[j] = array[i]; 37 | } 38 | return result; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/arangodb/velocypack/internal/util/DateUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DISCLAIMER 3 | * 4 | * Copyright 2016 ArangoDB GmbH, Cologne, Germany 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * Copyright holder is ArangoDB GmbH, Cologne, Germany 19 | */ 20 | 21 | package com.arangodb.velocypack.internal.util; 22 | 23 | import java.text.ParseException; 24 | import java.time.Instant; 25 | import java.time.ZoneOffset; 26 | import java.time.ZonedDateTime; 27 | import java.time.format.DateTimeFormatter; 28 | import java.time.format.DateTimeParseException; 29 | import java.util.Date; 30 | 31 | /** 32 | * @author Mark Vollmary 33 | * 34 | */ 35 | public class DateUtil { 36 | 37 | private final static DateTimeFormatter DATE_FORMATTER = DateTimeFormatter 38 | .ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") 39 | .withZone(ZoneOffset.UTC); 40 | 41 | private DateUtil() { 42 | super(); 43 | } 44 | 45 | public static java.util.Date toDate(final byte[] array, final int offset, final int length) { 46 | final long milliseconds = NumberUtil.toLong(array, offset, length); 47 | return new java.util.Date(milliseconds); 48 | } 49 | 50 | public static java.sql.Date toSQLDate(final byte[] array, final int offset, final int length) { 51 | final long milliseconds = NumberUtil.toLong(array, offset, length); 52 | return new java.sql.Date(milliseconds); 53 | } 54 | 55 | public static java.sql.Timestamp toSQLTimestamp(final byte[] array, final int offset, final int length) { 56 | final long milliseconds = NumberUtil.toLong(array, offset, length); 57 | return new java.sql.Timestamp(milliseconds); 58 | } 59 | 60 | public static java.util.Date parse(final String source) throws ParseException { 61 | try { 62 | return new Date(ZonedDateTime.parse(source).toInstant().toEpochMilli()); 63 | } catch (DateTimeParseException e) { 64 | throw new ParseException("Unparseable date: \"" + e.getParsedString() + "\"", e.getErrorIndex()); 65 | } 66 | } 67 | 68 | public static String format(final java.util.Date date) { 69 | return DATE_FORMATTER.format(ZonedDateTime.ofInstant(Instant.ofEpochMilli(date.getTime()), ZoneOffset.UTC)); 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/com/arangodb/velocypack/internal/util/NumberUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DISCLAIMER 3 | * 4 | * Copyright 2016 ArangoDB GmbH, Cologne, Germany 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * Copyright holder is ArangoDB GmbH, Cologne, Germany 19 | */ 20 | 21 | package com.arangodb.velocypack.internal.util; 22 | 23 | import java.math.BigInteger; 24 | 25 | /** 26 | * @author Mark Vollmary 27 | * 28 | */ 29 | public class NumberUtil { 30 | 31 | private static final int DOUBLE_BYTES = Double.SIZE / Byte.SIZE; 32 | private static final int LONG_BYTES = Long.SIZE / Byte.SIZE; 33 | 34 | private NumberUtil() { 35 | super(); 36 | } 37 | 38 | public static double toDouble(final byte[] array, final int offset, final int length) { 39 | return Double.longBitsToDouble(toLong(array, offset, DOUBLE_BYTES)); 40 | } 41 | 42 | public static long toLong(final byte[] array, final int offset, final int length) { 43 | return toLong(array, offset, length, false); 44 | } 45 | 46 | public static long toLong(final byte[] array, final int offset, final int length, final boolean fillNegativeBytes) { 47 | long result = 0; 48 | if (fillNegativeBytes && length < LONG_BYTES && array[(offset + length - 1)] <= (byte) -1) { 49 | for (int i = 0; i <= 8 - length; i++) { 50 | result <<= LONG_BYTES; 51 | result |= ((byte) -1 & 0xFF); 52 | } 53 | } 54 | for (int i = (offset + length - 1); i >= offset; i--) { 55 | result <<= LONG_BYTES; 56 | result |= (array[i] & 0xFF); 57 | } 58 | return result; 59 | } 60 | 61 | public static BigInteger toBigInteger(final byte[] array, final int offset, final int length) { 62 | BigInteger result = new BigInteger(1, new byte[] {}); 63 | for (int i = (offset + length - 1); i >= offset; i--) { 64 | result = result.shiftLeft(LONG_BYTES); 65 | result = result.or(BigInteger.valueOf(array[i] & 0xFF)); 66 | } 67 | return result; 68 | } 69 | 70 | /** 71 | * read a variable length integer in unsigned LEB128 format 72 | */ 73 | public static long readVariableValueLength(final byte[] array, final int offset, final boolean reverse) { 74 | long len = 0; 75 | byte v; 76 | long p = 0; 77 | int i = offset; 78 | do { 79 | v = array[i]; 80 | len += ((long) (v & (byte) 0x7f)) << p; 81 | p += 7; 82 | if (reverse) { 83 | --i; 84 | } else { 85 | ++i; 86 | } 87 | } while ((v & (byte) 0x80) != 0); 88 | return len; 89 | } 90 | 91 | /** 92 | * calculate the length of a variable length integer in unsigned LEB128 format 93 | */ 94 | public static long getVariableValueLength(final long value) { 95 | long len = 1; 96 | long val = value; 97 | while (val >= 0x80) { 98 | val >>= 7; 99 | ++len; 100 | } 101 | return len; 102 | } 103 | 104 | } 105 | -------------------------------------------------------------------------------- /src/main/java/com/arangodb/velocypack/internal/util/ObjectArrayUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DISCLAIMER 3 | * 4 | * Copyright 2016 ArangoDB GmbH, Cologne, Germany 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * Copyright holder is ArangoDB GmbH, Cologne, Germany 19 | */ 20 | 21 | package com.arangodb.velocypack.internal.util; 22 | 23 | /** 24 | * @author Mark Vollmary 25 | * 26 | */ 27 | public class ObjectArrayUtil { 28 | 29 | private static final int[] FIRST_SUB_MAP = { 30 | 0, // 0x00 None 31 | 1, // 0x01 empty array 32 | 2, // 0x02 array without index table 33 | 3, // 0x03 array without index table 34 | 5, // 0x04 array without index table 35 | 9, // 0x05 array without index table 36 | 3, // 0x06 array with index table 37 | 5, // 0x07 array with index table 38 | 9, // 0x08 array with index table 39 | 9, // 0x09 array with index table 40 | 1, // 0x0a empty object 41 | 3, // 0x0b object with sorted index table 42 | 5, // 0x0c object with sorted index table 43 | 9, // 0x0d object with sorted index table 44 | 9, // 0x0e object with sorted index table 45 | 3, // 0x0f object with unsorted index table 46 | 5, // 0x10 object with unsorted index table 47 | 9, // 0x11 object with unsorted index table 48 | 9 // 0x12 object with unsorted index table 49 | }; 50 | 51 | public static int getFirstSubMap(final byte key) { 52 | return FIRST_SUB_MAP[key & 0xff]; 53 | } 54 | 55 | private static final int[] OFFSET_SIZE = { 56 | 0, // 0x00 None 57 | 1, // 0x01 empty array 58 | 1, // 0x02 array without index table 59 | 2, // 0x03 array without index table 60 | 4, // 0x04 array without index table 61 | 8, // 0x05 array without index table 62 | 1, // 0x06 array with index table 63 | 2, // 0x07 array with index table 64 | 4, // 0x08 array with index table 65 | 8, // 0x09 array with index table 66 | 1, // 0x0a empty object 67 | 1, // 0x0b object with sorted index table 68 | 2, // 0x0c object with sorted index table 69 | 4, // 0x0d object with sorted index table 70 | 8, // 0x0e object with sorted index table 71 | 1, // 0x0f object with unsorted index table 72 | 2, // 0x10 object with unsorted index table 73 | 4, // 0x11 object with unsorted index table 74 | 8 // 0x12 object with unsorted index table 75 | }; 76 | 77 | private ObjectArrayUtil() { 78 | super(); 79 | } 80 | 81 | public static int getOffsetSize(final byte key) { 82 | return OFFSET_SIZE[key & 0xff]; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/com/arangodb/velocypack/internal/util/ValueLengthUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DISCLAIMER 3 | * 4 | * Copyright 2016 ArangoDB GmbH, Cologne, Germany 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * Copyright holder is ArangoDB GmbH, Cologne, Germany 19 | */ 20 | 21 | package com.arangodb.velocypack.internal.util; 22 | 23 | /** 24 | * @author Mark Vollmary 25 | * 26 | */ 27 | public class ValueLengthUtil { 28 | 29 | private static final int DOUBLE_BYTES = 8; 30 | private static final int LONG_BYTES = 8; 31 | private static final int CHARACTER_BYTES = 2; 32 | 33 | private static final int[] MAP = { 34 | 1, // 0x00 35 | 1, // 0x01 36 | 0, // 0x02 37 | 0, // 0x03 38 | 0, // 0x04 39 | 0, // 0x05 40 | 0, // 0x06 41 | 0, // 0x07 42 | 0, // 0x08 43 | 0, // 0x09 44 | 1, // 0x0a 45 | 0, // 0x0b 46 | 0, // 0x0c 47 | 0, // 0x0d 48 | 0, // 0x0e 49 | 0, // 0x0f 50 | 0, // 0x10 51 | 0, // 0x11 52 | 0, // 0x12 53 | 0, // 0x13 54 | 0, // 0x14 55 | 0, // 0x15 56 | 0, // 0x16 57 | 1, // 0x17 58 | 1, // 0x18 59 | 1, // 0x19 60 | 1, // 0x1a 61 | 1 + DOUBLE_BYTES, // 0x1b 62 | 1 + LONG_BYTES, // 0x1c 63 | 1 + CHARACTER_BYTES, // 0x1d 64 | 1, // 0x1e 65 | 1, // 0x1f 66 | 2, // 0x20 67 | 3, // 0x21 68 | 4, // 0x22 69 | 5, // 0x23 70 | 6, // 0x24 71 | 7, // 0x25 72 | 8, // 0x26 73 | 9, // 0x27 74 | 2, // 0x28 75 | 3, // 0x29 76 | 4, // 0x2a 77 | 5, // 0x2b 78 | 6, // 0x2c 79 | 7, // 0x2d 80 | 8, // 0x2e 81 | 9, // 0x2f 82 | 1, // 0x30 83 | 1, // 0x31 84 | 1, // 0x32 85 | 1, // 0x33 86 | 1, // 0x34 87 | 1, // 0x35 88 | 1, // 0x36 89 | 1, // 0x37 90 | 1, // 0x38 91 | 1, // 0x39 92 | 1, // 0x3a 93 | 1, // 0x3b 94 | 1, // 0x3c 95 | 1, // 0x3d 96 | 1, // 0x3e 97 | 1, // 0x3f 98 | 1, // 0x40 99 | 2, // 0x41 100 | 3, // 0x42 101 | 4, // 0x43 102 | 5, // 0x44 103 | 6, // 0x45 104 | 7, // 0x46 105 | 8, // 0x47 106 | 9, // 0x48 107 | 10, // 0x49 108 | 11, // 0x4a 109 | 12, // 0x4b 110 | 13, // 0x4c 111 | 14, // 0x4d 112 | 15, // 0x4e 113 | 16, // 0x4f 114 | 17, // 0x50 115 | 18, // 0x51 116 | 19, // 0x52 117 | 20, // 0x53 118 | 21, // 0x54 119 | 22, // 0x55 120 | 23, // 0x56 121 | 24, // 0x57 122 | 25, // 0x58 123 | 26, // 0x59 124 | 27, // 0x5a 125 | 28, // 0x5b 126 | 29, // 0x5c 127 | 30, // 0x5d 128 | 31, // 0x5e 129 | 32, // 0x5f 130 | 33, // 0x60 131 | 34, // 0x61 132 | 35, // 0x62 133 | 36, // 0x63 134 | 37, // 0x64 135 | 38, // 0x65 136 | 39, // 0x66 137 | 40, // 0x67 138 | 41, // 0x68 139 | 42, // 0x69 140 | 43, // 0x6a 141 | 44, // 0x6b 142 | 45, // 0x6c 143 | 46, // 0x6d 144 | 47, // 0x6e 145 | 48, // 0x6f 146 | 49, // 0x70 147 | 50, // 0x71 148 | 51, // 0x72 149 | 52, // 0x73 150 | 53, // 0x74 151 | 54, // 0x75 152 | 55, // 0x76 153 | 56, // 0x77 154 | 57, // 0x78 155 | 58, // 0x79 156 | 59, // 0x7a 157 | 60, // 0x7b 158 | 61, // 0x7c 159 | 62, // 0x7d 160 | 63, // 0x7e 161 | 64, // 0x7f 162 | 65, // 0x80 163 | 66, // 0x81 164 | 67, // 0x82 165 | 68, // 0x83 166 | 69, // 0x84 167 | 70, // 0x85 168 | 71, // 0x86 169 | 72, // 0x87 170 | 73, // 0x88 171 | 74, // 0x89 172 | 75, // 0x8a 173 | 76, // 0x8b 174 | 77, // 0x8c 175 | 78, // 0x8d 176 | 79, // 0x8e 177 | 80, // 0x8f 178 | 81, // 0x90 179 | 82, // 0x91 180 | 83, // 0x92 181 | 84, // 0x93 182 | 85, // 0x94 183 | 86, // 0x95 184 | 87, // 0x96 185 | 88, // 0x97 186 | 89, // 0x98 187 | 90, // 0x99 188 | 91, // 0x9a 189 | 92, // 0x9b 190 | 93, // 0x9c 191 | 94, // 0x9d 192 | 95, // 0x9e 193 | 96, // 0x9f 194 | 97, // 0xa0 195 | 98, // 0xa1 196 | 99, // 0xa2 197 | 100, // 0xa3 198 | 101, // 0xa4 199 | 102, // 0xa5 200 | 103, // 0xa6 201 | 104, // 0xa7 202 | 105, // 0xa8 203 | 106, // 0xa9 204 | 107, // 0xaa 205 | 108, // 0xab 206 | 109, // 0xac 207 | 110, // 0xad 208 | 111, // 0xae 209 | 112, // 0xaf 210 | 113, // 0xb0 211 | 114, // 0xb1 212 | 115, // 0xb2 213 | 116, // 0xb3 214 | 117, // 0xb4 215 | 118, // 0xb5 216 | 119, // 0xb6 217 | 120, // 0xb7 218 | 121, // 0xb8 219 | 122, // 0xb9 220 | 123, // 0xba 221 | 124, // 0xbb 222 | 125, // 0xbc 223 | 126, // 0xbd 224 | 127, // 0xbe 225 | 0, // 0xbf 226 | 0, // 0xc0 227 | 0, // 0xc1 228 | 0, // 0xc2 229 | 0, // 0xc3 230 | 0, // 0xc4 231 | 0, // 0xc5 232 | 0, // 0xc6 233 | 0, // 0xc7 234 | 0, // 0xc8 235 | 0, // 0xc9 236 | 0, // 0xca 237 | 0, // 0xcb 238 | 0, // 0xcc 239 | 0, // 0xcd 240 | 0, // 0xce 241 | 0, // 0xcf 242 | 0, // 0xd0 243 | 0, // 0xd1 244 | 0, // 0xd2 245 | 0, // 0xd3 246 | 0, // 0xd4 247 | 0, // 0xd5 248 | 0, // 0xd6 249 | 0, // 0xd7 250 | 0, // 0xd8 251 | 0, // 0xd9 252 | 0, // 0xda 253 | 0, // 0xdb 254 | 0, // 0xdc 255 | 0, // 0xdd 256 | 0, // 0xde 257 | 0, // 0xdf 258 | 0, // 0xe0 259 | 0, // 0xe1 260 | 0, // 0xe2 261 | 0, // 0xe3 262 | 0, // 0xe4 263 | 0, // 0xe5 264 | 0, // 0xe6 265 | 0, // 0xe7 266 | 0, // 0xe8 267 | 0, // 0xe9 268 | 0, // 0xea 269 | 0, // 0xeb 270 | 0, // 0xec 271 | 0, // 0xed 272 | 0, // 0xee 273 | 0, // 0xef 274 | 2, // 0xf0 275 | 3, // 0xf1 276 | 5, // 0xf2 277 | 9, // 0xf3 278 | 0, // 0xf4 279 | 0, // 0xf5 280 | 0, // 0xf6 281 | 0, // 0xf7 282 | 0, // 0xf8 283 | 0, // 0xf9 284 | 0, // 0xfa 285 | 0, // 0xfb 286 | 0, // 0xfc 287 | 0, // 0xfd 288 | 0, // 0xfe 289 | 0, // 0xff 290 | }; 291 | 292 | private ValueLengthUtil() { 293 | super(); 294 | } 295 | 296 | public static int get(final byte key) { 297 | return MAP[key & 0xff]; 298 | } 299 | 300 | } 301 | -------------------------------------------------------------------------------- /src/main/java/com/arangodb/velocypack/internal/util/ValueTypeUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DISCLAIMER 3 | * 4 | * Copyright 2016 ArangoDB GmbH, Cologne, Germany 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * Copyright holder is ArangoDB GmbH, Cologne, Germany 19 | */ 20 | 21 | package com.arangodb.velocypack.internal.util; 22 | 23 | import com.arangodb.velocypack.ValueType; 24 | 25 | /** 26 | * @author Mark Vollmary 27 | * 28 | */ 29 | public class ValueTypeUtil { 30 | 31 | private static final ValueType[] MAP = { 32 | ValueType.NONE, // 0x00 33 | ValueType.ARRAY, // 0x01 34 | ValueType.ARRAY, // 0x02 35 | ValueType.ARRAY, // 0x03 36 | ValueType.ARRAY, // 0x04 37 | ValueType.ARRAY, // 0x05 38 | ValueType.ARRAY, // 0x06 39 | ValueType.ARRAY, // 0x07 40 | ValueType.ARRAY, // 0x08 41 | ValueType.ARRAY, // 0x09 42 | ValueType.OBJECT, // 0x0a 43 | ValueType.OBJECT, // 0x0b 44 | ValueType.OBJECT, // 0x0c 45 | ValueType.OBJECT, // 0x0d 46 | ValueType.OBJECT, // 0x0e 47 | ValueType.OBJECT, // 0x0f 48 | ValueType.OBJECT, // 0x10 49 | ValueType.OBJECT, // 0x11 50 | ValueType.OBJECT, // 0x12 51 | ValueType.ARRAY, // 0x13 52 | ValueType.OBJECT, // 0x14 53 | ValueType.NONE, // 0x15 54 | ValueType.NONE, // 0x16 55 | ValueType.ILLEGAL, // 0x17 56 | ValueType.NULL, // 0x18 57 | ValueType.BOOL, // 0x19 58 | ValueType.BOOL, // 0x1a 59 | ValueType.DOUBLE, // 0x1b 60 | ValueType.UTC_DATE, // 0x1c 61 | ValueType.EXTERNAL, // 0x1d 62 | ValueType.MIN_KEY, // 0x1e 63 | ValueType.MAX_KEY, // 0x1f 64 | ValueType.INT, // 0x20 65 | ValueType.INT, // 0x21 66 | ValueType.INT, // 0x22 67 | ValueType.INT, // 0x23 68 | ValueType.INT, // 0x24 69 | ValueType.INT, // 0x25 70 | ValueType.INT, // 0x26 71 | ValueType.INT, // 0x27 72 | ValueType.UINT, // 0x28 73 | ValueType.UINT, // 0x29 74 | ValueType.UINT, // 0x2a 75 | ValueType.UINT, // 0x2b 76 | ValueType.UINT, // 0x2c 77 | ValueType.UINT, // 0x2d 78 | ValueType.UINT, // 0x2e 79 | ValueType.UINT, // 0x2f 80 | ValueType.SMALLINT, // 0x30 81 | ValueType.SMALLINT, // 0x31 82 | ValueType.SMALLINT, // 0x32 83 | ValueType.SMALLINT, // 0x33 84 | ValueType.SMALLINT, // 0x34 85 | ValueType.SMALLINT, // 0x35 86 | ValueType.SMALLINT, // 0x36 87 | ValueType.SMALLINT, // 0x37 88 | ValueType.SMALLINT, // 0x38 89 | ValueType.SMALLINT, // 0x39 90 | ValueType.SMALLINT, // 0x3a 91 | ValueType.SMALLINT, // 0x3b 92 | ValueType.SMALLINT, // 0x3c 93 | ValueType.SMALLINT, // 0x3d 94 | ValueType.SMALLINT, // 0x3e 95 | ValueType.SMALLINT, // 0x3f 96 | ValueType.STRING, // 0x40 97 | ValueType.STRING, // 0x41 98 | ValueType.STRING, // 0x42 99 | ValueType.STRING, // 0x43 100 | ValueType.STRING, // 0x44 101 | ValueType.STRING, // 0x45 102 | ValueType.STRING, // 0x46 103 | ValueType.STRING, // 0x47 104 | ValueType.STRING, // 0x48 105 | ValueType.STRING, // 0x49 106 | ValueType.STRING, // 0x4a 107 | ValueType.STRING, // 0x4b 108 | ValueType.STRING, // 0x4c 109 | ValueType.STRING, // 0x4d 110 | ValueType.STRING, // 0x4e 111 | ValueType.STRING, // 0x4f 112 | ValueType.STRING, // 0x50 113 | ValueType.STRING, // 0x51 114 | ValueType.STRING, // 0x52 115 | ValueType.STRING, // 0x53 116 | ValueType.STRING, // 0x54 117 | ValueType.STRING, // 0x55 118 | ValueType.STRING, // 0x56 119 | ValueType.STRING, // 0x57 120 | ValueType.STRING, // 0x58 121 | ValueType.STRING, // 0x59 122 | ValueType.STRING, // 0x5a 123 | ValueType.STRING, // 0x5b 124 | ValueType.STRING, // 0x5c 125 | ValueType.STRING, // 0x5d 126 | ValueType.STRING, // 0x5e 127 | ValueType.STRING, // 0x5f 128 | ValueType.STRING, // 0x60 129 | ValueType.STRING, // 0x61 130 | ValueType.STRING, // 0x62 131 | ValueType.STRING, // 0x63 132 | ValueType.STRING, // 0x64 133 | ValueType.STRING, // 0x65 134 | ValueType.STRING, // 0x66 135 | ValueType.STRING, // 0x67 136 | ValueType.STRING, // 0x68 137 | ValueType.STRING, // 0x69 138 | ValueType.STRING, // 0x6a 139 | ValueType.STRING, // 0x6b 140 | ValueType.STRING, // 0x6c 141 | ValueType.STRING, // 0x6d 142 | ValueType.STRING, // 0x6e 143 | ValueType.STRING, // 0x6f 144 | ValueType.STRING, // 0x70 145 | ValueType.STRING, // 0x71 146 | ValueType.STRING, // 0x72 147 | ValueType.STRING, // 0x73 148 | ValueType.STRING, // 0x74 149 | ValueType.STRING, // 0x75 150 | ValueType.STRING, // 0x76 151 | ValueType.STRING, // 0x77 152 | ValueType.STRING, // 0x78 153 | ValueType.STRING, // 0x79 154 | ValueType.STRING, // 0x7a 155 | ValueType.STRING, // 0x7b 156 | ValueType.STRING, // 0x7c 157 | ValueType.STRING, // 0x7d 158 | ValueType.STRING, // 0x7e 159 | ValueType.STRING, // 0x7f 160 | ValueType.STRING, // 0x80 161 | ValueType.STRING, // 0x81 162 | ValueType.STRING, // 0x82 163 | ValueType.STRING, // 0x83 164 | ValueType.STRING, // 0x84 165 | ValueType.STRING, // 0x85 166 | ValueType.STRING, // 0x86 167 | ValueType.STRING, // 0x87 168 | ValueType.STRING, // 0x88 169 | ValueType.STRING, // 0x89 170 | ValueType.STRING, // 0x8a 171 | ValueType.STRING, // 0x8b 172 | ValueType.STRING, // 0x8c 173 | ValueType.STRING, // 0x8d 174 | ValueType.STRING, // 0x8e 175 | ValueType.STRING, // 0x8f 176 | ValueType.STRING, // 0x90 177 | ValueType.STRING, // 0x91 178 | ValueType.STRING, // 0x92 179 | ValueType.STRING, // 0x93 180 | ValueType.STRING, // 0x94 181 | ValueType.STRING, // 0x95 182 | ValueType.STRING, // 0x96 183 | ValueType.STRING, // 0x97 184 | ValueType.STRING, // 0x98 185 | ValueType.STRING, // 0x99 186 | ValueType.STRING, // 0x9a 187 | ValueType.STRING, // 0x9b 188 | ValueType.STRING, // 0x9c 189 | ValueType.STRING, // 0x9d 190 | ValueType.STRING, // 0x9e 191 | ValueType.STRING, // 0x9f 192 | ValueType.STRING, // 0xa0 193 | ValueType.STRING, // 0xa1 194 | ValueType.STRING, // 0xa2 195 | ValueType.STRING, // 0xa3 196 | ValueType.STRING, // 0xa4 197 | ValueType.STRING, // 0xa5 198 | ValueType.STRING, // 0xa6 199 | ValueType.STRING, // 0xa7 200 | ValueType.STRING, // 0xa8 201 | ValueType.STRING, // 0xa9 202 | ValueType.STRING, // 0xaa 203 | ValueType.STRING, // 0xab 204 | ValueType.STRING, // 0xac 205 | ValueType.STRING, // 0xad 206 | ValueType.STRING, // 0xae 207 | ValueType.STRING, // 0xaf 208 | ValueType.STRING, // 0xb0 209 | ValueType.STRING, // 0xb1 210 | ValueType.STRING, // 0xb2 211 | ValueType.STRING, // 0xb3 212 | ValueType.STRING, // 0xb4 213 | ValueType.STRING, // 0xb5 214 | ValueType.STRING, // 0xb6 215 | ValueType.STRING, // 0xb7 216 | ValueType.STRING, // 0xb8 217 | ValueType.STRING, // 0xb9 218 | ValueType.STRING, // 0xba 219 | ValueType.STRING, // 0xbb 220 | ValueType.STRING, // 0xbc 221 | ValueType.STRING, // 0xbd 222 | ValueType.STRING, // 0xbe 223 | ValueType.STRING, // 0xbf 224 | ValueType.BINARY, // 0xc0 225 | ValueType.BINARY, // 0xc1 226 | ValueType.BINARY, // 0xc2 227 | ValueType.BINARY, // 0xc3 228 | ValueType.BINARY, // 0xc4 229 | ValueType.BINARY, // 0xc5 230 | ValueType.BINARY, // 0xc6 231 | ValueType.BINARY, // 0xc7 232 | ValueType.BCD, // 0xc8 233 | ValueType.BCD, // 0xc9 234 | ValueType.BCD, // 0xca 235 | ValueType.BCD, // 0xcb 236 | ValueType.BCD, // 0xcc 237 | ValueType.BCD, // 0xcd 238 | ValueType.BCD, // 0xce 239 | ValueType.BCD, // 0xcf 240 | ValueType.BCD, // 0xd0 241 | ValueType.BCD, // 0xd1 242 | ValueType.BCD, // 0xd2 243 | ValueType.BCD, // 0xd3 244 | ValueType.BCD, // 0xd4 245 | ValueType.BCD, // 0xd5 246 | ValueType.BCD, // 0xd6 247 | ValueType.BCD, // 0xd7 248 | ValueType.NONE, // 0xd8 249 | ValueType.NONE, // 0xd9 250 | ValueType.NONE, // 0xda 251 | ValueType.NONE, // 0xdb 252 | ValueType.NONE, // 0xdc 253 | ValueType.NONE, // 0xdd 254 | ValueType.NONE, // 0xde 255 | ValueType.NONE, // 0xdf 256 | ValueType.NONE, // 0xe0 257 | ValueType.NONE, // 0xe1 258 | ValueType.NONE, // 0xe2 259 | ValueType.NONE, // 0xe3 260 | ValueType.NONE, // 0xe4 261 | ValueType.NONE, // 0xe5 262 | ValueType.NONE, // 0xe6 263 | ValueType.NONE, // 0xe7 264 | ValueType.NONE, // 0xe8 265 | ValueType.NONE, // 0xe9 266 | ValueType.NONE, // 0xea 267 | ValueType.NONE, // 0xeb 268 | ValueType.NONE, // 0xec 269 | ValueType.NONE, // 0xed 270 | ValueType.TAGGED, // 0xee 271 | ValueType.TAGGED, // 0xef 272 | ValueType.CUSTOM, // 0xf0 273 | ValueType.CUSTOM, // 0xf1 274 | ValueType.CUSTOM, // 0xf2 275 | ValueType.CUSTOM, // 0xf3 276 | ValueType.CUSTOM, // 0xf4 277 | ValueType.CUSTOM, // 0xf5 278 | ValueType.CUSTOM, // 0xf6 279 | ValueType.CUSTOM, // 0xf7 280 | ValueType.CUSTOM, // 0xf8 281 | ValueType.CUSTOM, // 0xf9 282 | ValueType.CUSTOM, // 0xfa 283 | ValueType.CUSTOM, // 0xfb 284 | ValueType.CUSTOM, // 0xfc 285 | ValueType.CUSTOM, // 0xfd 286 | ValueType.CUSTOM, // 0xfe 287 | ValueType.CUSTOM, // 0xff 288 | }; 289 | 290 | private ValueTypeUtil() { 291 | super(); 292 | } 293 | 294 | public static ValueType get(final byte key) { 295 | return MAP[(int) key & 0xff]; 296 | } 297 | 298 | } 299 | -------------------------------------------------------------------------------- /src/test/java/com/arangodb/velocypack/VPackBuilderTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DISCLAIMER 3 | * 4 | * Copyright 2016 ArangoDB GmbH, Cologne, Germany 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * Copyright holder is ArangoDB GmbH, Cologne, Germany 19 | */ 20 | 21 | package com.arangodb.velocypack; 22 | 23 | import com.arangodb.velocypack.exception.VPackBuilderNeedOpenCompoundException; 24 | import com.arangodb.velocypack.exception.VPackBuilderNumberOutOfRangeException; 25 | import com.arangodb.velocypack.exception.VPackBuilderUnexpectedValueException; 26 | import com.arangodb.velocypack.exception.VPackException; 27 | import org.junit.Test; 28 | 29 | import java.math.BigInteger; 30 | import java.util.Date; 31 | 32 | import static org.hamcrest.Matchers.is; 33 | import static org.hamcrest.Matchers.notNullValue; 34 | import static org.hamcrest.MatcherAssert.assertThat; 35 | import static org.junit.Assert.fail; 36 | 37 | /** 38 | * @author Mark Vollmary 39 | * 40 | */ 41 | public class VPackBuilderTest { 42 | 43 | @Test 44 | public void empty() { 45 | final VPackSlice slice = new VPackBuilder().slice(); 46 | assertThat(slice.isNone(), is(true)); 47 | } 48 | 49 | @Test 50 | public void addNull() throws VPackException { 51 | final VPackBuilder builder = new VPackBuilder(); 52 | builder.add(ValueType.NULL); 53 | 54 | final VPackSlice slice = builder.slice(); 55 | assertThat(slice.isNull(), is(true)); 56 | } 57 | 58 | @Test 59 | public void addBooleanTrue() throws VPackException { 60 | final VPackBuilder builder = new VPackBuilder(); 61 | builder.add(true); 62 | 63 | final VPackSlice slice = builder.slice(); 64 | assertThat(slice.isBoolean(), is(true)); 65 | assertThat(slice.getAsBoolean(), is(true)); 66 | } 67 | 68 | @Test 69 | public void addBooleanFalse() throws VPackException { 70 | final VPackBuilder builder = new VPackBuilder(); 71 | builder.add(false); 72 | 73 | final VPackSlice slice = builder.slice(); 74 | assertThat(slice.isBoolean(), is(true)); 75 | assertThat(slice.getAsBoolean(), is(false)); 76 | } 77 | 78 | @Test 79 | public void addBooleanNull() throws VPackException { 80 | final VPackBuilder builder = new VPackBuilder(); 81 | builder.add((Boolean) null); 82 | 83 | final VPackSlice slice = builder.slice(); 84 | assertThat(slice.isNull(), is(true)); 85 | } 86 | 87 | @Test 88 | public void addDouble() throws VPackException { 89 | final VPackBuilder builder = new VPackBuilder(); 90 | final double value = Double.MAX_VALUE; 91 | builder.add(value); 92 | 93 | final VPackSlice slice = builder.slice(); 94 | assertThat(slice.isDouble(), is(true)); 95 | assertThat(slice.getAsDouble(), is(value)); 96 | } 97 | 98 | @Test 99 | public void addIntegerAsSmallIntMin() throws VPackException { 100 | final VPackBuilder builder = new VPackBuilder(); 101 | final int value = -6; 102 | builder.add(value); 103 | 104 | final VPackSlice slice = builder.slice(); 105 | assertThat(slice.isSmallInt(), is(true)); 106 | assertThat(slice.getAsInt(), is(value)); 107 | } 108 | 109 | @Test 110 | public void addByte() throws VPackException { 111 | final VPackBuilder builder = new VPackBuilder(); 112 | final Byte value = (byte) 0x11; 113 | builder.add(value); 114 | 115 | final VPackSlice slice = builder.slice(); 116 | assertThat(slice.isByte(), is(true)); 117 | assertThat(slice.getAsByte(), is(value)); 118 | } 119 | 120 | @Test 121 | public void addIntegerAsSmallIntMax() throws VPackException { 122 | final VPackBuilder builder = new VPackBuilder(); 123 | final int value = 9; 124 | builder.add(value); 125 | 126 | final VPackSlice slice = builder.slice(); 127 | assertThat(slice.isSmallInt(), is(true)); 128 | assertThat(slice.getAsInt(), is(value)); 129 | } 130 | 131 | @Test 132 | public void addLongAsSmallIntMin() throws VPackException { 133 | final VPackBuilder builder = new VPackBuilder(); 134 | final long value = -6; 135 | builder.add(value, ValueType.SMALLINT); 136 | 137 | final VPackSlice slice = builder.slice(); 138 | assertThat(slice.isSmallInt(), is(true)); 139 | assertThat(slice.getAsLong(), is(value)); 140 | } 141 | 142 | @Test 143 | public void addLongAsSmallIntMax() throws VPackException { 144 | final VPackBuilder builder = new VPackBuilder(); 145 | final long value = 9; 146 | builder.add(value, ValueType.SMALLINT); 147 | 148 | final VPackSlice slice = builder.slice(); 149 | assertThat(slice.isSmallInt(), is(true)); 150 | assertThat(slice.getAsLong(), is(value)); 151 | } 152 | 153 | @Test(expected = VPackBuilderNumberOutOfRangeException.class) 154 | public void addLongAsSmallIntOutofRange() throws VPackException { 155 | final VPackBuilder builder = new VPackBuilder(); 156 | final long value = Long.MAX_VALUE; 157 | builder.add(value, ValueType.SMALLINT); 158 | } 159 | 160 | @Test 161 | public void addBigIntegerAsSmallIntMin() throws VPackException { 162 | final VPackBuilder builder = new VPackBuilder(); 163 | final BigInteger value = BigInteger.valueOf(-6); 164 | builder.add(value, ValueType.SMALLINT); 165 | 166 | final VPackSlice slice = builder.slice(); 167 | assertThat(slice.isSmallInt(), is(true)); 168 | assertThat(slice.getAsBigInteger(), is(value)); 169 | } 170 | 171 | @Test 172 | public void addBigIntegerAsSmallIntMax() throws VPackException { 173 | final VPackBuilder builder = new VPackBuilder(); 174 | final BigInteger value = BigInteger.valueOf(9); 175 | builder.add(value, ValueType.SMALLINT); 176 | 177 | final VPackSlice slice = builder.slice(); 178 | assertThat(slice.isSmallInt(), is(true)); 179 | assertThat(slice.getAsBigInteger(), is(value)); 180 | } 181 | 182 | @Test(expected = VPackBuilderNumberOutOfRangeException.class) 183 | public void addBigIntegerAsSmallIntOutofRange() throws VPackException { 184 | final VPackBuilder builder = new VPackBuilder(); 185 | final BigInteger value = BigInteger.valueOf(Long.MAX_VALUE); 186 | builder.add(value, ValueType.SMALLINT); 187 | } 188 | 189 | @Test 190 | public void addIntegerAsInt() throws VPackException { 191 | final VPackBuilder builder = new VPackBuilder(); 192 | final int value = Integer.MAX_VALUE; 193 | builder.add(value); 194 | 195 | final VPackSlice slice = builder.slice(); 196 | assertThat(slice.isInt(), is(true)); 197 | assertThat(slice.getAsInt(), is(value)); 198 | } 199 | 200 | @Test 201 | public void addLongAsInt() throws VPackException { 202 | final VPackBuilder builder = new VPackBuilder(); 203 | final long value = Long.MAX_VALUE; 204 | builder.add(value, ValueType.INT); 205 | 206 | final VPackSlice slice = builder.slice(); 207 | assertThat(slice.isInt(), is(true)); 208 | assertThat(slice.getAsLong(), is(value)); 209 | } 210 | 211 | @Test 212 | public void addBigIntegerAsInt() throws VPackException { 213 | final VPackBuilder builder = new VPackBuilder(); 214 | final BigInteger value = BigInteger.valueOf(Long.MAX_VALUE); 215 | builder.add(value, ValueType.INT); 216 | 217 | final VPackSlice slice = builder.slice(); 218 | assertThat(slice.isInt(), is(true)); 219 | assertThat(slice.getAsBigInteger(), is(value)); 220 | } 221 | 222 | @Test 223 | public void addLongAsUInt() throws VPackException { 224 | final VPackBuilder builder = new VPackBuilder(); 225 | final long value = Long.MAX_VALUE; 226 | builder.add(value, ValueType.UINT); 227 | 228 | final VPackSlice slice = builder.slice(); 229 | assertThat(slice.isUInt(), is(true)); 230 | assertThat(slice.getAsLong(), is(value)); 231 | } 232 | 233 | @Test 234 | public void addBigIntegerAsUInt() throws VPackException { 235 | final VPackBuilder builder = new VPackBuilder(); 236 | final BigInteger value = BigInteger.valueOf(Long.MAX_VALUE); 237 | builder.add(value, ValueType.UINT); 238 | 239 | final VPackSlice slice = builder.slice(); 240 | assertThat(slice.isUInt(), is(true)); 241 | assertThat(slice.getAsBigInteger(), is(value)); 242 | } 243 | 244 | @Test(expected = VPackBuilderUnexpectedValueException.class) 245 | public void addLongAsUIntNegative() throws VPackException { 246 | final VPackBuilder builder = new VPackBuilder(); 247 | final long value = -10; 248 | builder.add(value, ValueType.UINT); 249 | } 250 | 251 | @Test(expected = VPackBuilderUnexpectedValueException.class) 252 | public void addBigIntegerAsUIntNegative() throws VPackException { 253 | final VPackBuilder builder = new VPackBuilder(); 254 | final BigInteger value = BigInteger.valueOf(-10); 255 | builder.add(value, ValueType.UINT); 256 | } 257 | 258 | @Test 259 | public void addDate() throws VPackException { 260 | final VPackBuilder builder = new VPackBuilder(); 261 | final Date date = new Date(); 262 | builder.add(date); 263 | 264 | final VPackSlice slice = builder.slice(); 265 | assertThat(slice.isDate(), is(true)); 266 | assertThat(slice.getAsDate(), is(date)); 267 | } 268 | 269 | @Test 270 | public void addSqlDate() throws VPackException { 271 | final VPackBuilder builder = new VPackBuilder(); 272 | final java.sql.Date date = new java.sql.Date(new Date().getTime()); 273 | builder.add(date); 274 | 275 | final VPackSlice slice = builder.slice(); 276 | assertThat(slice.isDate(), is(true)); 277 | assertThat(slice.getAsSQLDate(), is(date)); 278 | } 279 | 280 | @Test 281 | public void addSqlTimestamp() throws VPackException { 282 | final VPackBuilder builder = new VPackBuilder(); 283 | final java.sql.Timestamp timestamp = new java.sql.Timestamp(new Date().getTime()); 284 | builder.add(timestamp); 285 | 286 | final VPackSlice slice = builder.slice(); 287 | assertThat(slice.isDate(), is(true)); 288 | assertThat(slice.getAsSQLTimestamp(), is(timestamp)); 289 | } 290 | 291 | @Test 292 | public void addStringShort() throws VPackException { 293 | final VPackBuilder builder = new VPackBuilder(); 294 | final String s = "Hallo Welt!"; 295 | builder.add(s); 296 | 297 | final VPackSlice slice = builder.slice(); 298 | assertThat(slice.isString(), is(true)); 299 | assertThat(slice.getAsString(), is(s)); 300 | } 301 | 302 | @Test 303 | public void addStringLong() throws VPackException { 304 | final VPackBuilder builder = new VPackBuilder(); 305 | final String s = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus."; 306 | builder.add(s); 307 | 308 | final VPackSlice slice = builder.slice(); 309 | assertThat(slice.isString(), is(true)); 310 | assertThat(slice.getAsString(), is(s)); 311 | } 312 | 313 | @Test 314 | public void emptyArray() throws VPackException { 315 | final VPackBuilder builder = new VPackBuilder(); 316 | builder.add(ValueType.ARRAY); 317 | builder.close(); 318 | 319 | final VPackSlice slice = builder.slice(); 320 | assertThat(slice.isArray(), is(true)); 321 | assertThat(slice.getLength(), is(0)); 322 | try { 323 | slice.get(0); 324 | fail(); 325 | } catch (final IndexOutOfBoundsException ignored) { 326 | 327 | } 328 | } 329 | 330 | @Test 331 | public void compactArray() throws VPackException { 332 | final long[] expected = { 1, 16 }; 333 | final VPackBuilder builder = new VPackBuilder(); 334 | builder.add(ValueType.ARRAY, true); 335 | for (final long l : expected) { 336 | builder.add(l); 337 | } 338 | builder.close(); 339 | 340 | final VPackSlice slice = builder.slice(); 341 | assertThat(slice.isArray(), is(true)); 342 | assertThat(slice.getLength(), is(2)); 343 | for (int i = 0; i < expected.length; i++) { 344 | final VPackSlice at = slice.get(i); 345 | assertThat(at.isInteger(), is(true)); 346 | assertThat(at.getAsLong(), is(expected[i])); 347 | } 348 | } 349 | 350 | @Test 351 | public void arrayItemsSameLength() throws VPackException { 352 | VPackSlice sliceNotSame; 353 | { 354 | final VPackBuilder builder = new VPackBuilder(); 355 | builder.add(ValueType.ARRAY); 356 | builder.add("aa"); 357 | builder.add("a"); 358 | builder.close(); 359 | sliceNotSame = builder.slice(); 360 | } 361 | VPackSlice sliceSame; 362 | { 363 | final VPackBuilder builder = new VPackBuilder(); 364 | builder.add(ValueType.ARRAY); 365 | builder.add("aa"); 366 | builder.add("aa"); 367 | builder.close(); 368 | sliceSame = builder.slice(); 369 | } 370 | assertThat(sliceSame.getByteSize() < sliceNotSame.getByteSize(), is(true)); 371 | } 372 | 373 | @Test 374 | public void unindexedArray() throws VPackException { 375 | final long[] expected = { 1, 16 }; 376 | final VPackBuilder builder = new VPackBuilder(); 377 | builder.getOptions().setBuildUnindexedArrays(true); 378 | builder.add(ValueType.ARRAY, false); 379 | for (final long l : expected) { 380 | builder.add(l); 381 | } 382 | builder.close(); 383 | 384 | final VPackSlice slice = builder.slice(); 385 | assertThat(slice.isArray(), is(true)); 386 | assertThat(slice.getLength(), is(2)); 387 | for (int i = 0; i < expected.length; i++) { 388 | final VPackSlice at = slice.get(i); 389 | assertThat(at.isInteger(), is(true)); 390 | assertThat(at.getAsLong(), is(expected[i])); 391 | } 392 | } 393 | 394 | @Test 395 | public void unindexedSingletonArray() throws VPackException { 396 | final long[] expected = {1}; 397 | final VPackBuilder builder = new VPackBuilder(); 398 | builder.getOptions().setBuildUnindexedArrays(true); 399 | builder.add(ValueType.ARRAY, false); 400 | for (final long l : expected) { 401 | builder.add(l); 402 | } 403 | builder.close(); 404 | 405 | final VPackSlice slice = builder.slice(); 406 | assertThat(slice.isArray(), is(true)); 407 | assertThat(slice.getLength(), is(1)); 408 | for (int i = 0; i < expected.length; i++) { 409 | final VPackSlice at = slice.get(i); 410 | assertThat(at.isInteger(), is(true)); 411 | assertThat(at.getAsLong(), is(expected[i])); 412 | } 413 | } 414 | 415 | 416 | @Test 417 | public void indexedArray() throws VPackException { 418 | final long[] values = {1, 2, 3}; 419 | final VPackBuilder builder = new VPackBuilder(); 420 | builder.add(ValueType.ARRAY); 421 | for (final long l : values) { 422 | builder.add(l); 423 | } 424 | builder.close(); 425 | 426 | final VPackSlice slice = builder.slice(); 427 | assertThat(slice.isArray(), is(true)); 428 | assertThat(slice.getLength(), is(3)); 429 | } 430 | 431 | @Test 432 | public void indexedArray2ByteLength() throws VPackException { 433 | final int valueCount = 100; 434 | final VPackBuilder builder = new VPackBuilder(); 435 | builder.add(ValueType.ARRAY); 436 | for (long i = 0; i < valueCount; i++) { 437 | builder.add( 438 | i + "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus."); 439 | } 440 | builder.close(); 441 | 442 | final VPackSlice slice = builder.slice(); 443 | assertThat(slice.head(), is((byte) 0x07)); 444 | assertThat(slice.isArray(), is(true)); 445 | assertThat(slice.getLength(), is(valueCount)); 446 | } 447 | 448 | @Test 449 | public void indexedArray2ByteLengthNoIndexTable() throws VPackException { 450 | final int valueCount = 100; 451 | final VPackBuilder builder = new VPackBuilder(); 452 | builder.add(ValueType.ARRAY); 453 | for (long i = 0; i < valueCount; i++) { 454 | builder.add( 455 | "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus."); 456 | } 457 | builder.close(); 458 | 459 | final VPackSlice slice = builder.slice(); 460 | assertThat(slice.head(), is((byte) 0x03)); 461 | assertThat(slice.isArray(), is(true)); 462 | assertThat(slice.getLength(), is(valueCount)); 463 | } 464 | 465 | @Test 466 | public void indexedArray4ByteLength() throws VPackException { 467 | final int valueCount = 200; 468 | final VPackBuilder builder = new VPackBuilder(); 469 | builder.add(ValueType.ARRAY); 470 | for (long i = 0; i < valueCount; i++) { 471 | builder.add( 472 | "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus."); 473 | } 474 | builder.close(); 475 | 476 | final VPackSlice slice = builder.slice(); 477 | assertThat(slice.head(), is((byte) 0x04)); 478 | assertThat(slice.isArray(), is(true)); 479 | assertThat(slice.getLength(), is(valueCount)); 480 | } 481 | 482 | @Test 483 | public void indexedArray4ByteLengthNoIndexTable() throws VPackException { 484 | final int valueCount = 200; 485 | final VPackBuilder builder = new VPackBuilder(); 486 | builder.add(ValueType.ARRAY); 487 | for (long i = 0; i < valueCount; i++) { 488 | builder.add( 489 | i + "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus."); 490 | } 491 | builder.close(); 492 | 493 | final VPackSlice slice = builder.slice(); 494 | assertThat(slice.head(), is((byte) 0x08)); 495 | assertThat(slice.isArray(), is(true)); 496 | assertThat(slice.getLength(), is(valueCount)); 497 | } 498 | 499 | @Test 500 | public void arrayInArray() throws VPackException { 501 | final long[][] values = { { 1, 2, 3 }, { 1, 2, 3 } }; 502 | final VPackBuilder builder = new VPackBuilder(); 503 | builder.add(ValueType.ARRAY); 504 | for (final long[] ls : values) { 505 | builder.add(ValueType.ARRAY); 506 | for (final long l : ls) { 507 | builder.add(l); 508 | } 509 | builder.close(); 510 | } 511 | builder.close(); 512 | 513 | final VPackSlice slice = builder.slice(); 514 | assertThat(slice.isArray(), is(true)); 515 | assertThat(slice.getLength(), is(values.length)); 516 | for (int i = 0; i < values.length; i++) { 517 | final VPackSlice ls = slice.get(i); 518 | assertThat(ls.isArray(), is(true)); 519 | assertThat(ls.getLength(), is(values[i].length)); 520 | for (int j = 0; j < values[i].length; j++) { 521 | final VPackSlice l = ls.get(j); 522 | assertThat(l.isInteger(), is(true)); 523 | assertThat(l.getAsLong(), is(values[i][j])); 524 | } 525 | } 526 | } 527 | 528 | @Test 529 | public void arrayInArrayInArray() throws VPackException { 530 | final long[][][] values = { { { 1, 2, 3 } } }; 531 | final VPackBuilder builder = new VPackBuilder(); 532 | builder.add(ValueType.ARRAY); 533 | for (final long[][] lss : values) { 534 | builder.add(ValueType.ARRAY); 535 | for (final long[] ls : lss) { 536 | builder.add(ValueType.ARRAY); 537 | for (final long l : ls) { 538 | builder.add(l); 539 | } 540 | builder.close(); 541 | } 542 | builder.close(); 543 | } 544 | builder.close(); 545 | 546 | final VPackSlice slice = builder.slice(); 547 | assertThat(slice.isArray(), is(true)); 548 | assertThat(slice.getLength(), is(values.length)); 549 | for (int i = 0; i < values.length; i++) { 550 | final VPackSlice lls = slice.get(i); 551 | assertThat(lls.isArray(), is(true)); 552 | assertThat(lls.getLength(), is(values[i].length)); 553 | for (int j = 0; j < values[i].length; j++) { 554 | final VPackSlice ls = lls.get(i); 555 | assertThat(ls.isArray(), is(true)); 556 | assertThat(ls.getLength(), is(values[i][j].length)); 557 | for (int k = 0; k < values[i][j].length; k++) { 558 | final VPackSlice l = ls.get(k); 559 | assertThat(l.isInteger(), is(true)); 560 | assertThat(l.getAsLong(), is(values[i][j][k])); 561 | } 562 | } 563 | 564 | } 565 | } 566 | 567 | @Test 568 | public void emptyObject() throws VPackException { 569 | final VPackBuilder builder = new VPackBuilder(); 570 | builder.add(ValueType.OBJECT); 571 | builder.close(); 572 | 573 | final VPackSlice slice = builder.slice(); 574 | assertThat(slice.isObject(), is(true)); 575 | assertThat(slice.getLength(), is(0)); 576 | final VPackSlice a = slice.get("a"); 577 | assertThat(a.isNone(), is(true)); 578 | try { 579 | slice.keyAt(0); 580 | fail(); 581 | } catch (final IndexOutOfBoundsException ignored) { 582 | 583 | } 584 | try { 585 | slice.valueAt(0); 586 | fail(); 587 | } catch (final IndexOutOfBoundsException ignored) { 588 | 589 | } 590 | } 591 | 592 | @Test 593 | public void compactObject() throws VPackException { 594 | // {"a": 12, "b": true, "c": "xyz"} 595 | final VPackBuilder builder = new VPackBuilder(); 596 | builder.add(ValueType.OBJECT, true); 597 | builder.add("a", 12); 598 | builder.add("b", true); 599 | builder.add("c", "xyz"); 600 | builder.close(); 601 | 602 | final VPackSlice slice = builder.slice(); 603 | assertThat(slice.isObject(), is(true)); 604 | assertThat(slice.getLength(), is(3)); 605 | assertThat(slice.get("a").getAsLong(), is(12L)); 606 | assertThat(slice.get("b").getAsBoolean(), is(true)); 607 | assertThat(slice.get("c").getAsString(), is("xyz")); 608 | } 609 | 610 | @Test 611 | public void unindexedObject() throws VPackException { 612 | // {"a": 12, "b": true, "c": "xyz"} 613 | final VPackBuilder builder = new VPackBuilder(); 614 | builder.getOptions().setBuildUnindexedObjects(true); 615 | builder.add(ValueType.OBJECT, false); 616 | builder.add("a", 12); 617 | builder.add("b", true); 618 | builder.add("c", "xyz"); 619 | builder.close(); 620 | 621 | final VPackSlice slice = builder.slice(); 622 | assertThat(slice.isObject(), is(true)); 623 | assertThat(slice.getLength(), is(3)); 624 | assertThat(slice.get("a").getAsLong(), is(12L)); 625 | assertThat(slice.get("b").getAsBoolean(), is(true)); 626 | assertThat(slice.get("c").getAsString(), is("xyz")); 627 | } 628 | 629 | @Test 630 | public void indexedObject() throws VPackException { 631 | // {"a": 12, "b": true, "c": "xyz"} 632 | final VPackBuilder builder = new VPackBuilder(); 633 | builder.add(ValueType.OBJECT); 634 | builder.add("a", 12); 635 | builder.add("b", true); 636 | builder.add("c", "xyz"); 637 | builder.close(); 638 | 639 | final VPackSlice slice = builder.slice(); 640 | assertThat(slice.isObject(), is(true)); 641 | assertThat(slice.getLength(), is(3)); 642 | assertThat(slice.get("a").getAsLong(), is(12L)); 643 | assertThat(slice.get("b").getAsBoolean(), is(true)); 644 | assertThat(slice.get("c").getAsString(), is("xyz")); 645 | } 646 | 647 | @Test 648 | public void objectInObject() throws VPackException { 649 | // {"a":{"a1":1,"a2":2},"b":{"b1":1,"b2":1}} 650 | final VPackBuilder builder = new VPackBuilder(); 651 | builder.add(ValueType.OBJECT); 652 | { 653 | builder.add("a", ValueType.OBJECT); 654 | builder.add("a1", 1); 655 | builder.add("a2", 2); 656 | builder.close(); 657 | } 658 | { 659 | builder.add("b", ValueType.OBJECT); 660 | builder.add("b1", 1); 661 | builder.add("b2", 2); 662 | builder.close(); 663 | } 664 | builder.close(); 665 | 666 | final VPackSlice slice = builder.slice(); 667 | assertThat(slice.isObject(), is(true)); 668 | assertThat(slice.getLength(), is(2)); 669 | { 670 | final VPackSlice a = slice.get("a"); 671 | assertThat(a.isObject(), is(true)); 672 | assertThat(a.getLength(), is(2)); 673 | assertThat(a.get("a1").getAsLong(), is(1L)); 674 | assertThat(a.get("a2").getAsLong(), is(2L)); 675 | } 676 | { 677 | final VPackSlice b = slice.get("b"); 678 | assertThat(b.isObject(), is(true)); 679 | assertThat(b.getLength(), is(2)); 680 | assertThat(b.get("b1").getAsLong(), is(1L)); 681 | assertThat(b.get("b2").getAsLong(), is(2L)); 682 | } 683 | } 684 | 685 | @Test 686 | public void objectInObjectInObject() throws VPackException { 687 | // {"a":{"b":{"c":{"d":true}}} 688 | final VPackBuilder builder = new VPackBuilder(); 689 | builder.add(ValueType.OBJECT); 690 | builder.add("a", ValueType.OBJECT); 691 | builder.add("b", ValueType.OBJECT); 692 | builder.add("c", ValueType.OBJECT); 693 | builder.add("d", true); 694 | builder.close(); 695 | builder.close(); 696 | builder.close(); 697 | builder.close(); 698 | 699 | final VPackSlice slice = builder.slice(); 700 | assertThat(slice.isObject(), is(true)); 701 | assertThat(slice.getLength(), is(1)); 702 | final VPackSlice a = slice.get("a"); 703 | assertThat(a.isObject(), is(true)); 704 | assertThat(a.getLength(), is(1)); 705 | final VPackSlice b = a.get("b"); 706 | assertThat(b.isObject(), is(true)); 707 | assertThat(b.getLength(), is(1)); 708 | final VPackSlice c = b.get("c"); 709 | assertThat(c.isObject(), is(true)); 710 | assertThat(c.getLength(), is(1)); 711 | final VPackSlice d = c.get("d"); 712 | assertThat(d.isBoolean(), is(true)); 713 | assertThat(d.isTrue(), is(true)); 714 | } 715 | 716 | @Test 717 | public void objectAttributeNotFound() throws VPackException { 718 | final VPackBuilder builder = new VPackBuilder(); 719 | builder.add(ValueType.OBJECT); 720 | builder.add("a", "a"); 721 | builder.close(); 722 | final VPackSlice vpack = builder.slice(); 723 | assertThat(vpack.isObject(), is(true)); 724 | final VPackSlice b = vpack.get("b"); 725 | assertThat(b.isNone(), is(true)); 726 | } 727 | 728 | @Test 729 | public void object1ByteOffset() throws VPackException { 730 | final VPackBuilder builder = new VPackBuilder(); 731 | builder.add(ValueType.OBJECT); 732 | final int size = 5; 733 | for (int i = 0; i < size; i++) { 734 | builder.add(String.valueOf(i), ValueType.OBJECT); 735 | for (int j = 0; j < size; j++) { 736 | builder.add(String.valueOf(j), "test"); 737 | } 738 | builder.close(); 739 | } 740 | builder.close(); 741 | final VPackSlice vpack = builder.slice(); 742 | assertThat(vpack.isObject(), is(true)); 743 | assertThat(vpack.getLength(), is(size)); 744 | for (int i = 0; i < size; i++) { 745 | final VPackSlice attr = vpack.get(String.valueOf(i)); 746 | assertThat(attr.isObject(), is(true)); 747 | for (int j = 0; j < size; j++) { 748 | final VPackSlice childAttr = attr.get(String.valueOf(j)); 749 | assertThat(childAttr.isString(), is(true)); 750 | } 751 | } 752 | } 753 | 754 | @Test 755 | public void object2ByteOffset() throws VPackException { 756 | final VPackBuilder builder = new VPackBuilder(); 757 | builder.add(ValueType.OBJECT); 758 | final int size = 10; 759 | for (int i = 0; i < size; i++) { 760 | builder.add(String.valueOf(i), ValueType.OBJECT); 761 | for (int j = 0; j < size; j++) { 762 | builder.add(String.valueOf(j), "test"); 763 | } 764 | builder.close(); 765 | } 766 | builder.close(); 767 | final VPackSlice vpack = builder.slice(); 768 | assertThat(vpack.isObject(), is(true)); 769 | assertThat(vpack.getLength(), is(size)); 770 | for (int i = 0; i < size; i++) { 771 | final VPackSlice attr = vpack.get(String.valueOf(i)); 772 | assertThat(attr.isObject(), is(true)); 773 | for (int j = 0; j < size; j++) { 774 | final VPackSlice childAttr = attr.get(String.valueOf(j)); 775 | assertThat(childAttr.isString(), is(true)); 776 | } 777 | } 778 | } 779 | 780 | @Test 781 | public void sortObjectAttr() throws VPackException { 782 | final int min = 0; 783 | final int max = 9; 784 | final VPackBuilder builder = new VPackBuilder(); 785 | builder.add(ValueType.OBJECT); 786 | for (int i = max; i >= min; i--) { 787 | builder.add(String.valueOf(i), "test"); 788 | } 789 | builder.close(); 790 | final VPackSlice vpack = builder.slice(); 791 | assertThat(vpack.isObject(), is(true)); 792 | assertThat(vpack.getLength(), is(max - min + 1)); 793 | for (int i = min, j = 0; i <= max; i++, j++) { 794 | assertThat(vpack.keyAt(j).getAsString(), is(String.valueOf(i))); 795 | } 796 | } 797 | 798 | @Test 799 | public void sortObjectAttr2() throws VPackException { 800 | final String[] keys = { "a", "b", "c", "d", "e", "f", "g", "h" }; 801 | final String[] keysUnsorted = { "b", "d", "c", "e", "g", "f", "h", "a" }; 802 | assertThat(keysUnsorted.length, is(keys.length)); 803 | final VPackBuilder builder = new VPackBuilder(); 804 | builder.add(ValueType.OBJECT); 805 | for (String s : keysUnsorted) { 806 | builder.add(s, "test"); 807 | } 808 | builder.close(); 809 | final VPackSlice vpack = builder.slice(); 810 | assertThat(vpack.isObject(), is(true)); 811 | assertThat(vpack.getLength(), is(keys.length)); 812 | for (int i = 0; i < keys.length; i++) { 813 | assertThat(vpack.keyAt(i).getAsString(), is(keys[i])); 814 | } 815 | } 816 | 817 | @Test 818 | public void attributeAdapterDefaults() throws VPackException { 819 | final VPackSlice vpackWithAttrAdapter; 820 | { 821 | final VPackBuilder builder = new VPackBuilder(); 822 | builder.add(ValueType.OBJECT); 823 | builder.add("_key", "a"); 824 | builder.close(); 825 | vpackWithAttrAdapter = builder.slice(); 826 | assertThat(vpackWithAttrAdapter.isObject(), is(true)); 827 | } 828 | final VPackSlice vpackWithoutAttrAdapter; 829 | { 830 | final VPackBuilder builder = new VPackBuilder(); 831 | builder.add(ValueType.OBJECT); 832 | builder.add("_kay", "a"); 833 | builder.close(); 834 | vpackWithoutAttrAdapter = builder.slice(); 835 | assertThat(vpackWithoutAttrAdapter.isObject(), is(true)); 836 | } 837 | assertThat(vpackWithAttrAdapter.getByteSize() < vpackWithoutAttrAdapter.getByteSize(), is(true)); 838 | } 839 | 840 | @Test(expected = VPackBuilderNeedOpenCompoundException.class) 841 | public void closeClosed() throws VPackException { 842 | final VPackBuilder builder = new VPackBuilder(); 843 | builder.add(ValueType.OBJECT); 844 | builder.close(); 845 | builder.close(); 846 | } 847 | 848 | @Test 849 | public void addBinary() throws VPackException { 850 | final byte[] expected = new byte[] { 49, 50, 51, 52, 53, 54, 55, 56, 57 }; 851 | final VPackBuilder builder = new VPackBuilder(); 852 | builder.add(expected); 853 | final VPackSlice slice = builder.slice(); 854 | 855 | assertThat(slice.isBinary(), is(true)); 856 | assertThat(slice.getBinaryLength(), is(expected.length)); 857 | assertThat(slice.getAsBinary(), is(expected)); 858 | assertThat(slice.getByteSize(), is(1 + 4 + expected.length)); 859 | } 860 | 861 | @Test 862 | public void addVPack() throws VPackException { 863 | final VPackBuilder builder = new VPackBuilder(); 864 | builder.add(ValueType.OBJECT); 865 | builder.add("s", new VPackBuilder().add("test").slice()); 866 | builder.close(); 867 | final VPackSlice slice = builder.slice(); 868 | assertThat(slice, is(notNullValue())); 869 | assertThat(slice.isObject(), is(true)); 870 | assertThat(slice.get("s").isString(), is(true)); 871 | assertThat(slice.get("s").getAsString(), is("test")); 872 | assertThat(slice.size(), is(1)); 873 | } 874 | 875 | @Test 876 | public void addVPackObject() throws VPackException { 877 | final VPackBuilder builder = new VPackBuilder(); 878 | builder.add(ValueType.OBJECT); 879 | { 880 | final VPackBuilder builder2 = new VPackBuilder(); 881 | builder2.add(ValueType.OBJECT); 882 | builder2.add("s", "test"); 883 | builder2.close(); 884 | builder.add("o", builder2.slice()); 885 | } 886 | builder.close(); 887 | final VPackSlice slice = builder.slice(); 888 | assertThat(slice, is(notNullValue())); 889 | assertThat(slice.isObject(), is(true)); 890 | assertThat(slice.get("o").isObject(), is(true)); 891 | assertThat(slice.get("o").get("s").isString(), is(true)); 892 | assertThat(slice.get("o").get("s").getAsString(), is("test")); 893 | assertThat(slice.size(), is(1)); 894 | assertThat(slice.get("o").size(), is(1)); 895 | } 896 | 897 | @Test 898 | public void addVPackObjectInArray() throws VPackException { 899 | final VPackBuilder builder = new VPackBuilder(); 900 | builder.add(ValueType.ARRAY); 901 | for (int i = 0; i < 10; i++) { 902 | final VPackBuilder builder2 = new VPackBuilder(); 903 | builder2.add(ValueType.OBJECT); 904 | builder2.add("s", "test"); 905 | builder2.close(); 906 | builder.add(builder2.slice()); 907 | } 908 | builder.close(); 909 | final VPackSlice slice = builder.slice(); 910 | assertThat(slice, is(notNullValue())); 911 | assertThat(slice.isArray(), is(true)); 912 | assertThat(slice.size(), is(10)); 913 | for (int i = 0; i < 10; i++) { 914 | assertThat(slice.get(i).isObject(), is(true)); 915 | assertThat(slice.get(i).get("s").isString(), is(true)); 916 | assertThat(slice.get(i).get("s").getAsString(), is("test")); 917 | assertThat(slice.get(i).size(), is(1)); 918 | } 919 | } 920 | 921 | @Test 922 | public void nonASCII() { 923 | final String s = "·ÃÂ"; 924 | final VPackSlice vpack = new VPackBuilder().add(s).slice(); 925 | assertThat(vpack.isString(), is(true)); 926 | assertThat(vpack.getAsString(), is(s)); 927 | } 928 | 929 | @Test 930 | public void addLong() { 931 | final long value = 12345678901L; 932 | final VPackBuilder builder = new VPackBuilder().add(value); 933 | final VPackSlice vpack = builder.slice(); 934 | assertThat(vpack.getAsLong(), is(value)); 935 | } 936 | 937 | @Test 938 | public void addBitInteger() { 939 | final BigInteger value = new BigInteger("12345678901"); 940 | final VPackBuilder builder = new VPackBuilder().add(value); 941 | final VPackSlice vpack = builder.slice(); 942 | assertThat(vpack.getAsBigInteger(), is(value)); 943 | } 944 | 945 | @Test 946 | public void objectWithByteSize256() { 947 | final StringBuilder aa = new StringBuilder(); 948 | final int stringLength = 256 - 25; 949 | for (int i = 0; i < stringLength; ++i) { 950 | aa.append("a"); 951 | } 952 | final String foo = "foo"; 953 | final String bar1 = "bar1"; 954 | final String bar2 = "bar2"; 955 | final VPackSlice vpack = new VPackBuilder().add(ValueType.OBJECT).add(foo, ValueType.OBJECT).add(bar2, "") 956 | .add(bar1, aa.toString()).close().close().slice(); 957 | 958 | assertThat(vpack.isObject(), is(true)); 959 | assertThat(vpack.get(foo).isObject(), is(true)); 960 | assertThat(vpack.get(foo).get(bar1).isString(), is(true)); 961 | assertThat(vpack.get(foo).get(bar1).getLength(), is(stringLength)); 962 | assertThat(vpack.get(foo).get(bar2).isString(), is(true)); 963 | assertThat(vpack.get(foo).get(bar2).getLength(), is(0)); 964 | } 965 | 966 | @Test 967 | public void objectWithByteSizeOver65536() { 968 | final StringBuilder aa = new StringBuilder(); 969 | final int stringLength = 65536 - 25 - 8; 970 | for (int i = 0; i < stringLength; ++i) { 971 | aa.append("a"); 972 | } 973 | final String foo = "foo"; 974 | final String bar1 = "bar1"; 975 | final String bar2 = "bar2"; 976 | final VPackSlice vpack = new VPackBuilder().add(ValueType.OBJECT).add(foo, ValueType.OBJECT).add(bar2, "") 977 | .add(bar1, aa.toString()).close().close().slice(); 978 | 979 | assertThat(vpack.isObject(), is(true)); 980 | assertThat(vpack.get(foo).isObject(), is(true)); 981 | assertThat(vpack.get(foo).get(bar1).isString(), is(true)); 982 | assertThat(vpack.get(foo).get(bar1).getLength(), is(stringLength)); 983 | assertThat(vpack.get(foo).get(bar2).isString(), is(true)); 984 | assertThat(vpack.get(foo).get(bar2).getLength(), is(0)); 985 | } 986 | 987 | @Test 988 | public void nestedArray() { 989 | //@formatter:off 990 | final VPackSlice s = new VPackBuilder() 991 | .add(ValueType.OBJECT) 992 | .add("dddddddddddddd", ValueType.ARRAY) 993 | .add(ValueType.OBJECT) 994 | .add("dddddddddddddd", ValueType.OBJECT) 995 | .add("ddddddd",6) 996 | .close() 997 | .close() 998 | .add(ValueType.OBJECT) 999 | .add("ddddddddddddddddd","dddddddddddddddddddddd") 1000 | .close() 1001 | .add(ValueType.OBJECT) 1002 | .add("ddddddddddddddddddddddddd", ValueType.ARRAY).close() 1003 | .add("ddddddddddddddddda","dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd") 1004 | .add("dddddddddddddddddb","") 1005 | .add("dddddddddddddddddc",ValueType.ARRAY).close() 1006 | .add("ddddddddddddddd",-1) 1007 | .close() 1008 | .close() 1009 | .add("dddddddddd",0) 1010 | .close().slice(); 1011 | //@formatter:on 1012 | assertThat(s.isObject(), is(true)); 1013 | assertThat(s.get("dddddddddddddd").isArray(), is(true)); 1014 | assertThat(s.get("dddddddddddddd").size(), is(3)); 1015 | assertThat(s.get("dddddddddddddd").get(2).isObject(), is(true)); 1016 | } 1017 | 1018 | } 1019 | -------------------------------------------------------------------------------- /src/test/java/com/arangodb/velocypack/VPackUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DISCLAIMER 3 | * 4 | * Copyright 2016 ArangoDB GmbH, Cologne, Germany 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * Copyright holder is ArangoDB GmbH, Cologne, Germany 19 | */ 20 | 21 | package com.arangodb.velocypack; 22 | 23 | /** 24 | * @author Mark Vollmary 25 | * 26 | */ 27 | public class VPackUtil { 28 | 29 | private final static char[] hexArray = "0123456789ABCDEF".toCharArray(); 30 | 31 | public static String toHex(final VPackSlice vpack) { 32 | final byte[] bytes = vpack.getBuffer(); 33 | final int bytesLength = vpack.getByteSize(); 34 | final int bytesStart = vpack.getStart(); 35 | final char[] hexChars = new char[bytesLength * 2]; 36 | for (int j = 0; j < bytes.length; j++) { 37 | final int v = bytes[j+bytesStart] & 0xFF; 38 | hexChars[j * 2] = hexArray[v >>> 4]; 39 | hexChars[j * 2 + 1] = hexArray[v & 0x0F]; 40 | } 41 | return new String(hexChars).replaceAll("(.{32})", "$1\n").replaceAll("(.{2})", "0x$1 ").toLowerCase(); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/test/java/com/arangodb/velocypack/util/DateUtilTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DISCLAIMER 3 | * 4 | * Copyright 2018 ArangoDB GmbH, Cologne, Germany 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * Copyright holder is ArangoDB GmbH, Cologne, Germany 19 | */ 20 | 21 | package com.arangodb.velocypack.util; 22 | 23 | import static org.hamcrest.Matchers.is; 24 | import static org.hamcrest.MatcherAssert.assertThat; 25 | 26 | import java.util.Date; 27 | 28 | import org.junit.Test; 29 | 30 | import com.arangodb.velocypack.internal.util.DateUtil; 31 | 32 | /** 33 | * @author Mark Vollmary 34 | * 35 | */ 36 | public class DateUtilTest { 37 | 38 | @Test 39 | public void format() { 40 | assertThat(DateUtil.format(new Date(1523891841000L)), is("2018-04-16T15:17:21.000Z")); 41 | } 42 | 43 | @Test 44 | public void parse() throws Exception { 45 | assertThat(DateUtil.parse("2018-04-16T15:17:21.000Z").getTime(), is(1523891841000L)); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/test/java/com/arangodb/velocypack/util/SliceIteratorTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DISCLAIMER 3 | * 4 | * Copyright 2016 ArangoDB GmbH, Cologne, Germany 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * Copyright holder is ArangoDB GmbH, Cologne, Germany 19 | */ 20 | 21 | package com.arangodb.velocypack.util; 22 | 23 | import static org.hamcrest.Matchers.is; 24 | import static org.hamcrest.MatcherAssert.assertThat; 25 | 26 | import java.util.Map.Entry; 27 | import java.util.NoSuchElementException; 28 | 29 | import org.junit.Test; 30 | 31 | import com.arangodb.velocypack.ArrayIterator; 32 | import com.arangodb.velocypack.ObjectIterator; 33 | import com.arangodb.velocypack.VPackSlice; 34 | import com.arangodb.velocypack.exception.VPackValueTypeException; 35 | 36 | /** 37 | * @author Mark Vollmary 38 | * 39 | */ 40 | public class SliceIteratorTest { 41 | 42 | @Test 43 | public void objectIterator() { 44 | // {"a":1, "b":16} 45 | final VPackSlice slice = new VPackSlice( 46 | new byte[] { 0x14, 0x0a, 0x41, 0x61, 0x31, 0x41, 0x62, 0x28, 0x10, 0x02 }); 47 | { 48 | final ObjectIterator iterator = new ObjectIterator(slice); 49 | for (final String s : new String[] { "a", "b" }) { 50 | final Entry next = iterator.next(); 51 | assertThat(next.getKey(), is(s)); 52 | } 53 | } 54 | { 55 | final ObjectIterator iterator = new ObjectIterator(slice); 56 | for (final int i : new int[] { 1, 16 }) { 57 | final Entry next = iterator.next(); 58 | assertThat(next.getValue().getAsInt(), is(i)); 59 | } 60 | } 61 | } 62 | 63 | @Test(expected = NoSuchElementException.class) 64 | public void objectIteratorNoNext() { 65 | // {"a":1, "b":16} 66 | final VPackSlice slice = new VPackSlice( 67 | new byte[] { 0x14, 0x0a, 0x41, 0x61, 0x31, 0x41, 0x62, 0x28, 0x10, 0x02 }); 68 | final ObjectIterator iterator = new ObjectIterator(slice); 69 | 70 | for (final String s : new String[] { "a", "b" }) { 71 | final Entry next = iterator.next(); 72 | assertThat(next.getKey(), is(s)); 73 | } 74 | iterator.next();// no more elements 75 | } 76 | 77 | @Test(expected = VPackValueTypeException.class) 78 | public void objectIteratorWithArrayFail() { 79 | final VPackSlice slice = new VPackSlice(new byte[] { 0x13, 0x06, 0x31, 0x28, 0x10, 0x02 }); 80 | new ObjectIterator(slice); 81 | } 82 | 83 | @Test 84 | public void emptyObjectIterator() { 85 | final VPackSlice slice = new VPackSlice(new byte[] { 0x0a }); 86 | final ObjectIterator iterator = new ObjectIterator(slice); 87 | assertThat(iterator.hasNext(), is(false)); 88 | } 89 | 90 | @Test 91 | public void arrayIterator() { 92 | // { 1, 16 } 93 | final VPackSlice slice = new VPackSlice(new byte[] { 0x13, 0x06, 0x31, 0x28, 0x10, 0x02 }); 94 | final ArrayIterator iterator = new ArrayIterator(slice); 95 | 96 | for (final int i : new int[] { 1, 16 }) { 97 | final VPackSlice next = iterator.next(); 98 | assertThat(next.getAsInt(), is(i)); 99 | } 100 | } 101 | 102 | @Test(expected = NoSuchElementException.class) 103 | public void arrayIteratorNoNext() { 104 | // { 1, 16 } 105 | final VPackSlice slice = new VPackSlice(new byte[] { 0x13, 0x06, 0x31, 0x28, 0x10, 0x02 }); 106 | final ArrayIterator iterator = new ArrayIterator(slice); 107 | 108 | for (final int i : new int[] { 1, 16 }) { 109 | final VPackSlice next = iterator.next(); 110 | assertThat(next.getAsInt(), is(i)); 111 | } 112 | iterator.next();// no more elements 113 | } 114 | 115 | @Test(expected = VPackValueTypeException.class) 116 | public void arrayIteratorWithObjectFail() { 117 | final VPackSlice slice = new VPackSlice( 118 | new byte[] { 0x14, 0x0a, 0x41, 0x61, 0x31, 0x41, 0x62, 0x28, 0x10, 0x02 }); 119 | new ArrayIterator(slice); 120 | } 121 | 122 | @Test(expected = UnsupportedOperationException.class) 123 | public void removeFail() { 124 | final VPackSlice slice = new VPackSlice(new byte[] { 0x13, 0x06, 0x31, 0x28, 0x10, 0x02 }); 125 | final ArrayIterator iterator = new ArrayIterator(slice); 126 | iterator.remove(); 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /src/test/java/com/arangodb/velocypack/util/ValueTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DISCLAIMER 3 | * 4 | * Copyright 2016 ArangoDB GmbH, Cologne, Germany 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * Copyright holder is ArangoDB GmbH, Cologne, Germany 19 | */ 20 | 21 | package com.arangodb.velocypack.util; 22 | 23 | import java.math.BigInteger; 24 | 25 | import org.junit.Test; 26 | 27 | import com.arangodb.velocypack.ValueType; 28 | import com.arangodb.velocypack.exception.VPackValueTypeException; 29 | import com.arangodb.velocypack.internal.Value; 30 | 31 | /** 32 | * @author Mark Vollmary 33 | * 34 | */ 35 | public class ValueTest { 36 | 37 | @Test(expected = VPackValueTypeException.class) 38 | public void wrongType() { 39 | new Value(ValueType.STRING); 40 | } 41 | 42 | @Test(expected = VPackValueTypeException.class) 43 | public void wrongLongType() { 44 | new Value(1L, ValueType.STRING); 45 | } 46 | 47 | @Test(expected = VPackValueTypeException.class) 48 | public void wrongIntegerType() { 49 | new Value(1L, ValueType.STRING); 50 | } 51 | 52 | @Test(expected = VPackValueTypeException.class) 53 | public void wrongBigIntegerType() { 54 | new Value(new BigInteger("1"), ValueType.STRING); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/test/resources/logback-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | --------------------------------------------------------------------------------