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;