Exheredludis/ruby/choice.cc
Ciaran McCreesh 2259902ded Docs fix
2011-09-20 11:39:43 +01:00

502 lines
16 KiB
C++

/* 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 <paludis_ruby.hh>
#include <paludis/choice.hh>
#include <paludis/util/wrapped_forward_iterator.hh>
#include <ruby.h>
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<const Choices> 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<const Choices> 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<const Choices> self(value_to_choices(self_v));
std::string arg(StringValuePtr(arg_v));
std::shared_ptr<const ChoiceValue> 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<const Choice> 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 <typename R_, const R_ (Choice::* r_) () const>
struct ChoiceStringishMembers
{
static VALUE fetch(VALUE self_v)
{
try
{
std::shared_ptr<const Choice> 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 <typename R_, R_ (Choice::* r_) () const>
struct ChoiceBoolishMembers
{
static VALUE fetch(VALUE self_v)
{
try
{
std::shared_ptr<const Choice> 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 <typename R_, const R_ (ChoiceValue::* r_) () const>
struct ChoiceValueStringishMembers
{
static VALUE fetch(VALUE self_v)
{
try
{
std::shared_ptr<const ChoiceValue> 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 <typename R_, R_ (ChoiceValue::* r_) () const>
struct ChoiceValueBoolishMembers
{
static VALUE fetch(VALUE self_v)
{
try
{
std::shared_ptr<const ChoiceValue> 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<const ChoiceValue> 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<std::string, &Choice::raw_name>::fetch)), 0);
rb_define_method(c_choice, "human_name", RDOC_IS_STUPID(choice_human_name,
(&ChoiceStringishMembers<std::string, &Choice::human_name>::fetch)), 0);
rb_define_method(c_choice, "prefix", RDOC_IS_STUPID(choice_prefix,
(&ChoiceStringishMembers<ChoicePrefixName, &Choice::prefix>::fetch)), 0);
rb_define_method(c_choice, "contains_every_value?", RDOC_IS_STUPID(choice_contains_every_value,
(&ChoiceBoolishMembers<bool, &Choice::contains_every_value>::fetch)), 0);
rb_define_method(c_choice, "hidden?", RDOC_IS_STUPID(choice_hidden,
(&ChoiceBoolishMembers<bool, &Choice::hidden>::fetch)), 0);
rb_define_method(c_choice, "show_with_no_prefix?", RDOC_IS_STUPID(choice_show_with_no_prefix,
(&ChoiceBoolishMembers<bool, &Choice::show_with_no_prefix>::fetch)), 0);
rb_define_method(c_choice, "consider_added_or_changed?", RDOC_IS_STUPID(choice_consider_added_or_changed,
(&ChoiceBoolishMembers<bool, &Choice::consider_added_or_changed>::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<ChoiceOrigin>(0)), l_end(last_co) ; l != l_end ;
l = static_cast<ChoiceOrigin>(static_cast<int>(l) + 1))
rb_define_const(c_choice_origin, value_case_to_RubyCase(stringify(l)).c_str(), INT2FIX(l));
// cc_enum_special<paludis/choice.hh, ChoiceOrigin, c_choice_origin>
/*
* 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<UnprefixedChoiceName, &ChoiceValue::unprefixed_name>::fetch)), 0);
rb_define_method(c_choice_value, "name_with_prefix", RDOC_IS_STUPID(choice_value_name_with_prefix,
(&ChoiceValueStringishMembers<ChoiceNameWithPrefix, &ChoiceValue::name_with_prefix>::fetch)), 0);
rb_define_method(c_choice_value, "enabled?", RDOC_IS_STUPID(choice_value_enabled,
(&ChoiceValueBoolishMembers<bool, &ChoiceValue::enabled>::fetch)), 0);
rb_define_method(c_choice_value, "enabled_by_default?", RDOC_IS_STUPID(choice_value_enabled_by_default,
(&ChoiceValueBoolishMembers<bool, &ChoiceValue::enabled_by_default>::fetch)), 0);
rb_define_method(c_choice_value, "locked?", RDOC_IS_STUPID(choice_value_locked,
(&ChoiceValueBoolishMembers<bool, &ChoiceValue::locked>::fetch)), 0);
rb_define_method(c_choice_value, "description", RDOC_IS_STUPID(choice_value_description,
(&ChoiceValueStringishMembers<std::string, &ChoiceValue::description>::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<const Choices> & m)
{
std::shared_ptr<const Choices> * m_ptr(0);
try
{
m_ptr = new std::shared_ptr<const Choices>(m);
return Data_Wrap_Struct(c_choices, 0, &Common<std::shared_ptr<const Choices> >::free, m_ptr);
}
catch (const std::exception & e)
{
delete m_ptr;
exception_to_ruby_exception(e);
}
}
std::shared_ptr<const Choices>
paludis::ruby::value_to_choices(VALUE v)
{
if (rb_obj_is_kind_of(v, c_choices))
{
std::shared_ptr<const Choices> * v_ptr;
Data_Get_Struct(v, std::shared_ptr<const Choices>, 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<const Choice> & m)
{
std::shared_ptr<const Choice> * m_ptr(0);
try
{
m_ptr = new std::shared_ptr<const Choice>(m);
return Data_Wrap_Struct(c_choice, 0, &Common<std::shared_ptr<const Choice> >::free, m_ptr);
}
catch (const std::exception & e)
{
delete m_ptr;
exception_to_ruby_exception(e);
}
}
std::shared_ptr<const Choice>
paludis::ruby::value_to_choice(VALUE v)
{
if (rb_obj_is_kind_of(v, c_choice))
{
std::shared_ptr<const Choice> * v_ptr;
Data_Get_Struct(v, std::shared_ptr<const Choice>, 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<const ChoiceValue> & m)
{
std::shared_ptr<const ChoiceValue> * m_ptr(0);
try
{
m_ptr = new std::shared_ptr<const ChoiceValue>(m);
return Data_Wrap_Struct(c_choice_value, 0, &Common<std::shared_ptr<const ChoiceValue> >::free, m_ptr);
}
catch (const std::exception & e)
{
delete m_ptr;
exception_to_ruby_exception(e);
}
}
std::shared_ptr<const ChoiceValue>
paludis::ruby::value_to_choice_value(VALUE v)
{
if (rb_obj_is_kind_of(v, c_choice_value))
{
std::shared_ptr<const ChoiceValue> * v_ptr;
Data_Get_Struct(v, std::shared_ptr<const ChoiceValue>, 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);