## Copyright (C) 2009, 2010 Wayne Meissner# Copyright (C) 2009 Luc Heinrich## This file is part of ruby-ffi.## All rights reserved.## Redistribution and use in source and binary forms, with or without# modification, are permitted provided that the following conditions are met:## * Redistributions of source code must retain the above copyright notice, this# list of conditions and the following disclaimer.# * Redistributions in binary form must reproduce the above copyright notice# this list of conditions and the following disclaimer in the documentation# and/or other materials provided with the distribution.# * Neither the name of the Ruby FFI project nor the names of its contributors# may be used to endorse or promote products derived from this software# without specific prior written permission.## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.#moduleFFI# An instance of this class permits to manage {Enum}s. In fact, Enums is a collection of {Enum}s.classEnums# @return [nil]definitialize@all_enums=Array.new@tagged_enums=Hash.new@symbol_map=Hash.newend# @param [Enum] enum# Add an {Enum} to the collection.def<<(enum)@all_enums<<enum@tagged_enums[enum.tag]=enumunlessenum.tag.nil?@symbol_map.merge!(enum.symbol_map)end# @param query enum tag or part of an enum name# @return [Enum]# Find a {Enum} in collection.deffind(query)if@tagged_enums.has_key?(query)@tagged_enums[query]else@all_enums.detect{|enum|enum.symbols.include?(query)}endend# @param symbol a symbol to find in merge symbol maps of all enums.# @return a symboldef__map_symbol(symbol)@symbol_map[symbol]endend# Represents a C enum.## For a C enum:# enum fruits {# apple,# banana,# orange,# pineapple# };# are defined this vocabulary:# * a _symbol_ is a word from the enumeration (ie. _apple_, by example);# * a _value_ is the value of a symbol in the enumeration (by example, apple has value _0_ and banana _1_).classEnumincludeDataConverterattr_reader:tagattr_reader:native_type# @overload initialize(info, tag=nil)# @param [nil, Enumerable] info# @param [nil, Symbol] tag enum tag# @overload initialize(native_type, info, tag=nil)# @param [FFI::Type] native_type Native type for new Enum# @param [nil, Enumerable] info symbols and values for new Enum# @param [nil, Symbol] tag name of new Enumdefinitialize(*args)@native_type=args.first.kind_of?(FFI::Type)?args.shift:Type::INTinfo,@tag=*args@kv_map=Hash.newunlessinfo.nil?last_cst=nilvalue=0info.eachdo|i|caseiwhenSymbolraiseArgumentError,"duplicate enum key"if@kv_map.has_key?(i)@kv_map[i]=valuelast_cst=ivalue+=1whenInteger@kv_map[last_cst]=ivalue=i+1endendend@vk_map=@kv_map.invertend# @return [Array] enum symbol namesdefsymbols@kv_map.keysend# Get a symbol or a value from the enum.# @overload [](query)# Get enum value from symbol.# @param [Symbol] query# @return [Integer]# @overload [](query)# Get enum symbol from value.# @param [Integer] query# @return [Symbol]def[](query)casequerywhenSymbol@kv_map[query]whenInteger@vk_map[query]endendaliasfind[]# Get the symbol map.# @return [Hash]defsymbol_map@kv_mapendaliasto_hsymbol_mapaliasto_hashsymbol_map# @param [Symbol, Integer, #to_int] val# @param ctx unused# @return [Integer] value of a enum symboldefto_native(val,ctx)@kv_map[val]||ifval.is_a?(Integer)valelsifval.respond_to?(:to_int)val.to_intelseraiseArgumentError,"invalid enum value, #{val.inspect}"endend# @param val# @return symbol name if it exists for +val+.deffrom_native(val,ctx)@vk_map[val]||valendendend