You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by gi...@apache.org on 2023/05/11 12:20:44 UTC

[arrow-nanoarrow] branch main updated: Update dist/ for commit cc4041a57f2e8db5907c128e21c72947fdd539ce

This is an automated email from the ASF dual-hosted git repository.

github-bot pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-nanoarrow.git


The following commit(s) were added to refs/heads/main by this push:
     new d7cdb75  Update dist/ for commit cc4041a57f2e8db5907c128e21c72947fdd539ce
d7cdb75 is described below

commit d7cdb752c63e5a6220a7bc76920d661a299f604a
Author: GitHub Actions <ac...@github.com>
AuthorDate: Thu May 11 12:20:38 2023 +0000

    Update dist/ for commit cc4041a57f2e8db5907c128e21c72947fdd539ce
---
 dist/nanoarrow.c   |  16 ++++++--
 dist/nanoarrow.h   | 118 ++++++++++++++++++++++++++++++++++++++++++++++-------
 dist/nanoarrow.hpp |  50 +++++++++++++++++++++++
 3 files changed, 166 insertions(+), 18 deletions(-)

diff --git a/dist/nanoarrow.c b/dist/nanoarrow.c
index 0b8fc35..e5a256d 100644
--- a/dist/nanoarrow.c
+++ b/dist/nanoarrow.c
@@ -49,7 +49,13 @@ int ArrowErrorSet(struct ArrowError* error, const char* fmt, ...) {
   }
 }
 
-const char* ArrowErrorMessage(struct ArrowError* error) { return error->message; }
+const char* ArrowErrorMessage(struct ArrowError* error) {
+  if (error == NULL) {
+    return "";
+  } else {
+    return error->message;
+  }
+}
 
 void ArrowLayoutInit(struct ArrowLayout* layout, enum ArrowType storage_type) {
   layout->buffer_type[0] = NANOARROW_BUFFER_TYPE_VALIDITY;
@@ -2168,7 +2174,7 @@ ArrowErrorCode ArrowArrayFinishBuilding(struct ArrowArray* array,
   // in some implementations (at least one version of Arrow C++ at the time this
   // was added). Only do this fix if we can assume CPU data access.
   if (validation_level >= NANOARROW_VALIDATION_LEVEL_DEFAULT) {
-    NANOARROW_RETURN_NOT_OK(ArrowArrayFinalizeBuffers(array));
+    NANOARROW_RETURN_NOT_OK_WITH_ERROR(ArrowArrayFinalizeBuffers(array), error);
   }
 
   // Make sure the value we get with array->buffers[i] is set to the actual
@@ -2183,7 +2189,8 @@ ArrowErrorCode ArrowArrayFinishBuilding(struct ArrowArray* array,
   // into the wild that is going to segfault
   struct ArrowArrayView array_view;
 
-  NANOARROW_RETURN_NOT_OK(ArrowArrayViewInitFromArray(&array_view, array));
+  NANOARROW_RETURN_NOT_OK_WITH_ERROR(ArrowArrayViewInitFromArray(&array_view, array),
+                                     error);
 
   // Check buffer sizes once without using internal buffer data since
   // ArrowArrayViewSetArray() assumes that all the buffers are long enough
@@ -2277,6 +2284,7 @@ ArrowErrorCode ArrowArrayViewInitFromSchema(struct ArrowArrayView* array_view,
 
   result = ArrowArrayViewAllocateChildren(array_view, schema->n_children);
   if (result != NANOARROW_OK) {
+    ArrowErrorSet(error, "ArrowArrayViewAllocateChildren() failed");
     ArrowArrayViewReset(array_view);
     return result;
   }
@@ -2663,7 +2671,7 @@ ArrowErrorCode ArrowArrayViewValidateFull(struct ArrowArrayView* array_view,
                    array_view->union_type_id_map, array_view->n_children,
                    array_view->n_children)) {
       NANOARROW_RETURN_NOT_OK(ArrowAssertRangeInt8(array_view->buffer_views[0], 0,
-                                                   array_view->n_children - 1, error));
+                                                   (int8_t)(array_view->n_children - 1), error));
     } else {
       NANOARROW_RETURN_NOT_OK(ArrowAssertInt8In(array_view->buffer_views[0],
                                                 array_view->union_type_id_map + 128,
diff --git a/dist/nanoarrow.h b/dist/nanoarrow.h
index 90ce2dc..e3ebb0b 100644
--- a/dist/nanoarrow.h
+++ b/dist/nanoarrow.h
@@ -55,6 +55,11 @@
 
 
 
+#if defined(NANOARROW_DEBUG) && !defined(NANOARROW_PRINT_AND_DIE)
+#include <stdio.h>
+#include <stdlib.h>
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -191,6 +196,27 @@ static inline void ArrowArrayStreamMove(struct ArrowArrayStream* src,
 #define _NANOARROW_CHECK_RANGE(x_, min_, max_) \
   NANOARROW_RETURN_NOT_OK((x_ >= min_ && x_ <= max_) ? NANOARROW_OK : EINVAL)
 
+#if defined(NANOARROW_DEBUG)
+#define _NANOARROW_RETURN_NOT_OK_WITH_ERROR_IMPL(NAME, EXPR, ERROR_PTR_EXPR, EXPR_STR) \
+  do {                                                                                 \
+    const int NAME = (EXPR);                                                           \
+    if (NAME) {                                                                        \
+      ArrowErrorSet((ERROR_PTR_EXPR), "%s failed with errno %d\n* %s:%d", EXPR_STR,    \
+                    NAME, __FILE__, __LINE__);                                         \
+      return NAME;                                                                     \
+    }                                                                                  \
+  } while (0)
+#else
+#define _NANOARROW_RETURN_NOT_OK_WITH_ERROR_IMPL(NAME, EXPR, ERROR_PTR_EXPR, EXPR_STR) \
+  do {                                                                                 \
+    const int NAME = (EXPR);                                                           \
+    if (NAME) {                                                                        \
+      ArrowErrorSet((ERROR_PTR_EXPR), "%s failed with errno %d", EXPR_STR, NAME);      \
+      return NAME;                                                                     \
+    }                                                                                  \
+  } while (0)
+#endif
+
 /// \brief Return code for success.
 /// \ingroup nanoarrow-errors
 #define NANOARROW_OK 0
@@ -204,6 +230,47 @@ typedef int ArrowErrorCode;
 #define NANOARROW_RETURN_NOT_OK(EXPR) \
   _NANOARROW_RETURN_NOT_OK_IMPL(_NANOARROW_MAKE_NAME(errno_status_, __COUNTER__), EXPR)
 
+/// \brief Check the result of an expression and return it if not NANOARROW_OK,
+/// adding an auto-generated message to an ArrowError.
+/// \ingroup nanoarrow-errors
+///
+/// This macro is used to ensure that functions that accept an ArrowError
+/// as input always set its message when returning an error code (e.g., when calling
+/// a nanoarrow function that does *not* accept ArrowError).
+#define NANOARROW_RETURN_NOT_OK_WITH_ERROR(EXPR, ERROR_EXPR) \
+  _NANOARROW_RETURN_NOT_OK_WITH_ERROR_IMPL(                  \
+      _NANOARROW_MAKE_NAME(errno_status_, __COUNTER__), EXPR, ERROR_EXPR, #EXPR)
+
+#if defined(NANOARROW_DEBUG) && !defined(NANOARROW_PRINT_AND_DIE)
+#define NANOARROW_PRINT_AND_DIE(VALUE, EXPR_STR)                                  \
+  do {                                                                            \
+    fprintf(stderr, "%s failed with errno %d\n* %s:%d\n", EXPR_STR, (int)(VALUE), \
+            __FILE__, (int)__LINE__);                                             \
+    abort();                                                                      \
+  } while (0)
+#endif
+
+#if defined(NANOARROW_DEBUG)
+#define _NANOARROW_ASSERT_OK_IMPL(NAME, EXPR, EXPR_STR) \
+  do {                                                  \
+    const int NAME = (EXPR);                            \
+    if (NAME) NANOARROW_PRINT_AND_DIE(NAME, EXPR_STR);  \
+  } while (0)
+
+/// \brief Assert that an expression's value is NANOARROW_OK
+/// \ingroup nanoarrow-errors
+///
+/// If nanoarrow was built in debug mode (i.e., defined(NANOARROW_DEBUG) is true),
+/// print a message to stderr and abort. If nanoarrow was bulit in release mode,
+/// this statement has no effect. You can customize fatal error behaviour
+/// be defining the NANOARROW_PRINT_AND_DIE macro before including nanoarrow.h
+/// This macro is provided as a convenience for users and is not used internally.
+#define NANOARROW_ASSERT_OK(EXPR) \
+  _NANOARROW_ASSERT_OK_IMPL(_NANOARROW_MAKE_NAME(errno_status_, __COUNTER__), EXPR, #EXPR)
+#else
+#define NANOARROW_ASSERT_OK(EXPR) EXPR
+#endif
+
 static char _ArrowIsLittleEndian(void) {
   uint32_t check = 1;
   char first_byte;
@@ -866,7 +933,16 @@ struct ArrowBufferAllocator ArrowBufferDeallocator(
 /// need to communicate more verbose error information accept a pointer
 /// to an ArrowError. This can be stack or statically allocated. The
 /// content of the message is undefined unless an error code has been
-/// returned.
+/// returned. If a nanoarrow function is passed a non-null ArrowError pointer, the
+/// ArrowError pointed to by the argument will be propagated with a
+/// null-terminated error message. It is safe to pass a NULL ArrowError anywhere
+/// in the nanoarrow API.
+///
+/// Except where documented, it is generally not safe to continue after a
+/// function has returned a non-zero ArrowErrorCode. The NANOARROW_RETURN_NOT_OK and
+/// NANOARROW_ASSERT_OK macros are provided to help propagate errors. C++ clients can use
+/// the helpers provided in the nanoarrow.hpp header to facilitate using C++ idioms
+/// for memory management and error propgagtion.
 ///
 /// @{
 
@@ -876,10 +952,24 @@ struct ArrowError {
   char message[1024];
 };
 
-/// \brief Set the contents of an error using printf syntax
+/// \brief Ensure an ArrowError is null-terminated by zeroing the first character.
+///
+/// If error is NULL, this function does nothing.
+static inline void ArrowErrorInit(struct ArrowError* error) {
+  if (error) {
+    error->message[0] = '\0';
+  }
+}
+
+/// \brief Set the contents of an error using printf syntax.
+///
+/// If error is NULL, this function does nothing and returns NANOARROW_OK.
 ArrowErrorCode ArrowErrorSet(struct ArrowError* error, const char* fmt, ...);
 
 /// \brief Get the contents of an error
+///
+/// If error is NULL, returns "", or returns the contents of the error message
+/// otherwise.
 const char* ArrowErrorMessage(struct ArrowError* error);
 
 /// @}
@@ -2286,7 +2376,7 @@ static inline int8_t _ArrowParseUnionTypeIds(const char* type_ids, int8_t* out)
     }
 
     if (out != NULL) {
-      out[i] = type_id;
+      out[i] = (int8_t)type_id;
     }
 
     i++;
@@ -2559,10 +2649,10 @@ static inline ArrowErrorCode ArrowArrayAppendInt(struct ArrowArray* array,
       _NANOARROW_CHECK_RANGE(value, 0, INT64_MAX);
       return ArrowArrayAppendUInt(array, value);
     case NANOARROW_TYPE_DOUBLE:
-      NANOARROW_RETURN_NOT_OK(ArrowBufferAppendDouble(data_buffer, value));
+      NANOARROW_RETURN_NOT_OK(ArrowBufferAppendDouble(data_buffer, (double)value));
       break;
     case NANOARROW_TYPE_FLOAT:
-      NANOARROW_RETURN_NOT_OK(ArrowBufferAppendFloat(data_buffer, value));
+      NANOARROW_RETURN_NOT_OK(ArrowBufferAppendFloat(data_buffer, (float)value));
       break;
     case NANOARROW_TYPE_BOOL:
       NANOARROW_RETURN_NOT_OK(_ArrowArrayAppendBits(array, 1, value != 0, 1));
@@ -2609,10 +2699,10 @@ static inline ArrowErrorCode ArrowArrayAppendUInt(struct ArrowArray* array,
       _NANOARROW_CHECK_RANGE(value, 0, INT64_MAX);
       return ArrowArrayAppendInt(array, value);
     case NANOARROW_TYPE_DOUBLE:
-      NANOARROW_RETURN_NOT_OK(ArrowBufferAppendDouble(data_buffer, value));
+      NANOARROW_RETURN_NOT_OK(ArrowBufferAppendDouble(data_buffer, (double)value));
       break;
     case NANOARROW_TYPE_FLOAT:
-      NANOARROW_RETURN_NOT_OK(ArrowBufferAppendFloat(data_buffer, value));
+      NANOARROW_RETURN_NOT_OK(ArrowBufferAppendFloat(data_buffer, (float)value));
       break;
     case NANOARROW_TYPE_BOOL:
       NANOARROW_RETURN_NOT_OK(_ArrowArrayAppendBits(array, 1, value != 0, 1));
@@ -2675,7 +2765,7 @@ static inline ArrowErrorCode ArrowArrayAppendBytes(struct ArrowArray* array,
         return EINVAL;
       }
 
-      offset += value.size_bytes;
+      offset += (int32_t)value.size_bytes;
       NANOARROW_RETURN_NOT_OK(ArrowBufferAppend(offset_buffer, &offset, sizeof(int32_t)));
       NANOARROW_RETURN_NOT_OK(
           ArrowBufferAppend(data_buffer, value.data.data, value.size_bytes));
@@ -2932,9 +3022,9 @@ static inline int64_t ArrowArrayViewGetIntUnsafe(struct ArrowArrayView* array_vi
     case NANOARROW_TYPE_UINT8:
       return data_view->data.as_uint8[i];
     case NANOARROW_TYPE_DOUBLE:
-      return data_view->data.as_double[i];
+      return (int64_t)data_view->data.as_double[i];
     case NANOARROW_TYPE_FLOAT:
-      return data_view->data.as_float[i];
+      return (int64_t)data_view->data.as_float[i];
     case NANOARROW_TYPE_BOOL:
       return ArrowBitGet(data_view->data.as_uint8, i);
     default:
@@ -2964,9 +3054,9 @@ static inline uint64_t ArrowArrayViewGetUIntUnsafe(struct ArrowArrayView* array_
     case NANOARROW_TYPE_UINT8:
       return data_view->data.as_uint8[i];
     case NANOARROW_TYPE_DOUBLE:
-      return data_view->data.as_double[i];
+      return (uint64_t)data_view->data.as_double[i];
     case NANOARROW_TYPE_FLOAT:
-      return data_view->data.as_float[i];
+      return (uint64_t)data_view->data.as_float[i];
     case NANOARROW_TYPE_BOOL:
       return ArrowBitGet(data_view->data.as_uint8, i);
     default:
@@ -2980,9 +3070,9 @@ static inline double ArrowArrayViewGetDoubleUnsafe(struct ArrowArrayView* array_
   struct ArrowBufferView* data_view = &array_view->buffer_views[1];
   switch (array_view->storage_type) {
     case NANOARROW_TYPE_INT64:
-      return data_view->data.as_int64[i];
+      return (double)data_view->data.as_int64[i];
     case NANOARROW_TYPE_UINT64:
-      return data_view->data.as_uint64[i];
+      return (double)data_view->data.as_uint64[i];
     case NANOARROW_TYPE_INT32:
       return data_view->data.as_int32[i];
     case NANOARROW_TYPE_UINT32:
diff --git a/dist/nanoarrow.hpp b/dist/nanoarrow.hpp
index b01d2a6..e6adb3a 100644
--- a/dist/nanoarrow.hpp
+++ b/dist/nanoarrow.hpp
@@ -15,6 +15,7 @@
 // specific language governing permissions and limitations
 // under the License.
 
+#include <stdexcept>
 #include <vector>
 
 #include "nanoarrow.h"
@@ -31,6 +32,55 @@
 
 namespace nanoarrow {
 
+/// \defgroup nanoarrow_hpp-errors Error handling helpers
+///
+/// Most functions in the C API return an ArrowErrorCode to communicate
+/// possible failure. Except where documented, it is usually not safe to
+/// continue after a non-zero value has been returned. While the
+/// nanoarrow C++ helpers do not throw any exceptions of their own,
+/// these helpers are provided to facilitate using the nanoarrow C++ helpers
+/// in frameworks where this is a useful error handling idiom.
+///
+/// @{
+
+class Exception : public std::exception {
+ public:
+  Exception(const std::string& msg) : msg_(msg) {}
+  const char* what() const noexcept { return msg_.c_str(); }
+
+ private:
+  std::string msg_;
+};
+
+#if defined(NANOARROW_DEBUG)
+#define _NANOARROW_THROW_NOT_OK_IMPL(NAME, EXPR, EXPR_STR)                      \
+  do {                                                                          \
+    const int NAME = (EXPR);                                                    \
+    if (NAME) {                                                                 \
+      throw nanoarrow::Exception(                                               \
+          std::string(EXPR_STR) + std::string(" failed with errno ") +          \
+          std::to_string(NAME) + std::string("\n * ") + std::string(__FILE__) + \
+          std::string(":") + std::to_string(__LINE__) + std::string("\n"));     \
+    }                                                                           \
+  } while (0)
+#else
+#define _NANOARROW_THROW_NOT_OK_IMPL(NAME, EXPR, EXPR_STR)            \
+  do {                                                                \
+    const int NAME = (EXPR);                                          \
+    if (NAME) {                                                       \
+      throw nanoarrow::Exception(std::string(EXPR_STR) +              \
+                                 std::string(" failed with errno ") + \
+                                 std::to_string(NAME));               \
+    }                                                                 \
+  } while (0)
+#endif
+
+#define NANOARROW_THROW_NOT_OK(EXPR)                                                   \
+  _NANOARROW_THROW_NOT_OK_IMPL(_NANOARROW_MAKE_NAME(errno_status_, __COUNTER__), EXPR, \
+                               #EXPR)
+
+/// @}
+
 namespace internal {
 
 /// \defgroup nanoarrow_hpp-unique_base Base classes for Unique wrappers