On Sat, Nov 10, 2007 at 12:49:44PM +0100, Andre Poenitz wrote:

> On Thu, Nov 08, 2007 at 11:58:19PM +0100, Enrico Forestieri wrote:
> > > Hm... the easy way out would probably be an #include <string> or such
> > > guarded by #ifdef SOMETHING_CYGWIN_SPECIFIC.
> > 
> > I don't think this is cygwin specific, though.
> 
> Possibly. But as long as we don't have 

But we also have *BSD and Macs where USE_WCHAR_T is not defined.

> > > But there should be something cheaper.
> > > 
> > > Is USE_WCHAR_T defined for you?
> > 
> > No.
> 
> But there's a wchar_t type, but that's presumably only 16 bits, so we
> don't use it, right?

Right.

> > > For what types do you have char_traits<> specialized?
> > 
> > gcc has only specializations for char and wchar_t.
> 
> I guess that's the common pattern and they are the only ones that are
> required.

No, the standard doesn't require any specialization. It is gcc that
is only specializing for char and wchar_t. For example, MSVC has
no problems with any type, seemingly.

> > The only way out that I see is a full blown specialization for
> > lyx::char_type, something like:
> > 
> > template<>
> >     struct char_traits<lyx::char_type>
> >     {
> >        ... put here what is needed...
> >     };
> 
> That would be a solution, but it's already a bit more of 'handcoding'
> than I'd consider sensible. I mean, have a few typedefs instead of 
> #include <bigstuff> is ok, duplicating ~200 lines rather not...

The attached strfwd-2.diff fails at link time, but strfwd-3.diff works.
However, note that I would have to still include the wchar.h (for wint_t
and mbstate_t) and string.h C headers. Then, there still would be a
problem with the streamoff type. The standard says that it is
implementation dependent and I should include the ios header to get its
definition. Moreover, even if we limit the specialization to gcc, there
surely would be a problem with 64 bit machines. The moral is that gcc
sucks with respect to MSVC, at least in this area.

In the end I verified that simply omitting the forward declaration
for lyx::char_type char traits, it works. I admit that I don't know
why it does, though. Probably this means that it is not needed, after
all.

> Is your wchar_t really 16 bit?

Yes, and cannot be easily changed. However, I have hacked the STLport
library such that I can have a 32 bit wchar_t on Cygwin with all needed
specializations. Of course, I would still be lacking proper support for
ancillary wide char functions, as STLport relies on those provided by
the system. Nothing that could not be solved, but I already invested a
good deal of effort in implementing the missing facets for the current
solution and I am not willing to start it over again.

-- 
Enrico
Index: src/support/strfwd.h
===================================================================
--- src/support/strfwd.h        (revision 21530)
+++ src/support/strfwd.h        (working copy)
@@ -23,6 +23,7 @@ namespace lyx { typedef wchar_t char_typ
 
 #else
 
+#include <wchar.h>
 #include <boost/cstdint.hpp>
 namespace lyx { typedef boost::uint32_t char_type; }
 
@@ -37,6 +38,34 @@ template<typename Char> struct char_trai
 template<> struct char_traits<char>;
 #ifdef USE_WCHAR_T
 template<> struct char_traits<wchar_t>;
+#else
+typedef long long streamoff;
+template <typename State> class fpos;
+typedef fpos<mbstate_t> streampos;
+template<> struct char_traits<lyx::char_type> {
+       typedef lyx::char_type char_type;
+       typedef wint_t         int_type;
+       typedef streamoff      off_type;
+       typedef streampos      pos_type;
+       typedef mbstate_t      state_type;
+
+       static void assign(char_type & c1, char_type const & c2);
+       static bool eq(char_type const & c1, char_type const & c2);
+       static bool lt(char_type const & c1, char_type const & c2);
+       static int
+               compare(char_type const * s1, char_type const * s2, size_t n);
+       static size_t length(char_type const * s);
+       static char_type const *
+               find(char_type const * s, size_t n, char_type const & a);
+       static char_type * move(char_type * s1, char_type const * s2, size_t n);
+       static char_type * copy(char_type * s1, char_type const * s2, size_t n);
+       static char_type * assign(char_type* s, size_t n, char_type a);
+       static int_type eof();
+       static int_type not_eof(int_type const & c);
+       static char_type to_char_type(int_type const & c);
+       static int_type to_int_type(char_type const & c);
+       static bool eq_int_type(int_type const & c1, int_type const & c2);
+};
 #endif
 
 template<typename Char, typename Traits, typename Alloc> class basic_string;
Index: src/support/strfwd.h
===================================================================
--- src/support/strfwd.h        (revision 21530)
+++ src/support/strfwd.h        (working copy)
@@ -23,6 +23,8 @@ namespace lyx { typedef wchar_t char_typ
 
 #else
 
+#include <wchar.h>
+#include <string.h>
 #include <boost/cstdint.hpp>
 namespace lyx { typedef boost::uint32_t char_type; }
 
@@ -37,6 +39,89 @@ template<typename Char> struct char_trai
 template<> struct char_traits<char>;
 #ifdef USE_WCHAR_T
 template<> struct char_traits<wchar_t>;
+#else
+typedef long long streamoff;
+template <typename State> class fpos;
+typedef fpos<mbstate_t> streampos;
+template<> struct char_traits<lyx::char_type> {
+       typedef lyx::char_type char_type;
+       typedef wint_t         int_type;
+       typedef streamoff      off_type;
+       typedef streampos      pos_type;
+       typedef mbstate_t      state_type;
+
+       static void
+       assign(char_type & c1, char_type const & c2)
+       { c1 = c2; }
+
+       static bool
+       eq(char_type const & c1, char_type const & c2)
+       { return c1 == c2; }
+
+       static bool
+       lt(char_type const & c1, char_type const & c2)
+       { return c1 < c2; }
+
+       static int
+       compare(char_type const * s1, char_type const * s2, size_t n)
+       {
+               for (size_t i = 0; i < n; ++i)
+                       if (!eq(s1[i], s2[i]))
+                               return lt(s1[i], s2[i]) ? -1 : 1;
+               return 0;
+       }
+
+       static size_t
+       length(char_type const * s)
+       {
+               char_type const * p = s;
+               while (*p)
+                       +p;
+               return (p - s);
+       }
+
+       static char_type const *
+       find(char_type const * s, size_t n, char_type const & a)
+       {
+               for (char_type const * p = s; size_t(p - s) < n; ++p)
+                       if (*p == a)
+                               return p;
+               return 0;
+       }
+
+       static char_type *
+       move(char_type * s1, char_type const * s2, size_t n)
+       { return (char_type *) memmove(s1,s2, n * sizeof(char_type)); }
+
+       static char_type *
+       copy(char_type * s1, char_type const * s2, size_t n)
+       { return (char_type *) memcpy(s1, s2, n * sizeof(char_type)); }
+
+       static char_type *
+       assign(char_type* s, size_t n, char_type a)
+       {
+               for (char_type* p = s; p < s + n; ++p)
+                       assign(*p, a);
+               return s;
+       }
+
+       static int_type
+       eof() { return static_cast<int_type>(-1); }
+
+       static int_type
+       not_eof(int_type const & c)
+       { return eq_int_type(c, eof()) ? 0 : c; }
+
+       static char_type
+       to_char_type(int_type const & c) { return char_type(c); }
+
+       static int_type
+       to_int_type(char_type const & c) { return int_type(c); }
+
+       static bool
+       eq_int_type(int_type const & c1, int_type const & c2)
+       { return c1 == c2; }
+};
 #endif
 
 template<typename Char, typename Traits, typename Alloc> class basic_string;

Reply via email to