Re: TreeView::append_column_numeric() format?



On Mon, 2004-11-22 at 07:10, Murray Cumming wrote:
> >> So I would like to add another templated convenience method like this:
> >> Gtk::TreeView::append_column_numeric(TreeModelColumn& model,
> >> numeric_format);
> >>
> >> But what's the best way to specify the display format for the number?
> >> I'd
> >> rather not use that nasty printf() style format. Does C++ have something
> >> more suitable?
> >
> > Boost has a "format" object (described here:
> > http://www.boost.org/libs/format/doc/format.html)
> 
> Using a formatter object is a good idea, but it seems to mostly use the
> sprintf format anyway, with some extensions.
> 
> Also I would feel bad about reproducing so much code in gtkmm. And we
> can't depend on boost because it's not a stable (API or ABI) library yet.
> 
> If we find no better alternative to the sprintf format then we could just
> decide to live with
>   TreeView::append_column_numeric(TreeModelColumn& column, const
> Glib::ustring& format);
> where format is something like "%.4f" for 4decimal places.
> 
> > I'm not suggesting that this actual class should be used, but it's a
> > starting point for ideas. The Gtk::TreeView::append_column_numeric()
> > method could take an object that formats a number (perhaps with a number
> > of
> > simple/common ones supplied). I don't know how all this works underneath
> > though, does it need to translate to printf format for the Gtk+ interface,
> > or does all the formatting happen in the C++ wrapper?
> 
> Gtk+ has no equivalent for this. Their whole GtkTreeView API is much more
> unpleasant. And they are probably happy to use C-style sprintf formatting
> for this.

See http://www.3sinc.com/opensource/releases/libcast-0.1.0.tar.gz

This implements a lexical_cast<T> object which uses stringstream to
perform the "cast" of some user-defined object to a string.  It's useful
for generating ascii versions of int/float/whatever.  It also has
template parameters for "stream policy objects" to allow changing the
stream functions, so you can define policy objects for setting hex,
width, etc.  Also has a binder policy to make multiple changes.  Comes
with some examples, just no docs at the moment.

I think this could be helpful, either as a helper object passed in the
API, or as a basis for designing a template parameter for user-defined
conversions.

There's also a string_extract template function, which performs in the
opposite direction, given a string and returns an object via
operator>>.  This one may not be so well thought out, it was a quick
hack.

Regards,
Carl

Actually, header code is included.  There is a specialization for string
objects in a .cxx file, but you'll see what you need in the header, it's
mostly template code.


// -*- c++ -*-
// $RCSfile:$

// lexical_cast.hxx
//
// Copyright (C) 2004 Spatial Software Solutions, Inc.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library 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
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this library; if not, write to the Free
// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//

#ifndef CAST_LEXICALCAST
#define CAST_LEXICALCAST

////////////////////////////////////////////////////////////////////
// Includes

#include <string>
#include <strstream>
#include <iomanip>
#include <iostream>

////////////////////////////////////////////////////////////////////
// Class Definition

namespace Cast {

struct cast_policy_none {
    void Init(std::ostream& os) const {}
    void Cleanup(std::ostream& os) const {}
};
        
struct cast_policy_hex {
    void Init(std::ostream& os) const { os << std::hex;}
    void Cleanup(std::ostream& os) const { os << std::dec; }
};
        
struct cast_policy_quoted {
    cast_policy_quoted(char q = '\'') : quote(q) {}
    void Init(std::ostream& os) const { os << quote; }
    void Cleanup(std::ostream& os) const { os << quote; }
    char quote;
};
        
     
struct cast_policy_leadzero {
    void Init(std::ostream& os) const {
        os << std::setfill('0');
    }
    void Cleanup(std::ostream& os) const {}
};

template <int N>
struct cast_policy_width {
    void Init(std::ostream& os) const {
        os << std::setw(N);
    }
    void Cleanup(std::ostream& os) const {}
};

template<typename T, typename U>
struct cast_policy_bind {
	cast_policy_bind(const T& t = T(), const U& u = U()) : 
        first(t), second(u) 
        {}
	void Init(std::ostream& os) const {
		first.Init(os);
		second.Init(os);
	}
	void Cleanup(std::ostream& os) const {
		second.Cleanup(os);
		first.Cleanup(os);
	}
	T first;
	U second;
};

template <typename T, typename U>
cast_policy_bind<T,U> policy_binder(const T& t, const U& u)
{ return cast_policy_bind<T,U>(t, u); }


template <typename T>
std::string lexical_cast(const T& obj)
{
    std::ostrstream str;
	str << obj << std::ends;
	char* buf(str.str());
	std::string result(buf);
	delete[] buf;
	return result;
}

template <typename T, typename P>
std::string lexical_cast(const T& obj, const P& policy = P())
{
	std::ostrstream str;
    policy.Init(str);
	str << obj;
    policy.Cleanup(str);
    str << std::ends;
	char* buf(str.str());
	std::string result(buf);
	delete[] buf;
	return result;
}

std::string lexical_cast(const bool& obj);

template <typename P>
std::string lexical_cast(const bool& obj, const P& policy)
{
	std::ostrstream str;
    policy.Init(str);
	str << (obj ? "YES" : "NO");
    policy.Cleanup(str);
    str << std::ends;
	char* buf(str.str());
	std::string result(buf);
	delete[] buf;
	return result;
}

template <typename T>
std::string upper_cast(const T& obj)
{
    std::ostrstream str;
// 	str << uppercase << obj << std::ends;
    str << obj << std::ends;
	char* buf(str.str());
    // Because uppercase doesn't seem to work
    {
        for(char* it = buf; *it; ++it){
            if((*it <= 'z') && (*it >= 'a'))
                *it += 'A' - 'a';
        }
    }
	std::string result(buf);
	delete[] buf;
	return result;
}

template <typename T>
T string_extract(const std::string& str)
{
    std::istrstream s(str.c_str(), str.length());
    T result;
    s >> result;
    return result;
}

} // namespace

#endif // CAST_LEXICALCAST




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]