On Fri, Nov 10, 2006 at 06:43:58PM +0100, Georg Baum wrote:
> Enrico Forestieri wrote:
>
> > On Fri, Nov 10, 2006 at 05:45:18PM +0100, Georg Baum wrote:
> >> Enrico Forestieri wrote:
> >>
> >> > I am going to shove in the attached. There's a small optimization with
> >> > respect to the previous version.
> >>
> >> Can you explain why you implemented two facets? I would expect only one
> >> (with ascii_num_put_facet as name, since it can only cope with pure
> >> ascii).
> >
> > Strictly speaking, only the odocstream_num_put_facet would be needed.
> > I used the ascii_num_put_facet in order to have a number formatted as a
> > string using the already existing facets for basic_string<char>::iterator
> > instead of rolling out my own versions.
>
> I can understand that, but why do you not use std::num_put<char,
> std::basic_string<char>::iterator> directly?
Because when I did that (as done in the attached patch) I got the
following error:
g++ -DHAVE_CONFIG_H -I. -I../../../src/support -I../../src
-I../../../src/support/.. -I../../../boost -Wno-uninitialized -funsigned-char
-O2 -MT docstring.lo -MD -MP -MF .deps/docstring.Tpo -c
../../../src/support/docstring.C -o docstring.o
../../../src/support/docstring.C: In member function `virtual
std::ostreambuf_iterator<lyx::char_type, std::char_traits<lyx::char_type> >
lyx::ascii_num_put_facet::do_put(std::ostreambuf_iterator<lyx::char_type,
std::char_traits<lyx::char_type> >, std::ios_base&, lyx::char_type, long int)
const':
/usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/locale_facets.h:2404: error:
`std::num_put<_CharT, _OutIter>::~num_put() [with _CharT = char, _OutIter =
__gnu_cxx::__normal_iterator<char*, std::basic_string<char,
std::char_traits<char>, std::allocator<char> > >]' is protected
../../../src/support/docstring.C:407: error: within this context
make[5]: *** [docstring.lo] Error 1
> I really would prefer if
> odocstream_num_put_facet would be called ascii_num_put_facet, since that
> makes very clear that it can only deal with ASCII. For the same reason I
> would prefer to assert on fill < 0x80 instead of silently changing it to a
> space.
Or maybe throw num_put_failure() ?
> I don't think that we are using a different fill character anywhere,
> but if somebody does that it is better to crash than to silently alter the
> result. Your current ascii_num_put_facet is only an implementation detail,
> so I'd like that to be hidden in the num_put method.
In order to do that I have to avoid the above error. Any suggestions?
--
Enrico
Index: src/support/docstring.C
===================================================================
--- src/support/docstring.C (revision 15838)
+++ src/support/docstring.C (working copy)
@@ -14,6 +14,7 @@
#include "unicode.h"
#include <locale>
+#include <iostream>
#include <boost/assert.hpp>
@@ -388,14 +389,42 @@ protected:
};
-/// class to add our ascii_ctype_facet to the global locale
+/// Facet for converting numbers to ascii strings.
+/// Here we simply need defining the virtual do_put functions.
+class ascii_num_put_facet : public std::num_put<lyx::char_type,
std::ostreambuf_iterator<lyx::char_type, std::char_traits<lyx::char_type> > >
+{
+ typedef std::ostreambuf_iterator<lyx::char_type,
std::char_traits<lyx::char_type> > iter_type;
+public:
+ ascii_num_put_facet(size_t refs = 0) : std::num_put<lyx::char_type,
iter_type>(refs) {}
+
+protected:
+ iter_type
+ do_put(iter_type oit, std::ios_base & b, char_type fill, long v) const
+ {
+ std::string s;
+ // 64 is large enough
+ s.resize(64);
+ std::num_put<char, std::basic_string<char>::iterator> f;
+ std::string::const_iterator cit = s.begin();
+ std::string::const_iterator end =
+ f.put(s.begin(), b, fill < 0x80 ? fill : ' ', v);
+ for (; cit != end; ++cit, ++oit)
+ *oit = *cit;
+
+ return oit;
+ }
+};
+
+
+/// class to add our facets to the global locale
class locale_initializer {
public:
locale_initializer()
{
std::locale global;
- std::locale const loc(global, new ascii_ctype_facet);
- std::locale::global(loc);
+ std::locale const loc1(global, new ascii_ctype_facet);
+ std::locale const loc2(loc1, new ascii_num_put_facet);
+ std::locale::global(loc2);
}
};