class Wrapture::ClassSpec
A description of a class, including its constants, functions, and other details.
Attributes
The underlying struct of this class.
Public Class Methods
Gives the effective type of the given class spec hash.
# File lib/wrapture/class_spec.rb, line 54 def self.effective_type(spec) inferred_pointer_wrapper = spec['constructors'].any? do |func| func['wrapped-function']['return']['type'] == EQUIVALENT_POINTER_KEYWORD end if spec.key?('type') valid_types = %w[pointer struct] unless valid_types.include?(spec['type']) type_message = "#{spec['type']} is not a valid class type" raise InvalidSpecKey.new(type_message, valid_keys: valid_types) end spec['type'] elsif inferred_pointer_wrapper 'pointer' else 'struct' end end
Creates a class spec based on the provided hash spec.
The scope can be provided if available.
The hash must have the following keys:
- name
-
the name of the class
- namespace
-
the namespace to put the class into
- equivalent-struct
-
a hash describing the struct this class wraps
The following keys are optional:
- doc
-
a string containing the documentation for this class
- constructors
-
a list of function specs that can create this class
- destructor
-
a function spec for the destructor of the class
- functions
-
a list of function specs
- constants
-
a list of constant specs
# File lib/wrapture/class_spec.rb, line 92 def initialize(spec, scope: Scope.new) @spec = Marshal.load(Marshal.dump(spec)) TemplateSpec.replace_all_uses(@spec, *scope.templates) @spec = ClassSpec.normalize_spec_hash(@spec) @struct = if @spec.key?(EQUIVALENT_STRUCT_KEYWORD) StructSpec.new(@spec[EQUIVALENT_STRUCT_KEYWORD]) end @functions = @spec['constructors'].map do |constructor_spec| full_spec = constructor_spec.dup full_spec['name'] = @spec['name'] full_spec['params'] = constructor_spec['wrapped-function']['params'] FunctionSpec.new(full_spec, self, constructor: true) end if @spec.key?('destructor') destructor_spec = @spec['destructor'].dup destructor_spec['name'] = "~#{@spec['name']}" @functions << FunctionSpec.new(destructor_spec, self, destructor: true) end @spec['functions'].each do |function_spec| @functions << FunctionSpec.new(function_spec, self) end @constants = @spec['constants'].map do |constant_spec| ConstantSpec.new(constant_spec) end @doc = @spec.key?('doc') ? Comment.new(@spec['doc']) : nil scope << self @scope = scope end
Normalizes a hash specification of a class. Normalization will check for things like invalid keys, duplicate entries in include lists, and will set missing keys to their default values (for example, an empty list if no includes are given).
If this spec cannot be normalized, for example because it is invalid or it uses an unsupported version type, then an exception is raised.
# File lib/wrapture/class_spec.rb, line 32 def self.normalize_spec_hash(spec) raise NoNamespace unless spec.key?('namespace') raise MissingSpecKey, 'name key is required' unless spec.key?('name') Comment.validate_doc(spec['doc']) if spec.key?('doc') normalized = spec.dup normalized.default = [] normalized['version'] = Wrapture.spec_version(spec) normalized['includes'] = Wrapture.normalize_includes(spec['includes']) normalized['type'] = ClassSpec.effective_type(normalized) if spec.key?('parent') includes = Wrapture.normalize_includes(spec['parent']['includes']) normalized['parent']['includes'] = includes end normalized end
Public Instance Methods
Returns a cast of an instance of this class with the provided name to the specified type. Optionally the from parameter may hold the type of the instance, either a reference or a pointer.
# File lib/wrapture/class_spec.rb, line 134 def cast(instance, to, from = name) member_access = from.pointer? ? '->' : '.' struct = "struct #{@struct.name}" if [EQUIVALENT_STRUCT_KEYWORD, struct].include?(to) "#{'*' if pointer_wrapper?}#{instance}#{member_access}equivalent" elsif [EQUIVALENT_POINTER_KEYWORD, "#{struct} *"].include?(to) "#{'&' unless pointer_wrapper?}#{instance}#{member_access}equivalent" end end
Generates the wrapper class declaration and definition files.
# File lib/wrapture/class_spec.rb, line 147 def generate_wrappers [generate_declaration_file, generate_definition_file] end
The name of the class
# File lib/wrapture/class_spec.rb, line 152 def name @spec['name'] end
True if this class overloads the given one. A class is considered an overload if its parent is the given class, it has the same equivalent struct name, and the equivalent struct has a set of rules. The overloaded class cannot have any rules in its equivalent struct, or it will not be overloaded.
# File lib/wrapture/class_spec.rb, line 161 def overloads?(parent_spec) return false unless parent_spec.struct&.rules&.empty? parent_spec.struct.name == struct_name && parent_spec.name == parent_name && !@struct.rules.empty? end
The name of the parent of this class, or nil if there is no parent.
# File lib/wrapture/class_spec.rb, line 170 def parent_name @spec['parent']['name'] if child? end
Determines if this class is a wrapper for a struct pointer or not.
# File lib/wrapture/class_spec.rb, line 175 def pointer_wrapper? @spec['type'] == 'pointer' end
The name of the equivalent struct of this class.
# File lib/wrapture/class_spec.rb, line 180 def struct_name @struct.name end
Gives a code snippet that accesses the equivalent struct from within the class using the 'this' keyword.
# File lib/wrapture/class_spec.rb, line 186 def this_struct if pointer_wrapper? '*(this->equivalent)' else 'this->equivalent' end end
Gives a code snippet that accesses the equivalent struct pointer from within the class using the 'this' keyword.
# File lib/wrapture/class_spec.rb, line 196 def this_struct_pointer "#{'&' unless pointer_wrapper?}this->equivalent" end
Returns the ClassSpec
for the given type in this class's scope.
# File lib/wrapture/class_spec.rb, line 201 def type(type) @scope.type(type) end
Returns true if the given type exists in this class's scope.
# File lib/wrapture/class_spec.rb, line 206 def type?(type) @scope.type?(type) end