10 #include <type_traits> 23 :_notification(notification) {}
30 std::shared_ptr<librealsense::context>
ctx;
31 std::shared_ptr<librealsense::device_info>
info;
32 std::shared_ptr<librealsense::device_interface>
device;
43 template<
class T,
bool S>
48 out <<
':' << val << (last ?
"" :
", ");
58 static auto test(...)->std::false_type;
72 else out <<
"nullptr";
73 out << (last ?
"" :
", ");
84 if (val) out << (
int*)val;
85 else out <<
"nullptr";
86 out << (last ?
"" :
", ");
91 template<
class T>
void stream_args(std::ostream &
out,
const char * names,
const T & last)
97 template<
class T,
class... U>
void stream_args(std::ostream &
out,
const char * names,
const T &
first,
const U &... rest)
99 while (*names && *names !=
',') out << *names++;
102 while (*names && (*names ==
',' || isspace(*names))) ++names;
126 static api_objects& instance() {
127 static api_objects instance;
134 std::string register_new_object(
const std::string&
type,
const std::string& address)
136 std::lock_guard<std::mutex>
lock(_m);
137 return internal_register(type, address);
146 std::string augment_params(std::string
p)
148 std::lock_guard<std::mutex>
lock(_m);
149 std::string acc =
"";
150 std::string res =
"";
151 std::string
param =
"";
153 bool is_value =
false;
154 for (
auto i = 0;
i < p.size();
i++)
166 auto it = _names.find(acc);
167 if (
it != _names.end()) acc =
it->second;
172 std::stringstream ss; ss << (
int*)0;
173 if (acc.size() == ss.str().size())
175 acc = internal_register(param, acc);
178 res += param +
":" + acc;
179 if (
i != p.size() - 1) res +=
",";
191 void remove_object(
const std::string&
name)
193 std::lock_guard<std::mutex>
lock(_m);
194 auto it = _names.find(name);
195 if (
it != _names.end())
199 std::string internal_register(
const std::string&
type,
const std::string& address)
201 auto it = _counters.find(type);
202 if (
it == _counters.end()) _counters[type] = 0;
204 std::stringstream ss;
205 ss << type << _counters[
type];
206 _names[address] = ss.str();
207 return _names[address];
211 std::map<std::string, std::string> _names;
212 std::map<std::string, int> _counters;
219 api_logger(std::string
function)
220 : _function(
std::move(
function)), _result(
""), _param_str(
""), _type(
""),
221 _params([]() {
return std::string{}; })
224 LOG_DEBUG(
"/* Begin " << _function <<
" */");
227 std::size_t found = _function.find_last_of(
"_");
228 _type = _function.substr(found + 1);
230 check_if_deleter(
"rs2_delete");
231 check_if_deleter(
"rs2_release");
235 void check_if_deleter(
const char* prefix)
237 auto deleter_pos = _function.find(prefix);
238 if (deleter_pos == 0)
244 void set_return_value(std::string result)
249 void set_params(std::function<std::string()>
params)
254 std::string get_params() {
return _param_str = _params(); }
257 void report_pointer_return_type() { _returns_pointer =
true; }
262 auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
d).
count();
263 std::stringstream ss;
264 std::string prefix =
"";
265 if (_param_str ==
"") _param_str = _params();
267 auto&& objs = api_objects::instance();
268 if (_returns_pointer)
270 prefix = objs.register_new_object(_type, _result) +
" = ";
273 if (_is_deleter) objs.remove_object(_result);
274 if (_param_str !=
"") _param_str = objs.augment_params(_param_str);
276 ss << prefix << _function <<
"(" << _param_str <<
")";
277 if (_result !=
"") ss <<
" returned " << _result;
279 if (ms > 0) ss <<
" /* Took " << ms <<
"ms */";
284 std::string _function, _result, _type, _param_str;
285 std::function<std::string()> _params;
286 bool _returns_pointer =
false;
287 bool _is_deleter =
false;
289 std::chrono::high_resolution_clock::time_point _start;
295 template<
typename F,
typename R>
296 R fetch_return_type(F&
f,
R(F::*mf)()
const);
304 result_printer(api_logger* logger) : _logger(logger) {}
317 std::stringstream ss; ss << _res;
318 _logger->set_return_value(ss.str());
327 class result_printer<T*>
330 result_printer(api_logger* logger) : _logger(logger) {}
343 std::stringstream ss; ss << (
int*)_res;
345 _logger->report_pointer_return_type();
346 _logger->set_return_value(ss.str());
356 class result_printer<void>
359 result_printer(api_logger* logger) {}
366 #define BEGIN_API_CALL { api_logger __api_logger(__FUNCTION__); {\ 372 #define NOEXCEPT_RETURN(R, ...) };\ 373 result_printer<decltype(fetch_return_type(func, &decltype(func)::operator()))> __p(&__api_logger);\ 374 __api_logger.set_params([&](){ std::ostringstream ss; librealsense::stream_args(ss, #__VA_ARGS__, __VA_ARGS__); return ss.str(); });\ 376 return __p.invoke(func);\ 378 rs2_error* e; librealsense::translate_exception(__FUNCTION__, __api_logger.get_params(), &e);\ 379 LOG_WARNING(rs2_get_error_message(e)); rs2_free_error(e); __api_logger.report_error(); return R; } } } 381 #define HANDLE_EXCEPTIONS_AND_RETURN(R, ...) };\ 382 result_printer<decltype(fetch_return_type(func, &decltype(func)::operator()))> __p(&__api_logger);\ 383 __api_logger.set_params([&](){ std::ostringstream ss; librealsense::stream_args(ss, #__VA_ARGS__, __VA_ARGS__); return ss.str(); });\ 385 return __p.invoke(func);\ 387 librealsense::translate_exception(__FUNCTION__, __api_logger.get_params(), error); __api_logger.report_error(); return R; } } } 389 #define NOARGS_HANDLE_EXCEPTIONS_AND_RETURN(R, ...) };\ 390 result_printer<decltype(fetch_return_type(func, &decltype(func)::operator()))> __p(&__api_logger);\ 392 return __p.invoke(func);\ 393 } catch(...) { librealsense::translate_exception(__FUNCTION__, "", error); __api_logger.report_error(); return R; } } } 395 #else // No API tracing: 397 #define BEGIN_API_CALL try 398 #define NOEXCEPT_RETURN(R, ...) catch(...) { std::ostringstream ss; librealsense::stream_args(ss, #__VA_ARGS__, __VA_ARGS__); rs2_error* e; librealsense::translate_exception(__FUNCTION__, ss.str(), &e); LOG_WARNING(rs2_get_error_message(e)); rs2_free_error(e); return R; } 399 #define HANDLE_EXCEPTIONS_AND_RETURN(R, ...) catch(...) { std::ostringstream ss; librealsense::stream_args(ss, #__VA_ARGS__, __VA_ARGS__); librealsense::translate_exception(__FUNCTION__, ss.str(), error); return R; } 400 #define NOARGS_HANDLE_EXCEPTIONS_AND_RETURN(R) catch(...) { librealsense::translate_exception(__FUNCTION__, "", error); return R; } 401 #define NOARGS_HANDLE_EXCEPTIONS_AND_RETURN_VOID() catch(...) { librealsense::translate_exception(__FUNCTION__, "", error); } 405 #define VALIDATE_FIXED_SIZE(ARG, SIZE) if((ARG) != (SIZE)) { std::ostringstream ss; ss << "Unsupported size provided { " << ARG << " }," " expecting { " << SIZE << " }"; throw librealsense::invalid_value_exception(ss.str()); } 406 #define VALIDATE_NOT_NULL(ARG) if(!(ARG)) throw std::runtime_error("null pointer passed for argument \"" #ARG "\""); 407 #define VALIDATE_ENUM(ARG) if(!librealsense::is_valid(ARG)) { std::ostringstream ss; ss << "invalid enum value for argument \"" #ARG "\""; throw librealsense::invalid_value_exception(ss.str()); } 408 #define VALIDATE_OPTION(OBJ, OPT_ID) if(!OBJ->options->supports_option(OPT_ID)) { std::ostringstream ss; ss << "object doesn't support option #" << std::to_string(OPT_ID); throw librealsense::invalid_value_exception(ss.str()); } 409 #define VALIDATE_RANGE(ARG, MIN, MAX) if((ARG) < (MIN) || (ARG) > (MAX)) { std::ostringstream ss; ss << "out of range value for argument \"" #ARG "\""; throw librealsense::invalid_value_exception(ss.str()); } 410 #define VALIDATE_LE(ARG, MAX) if((ARG) > (MAX)) { std::ostringstream ss; ss << "out of range value for argument \"" #ARG "\""; throw std::runtime_error(ss.str()); } 411 #define VALIDATE_GT(ARG, MIN) if((ARG) <= (MIN)) { std::ostringstream ss; ss << "value is below allowed min for argument \"" #ARG "\""; throw std::runtime_error(ss.str()); } 412 #define VALIDATE_LT(ARG, MAX) if((ARG) >= (MAX)) { std::ostringstream ss; ss << "value is bigger than allowed max for argument \"" #ARG "\""; throw std::runtime_error(ss.str()); } 413 #define VALIDATE_INTERFACE_NO_THROW(X, T) \ 415 T* p = dynamic_cast<T*>(&(*X)); \ 418 auto ext = dynamic_cast<librealsense::extendable_interface*>(&(*X)); \ 419 if (ext == nullptr) return nullptr; \ 422 if(!ext->extend_to(TypeToExtension<T>::value, (void**)&p)) \ 430 #define VALIDATE_INTERFACE(X,T) \ 432 T* p = VALIDATE_INTERFACE_NO_THROW(X,T); \ 434 throw std::runtime_error("Object does not support \"" #T "\" interface! " ); \ 441 return version / 10000;
445 return (version % 10000) / 100;
449 return (version % 100);
462 <<
api_version_to_string(compiletime) <<
"! Make sure correct version of the library is installed (make install)");
472 if ((runtime_api_version < 10) || (api_version < 10))
475 if (api_version != runtime_api_version)
482 if (api_version != runtime_api_version)
static const textual_icon lock
rs2_exception_type
Exception types are the different categories of errors that RealSense API might return.
GLuint const GLchar * name
int rs2_get_api_version(rs2_error **error)
const librealsense::notification * _notification
const char * what() const noexcept override
rs2_error * rs2_create_error(const char *what, const char *name, const char *args, rs2_exception_type type)
std::shared_ptr< librealsense::device_info > info
void verify_version_compatibility(int api_version)
dispatcher invoke([&](dispatcher::cancellable_timer c) { std::this_thread::sleep_for(std::chrono::seconds(3));dispatched_end_verifier=true;})
void stream_arg(std::ostream &out, T *val, bool last)
int lrs_patch(int version)
std::shared_ptr< librealsense::device_interface > device
void report_version_mismatch(int runtime, int compiletime)
const char * rs2_get_error_message(const rs2_error *error)
void stream_arg(std::ostream &out, const T &val, bool last)
void stream_args(std::ostream &out, const char *names, const T &first, const U &... rest)
static void translate_exception(const char *name, std::string args, rs2_error **error)
GLenum const GLfloat * params
void stream_arg(std::ostream &out, T *val, bool last)
rs2_notification(const librealsense::notification *notification)
int lrs_major(int version)
std::shared_ptr< librealsense::context > ctx
LOG_INFO("Log message using LOG_INFO()")
rs2_exception_type get_exception_type() const noexcept
void report_error(std::string error)
int lrs_minor(int version)
typename ::boost::move_detail::remove_reference< T >::type && move(T &&t) BOOST_NOEXCEPT
std::string api_version_to_string(int version)
std::vector< uint8_t > buffer
std::string to_string(T value)