summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog14
-rw-r--r--examples/options/main.cc5
-rw-r--r--glib/src/optiongroup.ccg198
-rw-r--r--glib/src/optiongroup.hg31
4 files changed, 179 insertions, 69 deletions
diff --git a/ChangeLog b/ChangeLog
index 9bc1d9a9..19cf3047 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2007-02-10 Murray Cumming <murrayc@murrayc.com>
+
+ * examples/options/main.cc: Use a default value, to show that it
+ can be done.
+ (This change, from 2006-03-30 was restored after being accidentally lost on Apr 12 2006)
+
+2007-02-10 Armin Burgmeier <armin@arbur.net>
+
+ * glib/src/optiongroup.ccg: default_c_arg(): Set the initial
+ value of the C argument to the value the C++ argument has, to avoid
+ that glibmm resets arguments to zero that were not given on the
+ command line.
+ (This change, from 2006-03-30 was restored after being accidentally lost on Apr 12 2006)
+
Thu, 25 Jan 2007 23:13:05 +0100 Dodji Seketeli
* tools/m4/base.m4:
diff --git a/examples/options/main.cc b/examples/options/main.cc
index 2fa85376..cdc097e2 100644
--- a/examples/options/main.cc
+++ b/examples/options/main.cc
@@ -58,6 +58,7 @@ ExampleOptionGroup::ExampleOptionGroup()
entry3.set_long_name("goo");
entry3.set_short_name('g');
entry3.set_description("The Goo");
+ m_arg_goo = "default-goo-value"; //We can choose a default to be used if the user doesn't specify this option.
add_entry(entry3, m_arg_goo);
Glib::OptionEntry entry4;
@@ -75,12 +76,16 @@ ExampleOptionGroup::ExampleOptionGroup()
bool ExampleOptionGroup::on_pre_parse(Glib::OptionContext& context, Glib::OptionGroup& group)
{
//This is called before the m_arg_* instances are given their values.
+ // You do not need to override this method. This is just here to show you how,
+ // in case you want to do any extra processing.
return Glib::OptionGroup::on_pre_parse(context, group);
}
bool ExampleOptionGroup::on_post_parse(Glib::OptionContext& context, Glib::OptionGroup& group)
{
//This is called after the m_arg_* instances are given their values.
+ // You do not need to override this method. This is just here to show you how,
+ // in case you want to do any extra processing.
return Glib::OptionGroup::on_post_parse(context, group);
}
diff --git a/glib/src/optiongroup.ccg b/glib/src/optiongroup.ccg
index 77d3c713..c08c79a2 100644
--- a/glib/src/optiongroup.ccg
+++ b/glib/src/optiongroup.ccg
@@ -1,5 +1,5 @@
// -*- c++ -*-
-/* $Id$ */
+/* $Id: optiongroup.ccg,v 1.15.4.3 2006/03/30 12:19:58 murrayc Exp $ */
/* Copyright (C) 2002 The gtkmm Development Team
*
@@ -22,6 +22,7 @@
#include <glibmm/optioncontext.h>
#include <glibmm/utility.h>
//#include <glibmm/containers.h>
+#include <glib/gmem.h> // g_malloc
#include <glib/goption.h>
namespace Glib
@@ -37,7 +38,7 @@ static gboolean g_callback_pre_parse(GOptionContext* context, GOptionGroup* /* g
{
OptionContext cppContext(context, false /* take_ownership */);
//OptionGroup cppGroup(group, true /* take_copy */); //Maybe this should be option_group.
-
+
OptionGroup* option_group = static_cast<OptionGroup*>(data);
if(option_group)
return option_group->on_pre_parse(cppContext, *option_group);
@@ -49,7 +50,7 @@ static gboolean g_callback_post_parse(GOptionContext* context, GOptionGroup* /*
{
OptionContext cppContext(context, false /* take_ownership */);
//OptionGroup cppGroup(group, true /* take_copy */); //Maybe this should be option_group.
-
+
OptionGroup* option_group = static_cast<OptionGroup*>(data);
if(option_group)
{
@@ -63,7 +64,7 @@ static void g_callback_error(GOptionContext* context, GOptionGroup* /* group */,
{
OptionContext cppContext(context, false /* take_ownership */);
//OptionGroup cppGroup(group); //Maybe this should be option_group.
-
+
OptionGroup* option_group = static_cast<OptionGroup*>(data);
if(option_group)
return option_group->on_error(cppContext, *option_group);
@@ -99,7 +100,7 @@ OptionGroup::~OptionGroup()
CppOptionEntry& cpp_entry = iter->second;
cpp_entry.release_c_arg();
}
-
+
if(has_ownership_)
{
g_option_group_free(gobj());
@@ -110,15 +111,15 @@ OptionGroup::~OptionGroup()
void OptionGroup::add_entry(const OptionEntry& entry)
{
//It does not copy the entry, so it needs to live as long as the group.
-
+
//g_option_group_add_entries takes an array, with the last item in the array having a null long_name.
//Hopefully this will be properly documented eventually - see bug #
-
+
//Create a temporary array, just so we can give the correct thing to g_option_group_add_entries:
GOptionEntry array[2];
array[0] = *(entry.gobj()); //Copy contents.
GLIBMM_INITIALIZE_STRUCT(array[1], GOptionEntry);
-
+
g_option_group_add_entries(gobj(), array);
}
@@ -157,10 +158,11 @@ void OptionGroup::add_entry_with_wrapper(const OptionEntry& entry, GOptionArg ar
const Glib::ustring name = entry.get_long_name();
type_map_entries::iterator iterFind = map_entries_.find(name);
if( iterFind == map_entries_.end() ) //If we have not added this entry already
- {
+ {
CppOptionEntry cppEntry;
cppEntry.carg_type_ = arg_type;
cppEntry.allocate_c_arg();
+ cppEntry.set_c_arg_default(cpp_arg);
cppEntry.cpparg_ = cpp_arg;
@@ -171,36 +173,35 @@ void OptionGroup::add_entry_with_wrapper(const OptionEntry& entry, GOptionArg ar
cppEntry.entry_->gobj()->arg = arg_type;
cppEntry.entry_->gobj()->arg_data = cppEntry.carg_;
-
+
//Remember the C++/C mapping so that we can use it later:
map_entries_[name] = cppEntry;
add_entry(*(cppEntry.entry_));
}
}
-
+
bool OptionGroup::on_pre_parse(OptionContext& /* context */, OptionGroup& /* group */)
{
-
return true;
}
bool OptionGroup::on_post_parse(OptionContext& /* context */, OptionGroup& /* group */)
{
//Call this at the start of overrides.
-
+
//TODO: Maybe put this in the C callback:
-
+
//The C args have now been given values by GOption.
//Convert C values to C++ values:
-
+
for(type_map_entries::iterator iter = map_entries_.begin(); iter != map_entries_.end(); ++iter)
{
CppOptionEntry& cpp_entry = iter->second;
cpp_entry.convert_c_to_cpp();
}
-
+
return true;
}
@@ -212,20 +213,24 @@ void OptionGroup::on_error(OptionContext& /* context */, OptionGroup& /* group *
OptionGroup::CppOptionEntry::CppOptionEntry()
: carg_type_(G_OPTION_ARG_NONE), carg_(0), cpparg_(0), entry_(0)
{}
-
+
void OptionGroup::CppOptionEntry::allocate_c_arg()
{
//Create an instance of the appropriate C type.
//This will be destroyed in the OptionGroup destructor.
+ //
+ //We must also call set_c_arg_default() to give these C types the specified defaults based on the C++-typed arguments.
switch(carg_type_)
{
case G_OPTION_ARG_STRING: //The char* will be for UTF8 strins.
case G_OPTION_ARG_FILENAME: //The char* will be for strings in the current locale's encoding.
{
char** typed_arg = new char*;
- *typed_arg = 0; //The C code will allocate a char* and put it here, for us to g_free() later.
+ //The C code will allocate a char* and put it here, for us to g_free() later.
+ //Alternatively, set_c_arg_default() might allocate a char*, and the C code might or might not free and replace that.
+ *typed_arg = 0;
carg_ = typed_arg;
-
+
break;
}
case G_OPTION_ARG_INT:
@@ -233,7 +238,7 @@ void OptionGroup::CppOptionEntry::allocate_c_arg()
int* typed_arg = new int;
*typed_arg = 0;
carg_ = typed_arg;
-
+
break;
}
case G_OPTION_ARG_STRING_ARRAY:
@@ -242,7 +247,7 @@ void OptionGroup::CppOptionEntry::allocate_c_arg()
char*** typed_arg = new char**;
*typed_arg = 0;
carg_ = typed_arg;
-
+
break;
}
case G_OPTION_ARG_NONE: /* Actually a boolean. */
@@ -250,7 +255,88 @@ void OptionGroup::CppOptionEntry::allocate_c_arg()
gboolean* typed_arg = new gboolean;
*typed_arg = 0;
carg_ = typed_arg;
-
+
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+}
+
+void OptionGroup::CppOptionEntry::set_c_arg_default(void* cpp_arg)
+{
+ switch(carg_type_)
+ {
+ case G_OPTION_ARG_INT:
+ {
+ *static_cast<int*>(carg_) = *static_cast<int*>(cpp_arg);
+ break;
+ }
+ case G_OPTION_ARG_NONE:
+ {
+ *static_cast<gboolean*>(carg_) = *static_cast<bool*>(cpp_arg);
+ break;
+ }
+ case G_OPTION_ARG_STRING:
+ {
+ Glib::ustring* typed_cpp_arg = static_cast<Glib::ustring*>(cpp_arg);
+ if(typed_cpp_arg && !typed_cpp_arg->empty())
+ {
+ const char** typed_c_arg = static_cast<const char**>(carg_);
+ *typed_c_arg = g_strdup(typed_cpp_arg->c_str()); //Freed in release_c_arg().
+ }
+ break;
+ }
+ case G_OPTION_ARG_FILENAME:
+ {
+ std::string* typed_cpp_arg = static_cast<std::string*>(cpp_arg);
+ if(typed_cpp_arg && !typed_cpp_arg->empty())
+ {
+ const char** typed_c_arg = static_cast<const char**>(carg_);
+ *typed_c_arg = g_strdup(typed_cpp_arg->c_str()); //Freed in release_c_arg().
+ }
+ break;
+ }
+ case G_OPTION_ARG_STRING_ARRAY:
+ {
+ std::vector<Glib::ustring>* typed_cpp_arg = static_cast<std::vector<Glib::ustring>*>(cpp_arg);
+ if(typed_cpp_arg)
+ {
+ std::vector<Glib::ustring>& vec = *typed_cpp_arg;
+ const char** array = static_cast<const char**>( g_malloc(sizeof(gchar*) * (vec.size() + 1)) );
+
+ for(std::vector<Glib::ustring>::size_type i = 0; i < vec.size(); ++i)
+ {
+ array[i] = g_strdup( vec[i].c_str() );
+ }
+
+ array[vec.size()] = 0;
+
+ const char*** typed_c_arg = static_cast<const char***>(carg_);
+ *typed_c_arg = array;
+ }
+ break;
+ }
+ case G_OPTION_ARG_FILENAME_ARRAY:
+ {
+ std::vector<std::string>* typed_cpp_arg = static_cast<std::vector<std::string>*>(cpp_arg);
+ if(typed_cpp_arg)
+ {
+ std::vector<std::string>& vec = *typed_cpp_arg;
+ const char** array = static_cast<const char**>( g_malloc(sizeof(gchar*) * (vec.size() + 1)) );
+
+ for(std::vector<Glib::ustring>::size_type i = 0; i < vec.size(); ++i)
+ {
+ array[i] = g_strdup( vec[i].c_str() );
+ }
+
+ array[vec.size()] = 0;
+
+ const char*** typed_c_arg = static_cast<const char***>(carg_);
+ *typed_c_arg = array;
+ }
break;
}
default:
@@ -271,15 +357,15 @@ void OptionGroup::CppOptionEntry::release_c_arg()
case G_OPTION_ARG_STRING:
case G_OPTION_ARG_FILENAME:
{
- char** typed_arg = (char**)carg_;
+ char** typed_arg = static_cast<char**>(carg_);
g_free(*typed_arg); //Free the char* string at type_arg, which was allocated by the C code.
delete typed_arg; //Delete the char** that we allocated in allocate_c_arg;
-
+
break;
}
case G_OPTION_ARG_INT:
{
- int* typed_arg = (int*)carg_;
+ int* typed_arg = static_cast<int*>(carg_);
delete typed_arg;
break;
@@ -292,23 +378,23 @@ void OptionGroup::CppOptionEntry::release_c_arg()
}
case G_OPTION_ARG_NONE: /* Actually a boolean. */
{
- gboolean* typed_arg = (gboolean*)carg_;
+ gboolean* typed_arg = static_cast<gboolean*>(carg_);
delete typed_arg;
break;
}
default:
{
- /* TODO:
- G_OPTION_ARG_CALLBACK,
-*/
+ /* TODO:
+ G_OPTION_ARG_CALLBACK,
+ */
break;
}
}
-
+
carg_ = 0;
}
-
+
if(entry_)
delete entry_;
}
@@ -319,44 +405,44 @@ void OptionGroup::CppOptionEntry::convert_c_to_cpp()
{
case G_OPTION_ARG_STRING:
{
- char** typed_arg = (char**)carg_;
- Glib::ustring* typed_cpp_arg = (Glib::ustring*)cpparg_;
+ char** typed_arg = static_cast<char**>(carg_);
+ Glib::ustring* typed_cpp_arg = static_cast<Glib::ustring*>(cpparg_);
if(typed_arg && typed_cpp_arg)
{
char* pch = *typed_arg;
(*typed_cpp_arg) = Glib::convert_const_gchar_ptr_to_ustring(pch);
-
+
break;
}
}
case G_OPTION_ARG_FILENAME:
{
- char** typed_arg = (char**)carg_;
- std::string* typed_cpp_arg = (std::string*)cpparg_;
+ char** typed_arg = static_cast<char**>(carg_);
+ std::string* typed_cpp_arg = static_cast<std::string*>(cpparg_);
if(typed_arg && typed_cpp_arg)
{
char* pch = *typed_arg;
(*typed_cpp_arg) = Glib::convert_const_gchar_ptr_to_stdstring(pch);
-
+
break;
}
}
case G_OPTION_ARG_INT:
{
- *((int*)cpparg_) = *((int*)carg_);
+ *((int*)cpparg_) = *(static_cast<int*>(carg_));
break;
}
case G_OPTION_ARG_STRING_ARRAY:
{
- char*** typed_arg = (char***)carg_;
- vecustrings* typed_cpp_arg = (vecustrings*)cpparg_;
+ char*** typed_arg = static_cast<char***>(carg_);
+ vecustrings* typed_cpp_arg = static_cast<vecustrings*>(cpparg_);
if(typed_arg && typed_cpp_arg)
{
typed_cpp_arg->clear();
-
+
//The C array seems to be null-terminated.
//Glib::StringArrayHandle array_handle(*typed_arg, Glib::OWNERSHIP_NONE);
-
+
//The SUN Forte compiler complains about this:
// "optiongroup.cc", line 354: Error: Cannot assign Glib::ArrayHandle<Glib::ustring,
// Glib::Container_Helpers::TypeTraits<Glib::ustring>> to std::vector<Glib::ustring> without
@@ -369,14 +455,14 @@ void OptionGroup::CppOptionEntry::convert_c_to_cpp()
// cxx: Error: ../../glib/glibmm/containerhandle_shared.h, line 149: the operand
// of a pointer dynamic_cast must be a pointer to a complete class type
// return dynamic_cast<CppType>(Glib::wrap_auto(cobj, false /* take_copy */));
-
+
//for(Glib::StringArrayHandle::iterator iter = array_handle.begin(); iter != array_handle.end(); ++iter)
//{
// typed_cpp_arg->push_back(*iter);
//}
-
+
//So we do this:
-
+
char** char_array_next = *typed_arg;
while(char_array_next && *char_array_next)
{
@@ -384,19 +470,19 @@ void OptionGroup::CppOptionEntry::convert_c_to_cpp()
++char_array_next;
}
}
-
+
break;
}
case G_OPTION_ARG_FILENAME_ARRAY:
{
- char*** typed_arg = (char***)carg_;
- vecustrings* typed_cpp_arg = (vecustrings*)cpparg_;
+ char*** typed_arg = static_cast<char***>(carg_);
+ vecustrings* typed_cpp_arg = static_cast<vecustrings*>(cpparg_);
if(typed_arg && typed_cpp_arg)
{
typed_cpp_arg->clear();
-
+
//See comments above about the SUN Forte and Tru64 compilers.
-
+
char** char_array_next = *typed_arg;
while(char_array_next && *char_array_next)
{
@@ -404,20 +490,20 @@ void OptionGroup::CppOptionEntry::convert_c_to_cpp()
++char_array_next;
}
}
-
+
break;
}
case G_OPTION_ARG_NONE: /* Actually a boolean. */
{
- *((bool*)cpparg_) = *((gboolean*)carg_);
+ *(static_cast<bool*>(cpparg_)) = *(static_cast<gboolean*>(carg_));
break;
}
default:
{
/* TODO:
- G_OPTION_ARG_CALLBACK,
- */
- break;
+ G_OPTION_ARG_CALLBACK,
+ */
+ break;
}
}
}
@@ -427,6 +513,6 @@ GOptionGroup* OptionGroup::gobj_give_ownership()
has_ownership_ = false;
return gobj();
}
-
+
} // namespace Glib
diff --git a/glib/src/optiongroup.hg b/glib/src/optiongroup.hg
index f2ef9d44..c15b80d9 100644
--- a/glib/src/optiongroup.hg
+++ b/glib/src/optiongroup.hg
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $Id: optiongroup.hg,v 1.10.4.1 2006/03/30 12:19:58 murrayc Exp $ */
/* Copyright (C) 2004 The glibmm Development Team
*
@@ -61,21 +61,21 @@ public:
virtual bool on_post_parse(OptionContext& context, OptionGroup& group);
virtual void on_error(OptionContext& context, OptionGroup& group);
_IGNORE(g_option_group_set_parse_hooks, g_option_group_set_error_hook)
-
+
void add_entry(const OptionEntry& entry);
_IGNORE(g_option_group_add_entries)
-
-
+
+
typedef std::vector<Glib::ustring> vecustrings;
typedef std::vector<std::string> vecstrings;
-
+
void add_entry(const OptionEntry& entry, bool& arg);
void add_entry(const OptionEntry& entry, int& arg);
void add_entry(const OptionEntry& entry, Glib::ustring& arg);
void add_entry_filename(const OptionEntry& entry, std::string& arg);
void add_entry(const OptionEntry& entry, vecustrings& arg);
void add_entry_filename(const OptionEntry& entry, vecstrings& arg);
-
+
/* TODO:
void g_option_group_set_translate_func (GOptionGroup *group,
GTranslateFunc func,
@@ -83,36 +83,41 @@ void g_option_group_set_translate_func (GOptionGroup *group,
GDestroyNotify destroy_notify);
*/
_WRAP_METHOD(void set_translation_domain(const Glib::ustring& domain), g_option_group_set_translation_domain)
-
+
GOptionGroup* gobj() { return gobject_; }
const GOptionGroup* gobj() const { return gobject_; }
GOptionGroup* gobj_give_ownership();
-
+
protected:
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ /** This is not public API. It is an implementation detail.
+ */
class CppOptionEntry
{
public:
CppOptionEntry();
-
+
void allocate_c_arg();
+ void set_c_arg_default(void* cpp_arg);
void convert_c_to_cpp();
void release_c_arg();
-
+
GOptionArg carg_type_;
void* carg_;
void* cpparg_;
OptionEntry* entry_;
};
-
+
void add_entry_with_wrapper(const OptionEntry& entry, GOptionArg arg_type, void* cpp_arg);
-
+
//Map of entry names to CppOptionEntry:
typedef std::map<Glib::ustring, CppOptionEntry> type_map_entries;
type_map_entries map_entries_;
-
+
GOptionGroup* gobject_;
bool has_ownership_; //Whether the gobject_ belongs to this C++ instance.
+#endif //DOXYGEN_SHOULD_SKIP_THIS
};
} // namespace Glib