<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>はらぺこ日誌 &#187; iconv</title>
	<atom:link href="https://blog.harapeko.jp/tag/iconv/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.harapeko.jp</link>
	<description>株式会社はらぺこ 公式ブログ</description>
	<lastBuildDate>Mon, 30 Oct 2017 14:32:56 +0000</lastBuildDate>
	<language>ja</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.9.2</generator>
	<item>
		<title>char32_t だと regex が使えない</title>
		<link>https://blog.harapeko.jp/2010/09/22/u32regex-bad-cast/</link>
		<comments>https://blog.harapeko.jp/2010/09/22/u32regex-bad-cast/#comments</comments>
		<pubDate>Wed, 22 Sep 2010 02:21:44 +0000</pubDate>
		<dc:creator><![CDATA[村山 俊之]]></dc:creator>
				<category><![CDATA[技術メモ]]></category>
		<category><![CDATA[Boost]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[C++0x]]></category>
		<category><![CDATA[GCC]]></category>
		<category><![CDATA[iconv]]></category>
		<category><![CDATA[otoco]]></category>
		<category><![CDATA[Unicode]]></category>

		<guid isPermaLink="false">http://blog.harapeko.jp/?p=133</guid>
		<description><![CDATA[C++0x では UCS に対応し、専用の型やリテラルの記法が導入されました。その関係で、以下の点について調査 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>C++0x では UCS に対応し、<a href="http://ja.wikipedia.org/wiki/C%2B%2B0x#.E6.96.B0.E3.81.9F.E3.81.AA.E6.96.87.E5.AD.97.E5.88.97.E3.83.AA.E3.83.86.E3.83.A9.E3.83.AB" title="新たな文字列リテラル - C++0x - Wikipedia">専用の型やリテラルの記法が導入されました</a>。その関係で、以下の点について調査を行っていました。</p>
<ol>
<li>C++0x で UCS を UTF-32 として扱う型 <code>char32_t</code>, <code>u32string</code> およびリテラル <code>U"..."</code> と、 libiconv の UCS-4-INTERNAL との間に互換性はあるか。</li>
<li>C++0x で新たに追加された正規表現ライブラリ <code>&lt;regex&gt;</code> は利用可能か。</li>
<li><code>&lt;regex&gt;</code> が利用できない場合、 Boost.Regex を用いて UTF-32 文字列を処理することは可能か。</li>
</ol>
<p>これらの調査は、すべて otoco のコアデータを扱うプログラム内で内部文字列に UTF-32 を採用することを前提としたものでした。<br />
<span id="more-133"></span><br />
結論から言うと、<strong>内部文字列に UTF-32 を採用することは、現時点では諦めざるを得ない、ということになりました。＼(^O^)／</strong> 以下、その解説です。</p>
<p>1 については、互換性に問題がないことを確認しました。</p>
<p>2 についてですが、 GCC 4.5 の標準 C++ ライブラリでは、 <code>&lt;regex&gt;</code> のヘッダファイルは存在するものの、ライブラリの実体がまだ用意されていない、という状態のようでした。</p>
<p>で、 3 についてなのですが… 簡単のため、以下のサンプルを見てみることにします。</p>
<pre>
#include &lt;string&gt;
#include &lt;boost/regex.hpp&gt;

using namespace std;

typedef boost::basic_regex&lt;char32_t, boost::regex_traits&lt;char32_t&gt; &gt; u32regex;
typedef boost::match_results&lt;u32string::const_iterator&gt; u32smatch;

int main()
{
	u32string text(U&quot;C++0x のせかいへようこそ!!&quot;);
	u32string modified;
	u32regex reg(U&quot;せかい&quot;);
	u32smatch match;
	while (boost::regex_search(text, match, reg)) {
		modified += match.prefix().str() + U&quot;世界&quot;;
		text = match.suffix().str();
	}
	modified += text;
	return 0;
}
</pre>
<p>このサンプルは、期待通りに動作しても、何もしません。UTF-32 の文字列 <code>U"C++0x のせかいへようこそ!!"</code> の <code>U"せかい"</code> を <code>U"世界"</code> に置換する、という処理を内部で行うだけです。 <code>u32string</code> に対応した <code>iostream</code> があったとして、 UTF-32 をそのままコンソールやファイルに出しても不親切なだけなので、出力までやるなら libiconv と組み合わせるべきですが、プログラムが複雑になるので、ここではそこまで示していません (実際にはそこまで試そうとしていたのですが…)。</p>
<p>で、このプログラム、実際はどうなるのかというと、 GCC 4.5 でコンパイルは通るものの、実行すると、 <strong><code>u32regex</code> オブジェクト</strong> (これは <code>boost::basic_regex&lt;char32_t, boost::regex_traits&lt;char32_t&gt; &gt;</code> のシノニムですね) <strong>のコンストラクタが <code>std::bad_cast</code> 例外を送出します</strong>。どうやら、 Boost.Regex は <code>char32_t</code>、すなわち 32bits 以上の整数型を文字コードに使用するということ、を想定した作りにはなっていなかったようなのです。よーするに <code>char</code> と <code>wchar_t</code> しか想定していなかったんですね (ん? でも <a href="http://blog.harapeko.jp/2009/07/25/wchar_t-suck/" title="はらぺこ日誌» ブログアーカイブ » 頼りなさげな wchar_t">GCC の <code>wchar_t</code> は <code>uint32_t</code></a> だったような…)。</p>
<p>GCC の標準 C++ ライブラリが <code>&lt;regex&gt;</code> のライブラリを実装するのを悠長に待っても居られないので、方針を転換し、内部文字列は UTF-8 で実装せざるを得なさそうです。一応、UTF-8 は文字の先頭オクテットか否かを判断するのが容易なので (0&#215;80≦n≦0xBF 以外なら先頭オクテット)、文字境界の特定も文字数カウントも一度関数を書いてしまえば ok なのですが…。</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.harapeko.jp/2010/09/22/u32regex-bad-cast/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>libiconv で文字セット自動認識</title>
		<link>https://blog.harapeko.jp/2010/03/03/libiconv-gues/</link>
		<comments>https://blog.harapeko.jp/2010/03/03/libiconv-gues/#comments</comments>
		<pubDate>Wed, 03 Mar 2010 09:02:48 +0000</pubDate>
		<dc:creator><![CDATA[村山 俊之]]></dc:creator>
				<category><![CDATA[技術メモ]]></category>
		<category><![CDATA[活動記録]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[iconv]]></category>
		<category><![CDATA[otoco]]></category>
		<category><![CDATA[Unicode]]></category>
		<category><![CDATA[文字セット]]></category>
		<category><![CDATA[文字列処理]]></category>

		<guid isPermaLink="false">http://blog.harapeko.jp/?p=111</guid>
		<description><![CDATA[ご無沙汰ぶりです…。 以前、wchar_t はどうにも使い物にならないからどうしよう、といった記事を書いたので [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>ご無沙汰ぶりです…。</p>
<p>以前、<a href="http://blog.harapeko.jp/2009/07/25/wchar_t-suck/" title="はらぺこ日誌» ブログアーカイブ » 頼りなさげな wchar_t">wchar_t はどうにも使い物にならないからどうしよう</a>、といった記事を書いたのですが、その続きのお話です。</p>
<p>表題の通りで、 libiconv を用いて文字セットを自動認識する処理のサンプルを書いてみました。詳しい経緯は<a href="http://developer.harapeko.jp/trac/original/otoco/ticket/4" title="#4 (テキストファイルから読み込んだ文字列を wchar_t 配列と Unicode で扱う方法を調査する。) – otoco">Ticket 内で逐次コメントしています</a>。<br />
<span id="more-111"></span><br />
<a href="http://developer.harapeko.jp/trac/original/otoco/browser/trunk/sample/guessutf8.cpp" title="/trunk/sample/guessutf8.cpp – otoco">これ</a>がそのサンプルプログラムです。このプログラムは、</p>
<ol>
<li>標準入力からファイルを読み込み、</li>
<li>ファイルの文字セットを自動認識し、</li>
<li>句点「。」をピリオド「.」に、読点「、」をカンマ「,」に置換し、</li>
<li>UTF-8 に変換して標準出力に書き出す。</li>
</ol>
<p>ということをやるものです。</p>
<p>で、<a href="http://blog.harapeko.jp/2009/07/25/wchar_t-suck/" title="はらぺこ日誌» ブログアーカイブ » 頼りなさげな wchar_t">以前のブログ記事</a>では、</p>
<blockquote cite="http://blog.harapeko.jp/2009/07/25/wchar_t-suck/" title="はらぺこ日誌» ブログアーカイブ » 頼りなさげな wchar_t">
<p>というわけで、内部コードは wchar_t のような型名で定義するのではなく、より具体的に文字セットで定義した方が良さそうだなぁという結論に至りました。候補は以下の 2通りです。</p>
<ul>
<li>UCS4 を内部コードとし、物理型は符号無し 32bits 整数を適当な型名に typedef して用いる。</li>
<li>UTF-8 を内部コードとし、物理型は char を用いる。</li>
</ul>
</blockquote>
<p>と書いておりましたが、今回はこのうち、前者の UCS4 を内部コードとして用いる方法で実装しています。</p>
<p>とりあえず動いたから commit してみた、という段階なので、コメントが不十分だったり魔法の値が散らばっていたりと未熟なコードです。追々直していこうかと思っています。また、後者の UTF-8 を内部コードとして用いる方法についても併せて書いてみる予定です。</p>
<p>また、現状では boost::regex を用いたコードにはなっていないので (1文字ずつの置換なので UCS4 だと使う必要がないのよ、今のところ)、これを用いた形に修正した場合、どうなるか、といった辺りも試していきたいと思っています。実際にコードに起こしてみると、頭で分かっている以上の利点や問題点が分かってくるんじゃないかなと。</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.harapeko.jp/2010/03/03/libiconv-gues/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>頼りなさげな wchar_t</title>
		<link>https://blog.harapeko.jp/2009/07/25/wchar_t-suck/</link>
		<comments>https://blog.harapeko.jp/2009/07/25/wchar_t-suck/#comments</comments>
		<pubDate>Sat, 25 Jul 2009 09:42:17 +0000</pubDate>
		<dc:creator><![CDATA[村山 俊之]]></dc:creator>
				<category><![CDATA[技術メモ]]></category>
		<category><![CDATA[活動記録]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[iconv]]></category>
		<category><![CDATA[otoco]]></category>
		<category><![CDATA[Unicode]]></category>
		<category><![CDATA[wchar_t]]></category>
		<category><![CDATA[文字セット]]></category>
		<category><![CDATA[文字列処理]]></category>

		<guid isPermaLink="false">http://blog.harapeko.jp/?p=96</guid>
		<description><![CDATA[otoco に限らず、 PC 上で動作するプログラムの多くは、テキストを処理することを目的の一部またはすべてと [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>otoco に限らず、 PC 上で動作するプログラムの多くは、テキストを処理することを目的の一部またはすべてとしています。 otoco の場合は特に、どこの誰とも分からない人が MML を書き、それを読み込んで XML やら SMF やらオーディオやら楽譜やらに変換することを目的としているので、どこの誰が MML を (あるいは XML を直接) 書いても問題なく処理できるよう、文字セットの扱いには丁重でなければなりません。</p>
<p>当初の方針として、 otoco では内部コードに Unicode を使用し、その物理型は wchar_t で扱うつもりでいました。この辺、C/C++ でのクロスプラットフォーム開発に慣れていないと陥りやすい罠であるように思うのですが… 現状の wchar_t ははっきり言ってクロスプラットフォーム開発には向いていないものといわざるを得ないようです。</p>
<p>とりあえず確認しているのは Windows の VC++ 2008 と Linux の gcc だけなのですが、それだけでも調べた限りで以下のような相違点がありました。</p>
<p><span id="more-96"></span></p>
<table rules="all">
<tr>
<th>開発環境</th>
<th>文字セット</th>
<th>物理型</th>
</tr>
<tr>
<td>Windows + MS-VC++ 2008</td>
<td>UTF-16LE</td>
<td>符号無し 16bits 整数 (unsigned short)</td>
</tr>
<tr>
<td>Linux + gcc</td>
<td>UCS4</td>
<td>符号無し 32bits 整数 (uint32_t)</td>
</tr>
</table>
<p>まず文字セットですが、 UTF-16LE とはリトルエンディアンの UTF-16 エンコードのことで、 Unicode を表現するための<strong>ファイル形式</strong>です。ファイル形式であるということは、すなわちファイルに保存する方法を定めた形式であるということです。それに対して、 UCS4 はあくまで Unicode そのものであり、内部データ形式として扱えるものです。</p>
<p>具体的に何が違うのかというと、 UTF-16 の場合は配列内の数値 1つが必ず 1文字を表現するものであることを保証しません。実際、UTF-16 ではサロゲートペアを気にする必要があり、この処理を誤ると文字境界に破綻を来して文字化けの原因を作ってしまうことになります。これに対し、 UCS4 の場合は単に 31bits 以下の文字セットであり、それより拡張されないことが保証されています (万一拡張された場合は新たに UCS8 が規定されて包括されるのでしょうが、現実的にはあり得ないでしょう)。</p>
<p>私は元より Windows 畑の人なので、 wchar_t を使う場合でもサロゲートペアをどうにかすることを前提に考えていましたから、 GNU/Linux でのあり方はむしろ理想的とも思うのですが、反面内部的な処理に過ぎない部分でプラットフォーム依存を気にしながら実装しなければならないというのはあまり好ましいことではなく、そう考えると wchar_t という型は意味論的には破綻しているといわざるを得ないように思います。さらに BSD 系の UNIX 環境では wchar_t が扱う文字セットは環境のロケールに依存するなどという情報もあり… とてもじゃないですがそんなの考慮しきれるわけがありません ((((/;^^)/ 。</p>
<p>というわけで、内部コードは wchar_t のような型名で定義するのではなく、より具体的に文字セットで定義した方が良さそうだなぁという結論に至りました。候補は以下の 2通りです。</p>
<ul>
<li>UCS4 を内部コードとし、物理型は符号無し 32bits 整数を適当な型名に typedef して用いる。</li>
<li>UTF-8 を内部コードとし、物理型は char を用いる。</li>
</ul>
<p>前者のメリットは何と言っても多言語処理の確実性が高く、文字境界も気にする必要がないことです。例えば、配列の中の n個目の値は、確実に文字列の中の n個目の文字であることが保証されます。反面、 STL や Boost を用いた文字列処理においては、あらかじめ typedef された便利な型名を用いることができず、プログラム側で内部コード用に typedef したものをたくさん用意しておく必要が生じるでしょう。また、何より文字列リテラルが使えなくなるので、正規表現のハードコーディングには工夫を強いられることになります。</p>
<p>後者のメリットは STL の string や Boost.Regex に定義されている typedef がそのまま利用できること、そして何よりハードコーディングした文字列リテラルがそのまま利用できることです。正規表現の記述もこちらの方がよっぽどすっきりするでしょう。また、 XML の入出力を UTF-8 に限定して良いのであれば、その辺の実装も楽になるかも知れません。文字境界については注意する必要がありますが、例えば n文字目の検出は他のエンコーディングに比べれば容易であるのも UTF-8 の特徴でもあります (もちろん、UCS4 を用いる場合に比べれば、実装は複雑になりますが…)。</p>
<p>ちなみに、文字セットの変換にはやっぱり iconv を使うことになりそうです。 Windows 側はまだ試していないのですが… とりあえず近日中に iconv を用いた簡単なプロトタイプを書いて、上記の件も含めて検討してみる予定です…。</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.harapeko.jp/2009/07/25/wchar_t-suck/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
