Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-08-27 08:47:20

0001 // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
0002 // Use of this source code is governed by a BSD-style license that can be
0003 // found in the LICENSE file. See the AUTHORS file for names of contributors.
0004 //
0005 // A Status encapsulates the result of an operation.  It may indicate success,
0006 // or it may indicate an error with an associated error message.
0007 //
0008 // Multiple threads can invoke const methods on a Status without
0009 // external synchronization, but if any of the threads may call a
0010 // non-const method, all threads accessing the same Status must use
0011 // external synchronization.
0012 
0013 // Adapted from Apache Kudu, TensorFlow
0014 
0015 #pragma once
0016 
0017 #include <cstring>
0018 #include <iosfwd>
0019 #include <memory>
0020 #include <string>
0021 #include <utility>
0022 
0023 #include "arrow/util/compare.h"
0024 #include "arrow/util/macros.h"
0025 #include "arrow/util/string_builder.h"
0026 #include "arrow/util/visibility.h"
0027 
0028 #ifdef ARROW_EXTRA_ERROR_CONTEXT
0029 
0030 /// \brief Return with given status if condition is met.
0031 #  define ARROW_RETURN_IF_(condition, status, expr)   \
0032     do {                                              \
0033       if (ARROW_PREDICT_FALSE(condition)) {           \
0034         ::arrow::Status _st = (status);               \
0035         _st.AddContextLine(__FILE__, __LINE__, expr); \
0036         return _st;                                   \
0037       }                                               \
0038     } while (0)
0039 
0040 #else
0041 
0042 #  define ARROW_RETURN_IF_(condition, status, _) \
0043     do {                                         \
0044       if (ARROW_PREDICT_FALSE(condition)) {      \
0045         return (status);                         \
0046       }                                          \
0047     } while (0)
0048 
0049 #endif  // ARROW_EXTRA_ERROR_CONTEXT
0050 
0051 #define ARROW_RETURN_IF(condition, status) \
0052   ARROW_RETURN_IF_(condition, status, ARROW_STRINGIFY(status))
0053 
0054 /// \brief Propagate any non-successful Status to the caller
0055 #define ARROW_RETURN_NOT_OK(status)                                   \
0056   do {                                                                \
0057     ::arrow::Status __s = ::arrow::internal::GenericToStatus(status); \
0058     ARROW_RETURN_IF_(!__s.ok(), __s, ARROW_STRINGIFY(status));        \
0059   } while (false)
0060 
0061 /// \brief Given `expr` and `warn_msg`; log `warn_msg` if `expr` is a non-ok status
0062 #define ARROW_WARN_NOT_OK(expr, warn_msg) \
0063   do {                                    \
0064     ::arrow::Status _s = (expr);          \
0065     if (ARROW_PREDICT_FALSE(!_s.ok())) {  \
0066       _s.Warn(warn_msg);                  \
0067     }                                     \
0068   } while (false)
0069 
0070 #define RETURN_NOT_OK_ELSE(s, else_)                            \
0071   do {                                                          \
0072     ::arrow::Status _s = ::arrow::internal::GenericToStatus(s); \
0073     if (!_s.ok()) {                                             \
0074       else_;                                                    \
0075       return _s;                                                \
0076     }                                                           \
0077   } while (false)
0078 
0079 // This is an internal-use macro and should not be used in public headers.
0080 #ifndef RETURN_NOT_OK
0081 #  define RETURN_NOT_OK(s) ARROW_RETURN_NOT_OK(s)
0082 #endif
0083 
0084 namespace arrow {
0085 namespace internal {
0086 class StatusConstant;
0087 }
0088 
0089 enum class StatusCode : char {
0090   OK = 0,
0091   OutOfMemory = 1,
0092   KeyError = 2,
0093   TypeError = 3,
0094   Invalid = 4,
0095   IOError = 5,
0096   CapacityError = 6,
0097   IndexError = 7,
0098   Cancelled = 8,
0099   UnknownError = 9,
0100   NotImplemented = 10,
0101   SerializationError = 11,
0102   RError = 13,
0103   // Gandiva range of errors
0104   CodeGenError = 40,
0105   ExpressionValidationError = 41,
0106   ExecutionError = 42,
0107   // Continue generic codes.
0108   AlreadyExists = 45
0109 };
0110 
0111 /// \brief An opaque class that allows subsystems to retain
0112 /// additional information inside the Status.
0113 class ARROW_EXPORT StatusDetail {
0114  public:
0115   virtual ~StatusDetail() = default;
0116   /// \brief Return a unique id for the type of the StatusDetail
0117   /// (effectively a poor man's substitute for RTTI).
0118   virtual const char* type_id() const = 0;
0119   /// \brief Produce a human-readable description of this status.
0120   virtual std::string ToString() const = 0;
0121 
0122   bool operator==(const StatusDetail& other) const noexcept {
0123     return std::string(type_id()) == other.type_id() && ToString() == other.ToString();
0124   }
0125 };
0126 
0127 /// \brief Status outcome object (success or error)
0128 ///
0129 /// The Status object is an object holding the outcome of an operation.
0130 /// The outcome is represented as a StatusCode, either success
0131 /// (StatusCode::OK) or an error (any other of the StatusCode enumeration values).
0132 ///
0133 /// Additionally, if an error occurred, a specific error message is generally
0134 /// attached.
0135 class ARROW_EXPORT [[nodiscard]] Status : public util::EqualityComparable<Status>,
0136                                           public util::ToStringOstreamable<Status> {
0137  public:
0138   // Create a success status.
0139   constexpr Status() noexcept : state_(NULLPTR) {}
0140   ~Status() noexcept {
0141     if (ARROW_PREDICT_FALSE(state_ != NULL)) {
0142       if (!state_->is_constant) {
0143         DeleteState();
0144       }
0145     }
0146   }
0147 
0148   Status(StatusCode code, const std::string& msg);
0149   /// \brief Pluggable constructor for use by sub-systems.  detail cannot be null.
0150   Status(StatusCode code, std::string msg, std::shared_ptr<StatusDetail> detail);
0151 
0152   // Copy the specified status.
0153   inline Status(const Status& s);
0154   inline Status& operator=(const Status& s);
0155 
0156   // Move the specified status.
0157   inline Status(Status&& s) noexcept;
0158   inline Status& operator=(Status&& s) noexcept;
0159 
0160   inline bool Equals(const Status& s) const;
0161 
0162   // AND the statuses.
0163   inline Status operator&(const Status& s) const noexcept;
0164   inline Status operator&(Status&& s) const noexcept;
0165   inline Status& operator&=(const Status& s) noexcept;
0166   inline Status& operator&=(Status&& s) noexcept;
0167 
0168   /// Return a success status
0169   static Status OK() { return Status(); }
0170 
0171   template <typename... Args>
0172   static Status FromArgs(StatusCode code, Args&&... args) {
0173     return Status(code, util::StringBuilder(std::forward<Args>(args)...));
0174   }
0175 
0176   template <typename... Args>
0177   static Status FromDetailAndArgs(StatusCode code, std::shared_ptr<StatusDetail> detail,
0178                                   Args&&... args) {
0179     return Status(code, util::StringBuilder(std::forward<Args>(args)...),
0180                   std::move(detail));
0181   }
0182 
0183   /// Return an error status for out-of-memory conditions
0184   template <typename... Args>
0185   static Status OutOfMemory(Args&&... args) {
0186     return Status::FromArgs(StatusCode::OutOfMemory, std::forward<Args>(args)...);
0187   }
0188 
0189   /// Return an error status for failed key lookups (e.g. column name in a table)
0190   template <typename... Args>
0191   static Status KeyError(Args&&... args) {
0192     return Status::FromArgs(StatusCode::KeyError, std::forward<Args>(args)...);
0193   }
0194 
0195   /// Return an error status for type errors (such as mismatching data types)
0196   template <typename... Args>
0197   static Status TypeError(Args&&... args) {
0198     return Status::FromArgs(StatusCode::TypeError, std::forward<Args>(args)...);
0199   }
0200 
0201   /// Return an error status for unknown errors
0202   template <typename... Args>
0203   static Status UnknownError(Args&&... args) {
0204     return Status::FromArgs(StatusCode::UnknownError, std::forward<Args>(args)...);
0205   }
0206 
0207   /// Return an error status when an operation or a combination of operation and
0208   /// data types is unimplemented
0209   template <typename... Args>
0210   static Status NotImplemented(Args&&... args) {
0211     return Status::FromArgs(StatusCode::NotImplemented, std::forward<Args>(args)...);
0212   }
0213 
0214   /// Return an error status for invalid data (for example a string that fails parsing)
0215   template <typename... Args>
0216   static Status Invalid(Args&&... args) {
0217     return Status::FromArgs(StatusCode::Invalid, std::forward<Args>(args)...);
0218   }
0219 
0220   /// Return an error status for cancelled operation
0221   template <typename... Args>
0222   static Status Cancelled(Args&&... args) {
0223     return Status::FromArgs(StatusCode::Cancelled, std::forward<Args>(args)...);
0224   }
0225 
0226   /// Return an error status when an index is out of bounds
0227   template <typename... Args>
0228   static Status IndexError(Args&&... args) {
0229     return Status::FromArgs(StatusCode::IndexError, std::forward<Args>(args)...);
0230   }
0231 
0232   /// Return an error status when a container's capacity would exceed its limits
0233   template <typename... Args>
0234   static Status CapacityError(Args&&... args) {
0235     return Status::FromArgs(StatusCode::CapacityError, std::forward<Args>(args)...);
0236   }
0237 
0238   /// Return an error status when some IO-related operation failed
0239   template <typename... Args>
0240   static Status IOError(Args&&... args) {
0241     return Status::FromArgs(StatusCode::IOError, std::forward<Args>(args)...);
0242   }
0243 
0244   /// Return an error status when some (de)serialization operation failed
0245   template <typename... Args>
0246   static Status SerializationError(Args&&... args) {
0247     return Status::FromArgs(StatusCode::SerializationError, std::forward<Args>(args)...);
0248   }
0249 
0250   template <typename... Args>
0251   static Status RError(Args&&... args) {
0252     return Status::FromArgs(StatusCode::RError, std::forward<Args>(args)...);
0253   }
0254 
0255   template <typename... Args>
0256   static Status CodeGenError(Args&&... args) {
0257     return Status::FromArgs(StatusCode::CodeGenError, std::forward<Args>(args)...);
0258   }
0259 
0260   template <typename... Args>
0261   static Status ExpressionValidationError(Args&&... args) {
0262     return Status::FromArgs(StatusCode::ExpressionValidationError,
0263                             std::forward<Args>(args)...);
0264   }
0265 
0266   template <typename... Args>
0267   static Status ExecutionError(Args&&... args) {
0268     return Status::FromArgs(StatusCode::ExecutionError, std::forward<Args>(args)...);
0269   }
0270 
0271   template <typename... Args>
0272   static Status AlreadyExists(Args&&... args) {
0273     return Status::FromArgs(StatusCode::AlreadyExists, std::forward<Args>(args)...);
0274   }
0275 
0276   /// Return true iff the status indicates success.
0277   constexpr bool ok() const { return (state_ == NULLPTR); }
0278 
0279   /// Return true iff the status indicates an out-of-memory error.
0280   constexpr bool IsOutOfMemory() const { return code() == StatusCode::OutOfMemory; }
0281   /// Return true iff the status indicates a key lookup error.
0282   constexpr bool IsKeyError() const { return code() == StatusCode::KeyError; }
0283   /// Return true iff the status indicates invalid data.
0284   constexpr bool IsInvalid() const { return code() == StatusCode::Invalid; }
0285   /// Return true iff the status indicates a cancelled operation.
0286   constexpr bool IsCancelled() const { return code() == StatusCode::Cancelled; }
0287   /// Return true iff the status indicates an IO-related failure.
0288   constexpr bool IsIOError() const { return code() == StatusCode::IOError; }
0289   /// Return true iff the status indicates a container reaching capacity limits.
0290   constexpr bool IsCapacityError() const { return code() == StatusCode::CapacityError; }
0291   /// Return true iff the status indicates an out of bounds index.
0292   constexpr bool IsIndexError() const { return code() == StatusCode::IndexError; }
0293   /// Return true iff the status indicates a type error.
0294   constexpr bool IsTypeError() const { return code() == StatusCode::TypeError; }
0295   /// Return true iff the status indicates an unknown error.
0296   constexpr bool IsUnknownError() const { return code() == StatusCode::UnknownError; }
0297   /// Return true iff the status indicates an unimplemented operation.
0298   constexpr bool IsNotImplemented() const { return code() == StatusCode::NotImplemented; }
0299   /// Return true iff the status indicates a (de)serialization failure
0300   constexpr bool IsSerializationError() const {
0301     return code() == StatusCode::SerializationError;
0302   }
0303   /// Return true iff the status indicates a R-originated error.
0304   constexpr bool IsRError() const { return code() == StatusCode::RError; }
0305 
0306   constexpr bool IsCodeGenError() const { return code() == StatusCode::CodeGenError; }
0307 
0308   constexpr bool IsExpressionValidationError() const {
0309     return code() == StatusCode::ExpressionValidationError;
0310   }
0311 
0312   constexpr bool IsExecutionError() const { return code() == StatusCode::ExecutionError; }
0313   constexpr bool IsAlreadyExists() const { return code() == StatusCode::AlreadyExists; }
0314 
0315   /// \brief Return a string representation of this status suitable for printing.
0316   ///
0317   /// The string "OK" is returned for success.
0318   std::string ToString() const;
0319 
0320   /// \brief Return a string representation of this status without
0321   /// context lines suitable for printing.
0322   ///
0323   /// The string "OK" is returned for success.
0324   std::string ToStringWithoutContextLines() const;
0325 
0326   /// \brief Return a string representation of the status code, without the message
0327   /// text or POSIX code information.
0328   std::string CodeAsString() const;
0329   static std::string CodeAsString(StatusCode);
0330 
0331   /// \brief Return the StatusCode value attached to this status.
0332   constexpr StatusCode code() const { return ok() ? StatusCode::OK : state_->code; }
0333 
0334   /// \brief Return the specific error message attached to this status.
0335   const std::string& message() const;
0336 
0337   /// \brief Return the status detail attached to this message.
0338   const std::shared_ptr<StatusDetail>& detail() const;
0339 
0340   /// \brief Return a new Status copying the existing status, but
0341   /// updating with the existing detail.
0342   Status WithDetail(std::shared_ptr<StatusDetail> new_detail) const {
0343     return Status(code(), message(), std::move(new_detail));
0344   }
0345 
0346   /// \brief Return a new Status with changed message, copying the
0347   /// existing status code and detail.
0348   template <typename... Args>
0349   Status WithMessage(Args&&... args) const {
0350     return FromArgs(code(), std::forward<Args>(args)...).WithDetail(detail());
0351   }
0352 
0353   void Warn() const;
0354   void Warn(const std::string& message) const;
0355 
0356   [[noreturn]] void Abort() const;
0357   [[noreturn]] void Abort(const std::string& message) const;
0358 
0359 #ifdef ARROW_EXTRA_ERROR_CONTEXT
0360   void AddContextLine(const char* filename, int line, const char* expr);
0361 #endif
0362 
0363  private:
0364   struct State {
0365     StatusCode code;
0366     bool is_constant;
0367     std::string msg;
0368     std::shared_ptr<StatusDetail> detail;
0369   };
0370   // OK status has a `NULL` state_.  Otherwise, `state_` points to
0371   // a `State` structure containing the error code and message(s)
0372   State* state_;
0373 
0374   void DeleteState() noexcept {
0375     // ARROW-2400: On certain compilers, splitting off the slow path improves
0376     // performance significantly.
0377     delete state_;
0378   }
0379   void CopyFrom(const Status& s);
0380   inline void MoveFrom(Status& s);
0381 
0382   friend class internal::StatusConstant;
0383 };
0384 
0385 void Status::MoveFrom(Status& s) {
0386   if (ARROW_PREDICT_FALSE(state_ != NULL)) {
0387     if (!state_->is_constant) {
0388       DeleteState();
0389     }
0390   }
0391   state_ = s.state_;
0392   s.state_ = NULLPTR;
0393 }
0394 
0395 Status::Status(const Status& s) : state_{NULLPTR} { CopyFrom(s); }
0396 
0397 Status& Status::operator=(const Status& s) {
0398   // The following condition catches both aliasing (when this == &s),
0399   // and the common case where both s and *this are ok.
0400   if (state_ != s.state_) {
0401     CopyFrom(s);
0402   }
0403   return *this;
0404 }
0405 
0406 Status::Status(Status&& s) noexcept : state_(s.state_) { s.state_ = NULLPTR; }
0407 
0408 Status& Status::operator=(Status&& s) noexcept {
0409   MoveFrom(s);
0410   return *this;
0411 }
0412 
0413 bool Status::Equals(const Status& s) const {
0414   if (state_ == s.state_) {
0415     return true;
0416   }
0417 
0418   if (ok() || s.ok()) {
0419     return false;
0420   }
0421 
0422   if (detail() != s.detail()) {
0423     if ((detail() && !s.detail()) || (!detail() && s.detail())) {
0424       return false;
0425     }
0426     return *detail() == *s.detail();
0427   }
0428 
0429   return code() == s.code() && message() == s.message();
0430 }
0431 
0432 /// \cond FALSE
0433 // (note: emits warnings on Doxygen < 1.8.15,
0434 //  see https://github.com/doxygen/doxygen/issues/6295)
0435 Status Status::operator&(const Status& s) const noexcept {
0436   if (ok()) {
0437     return s;
0438   } else {
0439     return *this;
0440   }
0441 }
0442 
0443 Status Status::operator&(Status&& s) const noexcept {
0444   if (ok()) {
0445     return std::move(s);
0446   } else {
0447     return *this;
0448   }
0449 }
0450 
0451 Status& Status::operator&=(const Status& s) noexcept {
0452   if (ok() && !s.ok()) {
0453     CopyFrom(s);
0454   }
0455   return *this;
0456 }
0457 
0458 Status& Status::operator&=(Status&& s) noexcept {
0459   if (ok() && !s.ok()) {
0460     MoveFrom(s);
0461   }
0462   return *this;
0463 }
0464 /// \endcond
0465 
0466 namespace internal {
0467 
0468 // Extract Status from Status or Result<T>
0469 // Useful for the status check macros such as RETURN_NOT_OK.
0470 inline const Status& GenericToStatus(const Status& st) { return st; }
0471 inline Status GenericToStatus(Status&& st) { return std::move(st); }
0472 
0473 }  // namespace internal
0474 
0475 }  // namespace arrow