snowflake-connector-python 3.16.0__cp313-cp313-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (246) hide show
  1. snowflake/connector/__init__.py +96 -0
  2. snowflake/connector/_query_context_cache.py +276 -0
  3. snowflake/connector/_sql_util.py +48 -0
  4. snowflake/connector/_utils.py +70 -0
  5. snowflake/connector/arrow_context.py +203 -0
  6. snowflake/connector/auth/__init__.py +53 -0
  7. snowflake/connector/auth/_auth.py +586 -0
  8. snowflake/connector/auth/_http_server.py +220 -0
  9. snowflake/connector/auth/_oauth_base.py +400 -0
  10. snowflake/connector/auth/by_plugin.py +219 -0
  11. snowflake/connector/auth/default.py +36 -0
  12. snowflake/connector/auth/idtoken.py +72 -0
  13. snowflake/connector/auth/keypair.py +222 -0
  14. snowflake/connector/auth/no_auth.py +39 -0
  15. snowflake/connector/auth/oauth.py +49 -0
  16. snowflake/connector/auth/oauth_code.py +479 -0
  17. snowflake/connector/auth/oauth_credentials.py +66 -0
  18. snowflake/connector/auth/okta.py +335 -0
  19. snowflake/connector/auth/pat.py +39 -0
  20. snowflake/connector/auth/usrpwdmfa.py +69 -0
  21. snowflake/connector/auth/webbrowser.py +502 -0
  22. snowflake/connector/auth/workload_identity.py +94 -0
  23. snowflake/connector/azure_storage_client.py +276 -0
  24. snowflake/connector/backoff_policies.py +141 -0
  25. snowflake/connector/bind_upload_agent.py +89 -0
  26. snowflake/connector/cache.py +696 -0
  27. snowflake/connector/compat.py +127 -0
  28. snowflake/connector/config_manager.py +496 -0
  29. snowflake/connector/connection.py +2273 -0
  30. snowflake/connector/connection_diagnostic.py +776 -0
  31. snowflake/connector/constants.py +442 -0
  32. snowflake/connector/converter.py +785 -0
  33. snowflake/connector/converter_issue23517.py +87 -0
  34. snowflake/connector/converter_null.py +14 -0
  35. snowflake/connector/converter_snowsql.py +205 -0
  36. snowflake/connector/cursor.py +1951 -0
  37. snowflake/connector/dbapi.py +53 -0
  38. snowflake/connector/description.py +19 -0
  39. snowflake/connector/direct_file_operation_utils.py +88 -0
  40. snowflake/connector/encryption_util.py +220 -0
  41. snowflake/connector/errorcode.py +91 -0
  42. snowflake/connector/errors.py +615 -0
  43. snowflake/connector/externals_utils/__init__.py +0 -0
  44. snowflake/connector/externals_utils/externals_setup.py +27 -0
  45. snowflake/connector/feature.py +4 -0
  46. snowflake/connector/file_compression_type.py +118 -0
  47. snowflake/connector/file_lock.py +72 -0
  48. snowflake/connector/file_transfer_agent.py +1215 -0
  49. snowflake/connector/file_util.py +153 -0
  50. snowflake/connector/gcs_storage_client.py +474 -0
  51. snowflake/connector/gzip_decoder.py +85 -0
  52. snowflake/connector/local_storage_client.py +90 -0
  53. snowflake/connector/log_configuration.py +60 -0
  54. snowflake/connector/logging_utils/__init__.py +0 -0
  55. snowflake/connector/logging_utils/filters.py +72 -0
  56. snowflake/connector/nanoarrow_arrow_iterator.cp313-win_amd64.pyd +0 -0
  57. snowflake/connector/nanoarrow_cpp/ArrowIterator/ArrayConverter.cpp +60 -0
  58. snowflake/connector/nanoarrow_cpp/ArrowIterator/ArrayConverter.hpp +29 -0
  59. snowflake/connector/nanoarrow_cpp/ArrowIterator/BinaryConverter.cpp +19 -0
  60. snowflake/connector/nanoarrow_cpp/ArrowIterator/BinaryConverter.hpp +26 -0
  61. snowflake/connector/nanoarrow_cpp/ArrowIterator/BooleanConverter.cpp +21 -0
  62. snowflake/connector/nanoarrow_cpp/ArrowIterator/BooleanConverter.hpp +23 -0
  63. snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowChunkIterator.cpp +557 -0
  64. snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowChunkIterator.hpp +98 -0
  65. snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowIterator.cpp +125 -0
  66. snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowIterator.hpp +115 -0
  67. snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowTableIterator.cpp +1005 -0
  68. snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowTableIterator.hpp +127 -0
  69. snowflake/connector/nanoarrow_cpp/ArrowIterator/DateConverter.cpp +47 -0
  70. snowflake/connector/nanoarrow_cpp/ArrowIterator/DateConverter.hpp +46 -0
  71. snowflake/connector/nanoarrow_cpp/ArrowIterator/DecFloatConverter.cpp +83 -0
  72. snowflake/connector/nanoarrow_cpp/ArrowIterator/DecFloatConverter.hpp +35 -0
  73. snowflake/connector/nanoarrow_cpp/ArrowIterator/DecimalConverter.cpp +97 -0
  74. snowflake/connector/nanoarrow_cpp/ArrowIterator/DecimalConverter.hpp +72 -0
  75. snowflake/connector/nanoarrow_cpp/ArrowIterator/FixedSizeListConverter.cpp +73 -0
  76. snowflake/connector/nanoarrow_cpp/ArrowIterator/FixedSizeListConverter.hpp +28 -0
  77. snowflake/connector/nanoarrow_cpp/ArrowIterator/FloatConverter.cpp +30 -0
  78. snowflake/connector/nanoarrow_cpp/ArrowIterator/FloatConverter.hpp +35 -0
  79. snowflake/connector/nanoarrow_cpp/ArrowIterator/IColumnConverter.hpp +17 -0
  80. snowflake/connector/nanoarrow_cpp/ArrowIterator/IntConverter.cpp +23 -0
  81. snowflake/connector/nanoarrow_cpp/ArrowIterator/IntConverter.hpp +45 -0
  82. snowflake/connector/nanoarrow_cpp/ArrowIterator/IntervalConverter.cpp +71 -0
  83. snowflake/connector/nanoarrow_cpp/ArrowIterator/IntervalConverter.hpp +56 -0
  84. snowflake/connector/nanoarrow_cpp/ArrowIterator/LICENSE.txt +209 -0
  85. snowflake/connector/nanoarrow_cpp/ArrowIterator/MapConverter.cpp +75 -0
  86. snowflake/connector/nanoarrow_cpp/ArrowIterator/MapConverter.hpp +30 -0
  87. snowflake/connector/nanoarrow_cpp/ArrowIterator/ObjectConverter.cpp +46 -0
  88. snowflake/connector/nanoarrow_cpp/ArrowIterator/ObjectConverter.hpp +29 -0
  89. snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Common.cpp +8 -0
  90. snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Common.hpp +95 -0
  91. snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Helpers.cpp +57 -0
  92. snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Helpers.hpp +36 -0
  93. snowflake/connector/nanoarrow_cpp/ArrowIterator/SnowflakeType.cpp +34 -0
  94. snowflake/connector/nanoarrow_cpp/ArrowIterator/SnowflakeType.hpp +48 -0
  95. snowflake/connector/nanoarrow_cpp/ArrowIterator/StringConverter.cpp +19 -0
  96. snowflake/connector/nanoarrow_cpp/ArrowIterator/StringConverter.hpp +26 -0
  97. snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeConverter.cpp +36 -0
  98. snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeConverter.hpp +31 -0
  99. snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeStampConverter.cpp +346 -0
  100. snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeStampConverter.hpp +145 -0
  101. snowflake/connector/nanoarrow_cpp/ArrowIterator/Util/macros.hpp +14 -0
  102. snowflake/connector/nanoarrow_cpp/ArrowIterator/Util/time.cpp +65 -0
  103. snowflake/connector/nanoarrow_cpp/ArrowIterator/Util/time.hpp +68 -0
  104. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_accessors.h +101 -0
  105. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_alloc.h +127 -0
  106. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_assert.h +45 -0
  107. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_builder.h +1908 -0
  108. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_emitter.h +215 -0
  109. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_endian.h +125 -0
  110. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_epilogue.h +7 -0
  111. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_flatbuffers.h +55 -0
  112. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_identifier.h +148 -0
  113. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_iov.h +31 -0
  114. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_prologue.h +8 -0
  115. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_refmap.h +144 -0
  116. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_rtconfig.h +162 -0
  117. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_types.h +97 -0
  118. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_verifier.h +239 -0
  119. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/flatcc_portable.h +14 -0
  120. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/paligned_alloc.h +210 -0
  121. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pattributes.h +84 -0
  122. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic.h +84 -0
  123. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic_pop.h +20 -0
  124. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic_push.h +51 -0
  125. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pendian.h +206 -0
  126. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pendian_detect.h +118 -0
  127. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pinline.h +19 -0
  128. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pinttypes.h +52 -0
  129. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/portable.h +2 -0
  130. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/portable_basic.h +25 -0
  131. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstatic_assert.h +67 -0
  132. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstdalign.h +162 -0
  133. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstdint.h +898 -0
  134. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/punaligned.h +190 -0
  135. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pversion.h +6 -0
  136. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pwarnings.h +52 -0
  137. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc.c +3204 -0
  138. snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow.c +3217 -0
  139. snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow.h +3618 -0
  140. snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow.hpp +379 -0
  141. snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_arrow_iterator.pyx +256 -0
  142. snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_device.c +512 -0
  143. snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_device.h +350 -0
  144. snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_ipc.c +33273 -0
  145. snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_ipc.h +397 -0
  146. snowflake/connector/nanoarrow_cpp/Logging/logging.cpp +100 -0
  147. snowflake/connector/nanoarrow_cpp/Logging/logging.hpp +49 -0
  148. snowflake/connector/network.py +1297 -0
  149. snowflake/connector/ocsp_asn1crypto.py +447 -0
  150. snowflake/connector/ocsp_snowflake.py +1883 -0
  151. snowflake/connector/options.py +131 -0
  152. snowflake/connector/pandas_tools.py +732 -0
  153. snowflake/connector/proxy.py +43 -0
  154. snowflake/connector/py.typed +0 -0
  155. snowflake/connector/result_batch.py +786 -0
  156. snowflake/connector/result_set.py +319 -0
  157. snowflake/connector/s3_storage_client.py +605 -0
  158. snowflake/connector/secret_detector.py +181 -0
  159. snowflake/connector/sf_dirs.py +64 -0
  160. snowflake/connector/sfbinaryformat.py +35 -0
  161. snowflake/connector/sfdatetime.py +345 -0
  162. snowflake/connector/snow_logging.py +144 -0
  163. snowflake/connector/sqlstate.py +9 -0
  164. snowflake/connector/ssd_internal_keys.py +30 -0
  165. snowflake/connector/ssl_wrap_socket.py +134 -0
  166. snowflake/connector/storage_client.py +478 -0
  167. snowflake/connector/telemetry.py +249 -0
  168. snowflake/connector/telemetry_oob.py +543 -0
  169. snowflake/connector/test_util.py +30 -0
  170. snowflake/connector/time_util.py +159 -0
  171. snowflake/connector/token_cache.py +402 -0
  172. snowflake/connector/tool/__init__.py +0 -0
  173. snowflake/connector/tool/dump_certs.py +57 -0
  174. snowflake/connector/tool/dump_ocsp_response.py +139 -0
  175. snowflake/connector/tool/dump_ocsp_response_cache.py +194 -0
  176. snowflake/connector/tool/probe_connection.py +69 -0
  177. snowflake/connector/url_util.py +49 -0
  178. snowflake/connector/util_text.py +301 -0
  179. snowflake/connector/vendored/__init__.py +3 -0
  180. snowflake/connector/vendored/requests/LICENSE +175 -0
  181. snowflake/connector/vendored/requests/__init__.py +169 -0
  182. snowflake/connector/vendored/requests/__version__.py +14 -0
  183. snowflake/connector/vendored/requests/_internal_utils.py +50 -0
  184. snowflake/connector/vendored/requests/adapters.py +537 -0
  185. snowflake/connector/vendored/requests/api.py +157 -0
  186. snowflake/connector/vendored/requests/auth.py +315 -0
  187. snowflake/connector/vendored/requests/certs.py +17 -0
  188. snowflake/connector/vendored/requests/compat.py +79 -0
  189. snowflake/connector/vendored/requests/cookies.py +561 -0
  190. snowflake/connector/vendored/requests/exceptions.py +140 -0
  191. snowflake/connector/vendored/requests/help.py +134 -0
  192. snowflake/connector/vendored/requests/hooks.py +33 -0
  193. snowflake/connector/vendored/requests/models.py +1033 -0
  194. snowflake/connector/vendored/requests/sessions.py +833 -0
  195. snowflake/connector/vendored/requests/status_codes.py +128 -0
  196. snowflake/connector/vendored/requests/structures.py +99 -0
  197. snowflake/connector/vendored/requests/utils.py +1093 -0
  198. snowflake/connector/vendored/urllib3/LICENSE.txt +21 -0
  199. snowflake/connector/vendored/urllib3/__init__.py +85 -0
  200. snowflake/connector/vendored/urllib3/_collections.py +355 -0
  201. snowflake/connector/vendored/urllib3/_version.py +2 -0
  202. snowflake/connector/vendored/urllib3/connection.py +572 -0
  203. snowflake/connector/vendored/urllib3/connectionpool.py +1137 -0
  204. snowflake/connector/vendored/urllib3/contrib/__init__.py +0 -0
  205. snowflake/connector/vendored/urllib3/contrib/_appengine_environ.py +36 -0
  206. snowflake/connector/vendored/urllib3/contrib/_securetransport/__init__.py +0 -0
  207. snowflake/connector/vendored/urllib3/contrib/_securetransport/bindings.py +519 -0
  208. snowflake/connector/vendored/urllib3/contrib/_securetransport/low_level.py +397 -0
  209. snowflake/connector/vendored/urllib3/contrib/appengine.py +314 -0
  210. snowflake/connector/vendored/urllib3/contrib/ntlmpool.py +130 -0
  211. snowflake/connector/vendored/urllib3/contrib/pyopenssl.py +509 -0
  212. snowflake/connector/vendored/urllib3/contrib/securetransport.py +920 -0
  213. snowflake/connector/vendored/urllib3/contrib/socks.py +216 -0
  214. snowflake/connector/vendored/urllib3/exceptions.py +323 -0
  215. snowflake/connector/vendored/urllib3/fields.py +274 -0
  216. snowflake/connector/vendored/urllib3/filepost.py +98 -0
  217. snowflake/connector/vendored/urllib3/packages/__init__.py +0 -0
  218. snowflake/connector/vendored/urllib3/packages/backports/__init__.py +0 -0
  219. snowflake/connector/vendored/urllib3/packages/backports/makefile.py +51 -0
  220. snowflake/connector/vendored/urllib3/packages/backports/weakref_finalize.py +155 -0
  221. snowflake/connector/vendored/urllib3/packages/six.py +1076 -0
  222. snowflake/connector/vendored/urllib3/poolmanager.py +540 -0
  223. snowflake/connector/vendored/urllib3/request.py +191 -0
  224. snowflake/connector/vendored/urllib3/response.py +885 -0
  225. snowflake/connector/vendored/urllib3/util/__init__.py +49 -0
  226. snowflake/connector/vendored/urllib3/util/connection.py +156 -0
  227. snowflake/connector/vendored/urllib3/util/proxy.py +57 -0
  228. snowflake/connector/vendored/urllib3/util/queue.py +22 -0
  229. snowflake/connector/vendored/urllib3/util/request.py +146 -0
  230. snowflake/connector/vendored/urllib3/util/response.py +107 -0
  231. snowflake/connector/vendored/urllib3/util/retry.py +620 -0
  232. snowflake/connector/vendored/urllib3/util/ssl_.py +495 -0
  233. snowflake/connector/vendored/urllib3/util/ssl_match_hostname.py +159 -0
  234. snowflake/connector/vendored/urllib3/util/ssltransport.py +221 -0
  235. snowflake/connector/vendored/urllib3/util/timeout.py +271 -0
  236. snowflake/connector/vendored/urllib3/util/url.py +435 -0
  237. snowflake/connector/vendored/urllib3/util/wait.py +152 -0
  238. snowflake/connector/version.py +3 -0
  239. snowflake/connector/wif_util.py +407 -0
  240. snowflake_connector_python-3.16.0.dist-info/METADATA +1475 -0
  241. snowflake_connector_python-3.16.0.dist-info/RECORD +246 -0
  242. snowflake_connector_python-3.16.0.dist-info/WHEEL +5 -0
  243. snowflake_connector_python-3.16.0.dist-info/entry_points.txt +4 -0
  244. snowflake_connector_python-3.16.0.dist-info/licenses/LICENSE.txt +202 -0
  245. snowflake_connector_python-3.16.0.dist-info/licenses/NOTICE +8 -0
  246. snowflake_connector_python-3.16.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,3217 @@
1
+ // Licensed to the Apache Software Foundation (ASF) under one
2
+ // or more contributor license agreements. See the NOTICE file
3
+ // distributed with this work for additional information
4
+ // regarding copyright ownership. The ASF licenses this file
5
+ // to you under the Apache License, Version 2.0 (the
6
+ // "License"); you may not use this file except in compliance
7
+ // with the License. You may obtain a copy of the License at
8
+ //
9
+ // http://www.apache.org/licenses/LICENSE-2.0
10
+ //
11
+ // Unless required by applicable law or agreed to in writing,
12
+ // software distributed under the License is distributed on an
13
+ // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ // KIND, either express or implied. See the License for the
15
+ // specific language governing permissions and limitations
16
+ // under the License.
17
+
18
+ #include "nanoarrow.h"
19
+
20
+ #include <errno.h>
21
+ #include <stdarg.h>
22
+ #include <stddef.h>
23
+ #include <stdio.h>
24
+ #include <stdlib.h>
25
+ #include <string.h>
26
+
27
+ const char* ArrowNanoarrowVersion(void) { return NANOARROW_VERSION; }
28
+
29
+ int ArrowNanoarrowVersionInt(void) { return NANOARROW_VERSION_INT; }
30
+
31
+ int ArrowErrorSet(struct ArrowError* error, const char* fmt, ...) {
32
+ if (error == NULL) {
33
+ return NANOARROW_OK;
34
+ }
35
+
36
+ memset(error->message, 0, sizeof(error->message));
37
+
38
+ va_list args;
39
+ va_start(args, fmt);
40
+ int chars_needed =
41
+ vsnprintf(error->message, sizeof(error->message), fmt, args);
42
+ va_end(args);
43
+
44
+ if (chars_needed < 0) {
45
+ return EINVAL;
46
+ } else if (((size_t)chars_needed) >= sizeof(error->message)) {
47
+ return ERANGE;
48
+ } else {
49
+ return NANOARROW_OK;
50
+ }
51
+ }
52
+
53
+ const char* ArrowErrorMessage(struct ArrowError* error) {
54
+ if (error == NULL) {
55
+ return "";
56
+ } else {
57
+ return error->message;
58
+ }
59
+ }
60
+
61
+ void ArrowLayoutInit(struct ArrowLayout* layout, enum ArrowType storage_type) {
62
+ layout->buffer_type[0] = NANOARROW_BUFFER_TYPE_VALIDITY;
63
+ layout->buffer_data_type[0] = NANOARROW_TYPE_BOOL;
64
+ layout->buffer_type[1] = NANOARROW_BUFFER_TYPE_DATA;
65
+ layout->buffer_data_type[1] = storage_type;
66
+ layout->buffer_type[2] = NANOARROW_BUFFER_TYPE_NONE;
67
+ layout->buffer_data_type[2] = NANOARROW_TYPE_UNINITIALIZED;
68
+
69
+ layout->element_size_bits[0] = 1;
70
+ layout->element_size_bits[1] = 0;
71
+ layout->element_size_bits[2] = 0;
72
+
73
+ layout->child_size_elements = 0;
74
+
75
+ switch (storage_type) {
76
+ case NANOARROW_TYPE_UNINITIALIZED:
77
+ case NANOARROW_TYPE_NA:
78
+ layout->buffer_type[0] = NANOARROW_BUFFER_TYPE_NONE;
79
+ layout->buffer_data_type[0] = NANOARROW_TYPE_UNINITIALIZED;
80
+ layout->buffer_type[1] = NANOARROW_BUFFER_TYPE_NONE;
81
+ layout->buffer_data_type[1] = NANOARROW_TYPE_UNINITIALIZED;
82
+ layout->element_size_bits[0] = 0;
83
+ break;
84
+
85
+ case NANOARROW_TYPE_LIST:
86
+ case NANOARROW_TYPE_MAP:
87
+ layout->buffer_type[1] = NANOARROW_BUFFER_TYPE_DATA_OFFSET;
88
+ layout->buffer_data_type[1] = NANOARROW_TYPE_INT32;
89
+ layout->element_size_bits[1] = 32;
90
+ break;
91
+
92
+ case NANOARROW_TYPE_LARGE_LIST:
93
+ layout->buffer_type[1] = NANOARROW_BUFFER_TYPE_DATA_OFFSET;
94
+ layout->buffer_data_type[1] = NANOARROW_TYPE_INT64;
95
+ layout->element_size_bits[1] = 64;
96
+ break;
97
+
98
+ case NANOARROW_TYPE_STRUCT:
99
+ case NANOARROW_TYPE_FIXED_SIZE_LIST:
100
+ layout->buffer_type[1] = NANOARROW_BUFFER_TYPE_NONE;
101
+ layout->buffer_data_type[1] = NANOARROW_TYPE_UNINITIALIZED;
102
+ break;
103
+
104
+ case NANOARROW_TYPE_BOOL:
105
+ layout->element_size_bits[1] = 1;
106
+ break;
107
+
108
+ case NANOARROW_TYPE_UINT8:
109
+ case NANOARROW_TYPE_INT8:
110
+ layout->element_size_bits[1] = 8;
111
+ break;
112
+
113
+ case NANOARROW_TYPE_UINT16:
114
+ case NANOARROW_TYPE_INT16:
115
+ case NANOARROW_TYPE_HALF_FLOAT:
116
+ layout->element_size_bits[1] = 16;
117
+ break;
118
+
119
+ case NANOARROW_TYPE_UINT32:
120
+ case NANOARROW_TYPE_INT32:
121
+ case NANOARROW_TYPE_FLOAT:
122
+ layout->element_size_bits[1] = 32;
123
+ break;
124
+ case NANOARROW_TYPE_INTERVAL_MONTHS:
125
+ layout->buffer_data_type[1] = NANOARROW_TYPE_INT32;
126
+ layout->element_size_bits[1] = 32;
127
+ break;
128
+
129
+ case NANOARROW_TYPE_UINT64:
130
+ case NANOARROW_TYPE_INT64:
131
+ case NANOARROW_TYPE_DOUBLE:
132
+ case NANOARROW_TYPE_INTERVAL_DAY_TIME:
133
+ layout->element_size_bits[1] = 64;
134
+ break;
135
+
136
+ case NANOARROW_TYPE_DECIMAL128:
137
+ case NANOARROW_TYPE_INTERVAL_MONTH_DAY_NANO:
138
+ layout->element_size_bits[1] = 128;
139
+ break;
140
+
141
+ case NANOARROW_TYPE_DECIMAL256:
142
+ layout->element_size_bits[1] = 256;
143
+ break;
144
+
145
+ case NANOARROW_TYPE_FIXED_SIZE_BINARY:
146
+ layout->buffer_data_type[1] = NANOARROW_TYPE_BINARY;
147
+ break;
148
+
149
+ case NANOARROW_TYPE_DENSE_UNION:
150
+ layout->buffer_type[0] = NANOARROW_BUFFER_TYPE_TYPE_ID;
151
+ layout->buffer_data_type[0] = NANOARROW_TYPE_INT8;
152
+ layout->element_size_bits[0] = 8;
153
+ layout->buffer_type[1] = NANOARROW_BUFFER_TYPE_UNION_OFFSET;
154
+ layout->buffer_data_type[1] = NANOARROW_TYPE_INT32;
155
+ layout->element_size_bits[1] = 32;
156
+ break;
157
+
158
+ case NANOARROW_TYPE_SPARSE_UNION:
159
+ layout->buffer_type[0] = NANOARROW_BUFFER_TYPE_TYPE_ID;
160
+ layout->buffer_data_type[0] = NANOARROW_TYPE_INT8;
161
+ layout->element_size_bits[0] = 8;
162
+ layout->buffer_type[1] = NANOARROW_BUFFER_TYPE_NONE;
163
+ layout->buffer_data_type[1] = NANOARROW_TYPE_UNINITIALIZED;
164
+ break;
165
+
166
+ case NANOARROW_TYPE_STRING:
167
+ case NANOARROW_TYPE_BINARY:
168
+ layout->buffer_type[1] = NANOARROW_BUFFER_TYPE_DATA_OFFSET;
169
+ layout->buffer_data_type[1] = NANOARROW_TYPE_INT32;
170
+ layout->element_size_bits[1] = 32;
171
+ layout->buffer_type[2] = NANOARROW_BUFFER_TYPE_DATA;
172
+ layout->buffer_data_type[2] = storage_type;
173
+ break;
174
+
175
+ case NANOARROW_TYPE_LARGE_STRING:
176
+ layout->buffer_type[1] = NANOARROW_BUFFER_TYPE_DATA_OFFSET;
177
+ layout->buffer_data_type[1] = NANOARROW_TYPE_INT64;
178
+ layout->element_size_bits[1] = 64;
179
+ layout->buffer_type[2] = NANOARROW_BUFFER_TYPE_DATA;
180
+ layout->buffer_data_type[2] = NANOARROW_TYPE_STRING;
181
+ break;
182
+ case NANOARROW_TYPE_LARGE_BINARY:
183
+ layout->buffer_type[1] = NANOARROW_BUFFER_TYPE_DATA_OFFSET;
184
+ layout->buffer_data_type[1] = NANOARROW_TYPE_INT64;
185
+ layout->element_size_bits[1] = 64;
186
+ layout->buffer_type[2] = NANOARROW_BUFFER_TYPE_DATA;
187
+ layout->buffer_data_type[2] = NANOARROW_TYPE_BINARY;
188
+ break;
189
+
190
+ default:
191
+ break;
192
+ }
193
+ }
194
+
195
+ void* ArrowMalloc(int64_t size) { return malloc(size); }
196
+
197
+ void* ArrowRealloc(void* ptr, int64_t size) { return realloc(ptr, size); }
198
+
199
+ void ArrowFree(void* ptr) { free(ptr); }
200
+
201
+ static uint8_t* ArrowBufferAllocatorMallocReallocate(
202
+ struct ArrowBufferAllocator* allocator, uint8_t* ptr, int64_t old_size,
203
+ int64_t new_size) {
204
+ return (uint8_t*)ArrowRealloc(ptr, new_size);
205
+ }
206
+
207
+ static void ArrowBufferAllocatorMallocFree(
208
+ struct ArrowBufferAllocator* allocator, uint8_t* ptr, int64_t size) {
209
+ ArrowFree(ptr);
210
+ }
211
+
212
+ static struct ArrowBufferAllocator ArrowBufferAllocatorMalloc = {
213
+ &ArrowBufferAllocatorMallocReallocate, &ArrowBufferAllocatorMallocFree,
214
+ NULL};
215
+
216
+ struct ArrowBufferAllocator ArrowBufferAllocatorDefault(void) {
217
+ return ArrowBufferAllocatorMalloc;
218
+ }
219
+
220
+ static uint8_t* ArrowBufferAllocatorNeverReallocate(
221
+ struct ArrowBufferAllocator* allocator, uint8_t* ptr, int64_t old_size,
222
+ int64_t new_size) {
223
+ return NULL;
224
+ }
225
+
226
+ struct ArrowBufferAllocator ArrowBufferDeallocator(
227
+ void (*custom_free)(struct ArrowBufferAllocator* allocator, uint8_t* ptr,
228
+ int64_t size),
229
+ void* private_data) {
230
+ struct ArrowBufferAllocator allocator;
231
+ allocator.reallocate = &ArrowBufferAllocatorNeverReallocate;
232
+ allocator.free = custom_free;
233
+ allocator.private_data = private_data;
234
+ return allocator;
235
+ }
236
+ // Licensed to the Apache Software Foundation (ASF) under one
237
+ // or more contributor license agreements. See the NOTICE file
238
+ // distributed with this work for additional information
239
+ // regarding copyright ownership. The ASF licenses this file
240
+ // to you under the Apache License, Version 2.0 (the
241
+ // "License"); you may not use this file except in compliance
242
+ // with the License. You may obtain a copy of the License at
243
+ //
244
+ // http://www.apache.org/licenses/LICENSE-2.0
245
+ //
246
+ // Unless required by applicable law or agreed to in writing,
247
+ // software distributed under the License is distributed on an
248
+ // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
249
+ // KIND, either express or implied. See the License for the
250
+ // specific language governing permissions and limitations
251
+ // under the License.
252
+
253
+ #include <errno.h>
254
+ #include <stdio.h>
255
+ #include <stdlib.h>
256
+ #include <string.h>
257
+
258
+ #include "nanoarrow.h"
259
+
260
+ static void ArrowSchemaRelease(struct ArrowSchema* schema) {
261
+ if (schema->format != NULL) ArrowFree((void*)schema->format);
262
+ if (schema->name != NULL) ArrowFree((void*)schema->name);
263
+ if (schema->metadata != NULL) ArrowFree((void*)schema->metadata);
264
+
265
+ // This object owns the memory for all the children, but those
266
+ // children may have been generated elsewhere and might have
267
+ // their own release() callback.
268
+ if (schema->children != NULL) {
269
+ for (int64_t i = 0; i < schema->n_children; i++) {
270
+ if (schema->children[i] != NULL) {
271
+ if (schema->children[i]->release != NULL) {
272
+ schema->children[i]->release(schema->children[i]);
273
+ }
274
+
275
+ ArrowFree(schema->children[i]);
276
+ }
277
+ }
278
+
279
+ ArrowFree(schema->children);
280
+ }
281
+
282
+ // This object owns the memory for the dictionary but it
283
+ // may have been generated somewhere else and have its own
284
+ // release() callback.
285
+ if (schema->dictionary != NULL) {
286
+ if (schema->dictionary->release != NULL) {
287
+ schema->dictionary->release(schema->dictionary);
288
+ }
289
+
290
+ ArrowFree(schema->dictionary);
291
+ }
292
+
293
+ // private data not currently used
294
+ if (schema->private_data != NULL) {
295
+ ArrowFree(schema->private_data);
296
+ }
297
+
298
+ schema->release = NULL;
299
+ }
300
+
301
+ static const char* ArrowSchemaFormatTemplate(enum ArrowType type) {
302
+ switch (type) {
303
+ case NANOARROW_TYPE_UNINITIALIZED:
304
+ return NULL;
305
+ case NANOARROW_TYPE_NA:
306
+ return "n";
307
+ case NANOARROW_TYPE_BOOL:
308
+ return "b";
309
+
310
+ case NANOARROW_TYPE_UINT8:
311
+ return "C";
312
+ case NANOARROW_TYPE_INT8:
313
+ return "c";
314
+ case NANOARROW_TYPE_UINT16:
315
+ return "S";
316
+ case NANOARROW_TYPE_INT16:
317
+ return "s";
318
+ case NANOARROW_TYPE_UINT32:
319
+ return "I";
320
+ case NANOARROW_TYPE_INT32:
321
+ return "i";
322
+ case NANOARROW_TYPE_UINT64:
323
+ return "L";
324
+ case NANOARROW_TYPE_INT64:
325
+ return "l";
326
+
327
+ case NANOARROW_TYPE_HALF_FLOAT:
328
+ return "e";
329
+ case NANOARROW_TYPE_FLOAT:
330
+ return "f";
331
+ case NANOARROW_TYPE_DOUBLE:
332
+ return "g";
333
+
334
+ case NANOARROW_TYPE_STRING:
335
+ return "u";
336
+ case NANOARROW_TYPE_LARGE_STRING:
337
+ return "U";
338
+ case NANOARROW_TYPE_BINARY:
339
+ return "z";
340
+ case NANOARROW_TYPE_LARGE_BINARY:
341
+ return "Z";
342
+
343
+ case NANOARROW_TYPE_DATE32:
344
+ return "tdD";
345
+ case NANOARROW_TYPE_DATE64:
346
+ return "tdm";
347
+ case NANOARROW_TYPE_INTERVAL_MONTHS:
348
+ return "tiM";
349
+ case NANOARROW_TYPE_INTERVAL_DAY_TIME:
350
+ return "tiD";
351
+ case NANOARROW_TYPE_INTERVAL_MONTH_DAY_NANO:
352
+ return "tin";
353
+
354
+ case NANOARROW_TYPE_LIST:
355
+ return "+l";
356
+ case NANOARROW_TYPE_LARGE_LIST:
357
+ return "+L";
358
+ case NANOARROW_TYPE_STRUCT:
359
+ return "+s";
360
+ case NANOARROW_TYPE_MAP:
361
+ return "+m";
362
+
363
+ default:
364
+ return NULL;
365
+ }
366
+ }
367
+
368
+ static int ArrowSchemaInitChildrenIfNeeded(struct ArrowSchema* schema,
369
+ enum ArrowType type) {
370
+ switch (type) {
371
+ case NANOARROW_TYPE_LIST:
372
+ case NANOARROW_TYPE_LARGE_LIST:
373
+ case NANOARROW_TYPE_FIXED_SIZE_LIST:
374
+ NANOARROW_RETURN_NOT_OK(ArrowSchemaAllocateChildren(schema, 1));
375
+ ArrowSchemaInit(schema->children[0]);
376
+ NANOARROW_RETURN_NOT_OK(ArrowSchemaSetName(schema->children[0], "item"));
377
+ break;
378
+ case NANOARROW_TYPE_MAP:
379
+ NANOARROW_RETURN_NOT_OK(ArrowSchemaAllocateChildren(schema, 1));
380
+ NANOARROW_RETURN_NOT_OK(
381
+ ArrowSchemaInitFromType(schema->children[0], NANOARROW_TYPE_STRUCT));
382
+ NANOARROW_RETURN_NOT_OK(
383
+ ArrowSchemaSetName(schema->children[0], "entries"));
384
+ schema->children[0]->flags &= ~ARROW_FLAG_NULLABLE;
385
+ NANOARROW_RETURN_NOT_OK(
386
+ ArrowSchemaAllocateChildren(schema->children[0], 2));
387
+ ArrowSchemaInit(schema->children[0]->children[0]);
388
+ ArrowSchemaInit(schema->children[0]->children[1]);
389
+ NANOARROW_RETURN_NOT_OK(
390
+ ArrowSchemaSetName(schema->children[0]->children[0], "key"));
391
+ schema->children[0]->children[0]->flags &= ~ARROW_FLAG_NULLABLE;
392
+ NANOARROW_RETURN_NOT_OK(
393
+ ArrowSchemaSetName(schema->children[0]->children[1], "value"));
394
+ break;
395
+ default:
396
+ break;
397
+ }
398
+
399
+ return NANOARROW_OK;
400
+ }
401
+
402
+ void ArrowSchemaInit(struct ArrowSchema* schema) {
403
+ schema->format = NULL;
404
+ schema->name = NULL;
405
+ schema->metadata = NULL;
406
+ schema->flags = ARROW_FLAG_NULLABLE;
407
+ schema->n_children = 0;
408
+ schema->children = NULL;
409
+ schema->dictionary = NULL;
410
+ schema->private_data = NULL;
411
+ schema->release = &ArrowSchemaRelease;
412
+ }
413
+
414
+ ArrowErrorCode ArrowSchemaSetType(struct ArrowSchema* schema,
415
+ enum ArrowType type) {
416
+ // We don't allocate the dictionary because it has to be nullptr
417
+ // for non-dictionary-encoded arrays.
418
+
419
+ // Set the format to a valid format string for type
420
+ const char* template_format = ArrowSchemaFormatTemplate(type);
421
+
422
+ // If type isn't recognized and not explicitly unset
423
+ if (template_format == NULL && type != NANOARROW_TYPE_UNINITIALIZED) {
424
+ return EINVAL;
425
+ }
426
+
427
+ NANOARROW_RETURN_NOT_OK(ArrowSchemaSetFormat(schema, template_format));
428
+
429
+ // For types with an umabiguous child structure, allocate children
430
+ return ArrowSchemaInitChildrenIfNeeded(schema, type);
431
+ }
432
+
433
+ ArrowErrorCode ArrowSchemaSetTypeStruct(struct ArrowSchema* schema,
434
+ int64_t n_children) {
435
+ NANOARROW_RETURN_NOT_OK(ArrowSchemaSetType(schema, NANOARROW_TYPE_STRUCT));
436
+ NANOARROW_RETURN_NOT_OK(ArrowSchemaAllocateChildren(schema, n_children));
437
+ for (int64_t i = 0; i < n_children; i++) {
438
+ ArrowSchemaInit(schema->children[i]);
439
+ }
440
+
441
+ return NANOARROW_OK;
442
+ }
443
+
444
+ ArrowErrorCode ArrowSchemaInitFromType(struct ArrowSchema* schema,
445
+ enum ArrowType type) {
446
+ ArrowSchemaInit(schema);
447
+
448
+ int result = ArrowSchemaSetType(schema, type);
449
+ if (result != NANOARROW_OK) {
450
+ schema->release(schema);
451
+ return result;
452
+ }
453
+
454
+ return NANOARROW_OK;
455
+ }
456
+
457
+ ArrowErrorCode ArrowSchemaSetTypeFixedSize(struct ArrowSchema* schema,
458
+ enum ArrowType type,
459
+ int32_t fixed_size) {
460
+ if (fixed_size <= 0) {
461
+ return EINVAL;
462
+ }
463
+
464
+ char buffer[64];
465
+ int n_chars;
466
+ switch (type) {
467
+ case NANOARROW_TYPE_FIXED_SIZE_BINARY:
468
+ n_chars = snprintf(buffer, sizeof(buffer), "w:%d", (int)fixed_size);
469
+ break;
470
+ case NANOARROW_TYPE_FIXED_SIZE_LIST:
471
+ n_chars = snprintf(buffer, sizeof(buffer), "+w:%d", (int)fixed_size);
472
+ break;
473
+ default:
474
+ return EINVAL;
475
+ }
476
+
477
+ buffer[n_chars] = '\0';
478
+ NANOARROW_RETURN_NOT_OK(ArrowSchemaSetFormat(schema, buffer));
479
+
480
+ if (type == NANOARROW_TYPE_FIXED_SIZE_LIST) {
481
+ NANOARROW_RETURN_NOT_OK(ArrowSchemaInitChildrenIfNeeded(schema, type));
482
+ }
483
+
484
+ return NANOARROW_OK;
485
+ }
486
+
487
+ ArrowErrorCode ArrowSchemaSetTypeDecimal(struct ArrowSchema* schema,
488
+ enum ArrowType type,
489
+ int32_t decimal_precision,
490
+ int32_t decimal_scale) {
491
+ if (decimal_precision <= 0) {
492
+ return EINVAL;
493
+ }
494
+
495
+ char buffer[64];
496
+ int n_chars;
497
+ switch (type) {
498
+ case NANOARROW_TYPE_DECIMAL128:
499
+ n_chars = snprintf(buffer, sizeof(buffer), "d:%d,%d", decimal_precision,
500
+ decimal_scale);
501
+ break;
502
+ case NANOARROW_TYPE_DECIMAL256:
503
+ n_chars = snprintf(buffer, sizeof(buffer), "d:%d,%d,256",
504
+ decimal_precision, decimal_scale);
505
+ break;
506
+ default:
507
+ return EINVAL;
508
+ }
509
+
510
+ buffer[n_chars] = '\0';
511
+ return ArrowSchemaSetFormat(schema, buffer);
512
+ }
513
+
514
+ static const char* ArrowTimeUnitFormatString(enum ArrowTimeUnit time_unit) {
515
+ switch (time_unit) {
516
+ case NANOARROW_TIME_UNIT_SECOND:
517
+ return "s";
518
+ case NANOARROW_TIME_UNIT_MILLI:
519
+ return "m";
520
+ case NANOARROW_TIME_UNIT_MICRO:
521
+ return "u";
522
+ case NANOARROW_TIME_UNIT_NANO:
523
+ return "n";
524
+ default:
525
+ return NULL;
526
+ }
527
+ }
528
+
529
+ ArrowErrorCode ArrowSchemaSetTypeDateTime(struct ArrowSchema* schema,
530
+ enum ArrowType type,
531
+ enum ArrowTimeUnit time_unit,
532
+ const char* timezone) {
533
+ const char* time_unit_str = ArrowTimeUnitFormatString(time_unit);
534
+ if (time_unit_str == NULL) {
535
+ return EINVAL;
536
+ }
537
+
538
+ char buffer[128];
539
+ int n_chars;
540
+ switch (type) {
541
+ case NANOARROW_TYPE_TIME32:
542
+ case NANOARROW_TYPE_TIME64:
543
+ if (timezone != NULL) {
544
+ return EINVAL;
545
+ }
546
+ n_chars = snprintf(buffer, sizeof(buffer), "tt%s", time_unit_str);
547
+ break;
548
+ case NANOARROW_TYPE_TIMESTAMP:
549
+ if (timezone == NULL) {
550
+ timezone = "";
551
+ }
552
+ n_chars =
553
+ snprintf(buffer, sizeof(buffer), "ts%s:%s", time_unit_str, timezone);
554
+ break;
555
+ case NANOARROW_TYPE_DURATION:
556
+ if (timezone != NULL) {
557
+ return EINVAL;
558
+ }
559
+ n_chars = snprintf(buffer, sizeof(buffer), "tD%s", time_unit_str);
560
+ break;
561
+ default:
562
+ return EINVAL;
563
+ }
564
+
565
+ if (((size_t)n_chars) >= sizeof(buffer)) {
566
+ return ERANGE;
567
+ }
568
+
569
+ buffer[n_chars] = '\0';
570
+
571
+ return ArrowSchemaSetFormat(schema, buffer);
572
+ }
573
+
574
+ ArrowErrorCode ArrowSchemaSetTypeUnion(struct ArrowSchema* schema,
575
+ enum ArrowType type,
576
+ int64_t n_children) {
577
+ if (n_children < 0 || n_children > 127) {
578
+ return EINVAL;
579
+ }
580
+
581
+ // Max valid size would be +ud:0,1,...126 = 401 characters + null terminator
582
+ char format_out[512];
583
+ int64_t format_out_size = 512;
584
+ memset(format_out, 0, format_out_size);
585
+ int n_chars;
586
+ char* format_cursor = format_out;
587
+
588
+ switch (type) {
589
+ case NANOARROW_TYPE_SPARSE_UNION:
590
+ n_chars = snprintf(format_cursor, format_out_size, "+us:");
591
+ format_cursor += n_chars;
592
+ format_out_size -= n_chars;
593
+ break;
594
+ case NANOARROW_TYPE_DENSE_UNION:
595
+ n_chars = snprintf(format_cursor, format_out_size, "+ud:");
596
+ format_cursor += n_chars;
597
+ format_out_size -= n_chars;
598
+ break;
599
+ default:
600
+ return EINVAL;
601
+ }
602
+
603
+ if (n_children > 0) {
604
+ n_chars = snprintf(format_cursor, format_out_size, "0");
605
+ format_cursor += n_chars;
606
+ format_out_size -= n_chars;
607
+
608
+ for (int64_t i = 1; i < n_children; i++) {
609
+ n_chars = snprintf(format_cursor, format_out_size, ",%d", (int)i);
610
+ format_cursor += n_chars;
611
+ format_out_size -= n_chars;
612
+ }
613
+ }
614
+
615
+ NANOARROW_RETURN_NOT_OK(ArrowSchemaSetFormat(schema, format_out));
616
+
617
+ NANOARROW_RETURN_NOT_OK(ArrowSchemaAllocateChildren(schema, n_children));
618
+ for (int64_t i = 0; i < n_children; i++) {
619
+ ArrowSchemaInit(schema->children[i]);
620
+ }
621
+
622
+ return NANOARROW_OK;
623
+ }
624
+
625
+ ArrowErrorCode ArrowSchemaSetFormat(struct ArrowSchema* schema,
626
+ const char* format) {
627
+ if (schema->format != NULL) {
628
+ ArrowFree((void*)schema->format);
629
+ }
630
+
631
+ if (format != NULL) {
632
+ size_t format_size = strlen(format) + 1;
633
+ schema->format = (const char*)ArrowMalloc(format_size);
634
+ if (schema->format == NULL) {
635
+ return ENOMEM;
636
+ }
637
+
638
+ memcpy((void*)schema->format, format, format_size);
639
+ } else {
640
+ schema->format = NULL;
641
+ }
642
+
643
+ return NANOARROW_OK;
644
+ }
645
+
646
+ ArrowErrorCode ArrowSchemaSetName(struct ArrowSchema* schema,
647
+ const char* name) {
648
+ if (schema->name != NULL) {
649
+ ArrowFree((void*)schema->name);
650
+ }
651
+
652
+ if (name != NULL) {
653
+ size_t name_size = strlen(name) + 1;
654
+ schema->name = (const char*)ArrowMalloc(name_size);
655
+ if (schema->name == NULL) {
656
+ return ENOMEM;
657
+ }
658
+
659
+ memcpy((void*)schema->name, name, name_size);
660
+ } else {
661
+ schema->name = NULL;
662
+ }
663
+
664
+ return NANOARROW_OK;
665
+ }
666
+
667
+ ArrowErrorCode ArrowSchemaSetMetadata(struct ArrowSchema* schema,
668
+ const char* metadata) {
669
+ if (schema->metadata != NULL) {
670
+ ArrowFree((void*)schema->metadata);
671
+ }
672
+
673
+ if (metadata != NULL) {
674
+ size_t metadata_size = ArrowMetadataSizeOf(metadata);
675
+ schema->metadata = (const char*)ArrowMalloc(metadata_size);
676
+ if (schema->metadata == NULL) {
677
+ return ENOMEM;
678
+ }
679
+
680
+ memcpy((void*)schema->metadata, metadata, metadata_size);
681
+ } else {
682
+ schema->metadata = NULL;
683
+ }
684
+
685
+ return NANOARROW_OK;
686
+ }
687
+
688
+ ArrowErrorCode ArrowSchemaAllocateChildren(struct ArrowSchema* schema,
689
+ int64_t n_children) {
690
+ if (schema->children != NULL) {
691
+ return EEXIST;
692
+ }
693
+
694
+ if (n_children > 0) {
695
+ schema->children = (struct ArrowSchema**)ArrowMalloc(
696
+ n_children * sizeof(struct ArrowSchema*));
697
+
698
+ if (schema->children == NULL) {
699
+ return ENOMEM;
700
+ }
701
+
702
+ schema->n_children = n_children;
703
+
704
+ memset(schema->children, 0, n_children * sizeof(struct ArrowSchema*));
705
+
706
+ for (int64_t i = 0; i < n_children; i++) {
707
+ schema->children[i] =
708
+ (struct ArrowSchema*)ArrowMalloc(sizeof(struct ArrowSchema));
709
+
710
+ if (schema->children[i] == NULL) {
711
+ return ENOMEM;
712
+ }
713
+
714
+ schema->children[i]->release = NULL;
715
+ }
716
+ }
717
+
718
+ return NANOARROW_OK;
719
+ }
720
+
721
+ ArrowErrorCode ArrowSchemaAllocateDictionary(struct ArrowSchema* schema) {
722
+ if (schema->dictionary != NULL) {
723
+ return EEXIST;
724
+ }
725
+
726
+ schema->dictionary =
727
+ (struct ArrowSchema*)ArrowMalloc(sizeof(struct ArrowSchema));
728
+ if (schema->dictionary == NULL) {
729
+ return ENOMEM;
730
+ }
731
+
732
+ schema->dictionary->release = NULL;
733
+ return NANOARROW_OK;
734
+ }
735
+
736
+ ArrowErrorCode ArrowSchemaDeepCopy(struct ArrowSchema* schema,
737
+ struct ArrowSchema* schema_out) {
738
+ ArrowSchemaInit(schema_out);
739
+
740
+ int result = ArrowSchemaSetFormat(schema_out, schema->format);
741
+ if (result != NANOARROW_OK) {
742
+ schema_out->release(schema_out);
743
+ return result;
744
+ }
745
+
746
+ schema_out->flags = schema->flags;
747
+
748
+ result = ArrowSchemaSetName(schema_out, schema->name);
749
+ if (result != NANOARROW_OK) {
750
+ schema_out->release(schema_out);
751
+ return result;
752
+ }
753
+
754
+ result = ArrowSchemaSetMetadata(schema_out, schema->metadata);
755
+ if (result != NANOARROW_OK) {
756
+ schema_out->release(schema_out);
757
+ return result;
758
+ }
759
+
760
+ result = ArrowSchemaAllocateChildren(schema_out, schema->n_children);
761
+ if (result != NANOARROW_OK) {
762
+ schema_out->release(schema_out);
763
+ return result;
764
+ }
765
+
766
+ for (int64_t i = 0; i < schema->n_children; i++) {
767
+ result = ArrowSchemaDeepCopy(schema->children[i], schema_out->children[i]);
768
+ if (result != NANOARROW_OK) {
769
+ schema_out->release(schema_out);
770
+ return result;
771
+ }
772
+ }
773
+
774
+ if (schema->dictionary != NULL) {
775
+ result = ArrowSchemaAllocateDictionary(schema_out);
776
+ if (result != NANOARROW_OK) {
777
+ schema_out->release(schema_out);
778
+ return result;
779
+ }
780
+
781
+ result = ArrowSchemaDeepCopy(schema->dictionary, schema_out->dictionary);
782
+ if (result != NANOARROW_OK) {
783
+ schema_out->release(schema_out);
784
+ return result;
785
+ }
786
+ }
787
+
788
+ return NANOARROW_OK;
789
+ }
790
+
791
+ static void ArrowSchemaViewSetPrimitive(struct ArrowSchemaView* schema_view,
792
+ enum ArrowType type) {
793
+ schema_view->type = type;
794
+ schema_view->storage_type = type;
795
+ }
796
+
797
+ static ArrowErrorCode ArrowSchemaViewParse(struct ArrowSchemaView* schema_view,
798
+ const char* format,
799
+ const char** format_end_out,
800
+ struct ArrowError* error) {
801
+ *format_end_out = format;
802
+
803
+ // needed for decimal parsing
804
+ const char* parse_start;
805
+ char* parse_end;
806
+
807
+ switch (format[0]) {
808
+ case 'n':
809
+ schema_view->type = NANOARROW_TYPE_NA;
810
+ schema_view->storage_type = NANOARROW_TYPE_NA;
811
+ *format_end_out = format + 1;
812
+ return NANOARROW_OK;
813
+ case 'b':
814
+ ArrowSchemaViewSetPrimitive(schema_view, NANOARROW_TYPE_BOOL);
815
+ *format_end_out = format + 1;
816
+ return NANOARROW_OK;
817
+ case 'c':
818
+ ArrowSchemaViewSetPrimitive(schema_view, NANOARROW_TYPE_INT8);
819
+ *format_end_out = format + 1;
820
+ return NANOARROW_OK;
821
+ case 'C':
822
+ ArrowSchemaViewSetPrimitive(schema_view, NANOARROW_TYPE_UINT8);
823
+ *format_end_out = format + 1;
824
+ return NANOARROW_OK;
825
+ case 's':
826
+ ArrowSchemaViewSetPrimitive(schema_view, NANOARROW_TYPE_INT16);
827
+ *format_end_out = format + 1;
828
+ return NANOARROW_OK;
829
+ case 'S':
830
+ ArrowSchemaViewSetPrimitive(schema_view, NANOARROW_TYPE_UINT16);
831
+ *format_end_out = format + 1;
832
+ return NANOARROW_OK;
833
+ case 'i':
834
+ ArrowSchemaViewSetPrimitive(schema_view, NANOARROW_TYPE_INT32);
835
+ *format_end_out = format + 1;
836
+ return NANOARROW_OK;
837
+ case 'I':
838
+ ArrowSchemaViewSetPrimitive(schema_view, NANOARROW_TYPE_UINT32);
839
+ *format_end_out = format + 1;
840
+ return NANOARROW_OK;
841
+ case 'l':
842
+ ArrowSchemaViewSetPrimitive(schema_view, NANOARROW_TYPE_INT64);
843
+ *format_end_out = format + 1;
844
+ return NANOARROW_OK;
845
+ case 'L':
846
+ ArrowSchemaViewSetPrimitive(schema_view, NANOARROW_TYPE_UINT64);
847
+ *format_end_out = format + 1;
848
+ return NANOARROW_OK;
849
+ case 'e':
850
+ ArrowSchemaViewSetPrimitive(schema_view, NANOARROW_TYPE_HALF_FLOAT);
851
+ *format_end_out = format + 1;
852
+ return NANOARROW_OK;
853
+ case 'f':
854
+ ArrowSchemaViewSetPrimitive(schema_view, NANOARROW_TYPE_FLOAT);
855
+ *format_end_out = format + 1;
856
+ return NANOARROW_OK;
857
+ case 'g':
858
+ ArrowSchemaViewSetPrimitive(schema_view, NANOARROW_TYPE_DOUBLE);
859
+ *format_end_out = format + 1;
860
+ return NANOARROW_OK;
861
+
862
+ // decimal
863
+ case 'd':
864
+ if (format[1] != ':' || format[2] == '\0') {
865
+ ArrowErrorSet(error,
866
+ "Expected ':precision,scale[,bitwidth]' following 'd'",
867
+ format + 3);
868
+ return EINVAL;
869
+ }
870
+
871
+ parse_start = format + 2;
872
+ schema_view->decimal_precision =
873
+ (int32_t)strtol(parse_start, &parse_end, 10);
874
+ if (parse_end == parse_start || parse_end[0] != ',') {
875
+ ArrowErrorSet(error,
876
+ "Expected 'precision,scale[,bitwidth]' following 'd:'");
877
+ return EINVAL;
878
+ }
879
+
880
+ parse_start = parse_end + 1;
881
+ schema_view->decimal_scale = (int32_t)strtol(parse_start, &parse_end, 10);
882
+ if (parse_end == parse_start) {
883
+ ArrowErrorSet(error,
884
+ "Expected 'scale[,bitwidth]' following 'd:precision,'");
885
+ return EINVAL;
886
+ } else if (parse_end[0] != ',') {
887
+ schema_view->decimal_bitwidth = 128;
888
+ } else {
889
+ parse_start = parse_end + 1;
890
+ schema_view->decimal_bitwidth =
891
+ (int32_t)strtol(parse_start, &parse_end, 10);
892
+ if (parse_start == parse_end) {
893
+ ArrowErrorSet(error,
894
+ "Expected precision following 'd:precision,scale,'");
895
+ return EINVAL;
896
+ }
897
+ }
898
+
899
+ *format_end_out = parse_end;
900
+
901
+ switch (schema_view->decimal_bitwidth) {
902
+ case 128:
903
+ ArrowSchemaViewSetPrimitive(schema_view, NANOARROW_TYPE_DECIMAL128);
904
+ return NANOARROW_OK;
905
+ case 256:
906
+ ArrowSchemaViewSetPrimitive(schema_view, NANOARROW_TYPE_DECIMAL256);
907
+ return NANOARROW_OK;
908
+ default:
909
+ ArrowErrorSet(error,
910
+ "Expected decimal bitwidth of 128 or 256 but found %d",
911
+ (int)schema_view->decimal_bitwidth);
912
+ return EINVAL;
913
+ }
914
+
915
+ // validity + data
916
+ case 'w':
917
+ schema_view->type = NANOARROW_TYPE_FIXED_SIZE_BINARY;
918
+ schema_view->storage_type = NANOARROW_TYPE_FIXED_SIZE_BINARY;
919
+ if (format[1] != ':' || format[2] == '\0') {
920
+ ArrowErrorSet(error, "Expected ':<width>' following 'w'");
921
+ return EINVAL;
922
+ }
923
+
924
+ schema_view->fixed_size =
925
+ (int32_t)strtol(format + 2, (char**)format_end_out, 10);
926
+ return NANOARROW_OK;
927
+
928
+ // validity + offset + data
929
+ case 'z':
930
+ schema_view->type = NANOARROW_TYPE_BINARY;
931
+ schema_view->storage_type = NANOARROW_TYPE_BINARY;
932
+ *format_end_out = format + 1;
933
+ return NANOARROW_OK;
934
+ case 'u':
935
+ schema_view->type = NANOARROW_TYPE_STRING;
936
+ schema_view->storage_type = NANOARROW_TYPE_STRING;
937
+ *format_end_out = format + 1;
938
+ return NANOARROW_OK;
939
+
940
+ // validity + large_offset + data
941
+ case 'Z':
942
+ schema_view->type = NANOARROW_TYPE_LARGE_BINARY;
943
+ schema_view->storage_type = NANOARROW_TYPE_LARGE_BINARY;
944
+ *format_end_out = format + 1;
945
+ return NANOARROW_OK;
946
+ case 'U':
947
+ schema_view->type = NANOARROW_TYPE_LARGE_STRING;
948
+ schema_view->storage_type = NANOARROW_TYPE_LARGE_STRING;
949
+ *format_end_out = format + 1;
950
+ return NANOARROW_OK;
951
+
952
+ // nested types
953
+ case '+':
954
+ switch (format[1]) {
955
+ // list has validity + offset or offset
956
+ case 'l':
957
+ schema_view->storage_type = NANOARROW_TYPE_LIST;
958
+ schema_view->type = NANOARROW_TYPE_LIST;
959
+ *format_end_out = format + 2;
960
+ return NANOARROW_OK;
961
+
962
+ // large list has validity + large_offset or large_offset
963
+ case 'L':
964
+ schema_view->storage_type = NANOARROW_TYPE_LARGE_LIST;
965
+ schema_view->type = NANOARROW_TYPE_LARGE_LIST;
966
+ *format_end_out = format + 2;
967
+ return NANOARROW_OK;
968
+
969
+ // just validity buffer
970
+ case 'w':
971
+ if (format[2] != ':' || format[3] == '\0') {
972
+ ArrowErrorSet(error, "Expected ':<width>' following '+w'");
973
+ return EINVAL;
974
+ }
975
+
976
+ schema_view->storage_type = NANOARROW_TYPE_FIXED_SIZE_LIST;
977
+ schema_view->type = NANOARROW_TYPE_FIXED_SIZE_LIST;
978
+ schema_view->fixed_size =
979
+ (int32_t)strtol(format + 3, (char**)format_end_out, 10);
980
+ return NANOARROW_OK;
981
+ case 's':
982
+ schema_view->storage_type = NANOARROW_TYPE_STRUCT;
983
+ schema_view->type = NANOARROW_TYPE_STRUCT;
984
+ *format_end_out = format + 2;
985
+ return NANOARROW_OK;
986
+ case 'm':
987
+ schema_view->storage_type = NANOARROW_TYPE_MAP;
988
+ schema_view->type = NANOARROW_TYPE_MAP;
989
+ *format_end_out = format + 2;
990
+ return NANOARROW_OK;
991
+
992
+ // unions
993
+ case 'u':
994
+ switch (format[2]) {
995
+ case 'd':
996
+ schema_view->storage_type = NANOARROW_TYPE_DENSE_UNION;
997
+ schema_view->type = NANOARROW_TYPE_DENSE_UNION;
998
+ break;
999
+ case 's':
1000
+ schema_view->storage_type = NANOARROW_TYPE_SPARSE_UNION;
1001
+ schema_view->type = NANOARROW_TYPE_SPARSE_UNION;
1002
+ break;
1003
+ default:
1004
+ ArrowErrorSet(error,
1005
+ "Expected union format string +us:<type_ids> or "
1006
+ "+ud:<type_ids> but found '%s'",
1007
+ format);
1008
+ return EINVAL;
1009
+ }
1010
+
1011
+ if (format[3] == ':') {
1012
+ schema_view->union_type_ids = format + 4;
1013
+ int64_t n_type_ids =
1014
+ _ArrowParseUnionTypeIds(schema_view->union_type_ids, NULL);
1015
+ if (n_type_ids != schema_view->schema->n_children) {
1016
+ ArrowErrorSet(error,
1017
+ "Expected union type_ids parameter to be a "
1018
+ "comma-separated list of %ld "
1019
+ "values between 0 and 127 but found '%s'",
1020
+ (long)schema_view->schema->n_children,
1021
+ schema_view->union_type_ids);
1022
+ return EINVAL;
1023
+ }
1024
+ *format_end_out = format + strlen(format);
1025
+ return NANOARROW_OK;
1026
+ } else {
1027
+ ArrowErrorSet(
1028
+ error,
1029
+ "Expected union format string +us:<type_ids> or +ud:<type_ids> "
1030
+ "but found '%s'",
1031
+ format);
1032
+ return EINVAL;
1033
+ }
1034
+
1035
+ default:
1036
+ ArrowErrorSet(error,
1037
+ "Expected nested type format string but found '%s'",
1038
+ format);
1039
+ return EINVAL;
1040
+ }
1041
+
1042
+ // date/time types
1043
+ case 't':
1044
+ switch (format[1]) {
1045
+ // date
1046
+ case 'd':
1047
+ switch (format[2]) {
1048
+ case 'D':
1049
+ ArrowSchemaViewSetPrimitive(schema_view, NANOARROW_TYPE_INT32);
1050
+ schema_view->type = NANOARROW_TYPE_DATE32;
1051
+ *format_end_out = format + 3;
1052
+ return NANOARROW_OK;
1053
+ case 'm':
1054
+ ArrowSchemaViewSetPrimitive(schema_view, NANOARROW_TYPE_INT64);
1055
+ schema_view->type = NANOARROW_TYPE_DATE64;
1056
+ *format_end_out = format + 3;
1057
+ return NANOARROW_OK;
1058
+ default:
1059
+ ArrowErrorSet(error,
1060
+ "Expected 'D' or 'm' following 'td' but found '%s'",
1061
+ format + 2);
1062
+ return EINVAL;
1063
+ }
1064
+
1065
+ // time of day
1066
+ case 't':
1067
+ switch (format[2]) {
1068
+ case 's':
1069
+ ArrowSchemaViewSetPrimitive(schema_view, NANOARROW_TYPE_INT32);
1070
+ schema_view->type = NANOARROW_TYPE_TIME32;
1071
+ schema_view->time_unit = NANOARROW_TIME_UNIT_SECOND;
1072
+ *format_end_out = format + 3;
1073
+ return NANOARROW_OK;
1074
+ case 'm':
1075
+ ArrowSchemaViewSetPrimitive(schema_view, NANOARROW_TYPE_INT32);
1076
+ schema_view->type = NANOARROW_TYPE_TIME32;
1077
+ schema_view->time_unit = NANOARROW_TIME_UNIT_MILLI;
1078
+ *format_end_out = format + 3;
1079
+ return NANOARROW_OK;
1080
+ case 'u':
1081
+ ArrowSchemaViewSetPrimitive(schema_view, NANOARROW_TYPE_INT64);
1082
+ schema_view->type = NANOARROW_TYPE_TIME64;
1083
+ schema_view->time_unit = NANOARROW_TIME_UNIT_MICRO;
1084
+ *format_end_out = format + 3;
1085
+ return NANOARROW_OK;
1086
+ case 'n':
1087
+ ArrowSchemaViewSetPrimitive(schema_view, NANOARROW_TYPE_INT64);
1088
+ schema_view->type = NANOARROW_TYPE_TIME64;
1089
+ schema_view->time_unit = NANOARROW_TIME_UNIT_NANO;
1090
+ *format_end_out = format + 3;
1091
+ return NANOARROW_OK;
1092
+ default:
1093
+ ArrowErrorSet(error,
1094
+ "Expected 's', 'm', 'u', or 'n' following 'tt' but "
1095
+ "found '%s'",
1096
+ format + 2);
1097
+ return EINVAL;
1098
+ }
1099
+
1100
+ // timestamp
1101
+ case 's':
1102
+ switch (format[2]) {
1103
+ case 's':
1104
+ ArrowSchemaViewSetPrimitive(schema_view, NANOARROW_TYPE_INT64);
1105
+ schema_view->type = NANOARROW_TYPE_TIMESTAMP;
1106
+ schema_view->time_unit = NANOARROW_TIME_UNIT_SECOND;
1107
+ break;
1108
+ case 'm':
1109
+ ArrowSchemaViewSetPrimitive(schema_view, NANOARROW_TYPE_INT64);
1110
+ schema_view->type = NANOARROW_TYPE_TIMESTAMP;
1111
+ schema_view->time_unit = NANOARROW_TIME_UNIT_MILLI;
1112
+ break;
1113
+ case 'u':
1114
+ ArrowSchemaViewSetPrimitive(schema_view, NANOARROW_TYPE_INT64);
1115
+ schema_view->type = NANOARROW_TYPE_TIMESTAMP;
1116
+ schema_view->time_unit = NANOARROW_TIME_UNIT_MICRO;
1117
+ break;
1118
+ case 'n':
1119
+ ArrowSchemaViewSetPrimitive(schema_view, NANOARROW_TYPE_INT64);
1120
+ schema_view->type = NANOARROW_TYPE_TIMESTAMP;
1121
+ schema_view->time_unit = NANOARROW_TIME_UNIT_NANO;
1122
+ break;
1123
+ default:
1124
+ ArrowErrorSet(error,
1125
+ "Expected 's', 'm', 'u', or 'n' following 'ts' but "
1126
+ "found '%s'",
1127
+ format + 2);
1128
+ return EINVAL;
1129
+ }
1130
+
1131
+ if (format[3] != ':') {
1132
+ ArrowErrorSet(error, "Expected ':' following '%.3s' but found '%s'",
1133
+ format, format + 3);
1134
+ return EINVAL;
1135
+ }
1136
+
1137
+ schema_view->timezone = format + 4;
1138
+ *format_end_out = format + strlen(format);
1139
+ return NANOARROW_OK;
1140
+
1141
+ // duration
1142
+ case 'D':
1143
+ switch (format[2]) {
1144
+ case 's':
1145
+ ArrowSchemaViewSetPrimitive(schema_view, NANOARROW_TYPE_INT64);
1146
+ schema_view->type = NANOARROW_TYPE_DURATION;
1147
+ schema_view->time_unit = NANOARROW_TIME_UNIT_SECOND;
1148
+ *format_end_out = format + 3;
1149
+ return NANOARROW_OK;
1150
+ case 'm':
1151
+ ArrowSchemaViewSetPrimitive(schema_view, NANOARROW_TYPE_INT64);
1152
+ schema_view->type = NANOARROW_TYPE_DURATION;
1153
+ schema_view->time_unit = NANOARROW_TIME_UNIT_MILLI;
1154
+ *format_end_out = format + 3;
1155
+ return NANOARROW_OK;
1156
+ case 'u':
1157
+ ArrowSchemaViewSetPrimitive(schema_view, NANOARROW_TYPE_INT64);
1158
+ schema_view->type = NANOARROW_TYPE_DURATION;
1159
+ schema_view->time_unit = NANOARROW_TIME_UNIT_MICRO;
1160
+ *format_end_out = format + 3;
1161
+ return NANOARROW_OK;
1162
+ case 'n':
1163
+ ArrowSchemaViewSetPrimitive(schema_view, NANOARROW_TYPE_INT64);
1164
+ schema_view->type = NANOARROW_TYPE_DURATION;
1165
+ schema_view->time_unit = NANOARROW_TIME_UNIT_NANO;
1166
+ *format_end_out = format + 3;
1167
+ return NANOARROW_OK;
1168
+ default:
1169
+ ArrowErrorSet(
1170
+ error,
1171
+ "Expected 's', 'm', u', or 'n' following 'tD' but found '%s'",
1172
+ format + 2);
1173
+ return EINVAL;
1174
+ }
1175
+
1176
+ // interval
1177
+ case 'i':
1178
+ switch (format[2]) {
1179
+ case 'M':
1180
+ ArrowSchemaViewSetPrimitive(schema_view,
1181
+ NANOARROW_TYPE_INTERVAL_MONTHS);
1182
+ *format_end_out = format + 3;
1183
+ return NANOARROW_OK;
1184
+ case 'D':
1185
+ ArrowSchemaViewSetPrimitive(schema_view,
1186
+ NANOARROW_TYPE_INTERVAL_DAY_TIME);
1187
+ *format_end_out = format + 3;
1188
+ return NANOARROW_OK;
1189
+ case 'n':
1190
+ ArrowSchemaViewSetPrimitive(
1191
+ schema_view, NANOARROW_TYPE_INTERVAL_MONTH_DAY_NANO);
1192
+ *format_end_out = format + 3;
1193
+ return NANOARROW_OK;
1194
+ default:
1195
+ ArrowErrorSet(
1196
+ error,
1197
+ "Expected 'M', 'D', or 'n' following 'ti' but found '%s'",
1198
+ format + 2);
1199
+ return EINVAL;
1200
+ }
1201
+
1202
+ default:
1203
+ ArrowErrorSet(error,
1204
+ "Expected 'd', 't', 's', 'D', or 'i' following 't' but "
1205
+ "found '%s'",
1206
+ format + 1);
1207
+ return EINVAL;
1208
+ }
1209
+
1210
+ default:
1211
+ ArrowErrorSet(error, "Unknown format: '%s'", format);
1212
+ return EINVAL;
1213
+ }
1214
+ }
1215
+
1216
+ static ArrowErrorCode ArrowSchemaViewValidateNChildren(
1217
+ struct ArrowSchemaView* schema_view, int64_t n_children,
1218
+ struct ArrowError* error) {
1219
+ if (n_children != -1 && schema_view->schema->n_children != n_children) {
1220
+ ArrowErrorSet(error,
1221
+ "Expected schema with %d children but found %d children",
1222
+ (int)n_children, (int)schema_view->schema->n_children);
1223
+ return EINVAL;
1224
+ }
1225
+
1226
+ // Don't do a full validation of children but do check that they won't
1227
+ // segfault if inspected
1228
+ struct ArrowSchema* child;
1229
+ for (int64_t i = 0; i < schema_view->schema->n_children; i++) {
1230
+ child = schema_view->schema->children[i];
1231
+ if (child == NULL) {
1232
+ ArrowErrorSet(
1233
+ error, "Expected valid schema at schema->children[%d] but found NULL",
1234
+ i);
1235
+ return EINVAL;
1236
+ } else if (child->release == NULL) {
1237
+ ArrowErrorSet(error,
1238
+ "Expected valid schema at schema->children[%d] but found a "
1239
+ "released schema",
1240
+ i);
1241
+ return EINVAL;
1242
+ }
1243
+ }
1244
+
1245
+ return NANOARROW_OK;
1246
+ }
1247
+
1248
+ static ArrowErrorCode ArrowSchemaViewValidateUnion(
1249
+ struct ArrowSchemaView* schema_view, struct ArrowError* error) {
1250
+ return ArrowSchemaViewValidateNChildren(schema_view, -1, error);
1251
+ }
1252
+
1253
+ static ArrowErrorCode ArrowSchemaViewValidateMap(
1254
+ struct ArrowSchemaView* schema_view, struct ArrowError* error) {
1255
+ NANOARROW_RETURN_NOT_OK(
1256
+ ArrowSchemaViewValidateNChildren(schema_view, 1, error));
1257
+
1258
+ if (schema_view->schema->children[0]->n_children != 2) {
1259
+ ArrowErrorSet(error,
1260
+ "Expected child of map type to have 2 children but found %d",
1261
+ (int)schema_view->schema->children[0]->n_children);
1262
+ return EINVAL;
1263
+ }
1264
+
1265
+ if (strcmp(schema_view->schema->children[0]->format, "+s") != 0) {
1266
+ ArrowErrorSet(
1267
+ error, "Expected format of child of map type to be '+s' but found '%s'",
1268
+ schema_view->schema->children[0]->format);
1269
+ return EINVAL;
1270
+ }
1271
+
1272
+ if (schema_view->schema->children[0]->flags & ARROW_FLAG_NULLABLE) {
1273
+ ArrowErrorSet(
1274
+ error,
1275
+ "Expected child of map type to be non-nullable but was nullable");
1276
+ return EINVAL;
1277
+ }
1278
+
1279
+ if (schema_view->schema->children[0]->children[0]->flags &
1280
+ ARROW_FLAG_NULLABLE) {
1281
+ ArrowErrorSet(
1282
+ error, "Expected key of map type to be non-nullable but was nullable");
1283
+ return EINVAL;
1284
+ }
1285
+
1286
+ return NANOARROW_OK;
1287
+ }
1288
+
1289
+ static ArrowErrorCode ArrowSchemaViewValidateDictionary(
1290
+ struct ArrowSchemaView* schema_view, struct ArrowError* error) {
1291
+ // check for valid index type
1292
+ switch (schema_view->storage_type) {
1293
+ case NANOARROW_TYPE_UINT8:
1294
+ case NANOARROW_TYPE_INT8:
1295
+ case NANOARROW_TYPE_UINT16:
1296
+ case NANOARROW_TYPE_INT16:
1297
+ case NANOARROW_TYPE_UINT32:
1298
+ case NANOARROW_TYPE_INT32:
1299
+ case NANOARROW_TYPE_UINT64:
1300
+ case NANOARROW_TYPE_INT64:
1301
+ break;
1302
+ default:
1303
+ ArrowErrorSet(error,
1304
+ "Expected dictionary schema index type to be an integral "
1305
+ "type but found '%s'",
1306
+ schema_view->schema->format);
1307
+ return EINVAL;
1308
+ }
1309
+
1310
+ struct ArrowSchemaView dictionary_schema_view;
1311
+ return ArrowSchemaViewInit(&dictionary_schema_view,
1312
+ schema_view->schema->dictionary, error);
1313
+ }
1314
+
1315
+ static ArrowErrorCode ArrowSchemaViewValidate(
1316
+ struct ArrowSchemaView* schema_view, enum ArrowType type,
1317
+ struct ArrowError* error) {
1318
+ switch (type) {
1319
+ case NANOARROW_TYPE_NA:
1320
+ case NANOARROW_TYPE_BOOL:
1321
+ case NANOARROW_TYPE_UINT8:
1322
+ case NANOARROW_TYPE_INT8:
1323
+ case NANOARROW_TYPE_UINT16:
1324
+ case NANOARROW_TYPE_INT16:
1325
+ case NANOARROW_TYPE_UINT32:
1326
+ case NANOARROW_TYPE_INT32:
1327
+ case NANOARROW_TYPE_UINT64:
1328
+ case NANOARROW_TYPE_INT64:
1329
+ case NANOARROW_TYPE_HALF_FLOAT:
1330
+ case NANOARROW_TYPE_FLOAT:
1331
+ case NANOARROW_TYPE_DOUBLE:
1332
+ case NANOARROW_TYPE_DECIMAL128:
1333
+ case NANOARROW_TYPE_DECIMAL256:
1334
+ case NANOARROW_TYPE_STRING:
1335
+ case NANOARROW_TYPE_LARGE_STRING:
1336
+ case NANOARROW_TYPE_BINARY:
1337
+ case NANOARROW_TYPE_LARGE_BINARY:
1338
+ case NANOARROW_TYPE_DATE32:
1339
+ case NANOARROW_TYPE_DATE64:
1340
+ case NANOARROW_TYPE_INTERVAL_MONTHS:
1341
+ case NANOARROW_TYPE_INTERVAL_DAY_TIME:
1342
+ case NANOARROW_TYPE_INTERVAL_MONTH_DAY_NANO:
1343
+ case NANOARROW_TYPE_TIMESTAMP:
1344
+ case NANOARROW_TYPE_TIME32:
1345
+ case NANOARROW_TYPE_TIME64:
1346
+ case NANOARROW_TYPE_DURATION:
1347
+ return ArrowSchemaViewValidateNChildren(schema_view, 0, error);
1348
+
1349
+ case NANOARROW_TYPE_FIXED_SIZE_BINARY:
1350
+ if (schema_view->fixed_size <= 0) {
1351
+ ArrowErrorSet(
1352
+ error, "Expected size > 0 for fixed size binary but found size %d",
1353
+ schema_view->fixed_size);
1354
+ return EINVAL;
1355
+ }
1356
+ return ArrowSchemaViewValidateNChildren(schema_view, 0, error);
1357
+
1358
+ case NANOARROW_TYPE_LIST:
1359
+ case NANOARROW_TYPE_LARGE_LIST:
1360
+ case NANOARROW_TYPE_FIXED_SIZE_LIST:
1361
+ return ArrowSchemaViewValidateNChildren(schema_view, 1, error);
1362
+
1363
+ case NANOARROW_TYPE_STRUCT:
1364
+ return ArrowSchemaViewValidateNChildren(schema_view, -1, error);
1365
+
1366
+ case NANOARROW_TYPE_SPARSE_UNION:
1367
+ case NANOARROW_TYPE_DENSE_UNION:
1368
+ return ArrowSchemaViewValidateUnion(schema_view, error);
1369
+
1370
+ case NANOARROW_TYPE_MAP:
1371
+ return ArrowSchemaViewValidateMap(schema_view, error);
1372
+
1373
+ case NANOARROW_TYPE_DICTIONARY:
1374
+ return ArrowSchemaViewValidateDictionary(schema_view, error);
1375
+
1376
+ default:
1377
+ ArrowErrorSet(error, "Expected a valid enum ArrowType value but found %d",
1378
+ (int)schema_view->type);
1379
+ return EINVAL;
1380
+ }
1381
+
1382
+ return NANOARROW_OK;
1383
+ }
1384
+
1385
+ ArrowErrorCode ArrowSchemaViewInit(struct ArrowSchemaView* schema_view,
1386
+ struct ArrowSchema* schema,
1387
+ struct ArrowError* error) {
1388
+ if (schema == NULL) {
1389
+ ArrowErrorSet(error, "Expected non-NULL schema");
1390
+ return EINVAL;
1391
+ }
1392
+
1393
+ if (schema->release == NULL) {
1394
+ ArrowErrorSet(error, "Expected non-released schema");
1395
+ return EINVAL;
1396
+ }
1397
+
1398
+ schema_view->schema = schema;
1399
+
1400
+ const char* format = schema->format;
1401
+ if (format == NULL) {
1402
+ ArrowErrorSet(error,
1403
+ "Error parsing schema->format: Expected a null-terminated "
1404
+ "string but found NULL");
1405
+ return EINVAL;
1406
+ }
1407
+
1408
+ size_t format_len = strlen(format);
1409
+ if (format_len == 0) {
1410
+ ArrowErrorSet(
1411
+ error, "Error parsing schema->format: Expected a string with size > 0");
1412
+ return EINVAL;
1413
+ }
1414
+
1415
+ const char* format_end_out;
1416
+ ArrowErrorCode result =
1417
+ ArrowSchemaViewParse(schema_view, format, &format_end_out, error);
1418
+
1419
+ if (result != NANOARROW_OK) {
1420
+ if (error != NULL) {
1421
+ char child_error[1024];
1422
+ memcpy(child_error, ArrowErrorMessage(error), 1024);
1423
+ ArrowErrorSet(error, "Error parsing schema->format: %s", child_error);
1424
+ }
1425
+
1426
+ return result;
1427
+ }
1428
+
1429
+ if ((format + format_len) != format_end_out) {
1430
+ ArrowErrorSet(error,
1431
+ "Error parsing schema->format '%s': parsed %d/%d characters",
1432
+ format, (int)(format_end_out - format), (int)(format_len));
1433
+ return EINVAL;
1434
+ }
1435
+
1436
+ if (schema->dictionary != NULL) {
1437
+ schema_view->type = NANOARROW_TYPE_DICTIONARY;
1438
+ }
1439
+
1440
+ result =
1441
+ ArrowSchemaViewValidate(schema_view, schema_view->storage_type, error);
1442
+ if (result != NANOARROW_OK) {
1443
+ return result;
1444
+ }
1445
+
1446
+ if (schema_view->storage_type != schema_view->type) {
1447
+ result = ArrowSchemaViewValidate(schema_view, schema_view->type, error);
1448
+ if (result != NANOARROW_OK) {
1449
+ return result;
1450
+ }
1451
+ }
1452
+
1453
+ ArrowLayoutInit(&schema_view->layout, schema_view->storage_type);
1454
+ if (schema_view->storage_type == NANOARROW_TYPE_FIXED_SIZE_BINARY) {
1455
+ schema_view->layout.element_size_bits[1] = schema_view->fixed_size * 8;
1456
+ } else if (schema_view->storage_type == NANOARROW_TYPE_FIXED_SIZE_LIST) {
1457
+ schema_view->layout.child_size_elements = schema_view->fixed_size;
1458
+ }
1459
+
1460
+ schema_view->extension_name = ArrowCharView(NULL);
1461
+ schema_view->extension_metadata = ArrowCharView(NULL);
1462
+ ArrowMetadataGetValue(schema->metadata, ArrowCharView("ARROW:extension:name"),
1463
+ &schema_view->extension_name);
1464
+ ArrowMetadataGetValue(schema->metadata,
1465
+ ArrowCharView("ARROW:extension:metadata"),
1466
+ &schema_view->extension_metadata);
1467
+
1468
+ return NANOARROW_OK;
1469
+ }
1470
+
1471
+ static int64_t ArrowSchemaTypeToStringInternal(
1472
+ struct ArrowSchemaView* schema_view, char* out, int64_t n) {
1473
+ const char* type_string = ArrowTypeString(schema_view->type);
1474
+ switch (schema_view->type) {
1475
+ case NANOARROW_TYPE_DECIMAL128:
1476
+ case NANOARROW_TYPE_DECIMAL256:
1477
+ return snprintf(out, n, "%s(%d, %d)", type_string,
1478
+ (int)schema_view->decimal_precision,
1479
+ (int)schema_view->decimal_scale);
1480
+ case NANOARROW_TYPE_TIMESTAMP:
1481
+ return snprintf(out, n, "%s('%s', '%s')", type_string,
1482
+ ArrowTimeUnitString(schema_view->time_unit),
1483
+ schema_view->timezone);
1484
+ case NANOARROW_TYPE_TIME32:
1485
+ case NANOARROW_TYPE_TIME64:
1486
+ case NANOARROW_TYPE_DURATION:
1487
+ return snprintf(out, n, "%s('%s')", type_string,
1488
+ ArrowTimeUnitString(schema_view->time_unit));
1489
+ case NANOARROW_TYPE_FIXED_SIZE_BINARY:
1490
+ case NANOARROW_TYPE_FIXED_SIZE_LIST:
1491
+ return snprintf(out, n, "%s(%ld)", type_string,
1492
+ (long)schema_view->fixed_size);
1493
+ case NANOARROW_TYPE_SPARSE_UNION:
1494
+ case NANOARROW_TYPE_DENSE_UNION:
1495
+ return snprintf(out, n, "%s([%s])", type_string,
1496
+ schema_view->union_type_ids);
1497
+ default:
1498
+ return snprintf(out, n, "%s", type_string);
1499
+ }
1500
+ }
1501
+
1502
+ // Helper for bookkeeping to emulate sprintf()-like behaviour spread
1503
+ // among multiple sprintf calls.
1504
+ static inline void ArrowToStringLogChars(char** out, int64_t n_chars_last,
1505
+ int64_t* n_remaining,
1506
+ int64_t* n_chars) {
1507
+ *n_chars += n_chars_last;
1508
+ *n_remaining -= n_chars_last;
1509
+
1510
+ // n_remaining is never less than 0
1511
+ if (*n_remaining < 0) {
1512
+ *n_remaining = 0;
1513
+ }
1514
+
1515
+ // Can't do math on a NULL pointer
1516
+ if (*out != NULL) {
1517
+ *out += n_chars_last;
1518
+ }
1519
+ }
1520
+
1521
+ int64_t ArrowSchemaToString(struct ArrowSchema* schema, char* out, int64_t n,
1522
+ char recursive) {
1523
+ if (schema == NULL) {
1524
+ return snprintf(out, n, "[invalid: pointer is null]");
1525
+ }
1526
+
1527
+ if (schema->release == NULL) {
1528
+ return snprintf(out, n, "[invalid: schema is released]");
1529
+ }
1530
+
1531
+ struct ArrowSchemaView schema_view;
1532
+ struct ArrowError error;
1533
+
1534
+ if (ArrowSchemaViewInit(&schema_view, schema, &error) != NANOARROW_OK) {
1535
+ return snprintf(out, n, "[invalid: %s]", ArrowErrorMessage(&error));
1536
+ }
1537
+
1538
+ // Extension type and dictionary should include both the top-level type
1539
+ // and the storage type.
1540
+ int is_extension = schema_view.extension_name.size_bytes > 0;
1541
+ int is_dictionary = schema->dictionary != NULL;
1542
+ int64_t n_chars = 0;
1543
+ int64_t n_chars_last = 0;
1544
+
1545
+ // Uncommon but not technically impossible that both are true
1546
+ if (is_extension && is_dictionary) {
1547
+ n_chars_last = snprintf(out, n, "%.*s{dictionary(%s)<",
1548
+ (int)schema_view.extension_name.size_bytes,
1549
+ schema_view.extension_name.data,
1550
+ ArrowTypeString(schema_view.storage_type));
1551
+ } else if (is_extension) {
1552
+ n_chars_last =
1553
+ snprintf(out, n, "%.*s{", (int)schema_view.extension_name.size_bytes,
1554
+ schema_view.extension_name.data);
1555
+ } else if (is_dictionary) {
1556
+ n_chars_last = snprintf(out, n, "dictionary(%s)<",
1557
+ ArrowTypeString(schema_view.storage_type));
1558
+ }
1559
+
1560
+ ArrowToStringLogChars(&out, n_chars_last, &n, &n_chars);
1561
+
1562
+ if (!is_dictionary) {
1563
+ n_chars_last = ArrowSchemaTypeToStringInternal(&schema_view, out, n);
1564
+ } else {
1565
+ n_chars_last = ArrowSchemaToString(schema->dictionary, out, n, recursive);
1566
+ }
1567
+
1568
+ ArrowToStringLogChars(&out, n_chars_last, &n, &n_chars);
1569
+
1570
+ if (recursive && schema->format[0] == '+') {
1571
+ n_chars_last = snprintf(out, n, "<");
1572
+ ArrowToStringLogChars(&out, n_chars_last, &n, &n_chars);
1573
+
1574
+ for (int64_t i = 0; i < schema->n_children; i++) {
1575
+ if (i > 0) {
1576
+ n_chars_last = snprintf(out, n, ", ");
1577
+ ArrowToStringLogChars(&out, n_chars_last, &n, &n_chars);
1578
+ }
1579
+
1580
+ // ArrowSchemaToStringInternal() will validate the child and print the
1581
+ // error, but we need the name first
1582
+ if (schema->children[i] != NULL && schema->children[i]->release != NULL &&
1583
+ schema->children[i]->name != NULL) {
1584
+ n_chars_last = snprintf(out, n, "%s: ", schema->children[i]->name);
1585
+ ArrowToStringLogChars(&out, n_chars_last, &n, &n_chars);
1586
+ }
1587
+
1588
+ n_chars_last =
1589
+ ArrowSchemaToString(schema->children[i], out, n, recursive);
1590
+ ArrowToStringLogChars(&out, n_chars_last, &n, &n_chars);
1591
+ }
1592
+
1593
+ n_chars_last = snprintf(out, n, ">");
1594
+ ArrowToStringLogChars(&out, n_chars_last, &n, &n_chars);
1595
+ }
1596
+
1597
+ if (is_extension && is_dictionary) {
1598
+ n_chars += snprintf(out, n, ">}");
1599
+ } else if (is_extension) {
1600
+ n_chars += snprintf(out, n, "}");
1601
+ } else if (is_dictionary) {
1602
+ n_chars += snprintf(out, n, ">");
1603
+ }
1604
+
1605
+ return n_chars;
1606
+ }
1607
+
1608
+ ArrowErrorCode ArrowMetadataReaderInit(struct ArrowMetadataReader* reader,
1609
+ const char* metadata) {
1610
+ reader->metadata = metadata;
1611
+
1612
+ if (reader->metadata == NULL) {
1613
+ reader->offset = 0;
1614
+ reader->remaining_keys = 0;
1615
+ } else {
1616
+ memcpy(&reader->remaining_keys, reader->metadata, sizeof(int32_t));
1617
+ reader->offset = sizeof(int32_t);
1618
+ }
1619
+
1620
+ return NANOARROW_OK;
1621
+ }
1622
+
1623
+ ArrowErrorCode ArrowMetadataReaderRead(struct ArrowMetadataReader* reader,
1624
+ struct ArrowStringView* key_out,
1625
+ struct ArrowStringView* value_out) {
1626
+ if (reader->remaining_keys <= 0) {
1627
+ return EINVAL;
1628
+ }
1629
+
1630
+ int64_t pos = 0;
1631
+
1632
+ int32_t key_size;
1633
+ memcpy(&key_size, reader->metadata + reader->offset + pos, sizeof(int32_t));
1634
+ pos += sizeof(int32_t);
1635
+
1636
+ key_out->data = reader->metadata + reader->offset + pos;
1637
+ key_out->size_bytes = key_size;
1638
+ pos += key_size;
1639
+
1640
+ int32_t value_size;
1641
+ memcpy(&value_size, reader->metadata + reader->offset + pos, sizeof(int32_t));
1642
+ pos += sizeof(int32_t);
1643
+
1644
+ value_out->data = reader->metadata + reader->offset + pos;
1645
+ value_out->size_bytes = value_size;
1646
+ pos += value_size;
1647
+
1648
+ reader->offset += pos;
1649
+ reader->remaining_keys--;
1650
+ return NANOARROW_OK;
1651
+ }
1652
+
1653
+ int64_t ArrowMetadataSizeOf(const char* metadata) {
1654
+ if (metadata == NULL) {
1655
+ return 0;
1656
+ }
1657
+
1658
+ struct ArrowMetadataReader reader;
1659
+ struct ArrowStringView key;
1660
+ struct ArrowStringView value;
1661
+ ArrowMetadataReaderInit(&reader, metadata);
1662
+
1663
+ int64_t size = sizeof(int32_t);
1664
+ while (ArrowMetadataReaderRead(&reader, &key, &value) == NANOARROW_OK) {
1665
+ size +=
1666
+ sizeof(int32_t) + key.size_bytes + sizeof(int32_t) + value.size_bytes;
1667
+ }
1668
+
1669
+ return size;
1670
+ }
1671
+
1672
+ static ArrowErrorCode ArrowMetadataGetValueInternal(
1673
+ const char* metadata, struct ArrowStringView* key,
1674
+ struct ArrowStringView* value_out) {
1675
+ struct ArrowMetadataReader reader;
1676
+ struct ArrowStringView existing_key;
1677
+ struct ArrowStringView existing_value;
1678
+ ArrowMetadataReaderInit(&reader, metadata);
1679
+
1680
+ while (ArrowMetadataReaderRead(&reader, &existing_key, &existing_value) ==
1681
+ NANOARROW_OK) {
1682
+ int key_equal =
1683
+ key->size_bytes == existing_key.size_bytes &&
1684
+ strncmp(key->data, existing_key.data, existing_key.size_bytes) == 0;
1685
+ if (key_equal) {
1686
+ value_out->data = existing_value.data;
1687
+ value_out->size_bytes = existing_value.size_bytes;
1688
+ break;
1689
+ }
1690
+ }
1691
+
1692
+ return NANOARROW_OK;
1693
+ }
1694
+
1695
+ ArrowErrorCode ArrowMetadataGetValue(const char* metadata,
1696
+ struct ArrowStringView key,
1697
+ struct ArrowStringView* value_out) {
1698
+ if (value_out == NULL) {
1699
+ return EINVAL;
1700
+ }
1701
+
1702
+ return ArrowMetadataGetValueInternal(metadata, &key, value_out);
1703
+ }
1704
+
1705
+ char ArrowMetadataHasKey(const char* metadata, struct ArrowStringView key) {
1706
+ struct ArrowStringView value = ArrowCharView(NULL);
1707
+ ArrowMetadataGetValue(metadata, key, &value);
1708
+ return value.data != NULL;
1709
+ }
1710
+
1711
+ ArrowErrorCode ArrowMetadataBuilderInit(struct ArrowBuffer* buffer,
1712
+ const char* metadata) {
1713
+ ArrowBufferInit(buffer);
1714
+ return ArrowBufferAppend(buffer, metadata, ArrowMetadataSizeOf(metadata));
1715
+ }
1716
+
1717
+ static ArrowErrorCode ArrowMetadataBuilderAppendInternal(
1718
+ struct ArrowBuffer* buffer, struct ArrowStringView* key,
1719
+ struct ArrowStringView* value) {
1720
+ if (value == NULL) {
1721
+ return NANOARROW_OK;
1722
+ }
1723
+
1724
+ if (buffer->capacity_bytes == 0) {
1725
+ NANOARROW_RETURN_NOT_OK(ArrowBufferAppendInt32(buffer, 0));
1726
+ }
1727
+
1728
+ if (((size_t)buffer->capacity_bytes) < sizeof(int32_t)) {
1729
+ return EINVAL;
1730
+ }
1731
+
1732
+ int32_t n_keys;
1733
+ memcpy(&n_keys, buffer->data, sizeof(int32_t));
1734
+
1735
+ int32_t key_size = (int32_t)key->size_bytes;
1736
+ int32_t value_size = (int32_t)value->size_bytes;
1737
+ NANOARROW_RETURN_NOT_OK(ArrowBufferReserve(
1738
+ buffer, sizeof(int32_t) + key_size + sizeof(int32_t) + value_size));
1739
+
1740
+ ArrowBufferAppendUnsafe(buffer, &key_size, sizeof(int32_t));
1741
+ ArrowBufferAppendUnsafe(buffer, key->data, key_size);
1742
+ ArrowBufferAppendUnsafe(buffer, &value_size, sizeof(int32_t));
1743
+ ArrowBufferAppendUnsafe(buffer, value->data, value_size);
1744
+
1745
+ n_keys++;
1746
+ memcpy(buffer->data, &n_keys, sizeof(int32_t));
1747
+
1748
+ return NANOARROW_OK;
1749
+ }
1750
+
1751
+ static ArrowErrorCode ArrowMetadataBuilderSetInternal(
1752
+ struct ArrowBuffer* buffer, struct ArrowStringView* key,
1753
+ struct ArrowStringView* value) {
1754
+ // Inspect the current value to see if we can avoid copying the buffer
1755
+ struct ArrowStringView current_value = ArrowCharView(NULL);
1756
+ NANOARROW_RETURN_NOT_OK(ArrowMetadataGetValueInternal(
1757
+ (const char*)buffer->data, key, &current_value));
1758
+
1759
+ // The key should be removed but no key exists
1760
+ if (value == NULL && current_value.data == NULL) {
1761
+ return NANOARROW_OK;
1762
+ }
1763
+
1764
+ // The key/value can be appended because no key exists
1765
+ if (value != NULL && current_value.data == NULL) {
1766
+ return ArrowMetadataBuilderAppendInternal(buffer, key, value);
1767
+ }
1768
+
1769
+ struct ArrowMetadataReader reader;
1770
+ struct ArrowStringView existing_key;
1771
+ struct ArrowStringView existing_value;
1772
+ NANOARROW_RETURN_NOT_OK(
1773
+ ArrowMetadataReaderInit(&reader, (const char*)buffer->data));
1774
+
1775
+ struct ArrowBuffer new_buffer;
1776
+ NANOARROW_RETURN_NOT_OK(ArrowMetadataBuilderInit(&new_buffer, NULL));
1777
+
1778
+ while (reader.remaining_keys > 0) {
1779
+ int result =
1780
+ ArrowMetadataReaderRead(&reader, &existing_key, &existing_value);
1781
+ if (result != NANOARROW_OK) {
1782
+ ArrowBufferReset(&new_buffer);
1783
+ return result;
1784
+ }
1785
+
1786
+ if (key->size_bytes == existing_key.size_bytes &&
1787
+ strncmp((const char*)key->data, (const char*)existing_key.data,
1788
+ existing_key.size_bytes) == 0) {
1789
+ result = ArrowMetadataBuilderAppendInternal(&new_buffer, key, value);
1790
+ value = NULL;
1791
+ } else {
1792
+ result = ArrowMetadataBuilderAppendInternal(&new_buffer, &existing_key,
1793
+ &existing_value);
1794
+ }
1795
+
1796
+ if (result != NANOARROW_OK) {
1797
+ ArrowBufferReset(&new_buffer);
1798
+ return result;
1799
+ }
1800
+ }
1801
+
1802
+ ArrowBufferReset(buffer);
1803
+ ArrowBufferMove(&new_buffer, buffer);
1804
+ return NANOARROW_OK;
1805
+ }
1806
+
1807
+ ArrowErrorCode ArrowMetadataBuilderAppend(struct ArrowBuffer* buffer,
1808
+ struct ArrowStringView key,
1809
+ struct ArrowStringView value) {
1810
+ return ArrowMetadataBuilderAppendInternal(buffer, &key, &value);
1811
+ }
1812
+
1813
+ ArrowErrorCode ArrowMetadataBuilderSet(struct ArrowBuffer* buffer,
1814
+ struct ArrowStringView key,
1815
+ struct ArrowStringView value) {
1816
+ return ArrowMetadataBuilderSetInternal(buffer, &key, &value);
1817
+ }
1818
+
1819
+ ArrowErrorCode ArrowMetadataBuilderRemove(struct ArrowBuffer* buffer,
1820
+ struct ArrowStringView key) {
1821
+ return ArrowMetadataBuilderSetInternal(buffer, &key, NULL);
1822
+ }
1823
+ // Licensed to the Apache Software Foundation (ASF) under one
1824
+ // or more contributor license agreements. See the NOTICE file
1825
+ // distributed with this work for additional information
1826
+ // regarding copyright ownership. The ASF licenses this file
1827
+ // to you under the Apache License, Version 2.0 (the
1828
+ // "License"); you may not use this file except in compliance
1829
+ // with the License. You may obtain a copy of the License at
1830
+ //
1831
+ // http://www.apache.org/licenses/LICENSE-2.0
1832
+ //
1833
+ // Unless required by applicable law or agreed to in writing,
1834
+ // software distributed under the License is distributed on an
1835
+ // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
1836
+ // KIND, either express or implied. See the License for the
1837
+ // specific language governing permissions and limitations
1838
+ // under the License.
1839
+
1840
+ #include <errno.h>
1841
+ #include <stdlib.h>
1842
+ #include <string.h>
1843
+
1844
+ #include "nanoarrow.h"
1845
+
1846
+ static void ArrowArrayRelease(struct ArrowArray* array) {
1847
+ // Release buffers held by this array
1848
+ struct ArrowArrayPrivateData* private_data =
1849
+ (struct ArrowArrayPrivateData*)array->private_data;
1850
+ if (private_data != NULL) {
1851
+ ArrowBitmapReset(&private_data->bitmap);
1852
+ ArrowBufferReset(&private_data->buffers[0]);
1853
+ ArrowBufferReset(&private_data->buffers[1]);
1854
+ ArrowFree(private_data);
1855
+ }
1856
+
1857
+ // This object owns the memory for all the children, but those
1858
+ // children may have been generated elsewhere and might have
1859
+ // their own release() callback.
1860
+ if (array->children != NULL) {
1861
+ for (int64_t i = 0; i < array->n_children; i++) {
1862
+ if (array->children[i] != NULL) {
1863
+ if (array->children[i]->release != NULL) {
1864
+ array->children[i]->release(array->children[i]);
1865
+ }
1866
+
1867
+ ArrowFree(array->children[i]);
1868
+ }
1869
+ }
1870
+
1871
+ ArrowFree(array->children);
1872
+ }
1873
+
1874
+ // This object owns the memory for the dictionary but it
1875
+ // may have been generated somewhere else and have its own
1876
+ // release() callback.
1877
+ if (array->dictionary != NULL) {
1878
+ if (array->dictionary->release != NULL) {
1879
+ array->dictionary->release(array->dictionary);
1880
+ }
1881
+
1882
+ ArrowFree(array->dictionary);
1883
+ }
1884
+
1885
+ // Mark released
1886
+ array->release = NULL;
1887
+ }
1888
+
1889
+ static ArrowErrorCode ArrowArraySetStorageType(struct ArrowArray* array,
1890
+ enum ArrowType storage_type) {
1891
+ switch (storage_type) {
1892
+ case NANOARROW_TYPE_UNINITIALIZED:
1893
+ case NANOARROW_TYPE_NA:
1894
+ array->n_buffers = 0;
1895
+ break;
1896
+
1897
+ case NANOARROW_TYPE_FIXED_SIZE_LIST:
1898
+ case NANOARROW_TYPE_STRUCT:
1899
+ case NANOARROW_TYPE_SPARSE_UNION:
1900
+ array->n_buffers = 1;
1901
+ break;
1902
+
1903
+ case NANOARROW_TYPE_LIST:
1904
+ case NANOARROW_TYPE_LARGE_LIST:
1905
+ case NANOARROW_TYPE_MAP:
1906
+ case NANOARROW_TYPE_BOOL:
1907
+ case NANOARROW_TYPE_UINT8:
1908
+ case NANOARROW_TYPE_INT8:
1909
+ case NANOARROW_TYPE_UINT16:
1910
+ case NANOARROW_TYPE_INT16:
1911
+ case NANOARROW_TYPE_UINT32:
1912
+ case NANOARROW_TYPE_INT32:
1913
+ case NANOARROW_TYPE_UINT64:
1914
+ case NANOARROW_TYPE_INT64:
1915
+ case NANOARROW_TYPE_HALF_FLOAT:
1916
+ case NANOARROW_TYPE_FLOAT:
1917
+ case NANOARROW_TYPE_DOUBLE:
1918
+ case NANOARROW_TYPE_DECIMAL128:
1919
+ case NANOARROW_TYPE_DECIMAL256:
1920
+ case NANOARROW_TYPE_INTERVAL_MONTHS:
1921
+ case NANOARROW_TYPE_INTERVAL_DAY_TIME:
1922
+ case NANOARROW_TYPE_INTERVAL_MONTH_DAY_NANO:
1923
+ case NANOARROW_TYPE_FIXED_SIZE_BINARY:
1924
+ case NANOARROW_TYPE_DENSE_UNION:
1925
+ array->n_buffers = 2;
1926
+ break;
1927
+
1928
+ case NANOARROW_TYPE_STRING:
1929
+ case NANOARROW_TYPE_LARGE_STRING:
1930
+ case NANOARROW_TYPE_BINARY:
1931
+ case NANOARROW_TYPE_LARGE_BINARY:
1932
+ array->n_buffers = 3;
1933
+ break;
1934
+
1935
+ default:
1936
+ return EINVAL;
1937
+
1938
+ return NANOARROW_OK;
1939
+ }
1940
+
1941
+ struct ArrowArrayPrivateData* private_data =
1942
+ (struct ArrowArrayPrivateData*)array->private_data;
1943
+ private_data->storage_type = storage_type;
1944
+ return NANOARROW_OK;
1945
+ }
1946
+
1947
+ ArrowErrorCode ArrowArrayInitFromType(struct ArrowArray* array,
1948
+ enum ArrowType storage_type) {
1949
+ array->length = 0;
1950
+ array->null_count = 0;
1951
+ array->offset = 0;
1952
+ array->n_buffers = 0;
1953
+ array->n_children = 0;
1954
+ array->buffers = NULL;
1955
+ array->children = NULL;
1956
+ array->dictionary = NULL;
1957
+ array->release = &ArrowArrayRelease;
1958
+ array->private_data = NULL;
1959
+
1960
+ struct ArrowArrayPrivateData* private_data =
1961
+ (struct ArrowArrayPrivateData*)ArrowMalloc(
1962
+ sizeof(struct ArrowArrayPrivateData));
1963
+ if (private_data == NULL) {
1964
+ array->release = NULL;
1965
+ return ENOMEM;
1966
+ }
1967
+
1968
+ ArrowBitmapInit(&private_data->bitmap);
1969
+ ArrowBufferInit(&private_data->buffers[0]);
1970
+ ArrowBufferInit(&private_data->buffers[1]);
1971
+ private_data->buffer_data[0] = NULL;
1972
+ private_data->buffer_data[1] = NULL;
1973
+ private_data->buffer_data[2] = NULL;
1974
+
1975
+ array->private_data = private_data;
1976
+ array->buffers = (const void**)(&private_data->buffer_data);
1977
+
1978
+ int result = ArrowArraySetStorageType(array, storage_type);
1979
+ if (result != NANOARROW_OK) {
1980
+ array->release(array);
1981
+ return result;
1982
+ }
1983
+
1984
+ ArrowLayoutInit(&private_data->layout, storage_type);
1985
+ // We can only know this not to be true when initializing based on a schema
1986
+ // so assume this to be true.
1987
+ private_data->union_type_id_is_child_index = 1;
1988
+ return NANOARROW_OK;
1989
+ }
1990
+
1991
+ ArrowErrorCode ArrowArrayInitFromArrayView(struct ArrowArray* array,
1992
+ struct ArrowArrayView* array_view,
1993
+ struct ArrowError* error) {
1994
+ NANOARROW_RETURN_NOT_OK_WITH_ERROR(
1995
+ ArrowArrayInitFromType(array, array_view->storage_type), error);
1996
+ int result;
1997
+
1998
+ struct ArrowArrayPrivateData* private_data =
1999
+ (struct ArrowArrayPrivateData*)array->private_data;
2000
+ private_data->layout = array_view->layout;
2001
+
2002
+ if (array_view->n_children > 0) {
2003
+ result = ArrowArrayAllocateChildren(array, array_view->n_children);
2004
+ if (result != NANOARROW_OK) {
2005
+ array->release(array);
2006
+ return result;
2007
+ }
2008
+
2009
+ for (int64_t i = 0; i < array_view->n_children; i++) {
2010
+ result = ArrowArrayInitFromArrayView(array->children[i],
2011
+ array_view->children[i], error);
2012
+ if (result != NANOARROW_OK) {
2013
+ array->release(array);
2014
+ return result;
2015
+ }
2016
+ }
2017
+ }
2018
+
2019
+ if (array_view->dictionary != NULL) {
2020
+ result = ArrowArrayAllocateDictionary(array);
2021
+ if (result != NANOARROW_OK) {
2022
+ array->release(array);
2023
+ return result;
2024
+ }
2025
+
2026
+ result = ArrowArrayInitFromArrayView(array->dictionary,
2027
+ array_view->dictionary, error);
2028
+ if (result != NANOARROW_OK) {
2029
+ array->release(array);
2030
+ return result;
2031
+ }
2032
+ }
2033
+
2034
+ return NANOARROW_OK;
2035
+ }
2036
+
2037
+ ArrowErrorCode ArrowArrayInitFromSchema(struct ArrowArray* array,
2038
+ struct ArrowSchema* schema,
2039
+ struct ArrowError* error) {
2040
+ struct ArrowArrayView array_view;
2041
+ NANOARROW_RETURN_NOT_OK(
2042
+ ArrowArrayViewInitFromSchema(&array_view, schema, error));
2043
+ NANOARROW_RETURN_NOT_OK(
2044
+ ArrowArrayInitFromArrayView(array, &array_view, error));
2045
+ if (array_view.storage_type == NANOARROW_TYPE_DENSE_UNION ||
2046
+ array_view.storage_type == NANOARROW_TYPE_SPARSE_UNION) {
2047
+ struct ArrowArrayPrivateData* private_data =
2048
+ (struct ArrowArrayPrivateData*)array->private_data;
2049
+ // We can still build arrays if this isn't true; however, the append
2050
+ // functions won't work. Instead, we store this value and error only
2051
+ // when StartAppending is called.
2052
+ private_data->union_type_id_is_child_index =
2053
+ _ArrowUnionTypeIdsWillEqualChildIndices(schema->format + 4,
2054
+ schema->n_children);
2055
+ }
2056
+
2057
+ ArrowArrayViewReset(&array_view);
2058
+ return NANOARROW_OK;
2059
+ }
2060
+
2061
+ ArrowErrorCode ArrowArrayAllocateChildren(struct ArrowArray* array,
2062
+ int64_t n_children) {
2063
+ if (array->children != NULL) {
2064
+ return EINVAL;
2065
+ }
2066
+
2067
+ if (n_children == 0) {
2068
+ return NANOARROW_OK;
2069
+ }
2070
+
2071
+ array->children =
2072
+ (struct ArrowArray**)ArrowMalloc(n_children * sizeof(struct ArrowArray*));
2073
+ if (array->children == NULL) {
2074
+ return ENOMEM;
2075
+ }
2076
+
2077
+ memset(array->children, 0, n_children * sizeof(struct ArrowArray*));
2078
+
2079
+ for (int64_t i = 0; i < n_children; i++) {
2080
+ array->children[i] =
2081
+ (struct ArrowArray*)ArrowMalloc(sizeof(struct ArrowArray));
2082
+ if (array->children[i] == NULL) {
2083
+ return ENOMEM;
2084
+ }
2085
+ array->children[i]->release = NULL;
2086
+ }
2087
+
2088
+ array->n_children = n_children;
2089
+ return NANOARROW_OK;
2090
+ }
2091
+
2092
+ ArrowErrorCode ArrowArrayAllocateDictionary(struct ArrowArray* array) {
2093
+ if (array->dictionary != NULL) {
2094
+ return EINVAL;
2095
+ }
2096
+
2097
+ array->dictionary =
2098
+ (struct ArrowArray*)ArrowMalloc(sizeof(struct ArrowArray));
2099
+ if (array->dictionary == NULL) {
2100
+ return ENOMEM;
2101
+ }
2102
+
2103
+ array->dictionary->release = NULL;
2104
+ return NANOARROW_OK;
2105
+ }
2106
+
2107
+ void ArrowArraySetValidityBitmap(struct ArrowArray* array,
2108
+ struct ArrowBitmap* bitmap) {
2109
+ struct ArrowArrayPrivateData* private_data =
2110
+ (struct ArrowArrayPrivateData*)array->private_data;
2111
+ ArrowBufferMove(&bitmap->buffer, &private_data->bitmap.buffer);
2112
+ private_data->bitmap.size_bits = bitmap->size_bits;
2113
+ bitmap->size_bits = 0;
2114
+ private_data->buffer_data[0] = private_data->bitmap.buffer.data;
2115
+ array->null_count = -1;
2116
+ }
2117
+
2118
+ ArrowErrorCode ArrowArraySetBuffer(struct ArrowArray* array, int64_t i,
2119
+ struct ArrowBuffer* buffer) {
2120
+ struct ArrowArrayPrivateData* private_data =
2121
+ (struct ArrowArrayPrivateData*)array->private_data;
2122
+
2123
+ switch (i) {
2124
+ case 0:
2125
+ ArrowBufferMove(buffer, &private_data->bitmap.buffer);
2126
+ private_data->buffer_data[i] = private_data->bitmap.buffer.data;
2127
+ break;
2128
+ case 1:
2129
+ case 2:
2130
+ ArrowBufferMove(buffer, &private_data->buffers[i - 1]);
2131
+ private_data->buffer_data[i] = private_data->buffers[i - 1].data;
2132
+ break;
2133
+ default:
2134
+ return EINVAL;
2135
+ }
2136
+
2137
+ return NANOARROW_OK;
2138
+ }
2139
+
2140
+ static ArrowErrorCode ArrowArrayViewInitFromArray(
2141
+ struct ArrowArrayView* array_view, struct ArrowArray* array) {
2142
+ struct ArrowArrayPrivateData* private_data =
2143
+ (struct ArrowArrayPrivateData*)array->private_data;
2144
+
2145
+ ArrowArrayViewInitFromType(array_view, private_data->storage_type);
2146
+ array_view->layout = private_data->layout;
2147
+ array_view->array = array;
2148
+ array_view->length = array->length;
2149
+ array_view->offset = array->offset;
2150
+ array_view->null_count = array->null_count;
2151
+
2152
+ array_view->buffer_views[0].data.as_uint8 = private_data->bitmap.buffer.data;
2153
+ array_view->buffer_views[0].size_bytes =
2154
+ private_data->bitmap.buffer.size_bytes;
2155
+ array_view->buffer_views[1].data.as_uint8 = private_data->buffers[0].data;
2156
+ array_view->buffer_views[1].size_bytes = private_data->buffers[0].size_bytes;
2157
+ array_view->buffer_views[2].data.as_uint8 = private_data->buffers[1].data;
2158
+ array_view->buffer_views[2].size_bytes = private_data->buffers[1].size_bytes;
2159
+
2160
+ int result = ArrowArrayViewAllocateChildren(array_view, array->n_children);
2161
+ if (result != NANOARROW_OK) {
2162
+ ArrowArrayViewReset(array_view);
2163
+ return result;
2164
+ }
2165
+
2166
+ for (int64_t i = 0; i < array->n_children; i++) {
2167
+ result = ArrowArrayViewInitFromArray(array_view->children[i],
2168
+ array->children[i]);
2169
+ if (result != NANOARROW_OK) {
2170
+ ArrowArrayViewReset(array_view);
2171
+ return result;
2172
+ }
2173
+ }
2174
+
2175
+ if (array->dictionary != NULL) {
2176
+ result = ArrowArrayViewAllocateDictionary(array_view);
2177
+ if (result != NANOARROW_OK) {
2178
+ ArrowArrayViewReset(array_view);
2179
+ return result;
2180
+ }
2181
+
2182
+ result =
2183
+ ArrowArrayViewInitFromArray(array_view->dictionary, array->dictionary);
2184
+ if (result != NANOARROW_OK) {
2185
+ ArrowArrayViewReset(array_view);
2186
+ return result;
2187
+ }
2188
+ }
2189
+
2190
+ return NANOARROW_OK;
2191
+ }
2192
+
2193
+ static ArrowErrorCode ArrowArrayReserveInternal(
2194
+ struct ArrowArray* array, struct ArrowArrayView* array_view) {
2195
+ // Loop through buffers and reserve the extra space that we know about
2196
+ for (int64_t i = 0; i < array->n_buffers; i++) {
2197
+ // Don't reserve on a validity buffer that hasn't been allocated yet
2198
+ if (array_view->layout.buffer_type[i] == NANOARROW_BUFFER_TYPE_VALIDITY &&
2199
+ ArrowArrayBuffer(array, i)->data == NULL) {
2200
+ continue;
2201
+ }
2202
+
2203
+ int64_t additional_size_bytes = array_view->buffer_views[i].size_bytes -
2204
+ ArrowArrayBuffer(array, i)->size_bytes;
2205
+
2206
+ if (additional_size_bytes > 0) {
2207
+ NANOARROW_RETURN_NOT_OK(ArrowBufferReserve(ArrowArrayBuffer(array, i),
2208
+ additional_size_bytes));
2209
+ }
2210
+ }
2211
+
2212
+ // Recursively reserve children
2213
+ for (int64_t i = 0; i < array->n_children; i++) {
2214
+ NANOARROW_RETURN_NOT_OK(
2215
+ ArrowArrayReserveInternal(array->children[i], array_view->children[i]));
2216
+ }
2217
+
2218
+ return NANOARROW_OK;
2219
+ }
2220
+
2221
+ ArrowErrorCode ArrowArrayReserve(struct ArrowArray* array,
2222
+ int64_t additional_size_elements) {
2223
+ struct ArrowArrayView array_view;
2224
+ NANOARROW_RETURN_NOT_OK(ArrowArrayViewInitFromArray(&array_view, array));
2225
+
2226
+ // Calculate theoretical buffer sizes (recursively)
2227
+ ArrowArrayViewSetLength(&array_view,
2228
+ array->length + additional_size_elements);
2229
+
2230
+ // Walk the structure (recursively)
2231
+ int result = ArrowArrayReserveInternal(array, &array_view);
2232
+ ArrowArrayViewReset(&array_view);
2233
+ if (result != NANOARROW_OK) {
2234
+ return result;
2235
+ }
2236
+
2237
+ return NANOARROW_OK;
2238
+ }
2239
+
2240
+ static ArrowErrorCode ArrowArrayFinalizeBuffers(struct ArrowArray* array) {
2241
+ struct ArrowArrayPrivateData* private_data =
2242
+ (struct ArrowArrayPrivateData*)array->private_data;
2243
+
2244
+ // The only buffer finalizing this currently does is make sure the data
2245
+ // buffer for (Large)String|Binary is never NULL
2246
+ switch (private_data->storage_type) {
2247
+ case NANOARROW_TYPE_BINARY:
2248
+ case NANOARROW_TYPE_STRING:
2249
+ case NANOARROW_TYPE_LARGE_BINARY:
2250
+ case NANOARROW_TYPE_LARGE_STRING:
2251
+ if (ArrowArrayBuffer(array, 2)->data == NULL) {
2252
+ ArrowBufferAppendUInt8(ArrowArrayBuffer(array, 2), 0);
2253
+ }
2254
+ break;
2255
+ default:
2256
+ break;
2257
+ }
2258
+
2259
+ for (int64_t i = 0; i < array->n_children; i++) {
2260
+ NANOARROW_RETURN_NOT_OK(ArrowArrayFinalizeBuffers(array->children[i]));
2261
+ }
2262
+
2263
+ if (array->dictionary != NULL) {
2264
+ NANOARROW_RETURN_NOT_OK(ArrowArrayFinalizeBuffers(array->dictionary));
2265
+ }
2266
+
2267
+ return NANOARROW_OK;
2268
+ }
2269
+
2270
+ static void ArrowArrayFlushInternalPointers(struct ArrowArray* array) {
2271
+ struct ArrowArrayPrivateData* private_data =
2272
+ (struct ArrowArrayPrivateData*)array->private_data;
2273
+
2274
+ for (int64_t i = 0; i < 3; i++) {
2275
+ private_data->buffer_data[i] = ArrowArrayBuffer(array, i)->data;
2276
+ }
2277
+
2278
+ for (int64_t i = 0; i < array->n_children; i++) {
2279
+ ArrowArrayFlushInternalPointers(array->children[i]);
2280
+ }
2281
+
2282
+ if (array->dictionary != NULL) {
2283
+ ArrowArrayFlushInternalPointers(array->dictionary);
2284
+ }
2285
+ }
2286
+
2287
+ ArrowErrorCode ArrowArrayFinishBuilding(
2288
+ struct ArrowArray* array, enum ArrowValidationLevel validation_level,
2289
+ struct ArrowError* error) {
2290
+ // Even if the data buffer is size zero, the pointer value needed to be
2291
+ // non-null in some implementations (at least one version of Arrow C++ at the
2292
+ // time this was added). Only do this fix if we can assume CPU data access.
2293
+ if (validation_level >= NANOARROW_VALIDATION_LEVEL_DEFAULT) {
2294
+ NANOARROW_RETURN_NOT_OK_WITH_ERROR(ArrowArrayFinalizeBuffers(array), error);
2295
+ }
2296
+
2297
+ // Make sure the value we get with array->buffers[i] is set to the actual
2298
+ // pointer (which may have changed from the original due to reallocation)
2299
+ ArrowArrayFlushInternalPointers(array);
2300
+
2301
+ if (validation_level == NANOARROW_VALIDATION_LEVEL_NONE) {
2302
+ return NANOARROW_OK;
2303
+ }
2304
+
2305
+ // For validation, initialize an ArrowArrayView with our known buffer sizes
2306
+ struct ArrowArrayView array_view;
2307
+ NANOARROW_RETURN_NOT_OK_WITH_ERROR(
2308
+ ArrowArrayViewInitFromArray(&array_view, array), error);
2309
+ int result = ArrowArrayViewValidate(&array_view, validation_level, error);
2310
+ ArrowArrayViewReset(&array_view);
2311
+ return result;
2312
+ }
2313
+
2314
+ ArrowErrorCode ArrowArrayFinishBuildingDefault(struct ArrowArray* array,
2315
+ struct ArrowError* error) {
2316
+ return ArrowArrayFinishBuilding(array, NANOARROW_VALIDATION_LEVEL_DEFAULT,
2317
+ error);
2318
+ }
2319
+
2320
+ void ArrowArrayViewInitFromType(struct ArrowArrayView* array_view,
2321
+ enum ArrowType storage_type) {
2322
+ memset(array_view, 0, sizeof(struct ArrowArrayView));
2323
+ array_view->storage_type = storage_type;
2324
+ ArrowLayoutInit(&array_view->layout, storage_type);
2325
+ }
2326
+
2327
+ ArrowErrorCode ArrowArrayViewAllocateChildren(struct ArrowArrayView* array_view,
2328
+ int64_t n_children) {
2329
+ if (array_view->children != NULL) {
2330
+ return EINVAL;
2331
+ }
2332
+
2333
+ array_view->children = (struct ArrowArrayView**)ArrowMalloc(
2334
+ n_children * sizeof(struct ArrowArrayView*));
2335
+ if (array_view->children == NULL) {
2336
+ return ENOMEM;
2337
+ }
2338
+
2339
+ for (int64_t i = 0; i < n_children; i++) {
2340
+ array_view->children[i] = NULL;
2341
+ }
2342
+
2343
+ array_view->n_children = n_children;
2344
+
2345
+ for (int64_t i = 0; i < n_children; i++) {
2346
+ array_view->children[i] =
2347
+ (struct ArrowArrayView*)ArrowMalloc(sizeof(struct ArrowArrayView));
2348
+ if (array_view->children[i] == NULL) {
2349
+ return ENOMEM;
2350
+ }
2351
+ ArrowArrayViewInitFromType(array_view->children[i],
2352
+ NANOARROW_TYPE_UNINITIALIZED);
2353
+ }
2354
+
2355
+ return NANOARROW_OK;
2356
+ }
2357
+
2358
+ ArrowErrorCode ArrowArrayViewAllocateDictionary(
2359
+ struct ArrowArrayView* array_view) {
2360
+ if (array_view->dictionary != NULL) {
2361
+ return EINVAL;
2362
+ }
2363
+
2364
+ array_view->dictionary =
2365
+ (struct ArrowArrayView*)ArrowMalloc(sizeof(struct ArrowArrayView));
2366
+ if (array_view->dictionary == NULL) {
2367
+ return ENOMEM;
2368
+ }
2369
+
2370
+ ArrowArrayViewInitFromType(array_view->dictionary,
2371
+ NANOARROW_TYPE_UNINITIALIZED);
2372
+ return NANOARROW_OK;
2373
+ }
2374
+
2375
+ ArrowErrorCode ArrowArrayViewInitFromSchema(struct ArrowArrayView* array_view,
2376
+ struct ArrowSchema* schema,
2377
+ struct ArrowError* error) {
2378
+ struct ArrowSchemaView schema_view;
2379
+ int result = ArrowSchemaViewInit(&schema_view, schema, error);
2380
+ if (result != NANOARROW_OK) {
2381
+ return result;
2382
+ }
2383
+
2384
+ ArrowArrayViewInitFromType(array_view, schema_view.storage_type);
2385
+ array_view->layout = schema_view.layout;
2386
+
2387
+ result = ArrowArrayViewAllocateChildren(array_view, schema->n_children);
2388
+ if (result != NANOARROW_OK) {
2389
+ ArrowErrorSet(error, "ArrowArrayViewAllocateChildren() failed");
2390
+ ArrowArrayViewReset(array_view);
2391
+ return result;
2392
+ }
2393
+
2394
+ for (int64_t i = 0; i < schema->n_children; i++) {
2395
+ result = ArrowArrayViewInitFromSchema(array_view->children[i],
2396
+ schema->children[i], error);
2397
+ if (result != NANOARROW_OK) {
2398
+ ArrowArrayViewReset(array_view);
2399
+ return result;
2400
+ }
2401
+ }
2402
+
2403
+ if (schema->dictionary != NULL) {
2404
+ result = ArrowArrayViewAllocateDictionary(array_view);
2405
+ if (result != NANOARROW_OK) {
2406
+ ArrowArrayViewReset(array_view);
2407
+ return result;
2408
+ }
2409
+
2410
+ result = ArrowArrayViewInitFromSchema(array_view->dictionary,
2411
+ schema->dictionary, error);
2412
+ if (result != NANOARROW_OK) {
2413
+ ArrowArrayViewReset(array_view);
2414
+ return result;
2415
+ }
2416
+ }
2417
+
2418
+ if (array_view->storage_type == NANOARROW_TYPE_SPARSE_UNION ||
2419
+ array_view->storage_type == NANOARROW_TYPE_DENSE_UNION) {
2420
+ array_view->union_type_id_map = (int8_t*)ArrowMalloc(256 * sizeof(int8_t));
2421
+ if (array_view->union_type_id_map == NULL) {
2422
+ return ENOMEM;
2423
+ }
2424
+
2425
+ memset(array_view->union_type_id_map, -1, 256);
2426
+ int8_t n_type_ids = _ArrowParseUnionTypeIds(
2427
+ schema_view.union_type_ids, array_view->union_type_id_map + 128);
2428
+ for (int8_t child_index = 0; child_index < n_type_ids; child_index++) {
2429
+ int8_t type_id = array_view->union_type_id_map[128 + child_index];
2430
+ array_view->union_type_id_map[type_id] = child_index;
2431
+ }
2432
+ }
2433
+
2434
+ return NANOARROW_OK;
2435
+ }
2436
+
2437
+ void ArrowArrayViewReset(struct ArrowArrayView* array_view) {
2438
+ if (array_view->children != NULL) {
2439
+ for (int64_t i = 0; i < array_view->n_children; i++) {
2440
+ if (array_view->children[i] != NULL) {
2441
+ ArrowArrayViewReset(array_view->children[i]);
2442
+ ArrowFree(array_view->children[i]);
2443
+ }
2444
+ }
2445
+
2446
+ ArrowFree(array_view->children);
2447
+ }
2448
+
2449
+ if (array_view->dictionary != NULL) {
2450
+ ArrowArrayViewReset(array_view->dictionary);
2451
+ ArrowFree(array_view->dictionary);
2452
+ }
2453
+
2454
+ if (array_view->union_type_id_map != NULL) {
2455
+ ArrowFree(array_view->union_type_id_map);
2456
+ }
2457
+
2458
+ ArrowArrayViewInitFromType(array_view, NANOARROW_TYPE_UNINITIALIZED);
2459
+ }
2460
+
2461
+ void ArrowArrayViewSetLength(struct ArrowArrayView* array_view,
2462
+ int64_t length) {
2463
+ for (int i = 0; i < 3; i++) {
2464
+ int64_t element_size_bytes = array_view->layout.element_size_bits[i] / 8;
2465
+
2466
+ switch (array_view->layout.buffer_type[i]) {
2467
+ case NANOARROW_BUFFER_TYPE_VALIDITY:
2468
+ array_view->buffer_views[i].size_bytes = _ArrowBytesForBits(length);
2469
+ continue;
2470
+ case NANOARROW_BUFFER_TYPE_DATA_OFFSET:
2471
+ // Probably don't want/need to rely on the producer to have allocated an
2472
+ // offsets buffer of length 1 for a zero-size array
2473
+ array_view->buffer_views[i].size_bytes =
2474
+ (length != 0) * element_size_bytes * (length + 1);
2475
+ continue;
2476
+ case NANOARROW_BUFFER_TYPE_DATA:
2477
+ array_view->buffer_views[i].size_bytes =
2478
+ _ArrowRoundUpToMultipleOf8(array_view->layout.element_size_bits[i] *
2479
+ length) /
2480
+ 8;
2481
+ continue;
2482
+ case NANOARROW_BUFFER_TYPE_TYPE_ID:
2483
+ case NANOARROW_BUFFER_TYPE_UNION_OFFSET:
2484
+ array_view->buffer_views[i].size_bytes = element_size_bytes * length;
2485
+ continue;
2486
+ case NANOARROW_BUFFER_TYPE_NONE:
2487
+ array_view->buffer_views[i].size_bytes = 0;
2488
+ continue;
2489
+ }
2490
+ }
2491
+
2492
+ switch (array_view->storage_type) {
2493
+ case NANOARROW_TYPE_STRUCT:
2494
+ case NANOARROW_TYPE_SPARSE_UNION:
2495
+ for (int64_t i = 0; i < array_view->n_children; i++) {
2496
+ ArrowArrayViewSetLength(array_view->children[i], length);
2497
+ }
2498
+ break;
2499
+ case NANOARROW_TYPE_FIXED_SIZE_LIST:
2500
+ if (array_view->n_children >= 1) {
2501
+ ArrowArrayViewSetLength(
2502
+ array_view->children[0],
2503
+ length * array_view->layout.child_size_elements);
2504
+ }
2505
+ default:
2506
+ break;
2507
+ }
2508
+ }
2509
+
2510
+ // This version recursively extracts information from the array and stores it
2511
+ // in the array view, performing any checks that require the original array.
2512
+ static int ArrowArrayViewSetArrayInternal(struct ArrowArrayView* array_view,
2513
+ struct ArrowArray* array,
2514
+ struct ArrowError* error) {
2515
+ // Check length and offset
2516
+ if (array->offset < 0) {
2517
+ ArrowErrorSet(error,
2518
+ "Expected array offset >= 0 but found array offset of %ld",
2519
+ (long)array->offset);
2520
+ return EINVAL;
2521
+ }
2522
+
2523
+ if (array->length < 0) {
2524
+ ArrowErrorSet(error,
2525
+ "Expected array length >= 0 but found array length of %ld",
2526
+ (long)array->length);
2527
+ return EINVAL;
2528
+ }
2529
+
2530
+ array_view->array = array;
2531
+ array_view->offset = array->offset;
2532
+ array_view->length = array->length;
2533
+ array_view->null_count = array->null_count;
2534
+
2535
+ int64_t buffers_required = 0;
2536
+ for (int i = 0; i < 3; i++) {
2537
+ if (array_view->layout.buffer_type[i] == NANOARROW_BUFFER_TYPE_NONE) {
2538
+ break;
2539
+ }
2540
+
2541
+ buffers_required++;
2542
+
2543
+ // Set buffer pointer
2544
+ array_view->buffer_views[i].data.data = array->buffers[i];
2545
+
2546
+ // If non-null, set buffer size to unknown.
2547
+ if (array->buffers[i] == NULL) {
2548
+ array_view->buffer_views[i].size_bytes = 0;
2549
+ } else {
2550
+ array_view->buffer_views[i].size_bytes = -1;
2551
+ }
2552
+ }
2553
+
2554
+ // Check the number of buffers
2555
+ if (buffers_required != array->n_buffers) {
2556
+ ArrowErrorSet(error,
2557
+ "Expected array with %d buffer(s) but found %d buffer(s)",
2558
+ (int)buffers_required, (int)array->n_buffers);
2559
+ return EINVAL;
2560
+ }
2561
+
2562
+ // Check number of children
2563
+ if (array_view->n_children != array->n_children) {
2564
+ ArrowErrorSet(error, "Expected %ld children but found %ld children",
2565
+ (long)array_view->n_children, (long)array->n_children);
2566
+ return EINVAL;
2567
+ }
2568
+
2569
+ // Recurse for children
2570
+ for (int64_t i = 0; i < array_view->n_children; i++) {
2571
+ NANOARROW_RETURN_NOT_OK(ArrowArrayViewSetArrayInternal(
2572
+ array_view->children[i], array->children[i], error));
2573
+ }
2574
+
2575
+ // Check dictionary
2576
+ if (array->dictionary == NULL && array_view->dictionary != NULL) {
2577
+ ArrowErrorSet(error, "Expected dictionary but found NULL");
2578
+ return EINVAL;
2579
+ }
2580
+
2581
+ if (array->dictionary != NULL && array_view->dictionary == NULL) {
2582
+ ArrowErrorSet(error,
2583
+ "Expected NULL dictionary but found dictionary member");
2584
+ return EINVAL;
2585
+ }
2586
+
2587
+ if (array->dictionary != NULL) {
2588
+ NANOARROW_RETURN_NOT_OK(ArrowArrayViewSetArrayInternal(
2589
+ array_view->dictionary, array->dictionary, error));
2590
+ }
2591
+
2592
+ return NANOARROW_OK;
2593
+ }
2594
+
2595
+ static int ArrowArrayViewValidateMinimal(struct ArrowArrayView* array_view,
2596
+ struct ArrowError* error) {
2597
+ // Calculate buffer sizes that do not require buffer access. If marked as
2598
+ // unknown, assign the buffer size; otherwise, validate it.
2599
+ int64_t offset_plus_length = array_view->offset + array_view->length;
2600
+
2601
+ // Only loop over the first two buffers because the size of the third buffer
2602
+ // is always data dependent for all current Arrow types.
2603
+ for (int i = 0; i < 2; i++) {
2604
+ int64_t element_size_bytes = array_view->layout.element_size_bits[i] / 8;
2605
+ // Initialize with a value that will cause an error if accidentally used
2606
+ // uninitialized
2607
+ int64_t min_buffer_size_bytes = array_view->buffer_views[i].size_bytes + 1;
2608
+
2609
+ switch (array_view->layout.buffer_type[i]) {
2610
+ case NANOARROW_BUFFER_TYPE_VALIDITY:
2611
+ if (array_view->null_count == 0 &&
2612
+ array_view->buffer_views[i].size_bytes == 0) {
2613
+ continue;
2614
+ }
2615
+
2616
+ min_buffer_size_bytes = _ArrowBytesForBits(offset_plus_length);
2617
+ break;
2618
+ case NANOARROW_BUFFER_TYPE_DATA_OFFSET:
2619
+ // Probably don't want/need to rely on the producer to have allocated an
2620
+ // offsets buffer of length 1 for a zero-size array
2621
+ min_buffer_size_bytes = (offset_plus_length != 0) * element_size_bytes *
2622
+ (offset_plus_length + 1);
2623
+ break;
2624
+ case NANOARROW_BUFFER_TYPE_DATA:
2625
+ min_buffer_size_bytes =
2626
+ _ArrowRoundUpToMultipleOf8(array_view->layout.element_size_bits[i] *
2627
+ offset_plus_length) /
2628
+ 8;
2629
+ break;
2630
+ case NANOARROW_BUFFER_TYPE_TYPE_ID:
2631
+ case NANOARROW_BUFFER_TYPE_UNION_OFFSET:
2632
+ min_buffer_size_bytes = element_size_bytes * offset_plus_length;
2633
+ break;
2634
+ case NANOARROW_BUFFER_TYPE_NONE:
2635
+ continue;
2636
+ }
2637
+
2638
+ // Assign or validate buffer size
2639
+ if (array_view->buffer_views[i].size_bytes == -1) {
2640
+ array_view->buffer_views[i].size_bytes = min_buffer_size_bytes;
2641
+ } else if (array_view->buffer_views[i].size_bytes < min_buffer_size_bytes) {
2642
+ ArrowErrorSet(
2643
+ error,
2644
+ "Expected %s array buffer %d to have size >= %ld bytes but found "
2645
+ "buffer with %ld bytes",
2646
+ ArrowTypeString(array_view->storage_type), (int)i,
2647
+ (long)min_buffer_size_bytes,
2648
+ (long)array_view->buffer_views[i].size_bytes);
2649
+ return EINVAL;
2650
+ }
2651
+ }
2652
+
2653
+ // For list, fixed-size list and map views, we can validate the number of
2654
+ // children
2655
+ switch (array_view->storage_type) {
2656
+ case NANOARROW_TYPE_LIST:
2657
+ case NANOARROW_TYPE_LARGE_LIST:
2658
+ case NANOARROW_TYPE_FIXED_SIZE_LIST:
2659
+ case NANOARROW_TYPE_MAP:
2660
+ if (array_view->n_children != 1) {
2661
+ ArrowErrorSet(error,
2662
+ "Expected 1 child of %s array but found %ld child arrays",
2663
+ ArrowTypeString(array_view->storage_type),
2664
+ (long)array_view->n_children);
2665
+ return EINVAL;
2666
+ }
2667
+ default:
2668
+ break;
2669
+ }
2670
+
2671
+ // For struct, the sparse union, and the fixed-size list views, we can
2672
+ // validate child lengths.
2673
+ int64_t child_min_length;
2674
+ switch (array_view->storage_type) {
2675
+ case NANOARROW_TYPE_SPARSE_UNION:
2676
+ case NANOARROW_TYPE_STRUCT:
2677
+ child_min_length = (array_view->offset + array_view->length);
2678
+ for (int64_t i = 0; i < array_view->n_children; i++) {
2679
+ if (array_view->children[i]->length < child_min_length) {
2680
+ ArrowErrorSet(error,
2681
+ "Expected struct child %d to have length >= %ld but "
2682
+ "found child with "
2683
+ "length %ld",
2684
+ (int)(i + 1), (long)(child_min_length),
2685
+ (long)array_view->children[i]->length);
2686
+ return EINVAL;
2687
+ }
2688
+ }
2689
+ break;
2690
+
2691
+ case NANOARROW_TYPE_FIXED_SIZE_LIST:
2692
+ child_min_length = (array_view->offset + array_view->length) *
2693
+ array_view->layout.child_size_elements;
2694
+ if (array_view->children[0]->length < child_min_length) {
2695
+ ArrowErrorSet(
2696
+ error,
2697
+ "Expected child of fixed_size_list array to have length >= %ld but "
2698
+ "found array with length %ld",
2699
+ (long)child_min_length, (long)array_view->children[0]->length);
2700
+ return EINVAL;
2701
+ }
2702
+ break;
2703
+ default:
2704
+ break;
2705
+ }
2706
+
2707
+ // Recurse for children
2708
+ for (int64_t i = 0; i < array_view->n_children; i++) {
2709
+ NANOARROW_RETURN_NOT_OK(
2710
+ ArrowArrayViewValidateMinimal(array_view->children[i], error));
2711
+ }
2712
+
2713
+ // Recurse for dictionary
2714
+ if (array_view->dictionary != NULL) {
2715
+ NANOARROW_RETURN_NOT_OK(
2716
+ ArrowArrayViewValidateMinimal(array_view->dictionary, error));
2717
+ }
2718
+
2719
+ return NANOARROW_OK;
2720
+ }
2721
+
2722
+ static int ArrowArrayViewValidateDefault(struct ArrowArrayView* array_view,
2723
+ struct ArrowError* error) {
2724
+ // Perform minimal validation. This will validate or assign
2725
+ // buffer sizes as long as buffer access is not required.
2726
+ NANOARROW_RETURN_NOT_OK(ArrowArrayViewValidateMinimal(array_view, error));
2727
+
2728
+ // Calculate buffer sizes or child lengths that require accessing the offsets
2729
+ // buffer. Where appropriate, validate that the first offset is >= 0.
2730
+ // If a buffer size is marked as unknown, assign it; otherwise, validate it.
2731
+ int64_t offset_plus_length = array_view->offset + array_view->length;
2732
+
2733
+ int64_t first_offset;
2734
+ int64_t last_offset;
2735
+ switch (array_view->storage_type) {
2736
+ case NANOARROW_TYPE_STRING:
2737
+ case NANOARROW_TYPE_BINARY:
2738
+ if (array_view->buffer_views[1].size_bytes != 0) {
2739
+ first_offset = array_view->buffer_views[1].data.as_int32[0];
2740
+ if (first_offset < 0) {
2741
+ ArrowErrorSet(error, "Expected first offset >= 0 but found %ld",
2742
+ (long)first_offset);
2743
+ return EINVAL;
2744
+ }
2745
+
2746
+ last_offset =
2747
+ array_view->buffer_views[1].data.as_int32[offset_plus_length];
2748
+
2749
+ // If the data buffer size is unknown, assign it; otherwise, check it
2750
+ if (array_view->buffer_views[2].size_bytes == -1) {
2751
+ array_view->buffer_views[2].size_bytes = last_offset;
2752
+ } else if (array_view->buffer_views[2].size_bytes < last_offset) {
2753
+ ArrowErrorSet(
2754
+ error,
2755
+ "Expected %s array buffer 2 to have size >= %ld bytes but found "
2756
+ "buffer with %ld bytes",
2757
+ ArrowTypeString(array_view->storage_type), (long)last_offset,
2758
+ (long)array_view->buffer_views[2].size_bytes);
2759
+ return EINVAL;
2760
+ }
2761
+ }
2762
+ break;
2763
+
2764
+ case NANOARROW_TYPE_LARGE_STRING:
2765
+ case NANOARROW_TYPE_LARGE_BINARY:
2766
+ if (array_view->buffer_views[1].size_bytes != 0) {
2767
+ first_offset = array_view->buffer_views[1].data.as_int64[0];
2768
+ if (first_offset < 0) {
2769
+ ArrowErrorSet(error, "Expected first offset >= 0 but found %ld",
2770
+ (long)first_offset);
2771
+ return EINVAL;
2772
+ }
2773
+
2774
+ last_offset =
2775
+ array_view->buffer_views[1].data.as_int64[offset_plus_length];
2776
+
2777
+ // If the data buffer size is unknown, assign it; otherwise, check it
2778
+ if (array_view->buffer_views[2].size_bytes == -1) {
2779
+ array_view->buffer_views[2].size_bytes = last_offset;
2780
+ } else if (array_view->buffer_views[2].size_bytes < last_offset) {
2781
+ ArrowErrorSet(
2782
+ error,
2783
+ "Expected %s array buffer 2 to have size >= %ld bytes but found "
2784
+ "buffer with %ld bytes",
2785
+ ArrowTypeString(array_view->storage_type), (long)last_offset,
2786
+ (long)array_view->buffer_views[2].size_bytes);
2787
+ return EINVAL;
2788
+ }
2789
+ }
2790
+ break;
2791
+
2792
+ case NANOARROW_TYPE_STRUCT:
2793
+ for (int64_t i = 0; i < array_view->n_children; i++) {
2794
+ if (array_view->children[i]->length < offset_plus_length) {
2795
+ ArrowErrorSet(error,
2796
+ "Expected struct child %d to have length >= %ld but "
2797
+ "found child with "
2798
+ "length %ld",
2799
+ (int)(i + 1), (long)offset_plus_length,
2800
+ (long)array_view->children[i]->length);
2801
+ return EINVAL;
2802
+ }
2803
+ }
2804
+ break;
2805
+
2806
+ case NANOARROW_TYPE_LIST:
2807
+ case NANOARROW_TYPE_MAP:
2808
+ if (array_view->buffer_views[1].size_bytes != 0) {
2809
+ first_offset = array_view->buffer_views[1].data.as_int32[0];
2810
+ if (first_offset < 0) {
2811
+ ArrowErrorSet(error, "Expected first offset >= 0 but found %ld",
2812
+ (long)first_offset);
2813
+ return EINVAL;
2814
+ }
2815
+
2816
+ last_offset =
2817
+ array_view->buffer_views[1].data.as_int32[offset_plus_length];
2818
+ if (array_view->children[0]->length < last_offset) {
2819
+ ArrowErrorSet(error,
2820
+ "Expected child of %s array to have length >= %ld but "
2821
+ "found array with "
2822
+ "length %ld",
2823
+ ArrowTypeString(array_view->storage_type),
2824
+ (long)last_offset,
2825
+ (long)array_view->children[0]->length);
2826
+ return EINVAL;
2827
+ }
2828
+ }
2829
+ break;
2830
+
2831
+ case NANOARROW_TYPE_LARGE_LIST:
2832
+ if (array_view->buffer_views[1].size_bytes != 0) {
2833
+ first_offset = array_view->buffer_views[1].data.as_int64[0];
2834
+ if (first_offset < 0) {
2835
+ ArrowErrorSet(error, "Expected first offset >= 0 but found %ld",
2836
+ (long)first_offset);
2837
+ return EINVAL;
2838
+ }
2839
+
2840
+ last_offset =
2841
+ array_view->buffer_views[1].data.as_int64[offset_plus_length];
2842
+ if (array_view->children[0]->length < last_offset) {
2843
+ ArrowErrorSet(error,
2844
+ "Expected child of large list array to have length >= "
2845
+ "%ld but found array "
2846
+ "with length %ld",
2847
+ (long)last_offset,
2848
+ (long)array_view->children[0]->length);
2849
+ return EINVAL;
2850
+ }
2851
+ }
2852
+ break;
2853
+ default:
2854
+ break;
2855
+ }
2856
+
2857
+ // Recurse for children
2858
+ for (int64_t i = 0; i < array_view->n_children; i++) {
2859
+ NANOARROW_RETURN_NOT_OK(
2860
+ ArrowArrayViewValidateDefault(array_view->children[i], error));
2861
+ }
2862
+
2863
+ // Recurse for dictionary
2864
+ if (array_view->dictionary != NULL) {
2865
+ NANOARROW_RETURN_NOT_OK(
2866
+ ArrowArrayViewValidateDefault(array_view->dictionary, error));
2867
+ }
2868
+
2869
+ return NANOARROW_OK;
2870
+ }
2871
+
2872
+ ArrowErrorCode ArrowArrayViewSetArray(struct ArrowArrayView* array_view,
2873
+ struct ArrowArray* array,
2874
+ struct ArrowError* error) {
2875
+ // Extract information from the array into the array view
2876
+ NANOARROW_RETURN_NOT_OK(
2877
+ ArrowArrayViewSetArrayInternal(array_view, array, error));
2878
+
2879
+ // Run default validation. Because we've marked all non-NULL buffers as having
2880
+ // unknown size, validation will also update the buffer sizes as it goes.
2881
+ NANOARROW_RETURN_NOT_OK(ArrowArrayViewValidateDefault(array_view, error));
2882
+
2883
+ return NANOARROW_OK;
2884
+ }
2885
+
2886
+ ArrowErrorCode ArrowArrayViewSetArrayMinimal(struct ArrowArrayView* array_view,
2887
+ struct ArrowArray* array,
2888
+ struct ArrowError* error) {
2889
+ // Extract information from the array into the array view
2890
+ NANOARROW_RETURN_NOT_OK(
2891
+ ArrowArrayViewSetArrayInternal(array_view, array, error));
2892
+
2893
+ // Run default validation. Because we've marked all non-NULL buffers as having
2894
+ // unknown size, validation will also update the buffer sizes as it goes.
2895
+ NANOARROW_RETURN_NOT_OK(ArrowArrayViewValidateMinimal(array_view, error));
2896
+
2897
+ return NANOARROW_OK;
2898
+ }
2899
+
2900
+ static int ArrowAssertIncreasingInt32(struct ArrowBufferView view,
2901
+ struct ArrowError* error) {
2902
+ if (view.size_bytes <= (int64_t)sizeof(int32_t)) {
2903
+ return NANOARROW_OK;
2904
+ }
2905
+
2906
+ for (int64_t i = 1; i < view.size_bytes / (int64_t)sizeof(int32_t); i++) {
2907
+ if (view.data.as_int32[i] < view.data.as_int32[i - 1]) {
2908
+ ArrowErrorSet(error, "[%ld] Expected element size >= 0", (long)i);
2909
+ return EINVAL;
2910
+ }
2911
+ }
2912
+
2913
+ return NANOARROW_OK;
2914
+ }
2915
+
2916
+ static int ArrowAssertIncreasingInt64(struct ArrowBufferView view,
2917
+ struct ArrowError* error) {
2918
+ if (view.size_bytes <= (int64_t)sizeof(int64_t)) {
2919
+ return NANOARROW_OK;
2920
+ }
2921
+
2922
+ for (int64_t i = 1; i < view.size_bytes / (int64_t)sizeof(int64_t); i++) {
2923
+ if (view.data.as_int64[i] < view.data.as_int64[i - 1]) {
2924
+ ArrowErrorSet(error, "[%ld] Expected element size >= 0", (long)i);
2925
+ return EINVAL;
2926
+ }
2927
+ }
2928
+
2929
+ return NANOARROW_OK;
2930
+ }
2931
+
2932
+ static int ArrowAssertRangeInt8(struct ArrowBufferView view, int8_t min_value,
2933
+ int8_t max_value, struct ArrowError* error) {
2934
+ for (int64_t i = 0; i < view.size_bytes; i++) {
2935
+ if (view.data.as_int8[i] < min_value || view.data.as_int8[i] > max_value) {
2936
+ ArrowErrorSet(
2937
+ error,
2938
+ "[%ld] Expected buffer value between %d and %d but found value %d",
2939
+ (long)i, (int)min_value, (int)max_value, (int)view.data.as_int8[i]);
2940
+ return EINVAL;
2941
+ }
2942
+ }
2943
+
2944
+ return NANOARROW_OK;
2945
+ }
2946
+
2947
+ static int ArrowAssertInt8In(struct ArrowBufferView view, const int8_t* values,
2948
+ int64_t n_values, struct ArrowError* error) {
2949
+ for (int64_t i = 0; i < view.size_bytes; i++) {
2950
+ int item_found = 0;
2951
+ for (int64_t j = 0; j < n_values; j++) {
2952
+ if (view.data.as_int8[i] == values[j]) {
2953
+ item_found = 1;
2954
+ break;
2955
+ }
2956
+ }
2957
+
2958
+ if (!item_found) {
2959
+ ArrowErrorSet(error, "[%ld] Unexpected buffer value %d", (long)i,
2960
+ (int)view.data.as_int8[i]);
2961
+ return EINVAL;
2962
+ }
2963
+ }
2964
+
2965
+ return NANOARROW_OK;
2966
+ }
2967
+
2968
+ static int ArrowArrayViewValidateFull(struct ArrowArrayView* array_view,
2969
+ struct ArrowError* error) {
2970
+ for (int i = 0; i < 3; i++) {
2971
+ switch (array_view->layout.buffer_type[i]) {
2972
+ case NANOARROW_BUFFER_TYPE_DATA_OFFSET:
2973
+ if (array_view->layout.element_size_bits[i] == 32) {
2974
+ NANOARROW_RETURN_NOT_OK(
2975
+ ArrowAssertIncreasingInt32(array_view->buffer_views[i], error));
2976
+ } else {
2977
+ NANOARROW_RETURN_NOT_OK(
2978
+ ArrowAssertIncreasingInt64(array_view->buffer_views[i], error));
2979
+ }
2980
+ break;
2981
+ default:
2982
+ break;
2983
+ }
2984
+ }
2985
+
2986
+ if (array_view->storage_type == NANOARROW_TYPE_DENSE_UNION ||
2987
+ array_view->storage_type == NANOARROW_TYPE_SPARSE_UNION) {
2988
+ if (array_view->union_type_id_map == NULL) {
2989
+ // If the union_type_id map is NULL (e.g., when using
2990
+ // ArrowArrayInitFromType() + ArrowArrayAllocateChildren() +
2991
+ // ArrowArrayFinishBuilding()), we don't have enough information to
2992
+ // validate this buffer.
2993
+ ArrowErrorSet(
2994
+ error,
2995
+ "Insufficient information provided for validation of union array");
2996
+ return EINVAL;
2997
+ } else if (_ArrowParsedUnionTypeIdsWillEqualChildIndices(
2998
+ array_view->union_type_id_map, array_view->n_children,
2999
+ array_view->n_children)) {
3000
+ NANOARROW_RETURN_NOT_OK(
3001
+ ArrowAssertRangeInt8(array_view->buffer_views[0], 0,
3002
+ (int8_t)(array_view->n_children - 1), error));
3003
+ } else {
3004
+ NANOARROW_RETURN_NOT_OK(ArrowAssertInt8In(
3005
+ array_view->buffer_views[0], array_view->union_type_id_map + 128,
3006
+ array_view->n_children, error));
3007
+ }
3008
+ }
3009
+
3010
+ if (array_view->storage_type == NANOARROW_TYPE_DENSE_UNION &&
3011
+ array_view->union_type_id_map != NULL) {
3012
+ // Check that offsets refer to child elements that actually exist
3013
+ for (int64_t i = 0; i < array_view->length; i++) {
3014
+ int8_t child_id = ArrowArrayViewUnionChildIndex(array_view, i);
3015
+ int64_t offset = ArrowArrayViewUnionChildOffset(array_view, i);
3016
+ int64_t child_length = array_view->children[child_id]->length;
3017
+ if (offset < 0 || offset > child_length) {
3018
+ ArrowErrorSet(error,
3019
+ "[%ld] Expected union offset for child id %d to be "
3020
+ "between 0 and %ld but "
3021
+ "found offset value %ld",
3022
+ (long)i, (int)child_id, (long)child_length, offset);
3023
+ return EINVAL;
3024
+ }
3025
+ }
3026
+ }
3027
+
3028
+ // Recurse for children
3029
+ for (int64_t i = 0; i < array_view->n_children; i++) {
3030
+ NANOARROW_RETURN_NOT_OK(
3031
+ ArrowArrayViewValidateFull(array_view->children[i], error));
3032
+ }
3033
+
3034
+ // Dictionary valiation not implemented
3035
+ if (array_view->dictionary != NULL) {
3036
+ ArrowErrorSet(
3037
+ error, "Validation for dictionary-encoded arrays is not implemented");
3038
+ return ENOTSUP;
3039
+ }
3040
+
3041
+ return NANOARROW_OK;
3042
+ }
3043
+
3044
+ ArrowErrorCode ArrowArrayViewValidate(
3045
+ struct ArrowArrayView* array_view,
3046
+ enum ArrowValidationLevel validation_level, struct ArrowError* error) {
3047
+ switch (validation_level) {
3048
+ case NANOARROW_VALIDATION_LEVEL_NONE:
3049
+ return NANOARROW_OK;
3050
+ case NANOARROW_VALIDATION_LEVEL_MINIMAL:
3051
+ return ArrowArrayViewValidateMinimal(array_view, error);
3052
+ case NANOARROW_VALIDATION_LEVEL_DEFAULT:
3053
+ return ArrowArrayViewValidateDefault(array_view, error);
3054
+ case NANOARROW_VALIDATION_LEVEL_FULL:
3055
+ NANOARROW_RETURN_NOT_OK(ArrowArrayViewValidateDefault(array_view, error));
3056
+ return ArrowArrayViewValidateFull(array_view, error);
3057
+ }
3058
+
3059
+ ArrowErrorSet(error, "validation_level not recognized");
3060
+ return EINVAL;
3061
+ }
3062
+ // Licensed to the Apache Software Foundation (ASF) under one
3063
+ // or more contributor license agreements. See the NOTICE file
3064
+ // distributed with this work for additional information
3065
+ // regarding copyright ownership. The ASF licenses this file
3066
+ // to you under the Apache License, Version 2.0 (the
3067
+ // "License"); you may not use this file except in compliance
3068
+ // with the License. You may obtain a copy of the License at
3069
+ //
3070
+ // http://www.apache.org/licenses/LICENSE-2.0
3071
+ //
3072
+ // Unless required by applicable law or agreed to in writing,
3073
+ // software distributed under the License is distributed on an
3074
+ // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
3075
+ // KIND, either express or implied. See the License for the
3076
+ // specific language governing permissions and limitations
3077
+ // under the License.
3078
+
3079
+ #include <errno.h>
3080
+
3081
+ #include "nanoarrow.h"
3082
+
3083
+ struct BasicArrayStreamPrivate {
3084
+ struct ArrowSchema schema;
3085
+ int64_t n_arrays;
3086
+ struct ArrowArray* arrays;
3087
+ int64_t arrays_i;
3088
+ };
3089
+
3090
+ static int ArrowBasicArrayStreamGetSchema(struct ArrowArrayStream* array_stream,
3091
+ struct ArrowSchema* schema) {
3092
+ if (array_stream == NULL || array_stream->release == NULL) {
3093
+ return EINVAL;
3094
+ }
3095
+
3096
+ struct BasicArrayStreamPrivate* private_data =
3097
+ (struct BasicArrayStreamPrivate*)array_stream->private_data;
3098
+ return ArrowSchemaDeepCopy(&private_data->schema, schema);
3099
+ }
3100
+
3101
+ static int ArrowBasicArrayStreamGetNext(struct ArrowArrayStream* array_stream,
3102
+ struct ArrowArray* array) {
3103
+ if (array_stream == NULL || array_stream->release == NULL) {
3104
+ return EINVAL;
3105
+ }
3106
+
3107
+ struct BasicArrayStreamPrivate* private_data =
3108
+ (struct BasicArrayStreamPrivate*)array_stream->private_data;
3109
+
3110
+ if (private_data->arrays_i == private_data->n_arrays) {
3111
+ array->release = NULL;
3112
+ return NANOARROW_OK;
3113
+ }
3114
+
3115
+ ArrowArrayMove(&private_data->arrays[private_data->arrays_i++], array);
3116
+ return NANOARROW_OK;
3117
+ }
3118
+
3119
+ static const char* ArrowBasicArrayStreamGetLastError(
3120
+ struct ArrowArrayStream* array_stream) {
3121
+ return NULL;
3122
+ }
3123
+
3124
+ static void ArrowBasicArrayStreamRelease(
3125
+ struct ArrowArrayStream* array_stream) {
3126
+ if (array_stream == NULL || array_stream->release == NULL) {
3127
+ return;
3128
+ }
3129
+
3130
+ struct BasicArrayStreamPrivate* private_data =
3131
+ (struct BasicArrayStreamPrivate*)array_stream->private_data;
3132
+
3133
+ if (private_data->schema.release != NULL) {
3134
+ private_data->schema.release(&private_data->schema);
3135
+ }
3136
+
3137
+ for (int64_t i = 0; i < private_data->n_arrays; i++) {
3138
+ if (private_data->arrays[i].release != NULL) {
3139
+ private_data->arrays[i].release(&private_data->arrays[i]);
3140
+ }
3141
+ }
3142
+
3143
+ if (private_data->arrays != NULL) {
3144
+ ArrowFree(private_data->arrays);
3145
+ }
3146
+
3147
+ ArrowFree(private_data);
3148
+ array_stream->release = NULL;
3149
+ }
3150
+
3151
+ ArrowErrorCode ArrowBasicArrayStreamInit(struct ArrowArrayStream* array_stream,
3152
+ struct ArrowSchema* schema,
3153
+ int64_t n_arrays) {
3154
+ struct BasicArrayStreamPrivate* private_data =
3155
+ (struct BasicArrayStreamPrivate*)ArrowMalloc(
3156
+ sizeof(struct BasicArrayStreamPrivate));
3157
+ if (private_data == NULL) {
3158
+ return ENOMEM;
3159
+ }
3160
+
3161
+ ArrowSchemaMove(schema, &private_data->schema);
3162
+
3163
+ private_data->n_arrays = n_arrays;
3164
+ private_data->arrays = NULL;
3165
+ private_data->arrays_i = 0;
3166
+
3167
+ if (n_arrays > 0) {
3168
+ private_data->arrays =
3169
+ (struct ArrowArray*)ArrowMalloc(n_arrays * sizeof(struct ArrowArray));
3170
+ if (private_data->arrays == NULL) {
3171
+ ArrowBasicArrayStreamRelease(array_stream);
3172
+ return ENOMEM;
3173
+ }
3174
+ }
3175
+
3176
+ for (int64_t i = 0; i < private_data->n_arrays; i++) {
3177
+ private_data->arrays[i].release = NULL;
3178
+ }
3179
+
3180
+ array_stream->get_schema = &ArrowBasicArrayStreamGetSchema;
3181
+ array_stream->get_next = &ArrowBasicArrayStreamGetNext;
3182
+ array_stream->get_last_error = ArrowBasicArrayStreamGetLastError;
3183
+ array_stream->release = ArrowBasicArrayStreamRelease;
3184
+ array_stream->private_data = private_data;
3185
+ return NANOARROW_OK;
3186
+ }
3187
+
3188
+ void ArrowBasicArrayStreamSetArray(struct ArrowArrayStream* array_stream,
3189
+ int64_t i, struct ArrowArray* array) {
3190
+ struct BasicArrayStreamPrivate* private_data =
3191
+ (struct BasicArrayStreamPrivate*)array_stream->private_data;
3192
+ ArrowArrayMove(array, &private_data->arrays[i]);
3193
+ }
3194
+
3195
+ ArrowErrorCode ArrowBasicArrayStreamValidate(
3196
+ struct ArrowArrayStream* array_stream, struct ArrowError* error) {
3197
+ struct BasicArrayStreamPrivate* private_data =
3198
+ (struct BasicArrayStreamPrivate*)array_stream->private_data;
3199
+
3200
+ struct ArrowArrayView array_view;
3201
+ NANOARROW_RETURN_NOT_OK(
3202
+ ArrowArrayViewInitFromSchema(&array_view, &private_data->schema, error));
3203
+
3204
+ for (int64_t i = 0; i < private_data->n_arrays; i++) {
3205
+ if (private_data->arrays[i].release != NULL) {
3206
+ int result =
3207
+ ArrowArrayViewSetArray(&array_view, &private_data->arrays[i], error);
3208
+ if (result != NANOARROW_OK) {
3209
+ ArrowArrayViewReset(&array_view);
3210
+ return result;
3211
+ }
3212
+ }
3213
+ }
3214
+
3215
+ ArrowArrayViewReset(&array_view);
3216
+ return NANOARROW_OK;
3217
+ }