10 #include <type_traits>
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 ?
"" :
", ");
85 else out <<
"nullptr";
86 out << (last ?
"" :
", ");
91 template<
class T>
void stream_args(std::ostream &
out,
const char * names,
const T & last)
95 s.stream_arg(
out, last,
true);
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;
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)