Я написал обычай std::basic_streambuf
а также std::basic_ostream
потому что я хочу выходной поток, из которого я могу получить строку JNI способом, подобным тому, как вы можете вызвать std::ostringstream::str()
, Эти занятия довольно просты.
namespace myns {
class jni_utf16_streambuf : public std::basic_streambuf<char16_t>
{
JNIEnv * d_env;
std::vector<char16_t> d_buf;
virtual int_type overflow(int_type);
public:
jni_utf16_streambuf(JNIEnv *);
jstring jstr() const;
};
typedef std::basic_ostream<char16_t, std::char_traits<char16_t>> utf16_ostream;
class jni_utf16_ostream : public utf16_ostream
{
jni_utf16_streambuf d_buf;
public:
jni_utf16_ostream(JNIEnv *);
jstring jstr() const;
};
// ...
} // namespace myns
Кроме того, я сделал четыре перегрузки operator<<
все в одном пространстве имен:
namespace myns {
// ...
utf16_ostream& operator<<(utf16_ostream&, jstring) throw(std::bad_cast);
utf16_ostream& operator<<(utf16_ostream&, const char *);
utf16_ostream& operator<<(utf16_ostream&, const jni_utf16_string_region&);
jni_utf16_ostream& operator<<(jni_utf16_ostream&, jstring);
// ...
} // namespace myns
Реализация jni_utf16_streambuf::overflow(int_type)
тривиально. Он просто удваивает ширину буфера, помещает запрошенный символ и правильно устанавливает указатели base, put и end. Это проверено, и я уверен, что это работает.
jni_utf16_ostream
прекрасно работает вставка символов Юникода. Например, это работает нормально и приводит к потоку, содержащему «привет, мир»:
myns::jni_utf16_ostream o(env);
o << u"hello, wor" << u'l' << u'd';
Моя проблема в том, что как только я пытаюсь вставить целочисленное значение, устанавливается плохой бит потока, например:
myns::jni_utf16_ostream o(env);
if (o.badbit()) throw "bad bit before"; // does not throw
int32_t x(5);
o << x;
if (o.badbit()) throw "bad bit after"; // throws :(
Я не понимаю, почему это происходит! Есть ли какой-то другой метод на std::basic_streambuf
Мне нужно реализовать ????
Похоже, ответ таков char16_t
поддержка реализована только частично в GCC 4.8. Заголовки библиотеки не устанавливают фасеты, необходимые для преобразования чисел. Вот что говорит об этом проект Boost.Locale:
GNU GCC 4.5 / C ++ 0x Status
Компилятор GNU C ++ обеспечивает достойную поддержку символов C ++ 0x:
Стандартная библиотека не устанавливает для этого никакой std :: locale :: facets
поддержка, поэтому любая попытка отформатировать числа с использованием char16_t или char32_t
потоки просто потерпят неудачу. Стандартная библиотека пропускает специализацию для
требуются фасеты char16_t / char32_t локали, поэтому бэкенды «std» не
возможность сборки, так как отсутствуют важные символы, также не может быть кодековский фасет
создано также.Visual Studio 2010 (MSVC10) / C ++ 0x Status
MSVC предоставляет все необходимые аспекты, однако:
Стандартная библиотека не обеспечивает установки std :: locale :: id для
эти аспекты в DLL, поэтому он не может использоваться с флагами компилятора / MD, / MDd
и требует статической ссылки библиотеки времени выполнения. char16_t и char32_t
это не отдельные типы, а псевдонимы неподписанных коротких и
типы без знака, что противоречит требованиям C ++ 0x, что делает его
невозможно записать char16_t / char32_t в поток и вызвать несколько
разломы.
Других решений пока нет …