大阪市中央区 システムソフトウェア開発会社

営業時間:平日09:15〜18:15
MENU

C++でC風ライブラリを作る(UTF-8からUTF-32への変換編)

著者:高木信尚
公開日:2019/04/28
最終更新日:2019/04/28
カテゴリー:技術情報

高木です。

前回まではUTF-16やUTF-32からUTF-8への変換を行う関数を作りました。
今回からはその逆で、UTF-8からUTF-16やUTF-32への変換を行いたいと思います。
見た目、ちょっと紛らわしいので注意してください。

すべてを一気に実装するのは大変ですので、まずはUTF-8からUTF-32に変換するmbrtoct関数を作ることにします。
その後、UTF-16版のmbrtoct関数を作成し、続いてそれぞれのmbtoct関数を作るという流れで行きたいと思います。

とはいえ、UTF-8からUTF-32に変換するmbrtoct関数だけでもいろいろ考えないといけないことがあり大変です。
何が一番大変かというと、UTF-8が途中で終わっていた場合にmbstate_t型のオブジェクトに状態を保存して再開できるようにしないといけないところです。
今回は、完全なUTF-8が与えられた場合だけを考えることにします。

namespace cloverfield
{
  inline std::size_t mbrtoct(char32_t* pc32, char const* s, std::size_t n, mbstate_t* ps)
  {
    int c = static_cast<unsigned char>(*s);
    char32_t c32;
    std::size_t r;

    if (c < 0x80)
    {
      c32 = c;
      r = 1;
    }
    else if ((c & 0xe0) == 0xc0)
    {
      c32 = (c & 0x1f) << 6 | s[1] & 0x3f;
      if (c32 < 0x80)
        r = -1;
      else
        r = 2;
    }
    else if ((c & 0xf0) == 0xe0)
    {
      c32 = (c & 0xf) << 12 | (s[1] & 0x3f) << 6 | s[2] & 0x3f;
      if (c32 < 0x800)
        r = -1;
      else
        r = 3;
    }
    else if ((c & 0xf8) == 0xf0)
    {
      c32 = (c & 0x7) << 18 | (s[1] & 0x3f) << 12 | (s[2] & 0x3f) << 6 | s[3] & 0x3f;
      if (c32 < 0x10000 || 0x10ffff < c32)
        r = -1;
      else
        r = 4;
    }
    else
    {
      r = -1;
    }

    if (pc32 != nullptr)
      *pc32 = c32;
    return r;
  }
}

というわけで、今回はいったん素直に作ってみました。
psはもちろん、バイト数nでさえ使っていない簡易的なものです。
今回の結果を踏まえつつ、次回はより完成に近い形まで持っていきたいと考えています。

    上に戻る