[C++] 347 BBS閲覧アプリの製作 その31 無効なシーケンス混入による文字コード変換失敗 iconv / CP932

[Mac M2 Pro 12CPU, MacOS Ventura 13.3.1, clang 14.0.3]
(今回からM2 Pro 12コアCPUを使用)

とあるdatファイルをCP932からUTF-8へ変換しようとしたところエラーになりました。

どうやら無効なシーケンスが混ざっているようです。

以下のようにConvertShiftJISToUTF8関数を修正しました。

string ConvertShiftJISToUTF8(const string& input) {
    string output;

    // iconv_t cd = iconv_open("UTF-8", "SHIFT_JISX0213");
    iconv_t cd = iconv_open("UTF-8", "CP932");
    if (cd == (iconv_t)-1) {
        std::cerr << "Error: Failed to open iconv" << std::endl;
        return output;
    }

    size_t inBytes = input.size();
    size_t outBytes = inBytes * 4;
    char* inBuf = const_cast<char*>(input.c_str());
    char* outBuf = new char[outBytes];
    char* outPtr = outBuf;

    while (iconv(cd, &inBuf, &inBytes, &outPtr, &outBytes) == (size_t)-1) {
        if (errno == EILSEQ) {
            std::cerr << "EILSEQ:入力バッファに無効なシーケンスが含まれている" << std::endl;
            inBuf += 1; // 無効なシーケンスの分だけ入力バッファを進める
            inBytes -= 1; // 無効なシーケンスの分だけ入力バッファのサイズを減らす

        } else if (errno == EINVAL) {
            std::cerr << "EINVAL:入力バッファの終端が不完全" << std::endl;
            delete[] outBuf;
            iconv_close(cd);

            return "";
        } else if (errno == E2BIG) {
            std::cerr << "E2BIG:出力バッファが不足している" << std::endl;
            delete[] outBuf;
            iconv_close(cd);

            return "";
        } else {
            std::cerr << "その他のエラー" << std::endl;
            delete[] outBuf;
            iconv_close(cd);

            return "";
        }
    }
    output.assign(outBuf, outPtr - outBuf);

    delete[] outBuf;
    iconv_close(cd);

    return output;
}

ChatGPTに有益なヒントをもらいましたが、例示するコードが実にいい加減で少し振り回されました。追及しても虚偽説明が積み上がっていくばかりで無意味なやりとりになります。ChatGPTはネット情報から引用するだけで、検証する能力は皆無ですね。まあそんなもんです。

datファイルがCP932ではなく他のシフトJISを採用している可能性も考えましたが、今回は当てはまりませんでした。

ちなみにCP932(Windows-31J)と他のシフトJISとの文字集合の関係は以下のオイラー図のようになります。CP932は黄色です。

User:Hissakun~commonswiki, CC 表示-継承 3.0, https://commons.wikimedia.org/w/index.php?curid=82138426による