1 /* 2 Copyright (c) 2019, Michael Fisher <mfisher@kushview.net> 3 4 Permission to use, copy, modify, and/or distribute this software for any 5 purpose with or without fee is hereby granted, provided that the above 6 copyright notice and this permission notice appear in all copies. 7 8 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 /** @defgroup atom Atom 18 Dealing with LV2 Atoms 19 */ 20 21 #pragma once 22 23 #include <iostream> 24 #include <string> 25 26 #include <lv2/lv2plug.in/ns/ext/atom/atom.h> 27 #include <lv2/lv2plug.in/ns/ext/atom/forge.h> 28 #include <lv2/lv2plug.in/ns/ext/atom/util.h> 29 30 namespace lvtk { 31 /* @{ */ 32 /** Alias to `LV2_Atom_Event` */ 33 using AtomEvent = LV2_Atom_Event; 34 35 /** Alias to `LV2_Atom_Property_Body` */ 36 using PropertyBody = LV2_Atom_Property_Body ; 37 38 /** Alias to `LV2_Atom_Forge_Frame` */ 39 using ForgeFrame = LV2_Atom_Forge_Frame; 40 41 /** Alias to `LV2_Atom_Forge_Ref` */ 42 using ForgeRef = LV2_Atom_Forge_Ref; 43 44 /** Alias to `LV2_Atom_Object_Query` */ 45 using ObjectQuery = LV2_Atom_Object_Query; 46 47 /** An LV2_Atom_Object wrapper 48 @headerfile lvtk/ext/atom.hpp 49 */ 50 struct Object final 51 { 52 /** Create an Object from raw data. The data passed in will be casted 53 to a LV2_Atom_Object pointer 54 55 @param data Pointer to an LV2_Atom_Object 56 */ Objectlvtk::Object57 Object (const void* data) 58 : obj ((LV2_Atom_Object*) data) { } 59 60 /** Create an Object from a ForgeRef 61 62 @param ref A ForgeRef which will be casted to LV2_Atom_Object internally 63 */ Objectlvtk::Object64 Object (ForgeRef ref) 65 : obj ((LV2_Atom_Object*) ref) { } 66 67 /** Copy constructor only references the internal pointer */ Objectlvtk::Object68 Object (const Object& other) { 69 operator= (other); 70 } 71 72 /** @returns the object type */ otypelvtk::Object73 inline uint32_t otype() const { 74 return object_type(); 75 } 76 77 /** @returns the object type */ object_typelvtk::Object78 inline uint32_t object_type() const { 79 return obj->body.otype; 80 } 81 82 /** Return the object's id */ idlvtk::Object83 inline uint32_t id() const { 84 return obj->body.id; 85 } 86 87 /** Return the object's total size */ total_sizelvtk::Object88 inline uint32_t total_size() const { 89 return lv2_atom_total_size ((LV2_Atom*) obj); 90 } 91 92 /** Get an object's values for various keys. 93 94 The value pointer of each item in @p query will be set to the location of 95 the corresponding value in @p object. Every value pointer in @p query MUST 96 be initialised to NULL. This function reads @p object in a single linear 97 sweep. By allocating @p query on the stack, objects can be "queried" 98 quickly without allocating any memory. This method is realtime safe. 99 100 This function can only do "flat" queries, it is not smart enough to match 101 variables in nested objects. 102 */ querylvtk::Object103 inline void query (ObjectQuery& query) const { 104 lv2_atom_object_query (obj, &query); 105 } 106 107 /** Get the underlying LV2_Atom_Object pointer */ c_objlvtk::Object108 inline LV2_Atom_Object* c_obj() const { return obj; } 109 110 /** Pass this as a LV2_Atom Object* parameter */ operator LV2_Atom_Object*lvtk::Object111 inline operator LV2_Atom_Object*() const { return obj; } 112 113 /** Pass this as a const LV2_Atom Object* parameter */ operator const LV2_Atom_Object*lvtk::Object114 inline operator const LV2_Atom_Object*() const { return obj; } 115 116 /** Assignment operator takes reference of the internal pointer */ operator =lvtk::Object117 inline Object& operator= (const Object& other) { 118 obj = other.obj; 119 return *this; 120 } 121 122 /** @private */ 123 struct iterator { operator *lvtk::Object::iterator124 const PropertyBody& operator*() const { assert (index); return *index; } operator ->lvtk::Object::iterator125 const PropertyBody* operator->() const { assert (index); return index; } 126 operator ++lvtk::Object::iterator127 iterator& operator++() { 128 index = lv2_atom_object_next (index); 129 if (lv2_atom_object_is_end (&obj->body, obj->atom.size, index)) 130 index = nullptr; 131 return *this; 132 } 133 operator ++lvtk::Object::iterator134 iterator operator++ (int) { 135 iterator ret (obj, index); 136 ++(*this); 137 return ret; 138 } 139 operator ==lvtk::Object::iterator140 bool operator== (const iterator& other) const { return index == other.index; } operator !=lvtk::Object::iterator141 bool operator!= (const iterator& other) const { return index != other.index; } 142 143 private: 144 friend struct Object; iteratorlvtk::Object::iterator145 iterator (LV2_Atom_Object* o, LV2_Atom_Property_Body* i) 146 : index (i), obj (o) { } 147 LV2_Atom_Property_Body* index; 148 LV2_Atom_Object* obj; 149 }; 150 151 /** Start of properties */ beginlvtk::Object152 iterator begin() const { return iterator (obj, lv2_atom_object_begin (&obj->body)); } 153 154 /** End of properties */ endlvtk::Object155 iterator end() const { return iterator (obj, nullptr); } 156 157 private: 158 LV2_Atom_Object* obj = nullptr; 159 }; 160 161 /** An LV2_Atom wrapper 162 These are intended to be used on the stack 163 164 @headerfile lvtk/ext/atom.hpp 165 */ 166 struct Atom final 167 { 168 /** Create a null Atom */ Atomlvtk::Atom169 Atom() 170 : atom (nullptr) {} 171 172 /** Create an Atom from raw data */ Atomlvtk::Atom173 Atom (const void* data) 174 : atom (reinterpret_cast<const LV2_Atom*> (data)) { } 175 176 /** Create an Atom from a Forge Ref */ Atomlvtk::Atom177 Atom (ForgeRef ref) 178 : atom (reinterpret_cast<LV2_Atom*> (ref)) { } 179 180 /** Create an Atom from an AtomEvent */ Atomlvtk::Atom181 Atom (const AtomEvent* ev) 182 : atom (&ev->body) {} 183 184 /** Create an Atom from a CType reference */ Atomlvtk::Atom185 Atom (const LV2_Atom& ref) 186 : atom (&ref) {} 187 188 /** Create an Atom from an Object */ Atomlvtk::Atom189 Atom (const Object& obj) 190 : atom ((const LV2_Atom*) obj.c_obj()) { } 191 192 /** Pad a size to 64 bits 193 @param size The size to pad 194 @returns The padded size 195 */ pad_sizelvtk::Atom196 inline static uint32_t pad_size (uint32_t size) { 197 return lv2_atom_pad_size (size); 198 } 199 200 /** Determine if the Atom is null */ is_nulllvtk::Atom201 inline bool is_null() const { 202 return lv2_atom_is_null (atom); 203 } 204 205 /** Returns true if this atom has type and equals a given value 206 @param type The atom POD type 207 @param value The value to test 208 */ 209 template<typename POD> has_type_and_equalslvtk::Atom210 inline bool has_type_and_equals (uint32_t type, const POD& value) const { 211 return atom->type == type && operator== (value); 212 } 213 214 /** Get the Atom's body */ bodylvtk::Atom215 inline void* body() const { return LV2_ATOM_BODY (atom); } 216 217 /** Get the body as a boolean */ as_boollvtk::Atom218 inline bool as_bool() const { return ((LV2_Atom_Bool*)atom)->body > 0; } 219 220 /** Get the body as a float */ as_floatlvtk::Atom221 inline float as_float() const { return ((LV2_Atom_Float*)atom)->body; } 222 223 /** Get the body as a double */ as_doublelvtk::Atom224 inline double as_double() const { return ((LV2_Atom_Double*)atom)->body; } 225 226 /** Returns the atom casted to LV2_Atom_Object */ as_objectlvtk::Atom227 const Object as_object() const { return Object ((LV2_Atom_Object* ) atom); } 228 229 /** Get the body as a string */ as_stringlvtk::Atom230 inline const char* as_string() const { return (const char*) LV2_ATOM_BODY (atom); } 231 232 /** Get the body as a 32bit integer */ as_intlvtk::Atom233 inline int32_t as_int() const { return ((LV2_Atom_Int*)atom)->body; } 234 235 /** Get the body as a long */ as_longlvtk::Atom236 inline int64_t as_long() const { return ((LV2_Atom_Long*)atom)->body; } 237 238 /** Get the body as a URID */ as_uridlvtk::Atom239 inline uint32_t as_urid() const { return ((LV2_Atom_URID*)atom)->body; } 240 241 /** Get this Atom's type */ typelvtk::Atom242 inline uint32_t type() const { return atom->type; } 243 244 /** Get the Atom's total size */ total_sizelvtk::Atom245 inline uint32_t total_size() const { return lv2_atom_total_size (atom); } 246 247 /** Get the Atom's body size */ sizelvtk::Atom248 inline uint32_t size() const { return atom->size; } 249 250 /** Get the underlying LV2_Atom pointer */ c_objlvtk::Atom251 inline const LV2_Atom* c_obj() const { return atom; } 252 253 /** Castable to bool */ operator boollvtk::Atom254 inline operator bool() const { return ! lv2_atom_is_null (atom); } 255 256 /** Castable to const LV2_Atom* */ operator const LV2_Atom*lvtk::Atom257 inline operator const LV2_Atom*() const { return atom; } 258 259 /** Reference another atom 260 Does NOT make a copy, instead references the other 261 Atom's internal pointer 262 */ operator =lvtk::Atom263 inline Atom& operator= (const Atom& other) { 264 atom = other.atom; 265 return *this; 266 } 267 268 /** Equality operator */ operator ==lvtk::Atom269 inline bool operator== (const Atom& other) const { 270 return lv2_atom_equals (atom, other.atom); 271 } 272 273 /** Inequality operator */ operator !=lvtk::Atom274 inline bool operator!= (const Atom& other) const { 275 return ! lv2_atom_equals (atom, other.atom); 276 } 277 278 private: 279 friend struct Object; 280 const LV2_Atom* atom = nullptr; 281 282 /** @private Used by has_type_and_equals */ operator ==lvtk::Atom283 inline bool operator== (const LV2_URID& u) const { return (((LV2_Atom_URID*)atom)->body == u); } operator ==lvtk::Atom284 inline bool operator== (const int32_t& i) const { return (((LV2_Atom_Int*)atom)->body == i); } operator ==lvtk::Atom285 inline bool operator== (const int64_t& l) const { return (((LV2_Atom_Long*)atom)->body == l); } operator ==lvtk::Atom286 inline bool operator== (const float& f) const { return (((LV2_Atom_Float*)atom)->body == f); } operator ==lvtk::Atom287 inline bool operator== (const double& f) const { return (((LV2_Atom_Double*)atom)->body == f); } 288 }; 289 290 /** An LV2_Atom_Sequence wrapper. 291 292 Since this implements an STL style container, you can use it as follows: 293 @code 294 295 Sequence seq (my_lv2_sequence_ptr()); 296 for (const auto& ev : seq) { 297 // handle event 298 } 299 300 @endcode 301 @headerfile lvtk/ext/atom.hpp 302 */ 303 struct Sequence final 304 { 305 typedef AtomEvent* pointer; 306 typedef AtomEvent& reference; 307 typedef const AtomEvent* const_pointer; 308 typedef const AtomEvent& const_reference; 309 310 /** Create an Sequence from raw data 311 @param seq Pointer to an LV2_Atom_Sequence 312 */ Sequencelvtk::Sequence313 Sequence (const void* data) 314 : sequence ((LV2_Atom_Sequence*) data) { } 315 316 /** Create an AtomSequnce from an LV2_Atom_Sequence 317 @param seq The sequence to wrap 318 */ Sequencelvtk::Sequence319 Sequence (LV2_Atom_Sequence* seq) 320 : sequence (seq) { } 321 322 /** Create an Sequence from a ForgeRef */ Sequencelvtk::Sequence323 Sequence (ForgeRef ref) 324 : sequence ((LV2_Atom_Sequence*) ref) { } 325 326 /** Reset for writing */ resetlvtk::Sequence327 inline void reset() { 328 sequence->atom.size = sizeof (LV2_Atom_Sequence_Body); 329 } 330 331 /** Return the sequence body's pad. Currently unused per LV2 spec. */ padlvtk::Sequence332 inline uint32_t pad() const { return sequence->body.pad; } 333 334 /** Return the sequence's body size 335 @note This method does NOT return the number of events contained in 336 the Sequence. It is the size in terms of bytes. 337 */ sizelvtk::Sequence338 inline uint32_t size() const { return sequence->atom.size; } 339 340 /** Return the sequence's unit */ unitlvtk::Sequence341 inline uint32_t unit() const { return sequence->body.unit; } 342 343 /** Return the sequence's c-type */ c_objlvtk::Sequence344 inline LV2_Atom_Sequence* c_obj() { return sequence; } 345 346 /** Castable to bool. True if the sequence isn't nullptr */ operator boollvtk::Sequence347 inline operator bool() const { return sequence != 0; } 348 349 /** Castable to LV2_Atom_Sequence */ operator LV2_Atom_Sequence*lvtk::Sequence350 inline operator LV2_Atom_Sequence*() const { return sequence; } 351 352 /** @private */ operator uint8_t*lvtk::Sequence353 inline operator uint8_t*() const { return (uint8_t*) sequence; } 354 355 /** Append an AtomEvent to the end of the sequence. 356 357 Effectively this is the same as lv2_atom_sequence_append, but 358 re-implemented to avoid an extra function call. 359 360 @param ev The event to add 361 */ appendlvtk::Sequence362 inline void append (const AtomEvent& ev) { 363 if (AtomEvent* pos = lv2_atom_sequence_end (&sequence->body, sequence->atom.size)) { 364 auto total_size = (uint32_t)sizeof(ev) + ev.body.size; 365 memcpy (pos, &ev, total_size); 366 sequence->atom.size += lv2_atom_pad_size (total_size); 367 } 368 } 369 370 /** Insert an AtomEvent into the middle of the sequence 371 372 @param ev The event to insert 373 */ insertlvtk::Sequence374 inline void insert (const AtomEvent& ev) { 375 AtomEvent* e = lv2_atom_sequence_end (&sequence->body, sequence->atom.size); 376 LV2_ATOM_SEQUENCE_FOREACH (sequence, iter) { 377 if (iter->time.frames > ev.time.frames) { 378 memmove (((uint8_t*) iter) + lv2_atom_pad_size ((uint32_t) sizeof(*iter) + iter->body.size), 379 (uint8_t*) iter, 380 (uint8_t*) e - (uint8_t*) iter); 381 e = iter; 382 break; 383 } 384 } 385 386 if (e) { 387 auto total_size = (uint32_t)sizeof(ev) + ev.body.size; 388 memcpy (e, &ev, total_size); 389 sequence->atom.size += lv2_atom_pad_size (total_size); 390 } 391 } 392 393 /** @private */ 394 struct iterator { operator *lvtk::Sequence::iterator395 AtomEvent& operator*() { return *event; } operator ->lvtk::Sequence::iterator396 const AtomEvent* operator->() const { return event; } 397 operator ++lvtk::Sequence::iterator398 iterator& operator++() 399 { 400 event = lv2_atom_sequence_next (event); 401 return *this; 402 } 403 operator ++lvtk::Sequence::iterator404 iterator operator++(int) 405 { 406 iterator res (sequence, event); 407 ++(*this); 408 return res; 409 } 410 operator ==lvtk::Sequence::iterator411 inline bool operator== (const iterator& other) const { return event == other.event; } operator !=lvtk::Sequence::iterator412 inline bool operator!= (const iterator& other) const { return event != other.event; } 413 414 private: 415 friend struct Sequence; iteratorlvtk::Sequence::iterator416 iterator (LV2_Atom_Sequence *seq, AtomEvent* ev) 417 : event (ev), sequence (seq) { } 418 LV2_Atom_Event* event = nullptr; 419 LV2_Atom_Sequence* sequence = nullptr; 420 }; 421 422 /** @returns an iterator starting at the first event */ beginlvtk::Sequence423 inline iterator begin() const { 424 return iterator (sequence, lv2_atom_sequence_begin (&sequence->body)); 425 } 426 427 /** @returns the end iterator of this sequence */ endlvtk::Sequence428 inline iterator end() const { 429 return iterator (sequence, lv2_atom_sequence_end (&sequence->body, sequence->atom.size)); 430 } 431 432 private: 433 LV2_Atom_Sequence* sequence = nullptr; 434 uint32_t capacity = 0; 435 }; 436 437 /** Class wrapper around LV2_Atom_Forge 438 @headerfile lvtk/ext/atom.hpp 439 */ 440 struct Forge final : LV2_Atom_Forge 441 { 442 /** Uninitialized Forge. 443 Client code must call Forge::init() before using otherwise 444 written output will be unpredictable and likely cause a nasty crash 445 */ 446 Forge() = default; 447 448 /** Initialized Forge. 449 @param map The LV2_URID_Map to use for initialization 450 */ Forgelvtk::Forge451 Forge (LV2_URID_Map* map) { init (map); } 452 453 /** Initialize the underlying atom forge 454 @param map The mapping function needed for init 455 */ initlvtk::Forge456 inline void init (LV2_URID_Map* map) { 457 lv2_atom_forge_init (this, map); 458 } 459 460 /** Set the Forge's buffer 461 462 You must call this before writing Atoms with the forge. Failing 463 to do so could result in a nasty crash. 464 465 @param buf The buffer to use 466 @param size The size of the buffer 467 */ set_bufferlvtk::Forge468 inline void set_buffer (uint8_t* buf, uint32_t size) { 469 lv2_atom_forge_set_buffer (this, buf, size); 470 } 471 472 /** Forge the header of a sequence */ write_sequence_headlvtk::Forge473 inline ForgeRef write_sequence_head (ForgeFrame& frame, uint32_t unit) { 474 return lv2_atom_forge_sequence_head (this, &frame, unit); 475 } 476 477 /** Forge frame time (in a sequence) */ write_beat_timelvtk::Forge478 inline ForgeRef write_beat_time (double beats) { 479 return lv2_atom_forge_beat_time (this, beats); 480 } 481 482 /** Forge frame time (in a sequence). The returned ForgeRef is to an 483 LV2_Atom_Event 484 */ write_frame_timelvtk::Forge485 inline ForgeRef write_frame_time (int64_t frames) { 486 return lv2_atom_forge_frame_time (this, frames); 487 } 488 489 /** Write a property header 490 @param key The URID for the key 491 @param context The context 492 */ write_property_headlvtk::Forge493 inline ForgeRef write_property_head (uint32_t key, uint32_t context) { 494 return lv2_atom_forge_property_head (this, key, context); 495 } 496 497 /** Pop a forge frame 498 @param frame The frame to pop 499 */ poplvtk::Forge500 inline void pop (ForgeFrame& frame) { 501 lv2_atom_forge_pop (this, &frame); 502 } 503 504 /** Write an atom header 505 506 @param size The atom's body size 507 @param type The atom's body type 508 @return A reference to the written atom 509 */ write_atomlvtk::Forge510 inline ForgeRef write_atom (uint32_t size, uint32_t type) { 511 return lv2_atom_forge_atom (this, size, type); 512 } 513 write_keylvtk::Forge514 inline ForgeRef write_key (uint32_t urid) { 515 return lv2_atom_forge_key (this, urid); 516 } 517 518 /** Write an atom object */ write_objectlvtk::Forge519 inline ForgeRef write_object (ForgeFrame& frame, uint32_t id, uint32_t otype) { 520 return lv2_atom_forge_object (this, &frame, id, otype); 521 } 522 523 /** Write an atom path from string 524 525 @param path The path to forge 526 @return An Atom 527 */ write_pathlvtk::Forge528 inline ForgeRef write_path (const std::string& path) { 529 return lv2_atom_forge_path (this, path.c_str(), path.size()); 530 } 531 write_primitivelvtk::Forge532 inline ForgeRef write_primitive (const Atom& atom) { 533 return lv2_atom_forge_primitive (this, atom.c_obj()); 534 } 535 536 /** Write a boolean value 537 @param val The value to write 538 @returns A reference to the Atom 539 */ write_boollvtk::Forge540 inline ForgeRef write_bool (const bool val) { 541 return lv2_atom_forge_bool (this, val); 542 } 543 544 /** Write an integeger value 545 @param val The value to write 546 @returns A reference to the Atom 547 */ write_intlvtk::Forge548 inline ForgeRef write_int (const int val) { 549 return lv2_atom_forge_int (this, val); 550 } 551 552 /** Write a double value @param val the value to write 553 @param val The value to write 554 @returns A reference to the Atom 555 */ write_doublelvtk::Forge556 inline ForgeRef write_double (const double val) { 557 return lv2_atom_forge_double (this, val); 558 } 559 560 /** Write a float value */ write_floatlvtk::Forge561 inline ForgeRef write_float (const float val) { 562 return lv2_atom_forge_float (this, val); 563 } 564 565 /** Write a long integer value */ write_longlvtk::Forge566 inline ForgeRef write_long (const int64_t val) { 567 return lv2_atom_forge_long (this, val); 568 } 569 570 /** Write a string value */ write_stringlvtk::Forge571 inline ForgeRef write_string (const char* str) { 572 return lv2_atom_forge_string (this, str, strlen (str)); 573 } 574 575 /** Write a URI string */ write_urilvtk::Forge576 inline ForgeRef write_uri (const char* uri) { 577 return lv2_atom_forge_uri (this, uri, strlen (uri)); 578 } 579 580 /** Write raw data 581 @param data The data to write 582 @param size The size in bytes of data 583 */ write_rawlvtk::Forge584 inline ForgeRef write_raw (const void* data, uint32_t size) { 585 return lv2_atom_forge_raw (this, data, size); 586 } 587 588 /** Write a URID value 589 @param id The URID to write 590 */ write_uridlvtk::Forge591 inline ForgeRef write_urid (LV2_URID id) { 592 return lv2_atom_forge_urid (this, id); 593 } 594 }; 595 596 /** An LV2_Atom_Vector Wrapper 597 @headerfile lvtk/ext/atom.hpp 598 */ 599 struct Vector final 600 { Vectorlvtk::Vector601 inline Vector (ForgeRef ref) : vec ((LV2_Atom_Vector*) ref) { } 602 ~Vector() = default; 603 sizelvtk::Vector604 inline size_t size() const { return vec->atom.size / vec->body.child_size; } child_sizelvtk::Vector605 inline uint32_t child_size() const { return vec->body.child_size; } child_typelvtk::Vector606 inline uint32_t child_type() const { return vec->body.child_type; } c_objlvtk::Vector607 inline LV2_Atom_Vector* c_obj() const { return vec; } operator LV2_Atom_Vector*lvtk::Vector608 inline operator LV2_Atom_Vector* () const { return vec; } 609 610 /** @private */ 611 struct iterator { operator ++lvtk::Vector::iterator612 iterator& operator++() 613 { 614 offset += vec->body.child_size; 615 616 if (vec && offset >= vec->atom.size) 617 offset = vec->atom.size; 618 619 return *this; 620 } 621 operator ++lvtk::Vector::iterator622 iterator operator++(int) 623 { 624 iterator it (vec, offset); 625 ++(*this); 626 return it; 627 } 628 operator ==lvtk::Vector::iterator629 inline bool operator== (const iterator& other) const { return vec == other.vec && offset == other.offset; } operator !=lvtk::Vector::iterator630 inline bool operator!= (const iterator& other) const { return vec != other.vec && offset != other.offset; } 631 632 /** Reference another iterator */ operator =lvtk::Vector::iterator633 inline iterator& operator= (const iterator& other) { 634 this->vec = other.vec; 635 this->offset = other.offset; 636 return *this; 637 } 638 639 private: 640 friend class Vector; iteratorlvtk::Vector::iterator641 iterator (LV2_Atom_Vector *v, uint32_t os = 0) : vec (v), offset (os) { } 642 LV2_Atom_Vector* vec = nullptr; 643 uint32_t offset = 0; 644 }; 645 646 /** Returns an iterator to the begining of the vector */ beginlvtk::Vector647 iterator begin() const { return iterator (vec); } 648 649 /** Returns the end iterator */ endlvtk::Vector650 iterator end() const { return iterator (vec, vec->atom.size); } 651 652 private: 653 LV2_Atom_Vector* vec = nullptr; 654 }; 655 /* @} */ 656 } /* namespace lvtk */ 657