/* vim: set sw=4 sts=4 et foldmethod=syntax : */ /* * Copyright (c) 2008, 2009, 2011 Ciaran McCreesh * * This file is part of the Paludis package manager. Paludis is free software; * you can redistribute it and/or modify it under the terms of the GNU General * Public License version 2, as published by the Free Software Foundation. * * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include using namespace paludis; using namespace paludis::ruby; namespace { static VALUE c_choice; static VALUE c_choices; static VALUE c_choice_value; static VALUE c_choice_origin; /* * call-seq: * each {|choice| block } -> Nil * * Our Choice children. */ VALUE choices_each(VALUE self_v) { std::shared_ptr self(value_to_choices(self_v)); for (Choices::ConstIterator k(self->begin()), k_end(self->end()) ; k != k_end ; ++k) { VALUE val(choice_to_value(*k)); if (Qnil != val) rb_yield(val); } return Qnil; } /* * call-seq: * has_matching_contains_every_value_prefix?(prefix) -> true or false * * Do we have a Choice subkey with contains_every_value true and a prefix matching * this name? * * 0-based EAPIs don't require things like userland_GNU in IUSE. So if you're looking * for a flag and don't find it, check this method before issuing a QA notice. */ VALUE choices_has_matching_contains_every_value_prefix(VALUE self_v, VALUE arg_v) { try { std::shared_ptr self(value_to_choices(self_v)); std::string arg(StringValuePtr(arg_v)); return bool_to_value(self->has_matching_contains_every_value_prefix(ChoiceNameWithPrefix(arg))); } catch (const std::exception & e) { exception_to_ruby_exception(e); } } /* * call-seq: * find_by_name_with_prefix(prefix) -> ChoiceValue or Nil * * Find a ChoiceValue that has a particular prefix and name. * * Returns nil for no match. * * This is a convenient way of getting a particular use flag's details. Calling this * method with, say, "nls" or "ruby" will get the value for that flag without having * to hunt around in all the subkeys manually. Prefixes work too, e.g. "linguas_en" for * 0-based EAPIs or "linguas:en" for exheres EAPIs. */ VALUE choices_find_by_name_with_prefix(VALUE self_v, VALUE arg_v) { try { std::shared_ptr self(value_to_choices(self_v)); std::string arg(StringValuePtr(arg_v)); std::shared_ptr result(self->find_by_name_with_prefix(ChoiceNameWithPrefix(arg))); if (result) return choice_value_to_value(result); else return Qnil; } catch (const std::exception & e) { exception_to_ruby_exception(e); } } /* * call-seq: * each {|choice_value| block } -> Nil * * Our ChoiceValue children. */ VALUE choice_each(VALUE self_v) { std::shared_ptr self(value_to_choice(self_v)); for (Choice::ConstIterator k(self->begin()), k_end(self->end()) ; k != k_end ; ++k) { VALUE val(choice_value_to_value(*k)); if (Qnil != val) rb_yield(val); } return Qnil; } /* * call-seq: * raw_name -> String * * Our raw name, for example 'USE' or 'LINGUAS'. */ FAKE_RDOC_METHOD(choice_raw_name) /* * call-seq: * human_name -> String * * A human-readable name (often the same as raw_name). */ FAKE_RDOC_METHOD(choice_human_name) /* * call-seq: * prefix -> String * * The prefix for our ChoiceValue children. * * An empty string for USE and ARCH, 'linguas' for LINGUAS etc. */ FAKE_RDOC_METHOD(choice_prefix) template struct ChoiceStringishMembers { static VALUE fetch(VALUE self_v) { try { std::shared_ptr self(value_to_choice(self_v)); return rb_str_new2(stringify(((*self).*r_)()).c_str()); } catch (const std::exception & e) { exception_to_ruby_exception(e); } } }; /* * call-seq: * contains_every_value? -> true or false * * If true, pretend that we contain every possible value and that any value not listed * as a child exists and is not enabled. * * For pesky 0-based EAPIs that don't require things like userland_GNU in IUSE, and that * don't have a comprehensive list of possible values. */ FAKE_RDOC_METHOD(choice_contains_every_value) /* * call-seq: * hidden? -> true or false * * If true, this option should not usually be shown visually to a user. */ FAKE_RDOC_METHOD(choice_hidden) /* * call-seq: * show_with_no_prefix? -> true or false * * If true, hint that we're better not displaying our prefix to the user. * * This is used by --pretend --install and --query to avoid showing a Use: * prefix before a list of use flag names. */ FAKE_RDOC_METHOD(choice_show_with_no_prefix) /* * call-seq: * consider_added_or_changed? -> true or false * * If false, do not consider flags in this section for 'added' or 'changed' * detection. * * Used by build_options. */ FAKE_RDOC_METHOD(choice_consider_added_or_changed) template struct ChoiceBoolishMembers { static VALUE fetch(VALUE self_v) { try { std::shared_ptr self(value_to_choice(self_v)); return bool_to_value(((*self).*r_)()); } catch (const std::exception & e) { exception_to_ruby_exception(e); } } }; /* * call-seq: * unprefixed_name -> String * * Our name, without an prefix (for example, 'nls' or 'en'). */ FAKE_RDOC_METHOD(choice_value_unprefixed_name) /* * call-seq: * name_with_prefix -> String * * Our name, with prefix if there is one (for example, 'nls' or 'linguas_en'). */ FAKE_RDOC_METHOD(choice_value_name_with_prefix) /* * call-seq: * description -> String * * The flag's description, or an empty string. */ FAKE_RDOC_METHOD(choice_value_description) template struct ChoiceValueStringishMembers { static VALUE fetch(VALUE self_v) { try { std::shared_ptr self(value_to_choice_value(self_v)); return rb_str_new2(stringify(((*self).*r_)()).c_str()); } catch (const std::exception & e) { exception_to_ruby_exception(e); } } }; /* * call-seq: * enabled? -> true or false * * Is this flag enabled? */ FAKE_RDOC_METHOD(choice_value_enabled) /* * call-seq: * enabled_by_default? -> true or false * * Would this flag be enabled by default (i.e. before considering * any overrides from the Environment)? */ FAKE_RDOC_METHOD(choice_value_enabled_by_default) /* * call-seq: * locked? -> true or false * * Is this flag locked (forced or masked)? */ FAKE_RDOC_METHOD(choice_value_locked) template struct ChoiceValueBoolishMembers { static VALUE fetch(VALUE self_v) { try { std::shared_ptr self(value_to_choice_value(self_v)); return bool_to_value(((*self).*r_)()); } catch (const std::exception & e) { exception_to_ruby_exception(e); } } }; /* * call-seq: * origin -> ChoiceOrigin * * Is this flag explicitly listed? * * Use this to avoid showing things like LINGUAS values that aren't listed * in IUSE but that end up as a ChoiceValue anyway. */ VALUE choice_value_origin(VALUE self_v) { std::shared_ptr self(value_to_choice_value(self_v)); return INT2FIX(self->origin()); } void do_register_choice() { /* * Document-class: Paludis::Choices * * A collection of Choice objects for a PackageID. */ c_choices = rb_define_class_under(paludis_module(), "Choices", rb_cObject); rb_funcall(c_choices, rb_intern("private_class_method"), 1, rb_str_new2("new")); rb_define_method(c_choices, "each", RUBY_FUNC_CAST(&choices_each), 0); rb_include_module(c_choices, rb_mEnumerable); rb_define_method(c_choices, "find_by_name_with_prefix", RUBY_FUNC_CAST(&choices_find_by_name_with_prefix), 1); rb_define_method(c_choices, "has_matching_contains_every_value_prefix?", RUBY_FUNC_CAST(&choices_has_matching_contains_every_value_prefix), 1); /* * Document-class: Paludis::Choice * * A collection of ChoiceValue objects for a PackageID's Choices. */ c_choice = rb_define_class_under(paludis_module(), "Choice", rb_cObject); rb_funcall(c_choice, rb_intern("private_class_method"), 1, rb_str_new2("new")); rb_define_method(c_choice, "raw_name", RDOC_IS_STUPID(choice_raw_name, (&ChoiceStringishMembers::fetch)), 0); rb_define_method(c_choice, "human_name", RDOC_IS_STUPID(choice_human_name, (&ChoiceStringishMembers::fetch)), 0); rb_define_method(c_choice, "prefix", RDOC_IS_STUPID(choice_prefix, (&ChoiceStringishMembers::fetch)), 0); rb_define_method(c_choice, "contains_every_value?", RDOC_IS_STUPID(choice_contains_every_value, (&ChoiceBoolishMembers::fetch)), 0); rb_define_method(c_choice, "hidden?", RDOC_IS_STUPID(choice_hidden, (&ChoiceBoolishMembers::fetch)), 0); rb_define_method(c_choice, "show_with_no_prefix?", RDOC_IS_STUPID(choice_show_with_no_prefix, (&ChoiceBoolishMembers::fetch)), 0); rb_define_method(c_choice, "consider_added_or_changed?", RDOC_IS_STUPID(choice_consider_added_or_changed, (&ChoiceBoolishMembers::fetch)), 0); rb_define_method(c_choice, "each", RUBY_FUNC_CAST(&choice_each), 0); rb_include_module(c_choice, rb_mEnumerable); /* * Document-module: Paludis::ChoiceOrigin * * The origin of a Choice */ c_choice_origin = rb_define_module_under(paludis_module(), "ChoiceOrigin"); for (ChoiceOrigin l(static_cast(0)), l_end(last_co) ; l != l_end ; l = static_cast(static_cast(l) + 1)) rb_define_const(c_choice_origin, value_case_to_RubyCase(stringify(l)).c_str(), INT2FIX(l)); // cc_enum_special /* * Document-class: Paludis::ChoiceValue * * A single ChoiceValue object for a Choice. */ c_choice_value = rb_define_class_under(paludis_module(), "ChoiceValue", rb_cObject); rb_funcall(c_choice_value, rb_intern("private_class_method"), 1, rb_str_new2("new")); rb_define_method(c_choice_value, "unprefixed_name", RDOC_IS_STUPID(choice_value_unprefixed_name, (&ChoiceValueStringishMembers::fetch)), 0); rb_define_method(c_choice_value, "name_with_prefix", RDOC_IS_STUPID(choice_value_name_with_prefix, (&ChoiceValueStringishMembers::fetch)), 0); rb_define_method(c_choice_value, "enabled?", RDOC_IS_STUPID(choice_value_enabled, (&ChoiceValueBoolishMembers::fetch)), 0); rb_define_method(c_choice_value, "enabled_by_default?", RDOC_IS_STUPID(choice_value_enabled_by_default, (&ChoiceValueBoolishMembers::fetch)), 0); rb_define_method(c_choice_value, "locked?", RDOC_IS_STUPID(choice_value_locked, (&ChoiceValueBoolishMembers::fetch)), 0); rb_define_method(c_choice_value, "description", RDOC_IS_STUPID(choice_value_description, (&ChoiceValueStringishMembers::fetch)), 0); rb_define_method(c_choice_value, "origin", RUBY_FUNC_CAST(&choice_value_origin), 0); } } VALUE paludis::ruby::choices_to_value(const std::shared_ptr & m) { std::shared_ptr * m_ptr(0); try { m_ptr = new std::shared_ptr(m); return Data_Wrap_Struct(c_choices, 0, &Common >::free, m_ptr); } catch (const std::exception & e) { delete m_ptr; exception_to_ruby_exception(e); } } std::shared_ptr paludis::ruby::value_to_choices(VALUE v) { if (rb_obj_is_kind_of(v, c_choices)) { std::shared_ptr * v_ptr; Data_Get_Struct(v, std::shared_ptr, v_ptr); return *v_ptr; } else { rb_raise(rb_eTypeError, "Can't convert %s into Choices", rb_obj_classname(v)); } } VALUE paludis::ruby::choice_to_value(const std::shared_ptr & m) { std::shared_ptr * m_ptr(0); try { m_ptr = new std::shared_ptr(m); return Data_Wrap_Struct(c_choice, 0, &Common >::free, m_ptr); } catch (const std::exception & e) { delete m_ptr; exception_to_ruby_exception(e); } } std::shared_ptr paludis::ruby::value_to_choice(VALUE v) { if (rb_obj_is_kind_of(v, c_choice)) { std::shared_ptr * v_ptr; Data_Get_Struct(v, std::shared_ptr, v_ptr); return *v_ptr; } else { rb_raise(rb_eTypeError, "Can't convert %s into Choice", rb_obj_classname(v)); } } VALUE paludis::ruby::choice_value_to_value(const std::shared_ptr & m) { std::shared_ptr * m_ptr(0); try { m_ptr = new std::shared_ptr(m); return Data_Wrap_Struct(c_choice_value, 0, &Common >::free, m_ptr); } catch (const std::exception & e) { delete m_ptr; exception_to_ruby_exception(e); } } std::shared_ptr paludis::ruby::value_to_choice_value(VALUE v) { if (rb_obj_is_kind_of(v, c_choice_value)) { std::shared_ptr * v_ptr; Data_Get_Struct(v, std::shared_ptr, v_ptr); return *v_ptr; } else { rb_raise(rb_eTypeError, "Can't convert %s into ChoiceValue", rb_obj_classname(v)); } } RegisterRubyClass::Register paludis_ruby_register_choice PALUDIS_ATTRIBUTE((used)) (&do_register_choice);