10 #include <type_traits> 36 std::shared_ptr<librealsense::context>
ctx;
37 std::shared_ptr<librealsense::device_info>
info;
38 std::shared_ptr<librealsense::device_interface>
device;
47 template<
class T,
bool S>
50 void stream_arg(std::ostream & out,
const T& val,
bool last)
52 out <<
':' << val << (last ?
"" :
", ");
61 static auto test(
const S* t) -> decltype(std::cout << **t);
62 static auto test(...)->std::false_type;
76 else out <<
"nullptr";
77 out << (last ?
"" :
", ");
88 if (val) out << (
int*)val;
89 else out <<
"nullptr";
90 out << (last ?
"" :
", ");
95 template<
class T>
void stream_args(std::ostream & out,
const char * names,
const T & last)
101 template<
class T,
class... U>
void stream_args(std::ostream & out,
const char * names,
const T & first,
const U &... rest)
103 while (*names && *names !=
',') out << *names++;
106 while (*names && (*names ==
',' || isspace(*names))) ++names;
110 static void translate_exception(
const char *
name, std::string args,
rs2_error ** error)
114 catch (
const std::exception& e) {
if (error) *error =
new rs2_error{ e.what(),
name, move(args) }; }
115 catch (...) {
if (error) *error =
new rs2_error{
"unknown error",
name, move(args) }; }
128 static api_objects& instance() {
129 static api_objects instance;
136 std::string register_new_object(
const std::string& type,
const std::string& address)
138 std::lock_guard<std::mutex> lock(_m);
139 return internal_register(type, address);
148 std::string augment_params(std::string p)
150 std::lock_guard<std::mutex> lock(_m);
151 std::string acc =
"";
152 std::string res =
"";
153 std::string param =
"";
155 bool is_value =
false;
156 for (
auto i = 0; i < p.size(); i++)
168 auto it = _names.find(acc);
169 if (it != _names.end()) acc = it->second;
174 std::stringstream ss; ss << (
int*)0;
175 if (acc.size() == ss.str().size())
177 acc = internal_register(param, acc);
180 res += param +
":" + acc;
181 if (i != p.size() - 1) res +=
",";
193 void remove_object(
const std::string&
name)
195 std::lock_guard<std::mutex> lock(_m);
196 auto it = _names.find(
name);
197 if (it != _names.end())
201 std::string internal_register(
const std::string& type,
const std::string& address)
203 auto it = _counters.find(type);
204 if (it == _counters.end()) _counters[type] = 0;
206 std::stringstream ss;
207 ss << type << _counters[type];
208 _names[address] = ss.str();
209 return _names[address];
213 std::map<std::string, std::string> _names;
214 std::map<std::string, int> _counters;
221 api_logger(std::string
function)
222 : _function(
std::move(function)), _result(
""), _param_str(
""), _type(
""),
223 _params([]() {
return std::string{}; })
225 _start = std::chrono::high_resolution_clock::now();
226 LOG_DEBUG(
"/* Begin " << _function <<
" */");
229 std::size_t found = _function.find_last_of(
"_");
230 _type = _function.substr(found + 1);
232 check_if_deleter(
"rs2_delete");
233 check_if_deleter(
"rs2_release");
237 void check_if_deleter(
const char* prefix)
239 auto deleter_pos = _function.find(prefix);
240 if (deleter_pos == 0)
246 void set_return_value(std::string result)
248 _result = std::move(result);
251 void set_params(std::function<std::string()> params)
253 _params = std::move(params);
256 std::string get_params() {
return _param_str = _params(); }
258 void report_error() { _error =
true; }
259 void report_pointer_return_type() { _returns_pointer =
true; }
263 auto d = std::chrono::high_resolution_clock::now() - _start;
264 auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(d).count();
265 std::stringstream ss;
266 std::string prefix =
"";
267 if (_param_str ==
"") _param_str = _params();
269 auto&& objs = api_objects::instance();
270 if (_returns_pointer)
272 prefix = objs.register_new_object(_type, _result) +
" = ";
275 if (_is_deleter) objs.remove_object(_result);
276 if (_param_str !=
"") _param_str = objs.augment_params(_param_str);
278 ss << prefix << _function <<
"(" << _param_str <<
")";
279 if (_result !=
"") ss <<
" returned " << _result;
281 if (ms > 0) ss <<
" /* Took " << ms <<
"ms */";
286 std::string _function, _result, _type, _param_str;
287 std::function<std::string()> _params;
288 bool _returns_pointer =
false;
289 bool _is_deleter =
false;
291 std::chrono::high_resolution_clock::time_point _start;
297 template<
typename F,
typename R>
298 R fetch_return_type(F& f, R(F::*mf)()
const);
306 result_printer(api_logger* logger) : _logger(logger) {}
319 std::stringstream ss; ss << _res;
320 _logger->set_return_value(ss.str());
329 class result_printer<T*>
332 result_printer(api_logger* logger) : _logger(logger) {}
345 std::stringstream ss; ss << (
int*)_res;
347 _logger->report_pointer_return_type();
348 _logger->set_return_value(ss.str());
358 class result_printer<void>
361 result_printer(api_logger* logger) {}
363 void invoke(F func) { func(); }
368 #define BEGIN_API_CALL { api_logger __api_logger(__FUNCTION__); {\ 374 #define NOEXCEPT_RETURN(R, ...) };\ 375 result_printer<decltype(fetch_return_type(func, &decltype(func)::operator()))> __p(&__api_logger);\ 376 __api_logger.set_params([&](){ std::ostringstream ss; librealsense::stream_args(ss, #__VA_ARGS__, __VA_ARGS__); return ss.str(); });\ 378 return __p.invoke(func);\ 380 rs2_error* e; librealsense::translate_exception(__FUNCTION__, __api_logger.get_params(), &e);\ 381 LOG_WARNING(rs2_get_error_message(e)); rs2_free_error(e); __api_logger.report_error(); return R; } } } 383 #define HANDLE_EXCEPTIONS_AND_RETURN(R, ...) };\ 384 result_printer<decltype(fetch_return_type(func, &decltype(func)::operator()))> __p(&__api_logger);\ 385 __api_logger.set_params([&](){ std::ostringstream ss; librealsense::stream_args(ss, #__VA_ARGS__, __VA_ARGS__); return ss.str(); });\ 387 return __p.invoke(func);\ 389 librealsense::translate_exception(__FUNCTION__, __api_logger.get_params(), error); __api_logger.report_error(); return R; } } } 391 #define NOARGS_HANDLE_EXCEPTIONS_AND_RETURN(R, ...) };\ 392 result_printer<decltype(fetch_return_type(func, &decltype(func)::operator()))> __p(&__api_logger);\ 394 return __p.invoke(func);\ 395 } catch(...) { librealsense::translate_exception(__FUNCTION__, "", error); __api_logger.report_error(); return R; } } } 397 #else // No API tracing: 399 #define BEGIN_API_CALL try 400 #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; } 401 #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; } 402 #define NOARGS_HANDLE_EXCEPTIONS_AND_RETURN(R) catch(...) { librealsense::translate_exception(__FUNCTION__, "", error); return R; } 407 #define VALIDATE_NOT_NULL(ARG) if(!(ARG)) throw std::runtime_error("null pointer passed for argument \"" #ARG "\""); 408 #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()); } 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_INTERFACE_NO_THROW(X, T) \ 413 T* p = dynamic_cast<T*>(&(*X)); \ 416 auto ext = dynamic_cast<librealsense::extendable_interface*>(&(*X)); \ 417 if (ext == nullptr) return nullptr; \ 420 if(!ext->extend_to(TypeToExtension<T>::value, (void**)&p)) \ 428 #define VALIDATE_INTERFACE(X,T) \ 430 T* p = VALIDATE_INTERFACE_NO_THROW(X,T); \ 432 throw std::runtime_error("Object does not support \"" #T "\" interface! " ); \ rs2_exception_type
Exception types are the different categories of errors that RealSense API might return.
Definition: rs_types.h:28
const librealsense::notification * _notification
Definition: api.h:31
void stream_args(std::ostream &out, const char *names, const T &last)
Definition: api.h:95
const char * what() const noexcept override
Definition: types.h:147
std::shared_ptr< librealsense::device_info > info
Definition: api.h:37
std::string args
Definition: api.h:22
rs2_exception_type exception_type
Definition: api.h:23
void stream_arg(std::ostream &out, T *val, bool last)
Definition: api.h:85
std::shared_ptr< librealsense::device_interface > device
Definition: api.h:38
#define LOG_DEBUG(...)
Definition: types.h:107
void stream_arg(std::ostream &out, const T &val, bool last)
Definition: api.h:50
rs2_notification(const librealsense::notification *notification)
Definition: api.h:28
#define LOG_INFO(...)
Definition: types.h:108
std::shared_ptr< librealsense::context > ctx
Definition: api.h:36
rs2_exception_type get_exception_type() const noexcept
Definition: types.h:142
void stream_arg(std::ostream &out, T *val, bool last)
Definition: api.h:72
std::string message
Definition: api.h:20
std::vector< uint8_t > buffer
Definition: api.h:15
#define LOG_ERROR(...)
Definition: types.h:110