11#pragma once
22
3- #include < utility>
4-
53// https://github.com/nmslib/hnswlib/pull/508
64// This allows others to provide their own error stream (e.g. RcppHNSW)
75#ifndef HNSWLIB_ERR_OVERRIDE
@@ -121,8 +119,15 @@ static bool AVX512Capable() {
121119#include < queue>
122120#include < vector>
123121#include < iostream>
122+ #include < utility>
124123#include < string.h>
125124
125+ #if HNSWLIB_USE_ABSEIL
126+ #include " absl/status/status.h"
127+ #include " absl/status/statusor.h"
128+ #include " absl/strings/string_view.h"
129+ #endif
130+
126131namespace hnswlib {
127132
128133// hnswlib can be compiled in two modes: with and without exceptions.
@@ -139,102 +144,68 @@ namespace hnswlib {
139144// HNSWLIB_STATUS_OR_TYPE(t) -- return type for a function with a return value
140145// HNSWLIB_RETURN_OK_STATUS -- return an OK status or simply return.
141146
142- #define HNSWLIB_USE_EXCEPTIONS 0
143-
144- #ifndef HNSWLIB_USE_EXCEPTIONS
145- #define HNSWLIB_USE_EXCEPTIONS 1
146- #endif
147-
148- #if HNSWLIB_USE_EXCEPTIONS
147+ #if !HNSWLIB_USE_ABSEIL
149148
150149#define HNSWLIB_THROW_ERROR (message ) \
151150 throw std::runtime_error (message);
152151#define HNSWLIB_STATUS_TYPE void
153152#define HNSWLIB_STATUS_OR_TYPE (t ) t
154153#define HNSWLIB_RETURN_OK_STATUS return
155154#define HNSWLIB_EXTRACT_VALUE (status_or_value ) (status_or_value)
155+ #define HNSWLIB_ASSIGN_OR_RETURN (lhs, expression ) lhs = (expression)
156156#define HNSWLIB_RETURN_IF_VALUE_NOT_OK (status_or_value ) status_or_value
157157#define HNSWLIB_ASSIGN_VALUE_OR_THROW_IN_TEST (identifier, expression ) \
158158 auto identifier = (expression)
159- #else
160-
161- class Status {
162- public:
163- // Default constructor (OK status)
164- Status () : message_(nullptr ) {}
165-
166- // Constructor with an error message
167- Status (const char * message) : message_(message) {}
168-
169- // Returns true if the status is ok
170- bool ok () const { return message_ == nullptr ; }
171-
172- // Returns the error message, or nullptr if ok
173- const char * message () const { return message_; }
174-
175- private:
176- const char * message_; // Null if ok, error message otherwise
177- };
178-
179- template <typename T>
180- class StatusOr {
181- public:
182- // Default constructor
183- StatusOr () : status_(), value_() {}
184159
185- // Constructor with a value
186- StatusOr (T value) : status_(), value_(value) {}
187-
188- // Constructor with an error status
189- StatusOr (const char * error) : status_(error), value_() {}
190- StatusOr (Status status) : status_(status), value_() {}
191-
192- // Returns true if the status is ok
193- bool ok () const { return status_.ok (); }
194-
195- // Returns the value if the status is ok
196- T&& value() {
197- return std::move (value_);
198- }
199-
200- const T& value () const {
201- return value_;
202- }
203-
204- // Returns the value using the dereference operator
205- T operator *() const {
206- return value ();
207- }
208-
209- // Returns the error status if not ok
210- Status status () const { return status_; }
211-
212- private:
213- Status status_; // Status object
214- T value_; // The value
215- };
160+ #else
216161
217- #define HNSWLIB_STATUS_TYPE ::hnswlib ::Status
218- #define HNSWLIB_STATUS_OR_TYPE (t ) ::hnswlib ::StatusOr<t>
162+ #define HNSWLIB_STATUS_TYPE ::absl ::Status
163+ #define HNSWLIB_STATUS_OR_TYPE (t ) ::absl ::StatusOr<t>
219164#define HNSWLIB_THROW_ERROR (message ) \
220- return ::hnswlib::Status (message);
221- #define HNSWLIB_RETURN_OK_STATUS return ::hnswlib::Status ()
165+ return ::absl::UnknownError (message);
166+ #define HNSWLIB_RETURN_OK_STATUS return ::absl::OkStatus ()
222167#define HNSWLIB_RETURN_IF_VALUE_NOT_OK (status_or_value ) do { \
223168 if (!status_or_value.ok ()) { \
224169 return status_or_value.status (); \
225170 } \
226171} while (false )
227172#define HNSWLIB_EXTRACT_VALUE (status_or_value ) (status_or_value).value()
228- #define HNSWLIB_ASSIGN_VALUE_OR_THROW_IN_TEST_HELPER (identifier, expression, tmp_identifier ) \
173+
174+ #define HNSWLIB_CONCAT_NAME_HELPER (x, y ) x##y
175+ #define HNSWLIB_CONCAT_NAME (x, y ) HNSWLIB_CONCAT_NAME_HELPER(x, y)
176+ #define HNSWLIB_MAKE_TMP_IDENTIFIER (identifier ) \
177+ HNSWLIB_CONCAT_NAME (HNSWLIB_CONCAT_NAME(identifier, _tmp), __COUNTER__)
178+
179+ #define HNSWLIB_ASSIGN_OR_RETURN_HELPER (lhs, expression, tmp_identifier ) \
180+ auto tmp_identifier = (expression); \
181+ if (!tmp_identifier.ok()) { \
182+ return tmp_identifier.status (); \
183+ } \
184+ lhs = std::move(tmp_identifier.value());
185+
186+ #define HNSWLIB_ASSIGN_OR_RETURN (lhs, expression ) \
187+ HNSWLIB_ASSIGN_OR_RETURN_HELPER ( \
188+ lhs, \
189+ expression, \
190+ HNSWLIB_MAKE_TMP_IDENTIFIER (status_or_value))
191+
192+ #define HNSWLIB_ASSIGN_VALUE_OR_THROW_IN_TEST_HELPER ( \
193+ identifier, \
194+ expression, \
195+ tmp_identifier) \
229196 auto tmp_identifier = (expression); \
230197 if (!tmp_identifier.ok()) { \
231- throw std::runtime_error (tmp_identifier.status ().message ()); \
198+ auto message = tmp_identifier.status ().message (); \
199+ std::string message_str (message.data (), message.size ()); \
200+ throw std::runtime_error (message_str); \
232201 } \
233202 auto identifier = std::move(tmp_identifier.value());
234- #define HNSWLIB_MAKE_TMP_VAR_NAME (prefix, suffix ) prefix##_##suffix
235203
236204#define HNSWLIB_ASSIGN_VALUE_OR_THROW_IN_TEST (identifier, expression ) \
237- HNSWLIB_ASSIGN_VALUE_OR_THROW_IN_TEST_HELPER (identifier, expression, HNSWLIB_MAKE_TMP_VAR_NAME(identifier, __LINE__))
205+ HNSWLIB_ASSIGN_VALUE_OR_THROW_IN_TEST_HELPER ( \
206+ identifier, \
207+ expression, \
208+ HNSWLIB_MAKE_TMP_IDENTIFIER (identifier))
238209#endif
239210
240211typedef size_t labeltype;
@@ -323,7 +294,7 @@ class AlgorithmInterface {
323294 BaseFilterFunctor* isIdAllowed = nullptr ) const {
324295
325296 // Here searchKnn returns the result in the order of further first.
326- HNSWLIB_ASSIGN_VALUE_OR_THROW_IN_TEST ( ret, searchKnn (query_data, k, isIdAllowed));
297+ HNSWLIB_ASSIGN_OR_RETURN ( auto ret, searchKnn (query_data, k, isIdAllowed));
327298
328299 DistanceLabelVector result;
329300 size_t sz = ret.size ();
0 commit comments