class AutoC::Vector
Constants
- Range
Public Class Methods
new(type, element, parallel: nil, **kws)
click to toggle source
Calls superclass method
AutoC::Association::new
# File lib/autoc/vector.rb, line 26 def initialize(type, element, parallel: nil, **kws) super(type, element, :size_t, **kws) dependencies << STRING_H @parallel = parallel end
Public Instance Methods
_range_class(= Range)
click to toggle source
# File lib/autoc/vector.rb, line 22 def _range_class = Range def range = @range ||= _range_class.new(self, visibility: visibility, parallel: @parallel) def initialize(type, element, parallel: nil, **kws) super(type, element, :size_t, **kws) dependencies << STRING_H @parallel = parallel end def render_interface(stream) if public? stream << %{ /** #{defgroup} @brief Resizable vector of elements of type #{element} #{type} is a container that encapsulates dynamic size array of values of type #{element}. It is a contiguous direct access collection where elements can be directly referenced by an integer index belonging to the [0, @ref #{size}) range. For iteration over the vector elements refer to @ref #{range}. @see C++ [std::vector<T>](https://en.cppreference.com/w/cpp/container/vector) @since 2.0 */ } stream << %{ /** #{ingroup} @brief Opaque structure holding state of the vector @since 2.0 */ } else stream << PRIVATE end stream << %{ typedef struct { #{element.lvalue} elements; /**< @private */ size_t size; /**< @private */ } #{signature}; } end def render_implementation(stream) if element.orderable? stream << %{ static int #ifdef __POCC__ __cdecl #endif #{ascend}(const void* left, const void* right) { return #{element.compare.("(*(#{element.lvalue})left)", "(*(#{element.lvalue})right)")}; } static int #ifdef __POCC__ __cdecl #endif #{descend}(const void* left, const void* right) { return -#{ascend}(left, right); } #{sort.prototype} { qsort(#{storage(:target)}, #{size.('*target')}, sizeof(#{element}), direction > 0 ? #{ascend} : #{descend}); } } end super end def storage(target) = "#{target}->elements" # Return C pointer to contiguous storage def type_tag = "#{signature}<#{element}>" private def configure super method(:void, :_allocate, { target: lvalue, size: :size_t.const_rvalue }, visibility: :internal).configure do code %{ if((target->size = size) > 0) { #{storage(:target)} = #{memory.allocate(element, size)}; assert(#{storage(:target)}); } else { #{storage(:target)} = NULL; } } end method(:void, :create_size, { target: lvalue, size: :size_t.const_rvalue }, instance: :custom_create, constraint:-> { custom_constructible? && element.default_constructible? }).configure do code %{ size_t index; assert(target); #{_allocate.(target, size)}; for(index = 0; index < size; ++index) { #{element.default_create.("#{storage(:target)}[index]")}; } } header %{ @brief Create a new vector of specified size @param[out] target vector to be initialized @param[in] size size of new vector Each new vector's element is initialized with the respective default constructor. This function requires the element type to be *default constructible* (i.e. to have a well-defined parameterless constructor). @note Previous contents of `*target` is overwritten. @since 2.0 } end method(:void, :create_set, { target: lvalue, size: :size_t.const_rvalue, initializer: element.const_rvalue }, constraint:-> { element.copyable? }).configure do code %{ size_t index; assert(target); #{_allocate.(target, size)}; for(index = 0; index < size; ++index) { #{element.copy.("#{storage(:target)}[index]", initializer)}; } } header %{ @brief Create and initialize a new vector of specified size @param[out] target vector to be initialized @param[in] size size of new vector @param[in] initializer value to initialize the vector with Each new vector's element is set to a *copy* of the specified value. This function requires the element type to be *copyable* (i.e. to have a well-defined copy operation). @note Previous contents of `*target` is overwritten. @since 2.0 } end destroy_elements = "for(index = common_size; index < old_size; ++index) {#{element.destroy.('old_elements[index]')};}" if element.destructible? method(:void, :resize, { target: lvalue, new_size: :size_t.const_rvalue }, constraint:-> { element.default_constructible? }).configure do code %{ size_t old_size; assert(target); if((old_size = #{size.(target)}) != new_size) { size_t common_size, index; #{element.lvalue} new_elements; #{element.lvalue} old_elements; old_elements = #{storage(:target)}; #{_allocate.(target, new_size)}; new_elements = #{storage(:target)}; common_size = old_size < new_size ? old_size : new_size; /* min(old_size, new_size) */ if(common_size > 0) { memcpy(new_elements, old_elements, common_size*sizeof(#{element})); } for(index = common_size; index < new_size; ++index) { #{element.default_create.('new_elements[index]')}; } #{destroy_elements} #{memory.free(:old_elements)}; } } header %{ @brief Resize vector @param[out] target vector to be resized @param[in] new_size new size of new vector This function sets new size for existing vector, expanding or shrinking it - whatever is applicable. When expanding, new elements are default initialized. When shrinking, excessive elements are destroyed with the respective destructor. @since 2.0 } end default_create.configure do inline_code %{ assert(target); #{storage(:target)} = NULL; target->size = 0; } end destroy_elements = "for(index = 0; index < #{size}(target); ++index) {#{element.destroy.("#{storage(:target)}[index]")};}" if element.destructible? destroy.configure do code %{ #{'size_t index;' if element.destructible?} assert(target); #{destroy_elements} #{memory.free(storage(:target))}; } end copy.configure do code %{ size_t index, size; assert(target); assert(source); size = #{size.(source)}; #{_allocate.(target, :size)}; for(index = 0; index < size; ++index) { #{element.copy.("#{storage(:target)}[index]", "#{storage(:source)}[index]")}; } } end size.configure do inline_code %{ assert(target); return target->size; } end check.configure do dependencies << size inline_code %{ assert(target); return index < #{size.(target)}; } end empty.configure do dependencies << size inline_code %{ assert(target); return !#{size.(target)}; } end view.configure do dependencies << check inline_code %{ assert(target); assert(#{check.(target, index)}); return &#{storage(:target)}[index]; } end set.configure do dependencies << check << view inline_code %{ #{element.lvalue} e; assert(target); assert(#{check.(target, index)}); e = (#{element.lvalue})#{view.(target, index)}; #{element.destroy.('*e') if element.destructible?}; #{element.copy.('*e', value)}; } end method(:void, :sort, { target: rvalue, direction: :int.const_rvalue }, constraint:-> { orderable? }, abstract: true).configure do header %{ @brief Sort vector's values @param[in] target vector to sort @param[in] direction sorting direction This function performs in-place sorting of the contained elements. If `direction` is greater than zero, the elements are placed in ascending (lowest to highset) order, otherwise the elements are placed in descending (highest to lowest) order. The sorting process does not reallocate memory nor does it call elements' copy constructors. @since 2.0 } end end end # Vector Vector::Range = ContiguousRange
configure()
click to toggle source
Calls superclass method
AutoC::Sequential#configure
# File lib/autoc/vector.rb, line 103 def configure super method(:void, :_allocate, { target: lvalue, size: :size_t.const_rvalue }, visibility: :internal).configure do code %{ if((target->size = size) > 0) { #{storage(:target)} = #{memory.allocate(element, size)}; assert(#{storage(:target)}); } else { #{storage(:target)} = NULL; } } end method(:void, :create_size, { target: lvalue, size: :size_t.const_rvalue }, instance: :custom_create, constraint:-> { custom_constructible? && element.default_constructible? }).configure do code %{ size_t index; assert(target); #{_allocate.(target, size)}; for(index = 0; index < size; ++index) { #{element.default_create.("#{storage(:target)}[index]")}; } } header %{ @brief Create a new vector of specified size @param[out] target vector to be initialized @param[in] size size of new vector Each new vector's element is initialized with the respective default constructor. This function requires the element type to be *default constructible* (i.e. to have a well-defined parameterless constructor). @note Previous contents of `*target` is overwritten. @since 2.0 } end method(:void, :create_set, { target: lvalue, size: :size_t.const_rvalue, initializer: element.const_rvalue }, constraint:-> { element.copyable? }).configure do code %{ size_t index; assert(target); #{_allocate.(target, size)}; for(index = 0; index < size; ++index) { #{element.copy.("#{storage(:target)}[index]", initializer)}; } } header %{ @brief Create and initialize a new vector of specified size @param[out] target vector to be initialized @param[in] size size of new vector @param[in] initializer value to initialize the vector with Each new vector's element is set to a *copy* of the specified value. This function requires the element type to be *copyable* (i.e. to have a well-defined copy operation). @note Previous contents of `*target` is overwritten. @since 2.0 } end destroy_elements = "for(index = common_size; index < old_size; ++index) {#{element.destroy.('old_elements[index]')};}" if element.destructible? method(:void, :resize, { target: lvalue, new_size: :size_t.const_rvalue }, constraint:-> { element.default_constructible? }).configure do code %{ size_t old_size; assert(target); if((old_size = #{size.(target)}) != new_size) { size_t common_size, index; #{element.lvalue} new_elements; #{element.lvalue} old_elements; old_elements = #{storage(:target)}; #{_allocate.(target, new_size)}; new_elements = #{storage(:target)}; common_size = old_size < new_size ? old_size : new_size; /* min(old_size, new_size) */ if(common_size > 0) { memcpy(new_elements, old_elements, common_size*sizeof(#{element})); } for(index = common_size; index < new_size; ++index) { #{element.default_create.('new_elements[index]')}; } #{destroy_elements} #{memory.free(:old_elements)}; } } header %{ @brief Resize vector @param[out] target vector to be resized @param[in] new_size new size of new vector This function sets new size for existing vector, expanding or shrinking it - whatever is applicable. When expanding, new elements are default initialized. When shrinking, excessive elements are destroyed with the respective destructor. @since 2.0 } end default_create.configure do inline_code %{ assert(target); #{storage(:target)} = NULL; target->size = 0; } end destroy_elements = "for(index = 0; index < #{size}(target); ++index) {#{element.destroy.("#{storage(:target)}[index]")};}" if element.destructible? destroy.configure do code %{ #{'size_t index;' if element.destructible?} assert(target); #{destroy_elements} #{memory.free(storage(:target))}; } end copy.configure do code %{ size_t index, size; assert(target); assert(source); size = #{size.(source)}; #{_allocate.(target, :size)}; for(index = 0; index < size; ++index) { #{element.copy.("#{storage(:target)}[index]", "#{storage(:source)}[index]")}; } } end size.configure do inline_code %{ assert(target); return target->size; } end check.configure do dependencies << size inline_code %{ assert(target); return index < #{size.(target)}; } end empty.configure do dependencies << size inline_code %{ assert(target); return !#{size.(target)}; } end view.configure do dependencies << check inline_code %{ assert(target); assert(#{check.(target, index)}); return &#{storage(:target)}[index]; } end set.configure do dependencies << check << view inline_code %{ #{element.lvalue} e; assert(target); assert(#{check.(target, index)}); e = (#{element.lvalue})#{view.(target, index)}; #{element.destroy.('*e') if element.destructible?}; #{element.copy.('*e', value)}; } end method(:void, :sort, { target: rvalue, direction: :int.const_rvalue }, constraint:-> { orderable? }, abstract: true).configure do header %{ @brief Sort vector's values @param[in] target vector to sort @param[in] direction sorting direction This function performs in-place sorting of the contained elements. If `direction` is greater than zero, the elements are placed in ascending (lowest to highset) order, otherwise the elements are placed in descending (highest to lowest) order. The sorting process does not reallocate memory nor does it call elements' copy constructors. @since 2.0 } end end
range(= @range ||= _range_class.new(self, visibility: visibility, parallel: @parallel))
click to toggle source
# File lib/autoc/vector.rb, line 24 def range = @range ||= _range_class.new(self, visibility: visibility, parallel: @parallel) def initialize(type, element, parallel: nil, **kws) super(type, element, :size_t, **kws) dependencies << STRING_H @parallel = parallel end def render_interface(stream) if public? stream << %{ /** #{defgroup} @brief Resizable vector of elements of type #{element} #{type} is a container that encapsulates dynamic size array of values of type #{element}. It is a contiguous direct access collection where elements can be directly referenced by an integer index belonging to the [0, @ref #{size}) range. For iteration over the vector elements refer to @ref #{range}. @see C++ [std::vector<T>](https://en.cppreference.com/w/cpp/container/vector) @since 2.0 */ } stream << %{ /** #{ingroup} @brief Opaque structure holding state of the vector @since 2.0 */ } else stream << PRIVATE end stream << %{ typedef struct { #{element.lvalue} elements; /**< @private */ size_t size; /**< @private */ } #{signature}; } end def render_implementation(stream) if element.orderable? stream << %{ static int #ifdef __POCC__ __cdecl #endif #{ascend}(const void* left, const void* right) { return #{element.compare.("(*(#{element.lvalue})left)", "(*(#{element.lvalue})right)")}; } static int #ifdef __POCC__ __cdecl #endif #{descend}(const void* left, const void* right) { return -#{ascend}(left, right); } #{sort.prototype} { qsort(#{storage(:target)}, #{size.('*target')}, sizeof(#{element}), direction > 0 ? #{ascend} : #{descend}); } } end super end def storage(target) = "#{target}->elements" # Return C pointer to contiguous storage def type_tag = "#{signature}<#{element}>" private def configure super method(:void, :_allocate, { target: lvalue, size: :size_t.const_rvalue }, visibility: :internal).configure do code %{ if((target->size = size) > 0) { #{storage(:target)} = #{memory.allocate(element, size)}; assert(#{storage(:target)}); } else { #{storage(:target)} = NULL; } } end method(:void, :create_size, { target: lvalue, size: :size_t.const_rvalue }, instance: :custom_create, constraint:-> { custom_constructible? && element.default_constructible? }).configure do code %{ size_t index; assert(target); #{_allocate.(target, size)}; for(index = 0; index < size; ++index) { #{element.default_create.("#{storage(:target)}[index]")}; } } header %{ @brief Create a new vector of specified size @param[out] target vector to be initialized @param[in] size size of new vector Each new vector's element is initialized with the respective default constructor. This function requires the element type to be *default constructible* (i.e. to have a well-defined parameterless constructor). @note Previous contents of `*target` is overwritten. @since 2.0 } end method(:void, :create_set, { target: lvalue, size: :size_t.const_rvalue, initializer: element.const_rvalue }, constraint:-> { element.copyable? }).configure do code %{ size_t index; assert(target); #{_allocate.(target, size)}; for(index = 0; index < size; ++index) { #{element.copy.("#{storage(:target)}[index]", initializer)}; } } header %{ @brief Create and initialize a new vector of specified size @param[out] target vector to be initialized @param[in] size size of new vector @param[in] initializer value to initialize the vector with Each new vector's element is set to a *copy* of the specified value. This function requires the element type to be *copyable* (i.e. to have a well-defined copy operation). @note Previous contents of `*target` is overwritten. @since 2.0 } end destroy_elements = "for(index = common_size; index < old_size; ++index) {#{element.destroy.('old_elements[index]')};}" if element.destructible? method(:void, :resize, { target: lvalue, new_size: :size_t.const_rvalue }, constraint:-> { element.default_constructible? }).configure do code %{ size_t old_size; assert(target); if((old_size = #{size.(target)}) != new_size) { size_t common_size, index; #{element.lvalue} new_elements; #{element.lvalue} old_elements; old_elements = #{storage(:target)}; #{_allocate.(target, new_size)}; new_elements = #{storage(:target)}; common_size = old_size < new_size ? old_size : new_size; /* min(old_size, new_size) */ if(common_size > 0) { memcpy(new_elements, old_elements, common_size*sizeof(#{element})); } for(index = common_size; index < new_size; ++index) { #{element.default_create.('new_elements[index]')}; } #{destroy_elements} #{memory.free(:old_elements)}; } } header %{ @brief Resize vector @param[out] target vector to be resized @param[in] new_size new size of new vector This function sets new size for existing vector, expanding or shrinking it - whatever is applicable. When expanding, new elements are default initialized. When shrinking, excessive elements are destroyed with the respective destructor. @since 2.0 } end default_create.configure do inline_code %{ assert(target); #{storage(:target)} = NULL; target->size = 0; } end destroy_elements = "for(index = 0; index < #{size}(target); ++index) {#{element.destroy.("#{storage(:target)}[index]")};}" if element.destructible? destroy.configure do code %{ #{'size_t index;' if element.destructible?} assert(target); #{destroy_elements} #{memory.free(storage(:target))}; } end copy.configure do code %{ size_t index, size; assert(target); assert(source); size = #{size.(source)}; #{_allocate.(target, :size)}; for(index = 0; index < size; ++index) { #{element.copy.("#{storage(:target)}[index]", "#{storage(:source)}[index]")}; } } end size.configure do inline_code %{ assert(target); return target->size; } end check.configure do dependencies << size inline_code %{ assert(target); return index < #{size.(target)}; } end empty.configure do dependencies << size inline_code %{ assert(target); return !#{size.(target)}; } end view.configure do dependencies << check inline_code %{ assert(target); assert(#{check.(target, index)}); return &#{storage(:target)}[index]; } end set.configure do dependencies << check << view inline_code %{ #{element.lvalue} e; assert(target); assert(#{check.(target, index)}); e = (#{element.lvalue})#{view.(target, index)}; #{element.destroy.('*e') if element.destructible?}; #{element.copy.('*e', value)}; } end method(:void, :sort, { target: rvalue, direction: :int.const_rvalue }, constraint:-> { orderable? }, abstract: true).configure do header %{ @brief Sort vector's values @param[in] target vector to sort @param[in] direction sorting direction This function performs in-place sorting of the contained elements. If `direction` is greater than zero, the elements are placed in ascending (lowest to highset) order, otherwise the elements are placed in descending (highest to lowest) order. The sorting process does not reallocate memory nor does it call elements' copy constructors. @since 2.0 } end end end # Vector Vector::Range = ContiguousRange # Range
render_implementation(stream)
click to toggle source
Calls superclass method
# File lib/autoc/vector.rb, line 72 def render_implementation(stream) if element.orderable? stream << %{ static int #ifdef __POCC__ __cdecl #endif #{ascend}(const void* left, const void* right) { return #{element.compare.("(*(#{element.lvalue})left)", "(*(#{element.lvalue})right)")}; } static int #ifdef __POCC__ __cdecl #endif #{descend}(const void* left, const void* right) { return -#{ascend}(left, right); } #{sort.prototype} { qsort(#{storage(:target)}, #{size.('*target')}, sizeof(#{element}), direction > 0 ? #{ascend} : #{descend}); } } end super end
render_interface(stream)
click to toggle source
# File lib/autoc/vector.rb, line 32 def render_interface(stream) if public? stream << %{ /** #{defgroup} @brief Resizable vector of elements of type #{element} #{type} is a container that encapsulates dynamic size array of values of type #{element}. It is a contiguous direct access collection where elements can be directly referenced by an integer index belonging to the [0, @ref #{size}) range. For iteration over the vector elements refer to @ref #{range}. @see C++ [std::vector<T>](https://en.cppreference.com/w/cpp/container/vector) @since 2.0 */ } stream << %{ /** #{ingroup} @brief Opaque structure holding state of the vector @since 2.0 */ } else stream << PRIVATE end stream << %{ typedef struct { #{element.lvalue} elements; /**< @private */ size_t size; /**< @private */ } #{signature}; } end
storage(target)
click to toggle source
# File lib/autoc/vector.rb, line 97 def storage(target) = "#{target}->elements" # Return C pointer to contiguous storage def type_tag = "#{signature}<#{element}>" private def configure super method(:void, :_allocate, { target: lvalue, size: :size_t.const_rvalue }, visibility: :internal).configure do code %{ if((target->size = size) > 0) { #{storage(:target)} = #{memory.allocate(element, size)}; assert(#{storage(:target)}); } else { #{storage(:target)} = NULL; } } end method(:void, :create_size, { target: lvalue, size: :size_t.const_rvalue }, instance: :custom_create, constraint:-> { custom_constructible? && element.default_constructible? }).configure do code %{ size_t index; assert(target); #{_allocate.(target, size)}; for(index = 0; index < size; ++index) { #{element.default_create.("#{storage(:target)}[index]")}; } } header %{ @brief Create a new vector of specified size @param[out] target vector to be initialized @param[in] size size of new vector Each new vector's element is initialized with the respective default constructor. This function requires the element type to be *default constructible* (i.e. to have a well-defined parameterless constructor). @note Previous contents of `*target` is overwritten. @since 2.0 } end method(:void, :create_set, { target: lvalue, size: :size_t.const_rvalue, initializer: element.const_rvalue }, constraint:-> { element.copyable? }).configure do code %{ size_t index; assert(target); #{_allocate.(target, size)}; for(index = 0; index < size; ++index) { #{element.copy.("#{storage(:target)}[index]", initializer)}; } } header %{ @brief Create and initialize a new vector of specified size @param[out] target vector to be initialized @param[in] size size of new vector @param[in] initializer value to initialize the vector with Each new vector's element is set to a *copy* of the specified value. This function requires the element type to be *copyable* (i.e. to have a well-defined copy operation). @note Previous contents of `*target` is overwritten. @since 2.0 } end destroy_elements = "for(index = common_size; index < old_size; ++index) {#{element.destroy.('old_elements[index]')};}" if element.destructible? method(:void, :resize, { target: lvalue, new_size: :size_t.const_rvalue }, constraint:-> { element.default_constructible? }).configure do code %{ size_t old_size; assert(target); if((old_size = #{size.(target)}) != new_size) { size_t common_size, index; #{element.lvalue} new_elements; #{element.lvalue} old_elements; old_elements = #{storage(:target)}; #{_allocate.(target, new_size)}; new_elements = #{storage(:target)}; common_size = old_size < new_size ? old_size : new_size; /* min(old_size, new_size) */ if(common_size > 0) { memcpy(new_elements, old_elements, common_size*sizeof(#{element})); } for(index = common_size; index < new_size; ++index) { #{element.default_create.('new_elements[index]')}; } #{destroy_elements} #{memory.free(:old_elements)}; } } header %{ @brief Resize vector @param[out] target vector to be resized @param[in] new_size new size of new vector This function sets new size for existing vector, expanding or shrinking it - whatever is applicable. When expanding, new elements are default initialized. When shrinking, excessive elements are destroyed with the respective destructor. @since 2.0 } end default_create.configure do inline_code %{ assert(target); #{storage(:target)} = NULL; target->size = 0; } end destroy_elements = "for(index = 0; index < #{size}(target); ++index) {#{element.destroy.("#{storage(:target)}[index]")};}" if element.destructible? destroy.configure do code %{ #{'size_t index;' if element.destructible?} assert(target); #{destroy_elements} #{memory.free(storage(:target))}; } end copy.configure do code %{ size_t index, size; assert(target); assert(source); size = #{size.(source)}; #{_allocate.(target, :size)}; for(index = 0; index < size; ++index) { #{element.copy.("#{storage(:target)}[index]", "#{storage(:source)}[index]")}; } } end size.configure do inline_code %{ assert(target); return target->size; } end check.configure do dependencies << size inline_code %{ assert(target); return index < #{size.(target)}; } end empty.configure do dependencies << size inline_code %{ assert(target); return !#{size.(target)}; } end view.configure do dependencies << check inline_code %{ assert(target); assert(#{check.(target, index)}); return &#{storage(:target)}[index]; } end set.configure do dependencies << check << view inline_code %{ #{element.lvalue} e; assert(target); assert(#{check.(target, index)}); e = (#{element.lvalue})#{view.(target, index)}; #{element.destroy.('*e') if element.destructible?}; #{element.copy.('*e', value)}; } end method(:void, :sort, { target: rvalue, direction: :int.const_rvalue }, constraint:-> { orderable? }, abstract: true).configure do header %{ @brief Sort vector's values @param[in] target vector to sort @param[in] direction sorting direction This function performs in-place sorting of the contained elements. If `direction` is greater than zero, the elements are placed in ascending (lowest to highset) order, otherwise the elements are placed in descending (highest to lowest) order. The sorting process does not reallocate memory nor does it call elements' copy constructors. @since 2.0 } end end end # Vector Vector::Range = ContiguousRange # Range end
type_tag(= "
click to toggle source
# File lib/autoc/vector.rb, line 99 def type_tag = "#{signature}<#{element}>" private def configure super method(:void, :_allocate, { target: lvalue, size: :size_t.const_rvalue }, visibility: :internal).configure do code %{ if((target->size = size) > 0) { #{storage(:target)} = #{memory.allocate(element, size)}; assert(#{storage(:target)}); } else { #{storage(:target)} = NULL; } } end method(:void, :create_size, { target: lvalue, size: :size_t.const_rvalue }, instance: :custom_create, constraint:-> { custom_constructible? && element.default_constructible? }).configure do code %{ size_t index; assert(target); #{_allocate.(target, size)}; for(index = 0; index < size; ++index) { #{element.default_create.("#{storage(:target)}[index]")}; } } header %{ @brief Create a new vector of specified size @param[out] target vector to be initialized @param[in] size size of new vector Each new vector's element is initialized with the respective default constructor. This function requires the element type to be *default constructible* (i.e. to have a well-defined parameterless constructor). @note Previous contents of `*target` is overwritten. @since 2.0 } end method(:void, :create_set, { target: lvalue, size: :size_t.const_rvalue, initializer: element.const_rvalue }, constraint:-> { element.copyable? }).configure do code %{ size_t index; assert(target); #{_allocate.(target, size)}; for(index = 0; index < size; ++index) { #{element.copy.("#{storage(:target)}[index]", initializer)}; } } header %{ @brief Create and initialize a new vector of specified size @param[out] target vector to be initialized @param[in] size size of new vector @param[in] initializer value to initialize the vector with Each new vector's element is set to a *copy* of the specified value. This function requires the element type to be *copyable* (i.e. to have a well-defined copy operation). @note Previous contents of `*target` is overwritten. @since 2.0 } end destroy_elements = "for(index = common_size; index < old_size; ++index) {#{element.destroy.('old_elements[index]')};}" if element.destructible? method(:void, :resize, { target: lvalue, new_size: :size_t.const_rvalue }, constraint:-> { element.default_constructible? }).configure do code %{ size_t old_size; assert(target); if((old_size = #{size.(target)}) != new_size) { size_t common_size, index; #{element.lvalue} new_elements; #{element.lvalue} old_elements; old_elements = #{storage(:target)}; #{_allocate.(target, new_size)}; new_elements = #{storage(:target)}; common_size = old_size < new_size ? old_size : new_size; /* min(old_size, new_size) */ if(common_size > 0) { memcpy(new_elements, old_elements, common_size*sizeof(#{element})); } for(index = common_size; index < new_size; ++index) { #{element.default_create.('new_elements[index]')}; } #{destroy_elements} #{memory.free(:old_elements)}; } } header %{ @brief Resize vector @param[out] target vector to be resized @param[in] new_size new size of new vector This function sets new size for existing vector, expanding or shrinking it - whatever is applicable. When expanding, new elements are default initialized. When shrinking, excessive elements are destroyed with the respective destructor. @since 2.0 } end default_create.configure do inline_code %{ assert(target); #{storage(:target)} = NULL; target->size = 0; } end destroy_elements = "for(index = 0; index < #{size}(target); ++index) {#{element.destroy.("#{storage(:target)}[index]")};}" if element.destructible? destroy.configure do code %{ #{'size_t index;' if element.destructible?} assert(target); #{destroy_elements} #{memory.free(storage(:target))}; } end copy.configure do code %{ size_t index, size; assert(target); assert(source); size = #{size.(source)}; #{_allocate.(target, :size)}; for(index = 0; index < size; ++index) { #{element.copy.("#{storage(:target)}[index]", "#{storage(:source)}[index]")}; } } end size.configure do inline_code %{ assert(target); return target->size; } end check.configure do dependencies << size inline_code %{ assert(target); return index < #{size.(target)}; } end empty.configure do dependencies << size inline_code %{ assert(target); return !#{size.(target)}; } end view.configure do dependencies << check inline_code %{ assert(target); assert(#{check.(target, index)}); return &#{storage(:target)}[index]; } end set.configure do dependencies << check << view inline_code %{ #{element.lvalue} e; assert(target); assert(#{check.(target, index)}); e = (#{element.lvalue})#{view.(target, index)}; #{element.destroy.('*e') if element.destructible?}; #{element.copy.('*e', value)}; } end method(:void, :sort, { target: rvalue, direction: :int.const_rvalue }, constraint:-> { orderable? }, abstract: true).configure do header %{ @brief Sort vector's values @param[in] target vector to sort @param[in] direction sorting direction This function performs in-place sorting of the contained elements. If `direction` is greater than zero, the elements are placed in ascending (lowest to highset) order, otherwise the elements are placed in descending (highest to lowest) order. The sorting process does not reallocate memory nor does it call elements' copy constructors. @since 2.0 } end end end