ぬの部屋(仮)
nu-no-he-ya
  • 1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
     123456
    78910111213
    14151617181920
    21222324252627
    28      
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
    1234567
    891011121314
    15161718192021
    22232425262728
           
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
         12
    3456789
    10111213141516
    17181920212223
    242526272829 
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
        123
    45678910
    11121314151617
    18192021222324
    25262728   
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    15161718192021
    293031    
           
         12
    3456789
    10111213141516
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728     
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
          1
    2345678
    9101112131415
    16171819202122
    232425262728 
           
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
  • icuライブラリで書記素を扱うラッパーを作ってみた

    GTextの使用例

    #include <iostream>
    
    // 自作ラッパー
    #include "GraphemeText.hpp"
    
    #pragma warning(disable:4996)
    
    int main()
    {
      // 文字列の定義
      GText gtext(u"aあغ山👨‍👧經经");
    
      gtext.insert(0, u"غ");
    
      FILE* fp = fopen("C:\\test\\test.txt", "wb");
    
      for (size_t i = 0; i < gtext.length(); i++) {
    
        wchar_t c[100]{ 0 };
        int len = gtext[i].size();
        
        // 一文字書き込み
        memcpy(c, gtext[i].ptr(), len);
        fwrite(c, 1, len, fp);
      }
    
      fclose(fp);
    
    }
    

    GraphemeText.hpp

    #pragma once
    
    // 以下のdllを要求される
    // icudt69.dll
    // icuuc69.dll
    
    
    //! @brief 書記素クラス
    class Grapheme {
      void* _UnicodeString;
      int _index;
      int _length;
      enum UScriptCode _script;
      bool _emoji;
    public:
    
      Grapheme(void* _UnicodeString_, int _index_, int _length_);
      ~Grapheme() {}
    
      const char16_t* ptr()const;
    
      //! @brief この書記素の元の文字列上のindexを取得。
      int index()const { return _index; }
    
      //! @brief この書記素のchar16_tとしての文字数。
      int length()const {return _length;}
    
      //! @brief この書記素のバイト数。
      int size()const { return _length * 2; }
    
      //! @brief この文字の用字の種類
      enum UScriptCode script()const { return _script; }
    
      //! @brief これが絵文字かどうか
      bool isEmoji()const { return _emoji; }
    };

    ///////////////////////////////////
    //! @brief 書記素の配列オブジェクト class GText { struct GText_Impl* _impl; public: GText(const char16_t* text); GText(const GText& src); ~GText(); const Grapheme& operator[](const size_t index)const; //! @brief この文字列の書記素数 size_t length()const; //! @brief 書記素を一つ置き換える //! @attention Graphemeリストを更新するのでこれまでのGraphemeは使えなくなる void replace(const size_t index, const char16_t c); void replace(const size_t index, const char16_t* c); void erase(const size_t index); void insert(const size_t index, const char16_t c); void insert(const size_t index, const char16_t* c); const char16_t* ptr()const; //! @brief この文字列のバイト数 int size()const; };

    GraphemeText.cpp

    #include<vector>
    #include <string>
    
    #include <unicode/ucnv.h>
    #include <unicode/brkiter.h>
    #include <unicode/utypes.h>
    #include <unicode/uscript.h>
    
    #include "GraphemeText.hpp"
    
    
    // 要リンク
    #pragma comment(lib, "icuuc.lib")
    #pragma comment(lib, "icudt.lib")
    
    // 書記素クラス
    Grapheme::Grapheme(void* _UnicodeString_, int _index_, int _length_) :
      _UnicodeString(_UnicodeString_),
      _index(_index_),
      _length(_length_)
    {
    
      icu::UnicodeString* p = (icu::UnicodeString*)_UnicodeString;
    
      UErrorCode err;
    
      UChar32 c32 = p->char32At(_index);
    
      // スクリプト
      _script = uscript_getScript(c32, &err);
    
      _emoji = false;
      // 絵文字かどうかのフラグをセット
    
      _emoji |= (bool)u_getIntPropertyValue(c32, UCHAR_EMOJI);
      _emoji |= (bool)u_getIntPropertyValue(c32, UCHAR_EMOJI_PRESENTATION);
      _emoji |= (bool)u_getIntPropertyValue(c32, UCHAR_EMOJI_MODIFIER);
      _emoji |= (bool)u_getIntPropertyValue(c32, UCHAR_EMOJI_MODIFIER_BASE);
      _emoji |= (bool)u_getIntPropertyValue(c32, UCHAR_EMOJI_COMPONENT);
    
    
    }
    
    
    const char16_t* Grapheme::ptr()const {
      return static_cast<icu::UnicodeString*>(_UnicodeString)->getBuffer() + _index;
    }
    
    
    
    // Graphemeの配列を作成
    void
    makeGraphemeList(std::vector< Grapheme >& glist, icu::UnicodeString& text) { UErrorCode err; icu::BreakIterator* bi = icu::BreakIterator::createCharacterInstance( icu::Locale::getDefault(), err); if (bi == nullptr) throw "bi is NULL"; bi->setText(text); int32_t current = bi->first(); while (current != icu::BreakIterator::DONE) { int32_t prev = current; current = bi->next(); if (current == UBRK_DONE) { break; } int32_t count = current - prev;//文字の長さ //書記素保存 glist.emplace_back(&text, prev, count); } delete bi; }
    
          
    struct GText_Impl {
      std::vector< Grapheme > glist;
      icu::UnicodeString utext;
    };
    
    GText::GText(const char16_t* text) {
      _impl = new GText_Impl;
    
      _impl->utext = text;
    
      makeGraphemeList(_impl->glist, _impl->utext);
    }
    
    const char16_t* GText::ptr()const {
      return _impl->utext.getBuffer();
    }
    
    
    GText::GText(const GText& src) {
      _impl->utext = src._impl->utext;
    
      _impl->glist.clear();
    
      makeGraphemeList(_impl->glist, _impl->utext);
    
    }
    
    GText::~GText() {
      delete _impl;
    }
    
    const Grapheme& GText::operator[](const size_t index)const {
      return _impl->glist[index];
    }
    
    size_t GText::length()const {
      return _impl->glist.size();
    }
    int GText::size()const {
      return _impl->utext.length() * 2;
    }
    
    void GText::replace(const size_t index, const char16_t c) {
    
      if (index >= _impl->glist.size())
        throw "GText replace index is too big";
    
      _impl->utext.replace(_impl->glist[index].index(), _impl->glist[index].length(), c);
      _impl->glist.clear();
      makeGraphemeList(_impl->glist, _impl->utext);
    
    
    }
    
    void GText::replace(const size_t index, const char16_t* c) {
      if (index >= _impl->glist.size())
        throw "GText replace index is too big";
    
      size_t len = std::char_traits<char16_t>::length(c);
    
      _impl->utext.replace(_impl->glist[index].index(), _impl->glist[index].length(),c, len);
      _impl->glist.clear();
      makeGraphemeList(_impl->glist, _impl->utext);
    
    }
    
    
    void GText::erase(const size_t index) {
      if (index >= _impl->glist.size())
        throw "GText erase index is too big";
    
      _impl->utext.remove(_impl->glist[index].index(), _impl->glist[index].length());
    
      _impl->glist.clear();
      makeGraphemeList(_impl->glist, _impl->utext);
    }
    
    void GText::insert(const size_t index, const char16_t c) {
      if (index >= _impl->glist.size())
        throw "GText insert index is too big";
    
      _impl->utext.insert(_impl->glist[index].index(), c);
    
      _impl->glist.clear();
      makeGraphemeList(_impl->glist, _impl->utext);
    
    }
    
    void GText::insert(const size_t index, const char16_t* c) {
      if (index >= _impl->glist.size())
        throw "GText insert index is too big";
    
      size_t len = std::char_traits<char16_t>::length(c);
    
      _impl->utext.insert(_impl->glist[index].index(), c, len);
      _impl->glist.clear();
      makeGraphemeList(_impl->glist, _impl->utext);
    
    }