我编写了自定义std::basic_streambuf
和std::basic_ostream
,因为我想要一个输出流,我可以通过类似于调用std::ostringstream::str()
的方式获取JNI字符串。这些课很简单。
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)
的实施是微不足道的。它只是将缓冲区宽度加倍,放置请求的字符,并正确设置基本,放置和结束指针。经过测试,我确信它有效。
jni_utf16_ostream
可以很好地插入unicode字符。例如,这样可以正常工作并生成包含“hello,world”的流:
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
上是否有其他方法我需要实现????
答案 0 :(得分:1)
看起来答案是char16_t
支持仅部分在GCC 4.8中实现。库头不会安装转换数字所需的构面。 Here is what the Boost.Locale project says about it:
GNU GCC 4.5 / C ++ 0x状态
GNU C ++编译器提供了对C ++ 0x字符的不错支持:
标准库不为此安装任何std :: locale :: facets 支持使用char16_t或char32_t格式化数字的任何尝试 流只会失败。标准库错过了专业化 必需的char16_t / char32_t语言环境方面,所以“std”后端不是 可构建的基本符号缺失,也是codecvt facet不可能的 也创造了。
Visual Studio 2010(MSVC10)/ C ++ 0x状态
MSVC提供了所有必需的方面:
标准库不提供std :: locale :: id的安装 DLL中的这些方面因此不能与/ MD,/ MDd编译器标志一起使用 并需要运行时库的静态链接。 char16_t和char32_t 不是不同的类型,而是unsigned short和的别名 无符号类型与C ++ 0x要求相矛盾 不可能写char16_t / char32_t来流和导致多个 故障。