20 #define IIOPP_HAVE_STD_OPIONAL (__cplusplus >= 201703L || _MSC_VER >= 1910)
22 #if IIOPP_HAVE_STD_OPIONAL
25 #include <boost/optional.hpp>
28 #include <system_error>
30 #include <type_traits>
62 #if IIOPP_HAVE_STD_OPIONAL
65 using boost::optional;
82 cstr(std::string
const & s) : s(s.c_str()){}
83 cstr(
char const * s) : s(s){assert(s);}
84 cstr(
void const * s) : s(
static_cast<char const *
>(s)){assert(s);}
86 char const * c_str()
const {
return s;}
87 operator char const * ()
const {
return s;}
92 class error :
public std::system_error
95 using std::system_error::system_error;
109 inline optstr opt(
char const * s)
114 template <
class T,
class C> optional<T> maybe(C * obj)
116 return obj ? optional<T>{{obj}} : optional<T>{};
119 inline std::string err_str(
int err)
122 iio_strerror(err, buf,
sizeof(buf));
126 [[noreturn]]
inline void err(
int err,
char const * ctx)
129 throw error(err, std::generic_category(), ctx);
132 inline void check(
int ret,
char const * ctx)
142 T * check(T * ret,
char const * ctx)
144 if (
int e = iio_err(ret))
153 T check_n(T n,
char const * s)
156 impl::err(
static_cast<int>(-n), s);
164 template <
class container_T,
class element_T>
167 container_T & _me() {
return *
static_cast<container_T*
>(
this);}
175 typedef std::random_access_iterator_tag iterator_category;
176 typedef element_T value_type;
177 typedef decltype(std::declval<container_T>().size()) size_type;
178 typedef std::make_signed<size_type> difference_type;
179 typedef element_T *pointer;
180 typedef element_T &reference;
182 Iterator(container_T &cont, size_type idx) : c(cont), i(idx) {assert(idx <= cont.size());}
184 element_T operator*()
const {
return c[i]; }
185 Iterator& operator++() { assert(i <= c.size()); ++i;
return *
this;}
187 bool operator == (
const Iterator& rhs)
const { assert(&c == &rhs.c);
return i == rhs.i; }
188 bool operator != (
const Iterator& rhs)
const { assert(&c == &rhs.c);
return i != rhs.i; }
189 bool operator < (
const Iterator& rhs)
const { assert(&c == &rhs.c);
return i < rhs.i; }
190 bool operator > (
const Iterator& rhs)
const { assert(&c == &rhs.c);
return i > rhs.i; }
191 bool operator <= (
const Iterator& rhs)
const { assert(&c == &rhs.c);
return i <= rhs.i; }
192 bool operator >= (
const Iterator& rhs)
const { assert(&c == &rhs.c);
return i >= rhs.i; }
193 Iterator operator + (difference_type x)
const {
return Iterator(c, i + x); }
194 int operator - (
Iterator rhs)
const { assert(&c == &rhs.c);
return i - rhs.i; }
201 Iterator end() {
return Iterator(_me(), _me().size());}
214 Attr(iio_attr
const * attr) : p(attr){assert(attr);}
215 operator iio_attr
const * ()
const {
return p;}
217 cstr name() {
return iio_attr_get_name(p);}
218 cstr filename() {
return iio_attr_get_filename(p);}
219 cstr static_value() {
return iio_attr_get_static_value(p);}
221 size_t read_raw(
char * dst,
size_t size)
const {
return impl::check_n(iio_attr_read_raw(p, dst, size),
"iio_attr_read_raw");}
222 bool read_bool()
const {
bool val; impl::check(iio_attr_read_bool(p, &val),
"iio_attr_read_bool");
return val;}
223 double read_double()
const {
double val; impl::check(iio_attr_read_double(p, &val),
"iio_attr_read_double");
return val;}
224 long long read_longlong()
const {
long long val; impl::check(iio_attr_read_longlong(p, &val),
"iio_attr_read_longlong");
return val;}
226 size_t write_raw(
void const * src,
size_t len) {
return impl::check_n(iio_attr_write_raw(p, src, len),
"iio_attr_write_raw");}
227 size_t write_string(
cstr val) {
return impl::check_n(iio_attr_write_string(p, val),
"iio_attr_write_string");}
228 void write_bool(
bool val) {impl::check(iio_attr_write_bool(p, val),
"iio_attr_write_bool");}
229 void write_double(
double val) {impl::check(iio_attr_write_double(p, val),
"iio_attr_write_double");}
230 void write_longlong(
long long val) {impl::check(iio_attr_write_longlong(p, val),
"iio_attr_write_longlong");}
232 operator bool ()
const {
return read_bool();}
233 operator double ()
const {
return read_double();}
234 operator long long ()
const {
return read_longlong();}
236 cstr operator = (
cstr val){write_string(val);
return val;}
237 bool operator = (
bool val){write_bool(val);
return val;}
238 double operator = (
double val){write_double(val);
return val;}
239 long long operator = (
long long val){write_longlong(val);
return val;}
248 template <
class obj_T>
251 template <class obj_T,
252 unsigned int get_attrs_count_T(obj_T const *),
253 iio_attr const * get_attr_T(obj_T const *, unsigned int),
254 iio_attr const * find_attr_T(obj_T const *, char const *)
259 obj_T
const *
const _obj;
261 AttrSeqT(obj_T
const * obj) : _obj(obj){assert(obj);}
265 unsigned int size()
const {
return get_attrs_count_T(_obj);}
271 if (
auto ret = get_attr_T(_obj, idx))
273 throw std::out_of_range(
"invalid attribute index");
280 if (
auto ret = find_attr_T(_obj, name))
282 throw std::out_of_range(
"invalid attribute name");
286 template <
class obj_T, iio_attr const * find_attr_T(obj_T const *,
char const *)>
287 optional<Attr> attr(obj_T
const * obj,
cstr name)
289 return maybe<Attr>(find_attr_T(obj, name));
292 template <
class obj_T, iio_attr const * get_attr_T(obj_T const *,
unsigned int)>
293 optional<Attr> attr(obj_T
const * obj,
unsigned int index)
295 return maybe<Attr>(get_attr_T(obj, index));
309 template <
class obj_T,
class ptr_T,
void deleter_T(ptr_T *)>
315 Ptr(
Ptr const &) =
delete;
316 Ptr(
Ptr && rhs) : p(rhs.p) { rhs.p =
nullptr;}
317 explicit Ptr(ptr_T * obj) : p{obj}{}
318 ~
Ptr(){
if (p) deleter_T(
const_cast<ptr_T*
>(
static_cast<ptr_T const*
>(p)));}
320 Ptr & operator = (
Ptr &) =
delete;
321 void operator = (
Ptr && rhs)
329 operator obj_T * () {
return &p;}
330 operator obj_T * ()
const {
return &p;}
331 obj_T * operator -> () {
return &p;}
332 obj_T
const * operator -> ()
const {
return &p;}
339 iio_channels_mask
const *
const p;
343 ChannelsMask(iio_channels_mask
const * mask) : p(mask){assert(mask);}
344 operator iio_channels_mask
const * ()
const {
return p;}
362 Block(iio_block * block) : p(block){assert(block);}
363 operator iio_block * ()
const {
return p;}
365 void * start() {
return iio_block_start(p);}
366 void * first(iio_channel * chn) {
return iio_block_first(p, chn);}
367 void * end() {
return iio_block_end(p);}
368 ssize_t foreach_sample(
const struct iio_channels_mask *mask,
369 ssize_t (*callback)(
const struct iio_channel *chn,
void *src,
size_t bytes,
void *d),
372 return iio_block_foreach_sample(p, mask, callback, data);
375 void enqueue(
size_t bytes_used,
bool cyclic) {impl::check(iio_block_enqueue(p, bytes_used, cyclic),
"iio_block_enqueue");}
376 void dequeue(
bool nonblock) {impl::check(iio_block_dequeue(p, nonblock),
"iio_block_dequeue");}
386 iio_channel *
const p;
390 Channel(iio_channel * chan) : p(chan), attrs(chan){assert(chan);}
391 operator iio_channel * ()
const {
return p;}
395 iio_channel_get_attrs_count,
396 iio_channel_get_attr,
397 iio_channel_find_attr
406 cstr id()
const {
return iio_channel_get_id(p);}
407 optstr name()
const {
return impl::opt(iio_channel_get_name(p));}
408 bool is_output()
const {
return iio_channel_is_output(p);}
409 bool is_scan_element()
const {
return iio_channel_is_scan_element(p);}
410 unsigned int attrs_count()
const {
return iio_channel_get_attrs_count(p);}
411 optional<Attr> attr(
unsigned int index) {
return impl::maybe<Attr>(iio_channel_get_attr(p, index));}
412 optional<Attr> find_attr(
cstr name) {
return impl::maybe<Attr>(iio_channel_find_attr(p, name));}
413 void enable(iio_channels_mask * mask) {iio_channel_enable(p, mask);}
414 void disable(iio_channels_mask * mask) {iio_channel_disable(p, mask);}
415 bool is_enabled(iio_channels_mask * mask)
const {
return iio_channel_is_enabled(p, mask);}
416 size_t read(
Block block,
void * dst,
size_t len,
bool raw)
const;
417 size_t write(
Block block,
void const * src,
size_t len,
bool raw);
418 void set_data(
void * data){iio_channel_set_data(p, data);}
419 void * data()
const {
return iio_channel_get_data(p);}
420 iio_chan_type type()
const {
return iio_channel_get_type(p);}
421 iio_modifier modifier()
const {
return iio_channel_get_modifier(p);}
422 hwmon_chan_type hwmon_type()
const {
return hwmon_channel_get_type(p);}
423 unsigned long index()
const {
return impl::check_n(iio_channel_get_index(p),
"iio_channel_get_index");}
424 iio_data_format
const * data_format()
const {
return iio_channel_get_data_format(p);}
425 void convert(
void * dst,
void const * src)
const {iio_channel_convert(p, dst, src);}
426 void convert_inverse(
void * dst,
void const * src)
const {iio_channel_convert_inverse(p, dst, src);}
433 iio_stream *
const p;
437 Stream(iio_stream * s) : p(s){assert(s);}
438 operator iio_stream * ()
const {
return p;}
440 Block next_block() {
return const_cast<iio_block *
>(impl::check(iio_stream_get_next_block(p),
"iio_stream_get_next_block")); }
450 iio_event_type type()
const {
return iio_event_get_type(
this);}
451 iio_event_direction direction()
const {
return iio_event_get_direction(
this);}
452 optional<Channel> channel(iio_device * dev,
bool diff){
return impl::maybe<Channel>(
const_cast<iio_channel*
>(iio_event_get_channel(
this, dev, diff)));}
459 iio_event_stream *
const p;
463 EventStream(iio_event_stream * s) : p(s){assert(p);}
464 operator iio_event_stream * ()
const {
return p;}
466 Event read(
bool nonblock) {iio_event ev; impl::check(iio_event_stream_read(p, &ev, nonblock),
"iio_event_stream_read");
return static_cast<Event&
>(ev);}
476 iio_buffer *
const p;
479 Buffer(iio_buffer * buffer) : p(buffer), attrs(buffer){assert(buffer);}
480 operator iio_buffer * ()
const {
return p;}
484 iio_buffer_get_attrs_count,
495 unsigned int attrs_count()
const {
return iio_buffer_get_attrs_count(p);}
496 optional<Attr> get_attr(
unsigned int index) {
return impl::maybe<Attr>(iio_buffer_get_attr(p, index));}
497 optional<Attr> find_attr(
cstr name) {
return impl::maybe<Attr>(iio_buffer_find_attr(p, name));}
498 void set_data(
void * data){iio_buffer_set_data(p, data);}
499 void * data() {
return iio_buffer_get_data(p);}
500 void cancel() {iio_buffer_cancel(p);}
501 void enable() {impl::check(iio_buffer_enable(p),
"iio_buffer_enable");}
502 void disable() {impl::check(iio_buffer_disable(p),
"iio_buffer_disable");}
503 ChannelsMask channels_mask() {
return iio_buffer_get_channels_mask(p);}
504 BlockPtr create_block(
size_t size) {
return BlockPtr{impl::check(iio_buffer_create_block(p, size),
"iio_buffer_create_block")}; }
505 StreamPtr create_stream(
size_t nb_blocks,
size_t sample_count) {
return StreamPtr{impl::check(iio_buffer_create_stream(p, nb_blocks, sample_count),
"iio_buffer_create_stream")}; }
514 iio_device *
const p;
517 unsigned int size()
const
519 return channels_count();
522 Channel operator [](
unsigned int i)
524 if (
auto maybeCh = channel(i))
527 throw std::out_of_range(
"channel index out of range");
532 iio_device_get_attrs_count,
544 iio_device_get_debug_attrs_count,
545 iio_device_get_debug_attr,
546 iio_device_find_debug_attr
556 Device(iio_device * dev) : p(dev), attrs(dev), debug_attrs(dev) {assert(dev);}
557 operator iio_device * ()
const {
return p;}
560 cstr id()
const {
return iio_device_get_id(p);}
561 optstr name()
const {
return impl::opt(iio_device_get_name(p));}
562 optstr label()
const {
return impl::opt(iio_device_get_label(p));}
563 unsigned int channels_count()
const {
return iio_device_get_channels_count(p);}
564 unsigned int attrs_count()
const {
return iio_device_get_attrs_count(p);}
565 optional<Channel> channel(
unsigned int idx)
const {
return impl::maybe<Channel>(iio_device_get_channel(p, idx));}
566 optional<Attr> attr(
unsigned int idx) {
return impl::attr<iio_device, iio_device_get_attr>(p, idx);}
567 optional<Channel> find_channel(
cstr name,
bool output)
const {
return impl::maybe<Channel>(iio_device_find_channel(p, name, output));}
568 optional<Attr> find_attr(
cstr name) {
return impl::attr<iio_device, iio_device_find_attr>(p, name);}
569 void set_data(
void * data){iio_device_set_data(p, data);}
570 void * data()
const {
return iio_device_get_data(p);}
571 Device trigger()
const {
return Device{
const_cast<iio_device*
>(impl::check(iio_device_get_trigger(p),
"iio_device_get_trigger"))};}
572 void set_trigger(iio_device
const * trigger) {impl::check(iio_device_set_trigger(p, trigger),
"iio_device_set_trigger");}
573 bool is_trigger()
const {
return iio_device_is_trigger(p);}
574 BufferPtr create_buffer(
unsigned int idx, iio_channels_mask * mask) {
return BufferPtr(impl::check(iio_device_create_buffer(p, idx, mask),
"iio_device_create_buffer"));}
575 bool is_hwmon()
const {
return iio_device_is_hwmon(p);}
576 EventStreamPtr create_event_stream() {
return EventStreamPtr{impl::check(iio_device_create_event_stream(p),
"iio_device_create_event_stream")};}
577 ssize_t sample_size(iio_channels_mask * mask)
const {
return impl::check_n(iio_device_get_sample_size(p, mask),
"iio_device_get_sample_size");}
578 unsigned int debug_attrs_count()
const {
return iio_device_get_debug_attrs_count(p);}
579 optional<Attr> debug_attr(
unsigned int idx) {
return impl::attr<iio_device, iio_device_get_debug_attr>(p, idx);}
580 optional<Attr> find_debug_attr(
cstr name) {
return impl::attr<iio_device, iio_device_find_debug_attr>(p, name);}
581 void reg_write(uint32_t address, uint32_t
value) {impl::check(iio_device_reg_write(p, address,
value),
"iio_device_reg_write");}
582 uint32_t reg_read(uint32_t address) {uint32_t
value; impl::check(iio_device_reg_read(p, address, &
value),
"iio_device_reg_read");
return value;}
591 iio_context *
const p;
593 unsigned int size()
const
595 return devices_count();
598 Device operator [](
unsigned int i)
600 if (
auto maybeDev = device(i))
603 throw std::out_of_range(
"device index out of range");
608 iio_context_get_attrs_count,
609 iio_context_get_attr,
610 iio_context_find_attr
620 Context(iio_context * ctx) : p(ctx), attrs(ctx) {assert(ctx);}
621 operator iio_context * ()
const {
return p;}
623 unsigned int version_major()
const {
return iio_context_get_version_major(p); }
624 unsigned int version_minor()
const {
return iio_context_get_version_minor(p); }
625 cstr version_tag()
const {
return iio_context_get_version_tag(p); }
626 CstrPtr xml()
const {
return CstrPtr{impl::check(iio_context_get_xml(p),
"iio_context_get_xml")};}
627 cstr name()
const {
return iio_context_get_name(p); }
628 cstr description()
const {
return iio_context_get_description(p); }
629 unsigned int attrs_count()
const {
return iio_context_get_attrs_count(p);}
630 optional<Attr> attr(
unsigned int idx) {
return impl::attr<iio_context, iio_context_get_attr>(p, idx);}
631 optional<Attr> find_attr(
cstr name) {
return impl::attr<iio_context, iio_context_find_attr>(p, name);}
632 unsigned int devices_count()
const {
return iio_context_get_devices_count(p);}
633 optional<Device> device(
unsigned int idx)
const {
return impl::maybe<Device>(iio_context_get_device(p, idx)); }
634 optional<Device> find_device(
cstr name)
const {
return impl::maybe<Device>(iio_context_find_device(p, name));}
635 void set_timeout(
unsigned int timeout_ms){impl::check(iio_context_set_timeout(p, timeout_ms),
"iio_context_set_timeout");}
636 iio_context_params
const * params()
const {
return iio_context_get_params(p);}
637 void set_data(
void * data){iio_context_set_data(p, data);}
638 void * data()
const {
return iio_context_get_data(p);}
643 inline Buffer Block::buffer() {
return iio_block_get_buffer(p);}
644 inline Context Device::context(){
return const_cast<iio_context*
>(iio_device_get_context(p));}
645 inline Device Channel::device()
const {
return const_cast<iio_device*
>(iio_channel_get_device(p));}
646 inline Device Buffer::device() {
return const_cast<iio_device*
>(iio_buffer_get_device(p));}
647 inline size_t Channel::read(Block block,
void * dst,
size_t len,
bool raw)
const {
return iio_channel_read(p, block, dst, len, raw);}
648 inline size_t Channel::write(Block block,
void const * src,
size_t len,
bool raw) {
return iio_channel_write(p, block, src, len, raw);}
654 return ContextPtr{impl::check(iio_create_context(params, uri),
"iio_create_context")};
661 struct iio_scan const *
const p;
666 ScanResult(
struct iio_scan
const * scan,
size_t index) : p(scan), idx(index){assert(scan);}
668 cstr description()
const {
return iio_scan_get_description(p, idx);}
669 cstr uri()
const {
return iio_scan_get_description(p, idx);}
676 struct iio_scan const *
const p;
680 return results_count();
683 ScanResult operator [](
size_t i)
685 assert(i < results_count());
686 return ScanResult{p, i};
690 Scan(
struct iio_scan
const * scan) : p(scan){assert(scan);}
691 operator struct iio_scan const * ()
const {
return p;}
692 size_t results_count()
const {
return iio_scan_get_results_count(p);}
697 ScanPtr scan(
struct iio_context_params
const * params,
char const * backends)
699 return ScanPtr(impl::check(iio_scan(params, backends),
"iio_scan"));
709 if (
auto att = ch.find_attr(
"input"))
710 return att->read_double() / 1000;
713 if (
auto att = ch.find_attr(
"scale"))
714 scale = att->read_double();
717 if (
auto att = ch.find_attr(
"offset"))
718 offset = att->read_double();
720 if (
auto att = ch.find_attr(
"raw"))
721 return (att->read_double() + offset) * scale / 1000.;
723 impl::err(ENOENT,
"channel does not provide raw value");