text: // Copyright (C) 2020 T. Zachary Laine
  //
  // Distributed under the Boost Software License, Version 1.0. (See
  // accompanying file LICENSE_1_0.txt or copy at
  // http://www.boost.org/LICENSE_1_0.txt)
  
  // Warning! This file is autogenerated.
  #include <boost/text/grapheme_iterator.hpp>
  #include <boost/text/transcode_iterator.hpp>
  
  #include <gtest/gtest.h>
  
  #include <algorithm>
  
  
  
  TEST(grapheme, iterator_08_0_fwd)
  {
      // ÷ 11A8 ÷ 1100 ÷	
      // ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) ÷ [999.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3]
      {
          uint32_t const cps[] = { 0x11A8, 0x1100 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_0_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0x11A8, 0x1100 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
      }
  }
  TEST(grapheme, iterator_08_0_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0x11A8, 0x1100 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
      }
  }
  TEST(grapheme, iterator_08_0_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0x11A8, 0x1100 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_0_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0x11A8, 0x1100 };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 2),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 2, cps + 2),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(*it->end(), cps[1]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[1]);
  
          ++it;
  
          EXPECT_EQ(*it.base(), cps[1]);
          EXPECT_EQ(*it->begin(), cps[1]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[1]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[1]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[2]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_1_fwd)
  {
      // ÷ 11A8 × 0308 ÷ 1100 ÷	
      // ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3]
      {
          uint32_t const cps[] = { 0x11A8, 0x0308, 0x1100 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_1_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0x11A8, 0x0308, 0x1100 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_1_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0x11A8, 0x0308, 0x1100 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_1_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0x11A8, 0x0308, 0x1100 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_1_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0x11A8, 0x0308, 0x1100 };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 3),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 3, cps + 3),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(*it->end(), cps[2]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[2]);
  
          ++it;
  
          EXPECT_EQ(*it.base(), cps[2]);
          EXPECT_EQ(*it->begin(), cps[2]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[3]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[3]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_2_fwd)
  {
      // ÷ 11A8 ÷ 1160 ÷	
      // ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) ÷ [999.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3]
      {
          uint32_t const cps[] = { 0x11A8, 0x1160 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_2_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0x11A8, 0x1160 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
      }
  }
  TEST(grapheme, iterator_08_2_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0x11A8, 0x1160 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
      }
  }
  TEST(grapheme, iterator_08_2_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0x11A8, 0x1160 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_2_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0x11A8, 0x1160 };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 2),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 2, cps + 2),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(*it->end(), cps[1]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[1]);
  
          ++it;
  
          EXPECT_EQ(*it.base(), cps[1]);
          EXPECT_EQ(*it->begin(), cps[1]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[1]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[1]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[2]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_3_fwd)
  {
      // ÷ 11A8 × 0308 ÷ 1160 ÷	
      // ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3]
      {
          uint32_t const cps[] = { 0x11A8, 0x0308, 0x1160 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_3_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0x11A8, 0x0308, 0x1160 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_3_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0x11A8, 0x0308, 0x1160 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_3_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0x11A8, 0x0308, 0x1160 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_3_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0x11A8, 0x0308, 0x1160 };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 3),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 3, cps + 3),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(*it->end(), cps[2]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[2]);
  
          ++it;
  
          EXPECT_EQ(*it.base(), cps[2]);
          EXPECT_EQ(*it->begin(), cps[2]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[3]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[3]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_4_fwd)
  {
      // ÷ 11A8 × 11A8 ÷	
      // ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [8.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3]
      {
          uint32_t const cps[] = { 0x11A8, 0x11A8 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_4_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0x11A8, 0x11A8 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_4_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0x11A8, 0x11A8 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_4_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0x11A8, 0x11A8 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_4_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0x11A8, 0x11A8 };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 2),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 2, cps + 2),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[2]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_5_fwd)
  {
      // ÷ 11A8 × 0308 ÷ 11A8 ÷	
      // ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3]
      {
          uint32_t const cps[] = { 0x11A8, 0x0308, 0x11A8 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_5_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0x11A8, 0x0308, 0x11A8 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_5_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0x11A8, 0x0308, 0x11A8 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_5_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0x11A8, 0x0308, 0x11A8 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_5_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0x11A8, 0x0308, 0x11A8 };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 3),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 3, cps + 3),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(*it->end(), cps[2]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[2]);
  
          ++it;
  
          EXPECT_EQ(*it.base(), cps[2]);
          EXPECT_EQ(*it->begin(), cps[2]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[3]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[3]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_6_fwd)
  {
      // ÷ 11A8 ÷ AC00 ÷	
      // ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3]
      {
          uint32_t const cps[] = { 0x11A8, 0xAC00 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_6_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0x11A8, 0xAC00 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
      }
  }
  TEST(grapheme, iterator_08_6_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0x11A8, 0xAC00 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
      }
  }
  TEST(grapheme, iterator_08_6_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0x11A8, 0xAC00 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_6_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0x11A8, 0xAC00 };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 2),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 2, cps + 2),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(*it->end(), cps[1]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[1]);
  
          ++it;
  
          EXPECT_EQ(*it.base(), cps[1]);
          EXPECT_EQ(*it->begin(), cps[1]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[1]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[1]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[2]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_7_fwd)
  {
      // ÷ 11A8 × 0308 ÷ AC00 ÷	
      // ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3]
      {
          uint32_t const cps[] = { 0x11A8, 0x0308, 0xAC00 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_7_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0x11A8, 0x0308, 0xAC00 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_7_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0x11A8, 0x0308, 0xAC00 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_7_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0x11A8, 0x0308, 0xAC00 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_7_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0x11A8, 0x0308, 0xAC00 };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 3),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 3, cps + 3),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(*it->end(), cps[2]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[2]);
  
          ++it;
  
          EXPECT_EQ(*it.base(), cps[2]);
          EXPECT_EQ(*it->begin(), cps[2]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[3]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[3]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_8_fwd)
  {
      // ÷ 11A8 ÷ AC01 ÷	
      // ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3]
      {
          uint32_t const cps[] = { 0x11A8, 0xAC01 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_8_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0x11A8, 0xAC01 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
      }
  }
  TEST(grapheme, iterator_08_8_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0x11A8, 0xAC01 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
      }
  }
  TEST(grapheme, iterator_08_8_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0x11A8, 0xAC01 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_8_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0x11A8, 0xAC01 };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 2),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 2, cps + 2),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(*it->end(), cps[1]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[1]);
  
          ++it;
  
          EXPECT_EQ(*it.base(), cps[1]);
          EXPECT_EQ(*it->begin(), cps[1]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[1]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[1]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[2]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_9_fwd)
  {
      // ÷ 11A8 × 0308 ÷ AC01 ÷	
      // ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3]
      {
          uint32_t const cps[] = { 0x11A8, 0x0308, 0xAC01 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_9_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0x11A8, 0x0308, 0xAC01 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_9_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0x11A8, 0x0308, 0xAC01 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_9_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0x11A8, 0x0308, 0xAC01 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_9_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0x11A8, 0x0308, 0xAC01 };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 3),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 3, cps + 3),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(*it->end(), cps[2]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[2]);
  
          ++it;
  
          EXPECT_EQ(*it.base(), cps[2]);
          EXPECT_EQ(*it->begin(), cps[2]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[3]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[3]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_10_fwd)
  {
      // ÷ 11A8 ÷ 231A ÷	
      // ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) ÷ [999.0] WATCH (ExtPict) ÷ [0.3]
      {
          uint32_t const cps[] = { 0x11A8, 0x231A };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_10_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0x11A8, 0x231A };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
      }
  }
  TEST(grapheme, iterator_08_10_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0x11A8, 0x231A };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
      }
  }
  TEST(grapheme, iterator_08_10_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0x11A8, 0x231A };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_10_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0x11A8, 0x231A };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 2),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 2, cps + 2),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(*it->end(), cps[1]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[1]);
  
          ++it;
  
          EXPECT_EQ(*it.base(), cps[1]);
          EXPECT_EQ(*it->begin(), cps[1]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[1]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[1]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[2]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_11_fwd)
  {
      // ÷ 11A8 × 0308 ÷ 231A ÷	
      // ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] WATCH (ExtPict) ÷ [0.3]
      {
          uint32_t const cps[] = { 0x11A8, 0x0308, 0x231A };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_11_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0x11A8, 0x0308, 0x231A };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_11_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0x11A8, 0x0308, 0x231A };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_11_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0x11A8, 0x0308, 0x231A };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_11_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0x11A8, 0x0308, 0x231A };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 3),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 3, cps + 3),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(*it->end(), cps[2]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[2]);
  
          ++it;
  
          EXPECT_EQ(*it.base(), cps[2]);
          EXPECT_EQ(*it->begin(), cps[2]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[3]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[3]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_12_fwd)
  {
      // ÷ 11A8 × 0300 ÷	
      // ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3]
      {
          uint32_t const cps[] = { 0x11A8, 0x0300 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_12_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0x11A8, 0x0300 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_12_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0x11A8, 0x0300 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_12_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0x11A8, 0x0300 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_12_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0x11A8, 0x0300 };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 2),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 2, cps + 2),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[2]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_13_fwd)
  {
      // ÷ 11A8 × 0308 × 0300 ÷	
      // ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3]
      {
          uint32_t const cps[] = { 0x11A8, 0x0308, 0x0300 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_13_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0x11A8, 0x0308, 0x0300 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 3);
      }
  }
  TEST(grapheme, iterator_08_13_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0x11A8, 0x0308, 0x0300 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 3);
      }
  }
  TEST(grapheme, iterator_08_13_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0x11A8, 0x0308, 0x0300 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_13_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0x11A8, 0x0308, 0x0300 };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 3),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 3, cps + 3),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[3]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[3]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_14_fwd)
  {
      // ÷ 11A8 × 200D ÷	
      // ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3]
      {
          uint32_t const cps[] = { 0x11A8, 0x200D };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_14_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0x11A8, 0x200D };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_14_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0x11A8, 0x200D };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_14_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0x11A8, 0x200D };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_14_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0x11A8, 0x200D };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 2),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 2, cps + 2),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[2]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_15_fwd)
  {
      // ÷ 11A8 × 0308 × 200D ÷	
      // ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3]
      {
          uint32_t const cps[] = { 0x11A8, 0x0308, 0x200D };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_15_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0x11A8, 0x0308, 0x200D };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 3);
      }
  }
  TEST(grapheme, iterator_08_15_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0x11A8, 0x0308, 0x200D };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 3);
      }
  }
  TEST(grapheme, iterator_08_15_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0x11A8, 0x0308, 0x200D };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_15_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0x11A8, 0x0308, 0x200D };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 3),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 3, cps + 3),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[3]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[3]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_16_fwd)
  {
      // ÷ 11A8 ÷ 0378 ÷	
      // ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) ÷ [999.0] <reserved-0378> (Other) ÷ [0.3]
      {
          uint32_t const cps[] = { 0x11A8, 0x0378 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_16_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0x11A8, 0x0378 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
      }
  }
  TEST(grapheme, iterator_08_16_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0x11A8, 0x0378 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
      }
  }
  TEST(grapheme, iterator_08_16_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0x11A8, 0x0378 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_16_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0x11A8, 0x0378 };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 2),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 2, cps + 2),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(*it->end(), cps[1]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[1]);
  
          ++it;
  
          EXPECT_EQ(*it.base(), cps[1]);
          EXPECT_EQ(*it->begin(), cps[1]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[1]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[1]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[2]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_17_fwd)
  {
      // ÷ 11A8 × 0308 ÷ 0378 ÷	
      // ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] <reserved-0378> (Other) ÷ [0.3]
      {
          uint32_t const cps[] = { 0x11A8, 0x0308, 0x0378 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_17_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0x11A8, 0x0308, 0x0378 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_17_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0x11A8, 0x0308, 0x0378 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_17_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0x11A8, 0x0308, 0x0378 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_17_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0x11A8, 0x0308, 0x0378 };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 3),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 3, cps + 3),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(*it->end(), cps[2]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[2]);
  
          ++it;
  
          EXPECT_EQ(*it.base(), cps[2]);
          EXPECT_EQ(*it->begin(), cps[2]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[3]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[3]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_18_fwd)
  {
      // ÷ 11A8 ÷ D800 ÷	
      // ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) ÷ [5.0] <surrogate-D800> (Control) ÷ [0.3]
      {
          uint32_t const cps[] = { 0x11A8, 0xD800 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_18_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0x11A8, 0xD800 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
      }
  }
  TEST(grapheme, iterator_08_18_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0x11A8, 0xD800 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
      }
  }
  TEST(grapheme, iterator_08_18_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0x11A8, 0xD800 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  // Skipping from-utf8 test due to presence of surrogate code point.
  
  TEST(grapheme, iterator_08_19_fwd)
  {
      // ÷ 11A8 × 0308 ÷ D800 ÷	
      // ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] <surrogate-D800> (Control) ÷ [0.3]
      {
          uint32_t const cps[] = { 0x11A8, 0x0308, 0xD800 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_19_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0x11A8, 0x0308, 0xD800 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_19_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0x11A8, 0x0308, 0xD800 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_19_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0x11A8, 0x0308, 0xD800 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  // Skipping from-utf8 test due to presence of surrogate code point.
  
  TEST(grapheme, iterator_08_20_fwd)
  {
      // ÷ AC00 ÷ 0020 ÷	
      // ÷ [0.2] HANGUL SYLLABLE GA (LV) ÷ [999.0] SPACE (Other) ÷ [0.3]
      {
          uint32_t const cps[] = { 0xAC00, 0x0020 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_20_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0xAC00, 0x0020 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
      }
  }
  TEST(grapheme, iterator_08_20_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0xAC00, 0x0020 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
      }
  }
  TEST(grapheme, iterator_08_20_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0xAC00, 0x0020 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_20_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0xAC00, 0x0020 };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 2),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 2, cps + 2),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(*it->end(), cps[1]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[1]);
  
          ++it;
  
          EXPECT_EQ(*it.base(), cps[1]);
          EXPECT_EQ(*it->begin(), cps[1]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[1]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[1]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[2]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_21_fwd)
  {
      // ÷ AC00 × 0308 ÷ 0020 ÷	
      // ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] SPACE (Other) ÷ [0.3]
      {
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x0020 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_21_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x0020 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_21_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x0020 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_21_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x0020 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_21_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x0020 };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 3),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 3, cps + 3),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(*it->end(), cps[2]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[2]);
  
          ++it;
  
          EXPECT_EQ(*it.base(), cps[2]);
          EXPECT_EQ(*it->begin(), cps[2]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[3]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[3]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_22_fwd)
  {
      // ÷ AC00 ÷ 000D ÷	
      // ÷ [0.2] HANGUL SYLLABLE GA (LV) ÷ [5.0] <CARRIAGE RETURN (CR)> (CR) ÷ [0.3]
      {
          uint32_t const cps[] = { 0xAC00, 0x000D };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_22_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0xAC00, 0x000D };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
      }
  }
  TEST(grapheme, iterator_08_22_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0xAC00, 0x000D };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
      }
  }
  TEST(grapheme, iterator_08_22_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0xAC00, 0x000D };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_22_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0xAC00, 0x000D };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 2),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 2, cps + 2),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(*it->end(), cps[1]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[1]);
  
          ++it;
  
          EXPECT_EQ(*it.base(), cps[1]);
          EXPECT_EQ(*it->begin(), cps[1]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[1]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[1]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[2]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_23_fwd)
  {
      // ÷ AC00 × 0308 ÷ 000D ÷	
      // ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] <CARRIAGE RETURN (CR)> (CR) ÷ [0.3]
      {
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x000D };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_23_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x000D };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_23_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x000D };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_23_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x000D };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_23_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x000D };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 3),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 3, cps + 3),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(*it->end(), cps[2]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[2]);
  
          ++it;
  
          EXPECT_EQ(*it.base(), cps[2]);
          EXPECT_EQ(*it->begin(), cps[2]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[3]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[3]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_24_fwd)
  {
      // ÷ AC00 ÷ 000A ÷	
      // ÷ [0.2] HANGUL SYLLABLE GA (LV) ÷ [5.0] <LINE FEED (LF)> (LF) ÷ [0.3]
      {
          uint32_t const cps[] = { 0xAC00, 0x000A };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_24_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0xAC00, 0x000A };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
      }
  }
  TEST(grapheme, iterator_08_24_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0xAC00, 0x000A };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
      }
  }
  TEST(grapheme, iterator_08_24_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0xAC00, 0x000A };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_24_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0xAC00, 0x000A };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 2),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 2, cps + 2),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(*it->end(), cps[1]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[1]);
  
          ++it;
  
          EXPECT_EQ(*it.base(), cps[1]);
          EXPECT_EQ(*it->begin(), cps[1]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[1]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[1]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[2]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_25_fwd)
  {
      // ÷ AC00 × 0308 ÷ 000A ÷	
      // ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] <LINE FEED (LF)> (LF) ÷ [0.3]
      {
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x000A };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_25_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x000A };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_25_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x000A };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_25_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x000A };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_25_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x000A };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 3),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 3, cps + 3),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(*it->end(), cps[2]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[2]);
  
          ++it;
  
          EXPECT_EQ(*it.base(), cps[2]);
          EXPECT_EQ(*it->begin(), cps[2]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[3]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[3]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_26_fwd)
  {
      // ÷ AC00 ÷ 0001 ÷	
      // ÷ [0.2] HANGUL SYLLABLE GA (LV) ÷ [5.0] <START OF HEADING> (Control) ÷ [0.3]
      {
          uint32_t const cps[] = { 0xAC00, 0x0001 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_26_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0xAC00, 0x0001 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
      }
  }
  TEST(grapheme, iterator_08_26_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0xAC00, 0x0001 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
      }
  }
  TEST(grapheme, iterator_08_26_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0xAC00, 0x0001 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_26_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0xAC00, 0x0001 };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 2),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 2, cps + 2),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(*it->end(), cps[1]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[1]);
  
          ++it;
  
          EXPECT_EQ(*it.base(), cps[1]);
          EXPECT_EQ(*it->begin(), cps[1]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[1]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[1]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[2]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_27_fwd)
  {
      // ÷ AC00 × 0308 ÷ 0001 ÷	
      // ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] <START OF HEADING> (Control) ÷ [0.3]
      {
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x0001 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_27_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x0001 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_27_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x0001 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_27_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x0001 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_27_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x0001 };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 3),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 3, cps + 3),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(*it->end(), cps[2]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[2]);
  
          ++it;
  
          EXPECT_EQ(*it.base(), cps[2]);
          EXPECT_EQ(*it->begin(), cps[2]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[3]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[3]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_28_fwd)
  {
      // ÷ AC00 × 034F ÷	
      // ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING GRAPHEME JOINER (Extend) ÷ [0.3]
      {
          uint32_t const cps[] = { 0xAC00, 0x034F };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_28_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0xAC00, 0x034F };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_28_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0xAC00, 0x034F };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_28_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0xAC00, 0x034F };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_28_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0xAC00, 0x034F };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 2),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 2, cps + 2),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[2]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_29_fwd)
  {
      // ÷ AC00 × 0308 × 034F ÷	
      // ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAPHEME JOINER (Extend) ÷ [0.3]
      {
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x034F };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_29_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x034F };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 3);
      }
  }
  TEST(grapheme, iterator_08_29_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x034F };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 3);
      }
  }
  TEST(grapheme, iterator_08_29_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x034F };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_29_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x034F };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 3),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 3, cps + 3),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[3]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[3]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_30_fwd)
  {
      // ÷ AC00 ÷ 1F1E6 ÷	
      // ÷ [0.2] HANGUL SYLLABLE GA (LV) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3]
      {
          uint32_t const cps[] = { 0xAC00, 0x1F1E6 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_30_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0xAC00, 0x1F1E6 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
      }
  }
  TEST(grapheme, iterator_08_30_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0xAC00, 0x1F1E6 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
      }
  }
  TEST(grapheme, iterator_08_30_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0xAC00, 0x1F1E6 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_30_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0xAC00, 0x1F1E6 };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 2),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 2, cps + 2),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(*it->end(), cps[1]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[1]);
  
          ++it;
  
          EXPECT_EQ(*it.base(), cps[1]);
          EXPECT_EQ(*it->begin(), cps[1]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[1]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[1]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[2]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_31_fwd)
  {
      // ÷ AC00 × 0308 ÷ 1F1E6 ÷	
      // ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3]
      {
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x1F1E6 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_31_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x1F1E6 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_31_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x1F1E6 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_31_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x1F1E6 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_31_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x1F1E6 };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 3),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 3, cps + 3),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(*it->end(), cps[2]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[2]);
  
          ++it;
  
          EXPECT_EQ(*it.base(), cps[2]);
          EXPECT_EQ(*it->begin(), cps[2]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[3]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[3]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_32_fwd)
  {
      // ÷ AC00 ÷ 0600 ÷	
      // ÷ [0.2] HANGUL SYLLABLE GA (LV) ÷ [999.0] ARABIC NUMBER SIGN (Prepend) ÷ [0.3]
      {
          uint32_t const cps[] = { 0xAC00, 0x0600 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_32_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0xAC00, 0x0600 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
      }
  }
  TEST(grapheme, iterator_08_32_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0xAC00, 0x0600 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
      }
  }
  TEST(grapheme, iterator_08_32_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0xAC00, 0x0600 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_32_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0xAC00, 0x0600 };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 2),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 2, cps + 2),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(*it->end(), cps[1]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[1]);
  
          ++it;
  
          EXPECT_EQ(*it.base(), cps[1]);
          EXPECT_EQ(*it->begin(), cps[1]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[1]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[1]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[2]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_33_fwd)
  {
      // ÷ AC00 × 0308 ÷ 0600 ÷	
      // ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] ARABIC NUMBER SIGN (Prepend) ÷ [0.3]
      {
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x0600 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_33_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x0600 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_33_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x0600 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_33_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x0600 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_33_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x0600 };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 3),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 3, cps + 3),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(*it->end(), cps[2]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[2]);
  
          ++it;
  
          EXPECT_EQ(*it.base(), cps[2]);
          EXPECT_EQ(*it->begin(), cps[2]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[3]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[3]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_34_fwd)
  {
      // ÷ AC00 × 0903 ÷	
      // ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.1] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [0.3]
      {
          uint32_t const cps[] = { 0xAC00, 0x0903 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_34_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0xAC00, 0x0903 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_34_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0xAC00, 0x0903 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_34_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0xAC00, 0x0903 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_34_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0xAC00, 0x0903 };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 2),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 2, cps + 2),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[2]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_35_fwd)
  {
      // ÷ AC00 × 0308 × 0903 ÷	
      // ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.1] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [0.3]
      {
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x0903 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_35_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x0903 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 3);
      }
  }
  TEST(grapheme, iterator_08_35_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x0903 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 3);
      }
  }
  TEST(grapheme, iterator_08_35_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x0903 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_35_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x0903 };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 3),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 3, cps + 3),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[3]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[3]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_36_fwd)
  {
      // ÷ AC00 ÷ 1100 ÷	
      // ÷ [0.2] HANGUL SYLLABLE GA (LV) ÷ [999.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3]
      {
          uint32_t const cps[] = { 0xAC00, 0x1100 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_36_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0xAC00, 0x1100 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
      }
  }
  TEST(grapheme, iterator_08_36_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0xAC00, 0x1100 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
      }
  }
  TEST(grapheme, iterator_08_36_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0xAC00, 0x1100 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_36_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0xAC00, 0x1100 };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 2),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 2, cps + 2),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(*it->end(), cps[1]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[1]);
  
          ++it;
  
          EXPECT_EQ(*it.base(), cps[1]);
          EXPECT_EQ(*it->begin(), cps[1]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[1]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[1]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[2]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_37_fwd)
  {
      // ÷ AC00 × 0308 ÷ 1100 ÷	
      // ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3]
      {
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x1100 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_37_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x1100 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_37_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x1100 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_37_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x1100 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_37_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x1100 };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 3),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 3, cps + 3),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(*it->end(), cps[2]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[2]);
  
          ++it;
  
          EXPECT_EQ(*it.base(), cps[2]);
          EXPECT_EQ(*it->begin(), cps[2]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[3]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[3]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_38_fwd)
  {
      // ÷ AC00 × 1160 ÷	
      // ÷ [0.2] HANGUL SYLLABLE GA (LV) × [7.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3]
      {
          uint32_t const cps[] = { 0xAC00, 0x1160 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_38_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0xAC00, 0x1160 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_38_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0xAC00, 0x1160 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_38_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0xAC00, 0x1160 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_38_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0xAC00, 0x1160 };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 2),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 2, cps + 2),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[2]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_39_fwd)
  {
      // ÷ AC00 × 0308 ÷ 1160 ÷	
      // ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3]
      {
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x1160 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_39_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x1160 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_39_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x1160 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_39_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x1160 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_39_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x1160 };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 3),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 3, cps + 3),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(*it->end(), cps[2]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[2]);
  
          ++it;
  
          EXPECT_EQ(*it.base(), cps[2]);
          EXPECT_EQ(*it->begin(), cps[2]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[3]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[3]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_40_fwd)
  {
      // ÷ AC00 × 11A8 ÷	
      // ÷ [0.2] HANGUL SYLLABLE GA (LV) × [7.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3]
      {
          uint32_t const cps[] = { 0xAC00, 0x11A8 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_40_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0xAC00, 0x11A8 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_40_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0xAC00, 0x11A8 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_40_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0xAC00, 0x11A8 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_40_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0xAC00, 0x11A8 };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 2),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 2, cps + 2),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[2]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_41_fwd)
  {
      // ÷ AC00 × 0308 ÷ 11A8 ÷	
      // ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3]
      {
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x11A8 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_41_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x11A8 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_41_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x11A8 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_41_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x11A8 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_41_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x11A8 };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 3),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 3, cps + 3),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(*it->end(), cps[2]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[2]);
  
          ++it;
  
          EXPECT_EQ(*it.base(), cps[2]);
          EXPECT_EQ(*it->begin(), cps[2]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[3]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[3]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_42_fwd)
  {
      // ÷ AC00 ÷ AC00 ÷	
      // ÷ [0.2] HANGUL SYLLABLE GA (LV) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3]
      {
          uint32_t const cps[] = { 0xAC00, 0xAC00 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_42_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0xAC00, 0xAC00 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
      }
  }
  TEST(grapheme, iterator_08_42_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0xAC00, 0xAC00 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
      }
  }
  TEST(grapheme, iterator_08_42_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0xAC00, 0xAC00 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_42_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0xAC00, 0xAC00 };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 2),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 2, cps + 2),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(*it->end(), cps[1]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[1]);
  
          ++it;
  
          EXPECT_EQ(*it.base(), cps[1]);
          EXPECT_EQ(*it->begin(), cps[1]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[1]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[1]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[2]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_43_fwd)
  {
      // ÷ AC00 × 0308 ÷ AC00 ÷	
      // ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3]
      {
          uint32_t const cps[] = { 0xAC00, 0x0308, 0xAC00 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_43_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0xAC00, 0x0308, 0xAC00 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_43_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0xAC00, 0x0308, 0xAC00 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_43_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0xAC00, 0x0308, 0xAC00 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_43_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0xAC00, 0x0308, 0xAC00 };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 3),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 3, cps + 3),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(*it->end(), cps[2]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[2]);
  
          ++it;
  
          EXPECT_EQ(*it.base(), cps[2]);
          EXPECT_EQ(*it->begin(), cps[2]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[3]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[3]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_44_fwd)
  {
      // ÷ AC00 ÷ AC01 ÷	
      // ÷ [0.2] HANGUL SYLLABLE GA (LV) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3]
      {
          uint32_t const cps[] = { 0xAC00, 0xAC01 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_44_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0xAC00, 0xAC01 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
      }
  }
  TEST(grapheme, iterator_08_44_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0xAC00, 0xAC01 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
      }
  }
  TEST(grapheme, iterator_08_44_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0xAC00, 0xAC01 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_44_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0xAC00, 0xAC01 };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 2),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 2, cps + 2),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(*it->end(), cps[1]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[1]);
  
          ++it;
  
          EXPECT_EQ(*it.base(), cps[1]);
          EXPECT_EQ(*it->begin(), cps[1]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[1]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[1]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[2]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_45_fwd)
  {
      // ÷ AC00 × 0308 ÷ AC01 ÷	
      // ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3]
      {
          uint32_t const cps[] = { 0xAC00, 0x0308, 0xAC01 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_45_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0xAC00, 0x0308, 0xAC01 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_45_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0xAC00, 0x0308, 0xAC01 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_45_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0xAC00, 0x0308, 0xAC01 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_45_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0xAC00, 0x0308, 0xAC01 };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 3),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 3, cps + 3),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(*it->end(), cps[2]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[2]);
  
          ++it;
  
          EXPECT_EQ(*it.base(), cps[2]);
          EXPECT_EQ(*it->begin(), cps[2]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[3]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[3]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_46_fwd)
  {
      // ÷ AC00 ÷ 231A ÷	
      // ÷ [0.2] HANGUL SYLLABLE GA (LV) ÷ [999.0] WATCH (ExtPict) ÷ [0.3]
      {
          uint32_t const cps[] = { 0xAC00, 0x231A };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_46_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0xAC00, 0x231A };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
      }
  }
  TEST(grapheme, iterator_08_46_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0xAC00, 0x231A };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
      }
  }
  TEST(grapheme, iterator_08_46_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0xAC00, 0x231A };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 1);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 1);
          EXPECT_EQ((*it).begin(), cps + 1);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_46_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0xAC00, 0x231A };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 2),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 2, cps + 2),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(*it->end(), cps[1]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[1]);
  
          ++it;
  
          EXPECT_EQ(*it.base(), cps[1]);
          EXPECT_EQ(*it->begin(), cps[1]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[1]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[1]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[2]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_47_fwd)
  {
      // ÷ AC00 × 0308 ÷ 231A ÷	
      // ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] WATCH (ExtPict) ÷ [0.3]
      {
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x231A };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_47_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x231A };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_47_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x231A };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_47_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x231A };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), cps + 2);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_47_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x231A };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 3),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 3, cps + 3),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(*it->end(), cps[2]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[2]);
  
          ++it;
  
          EXPECT_EQ(*it.base(), cps[2]);
          EXPECT_EQ(*it->begin(), cps[2]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[3]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[3]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_48_fwd)
  {
      // ÷ AC00 × 0300 ÷	
      // ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3]
      {
          uint32_t const cps[] = { 0xAC00, 0x0300 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_48_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0xAC00, 0x0300 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_48_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0xAC00, 0x0300 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
      }
  }
  TEST(grapheme, iterator_08_48_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0xAC00, 0x0300 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 2, cps + 2);
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 2);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 2);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_48_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0xAC00, 0x0300 };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 2),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 2, cps + 2),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[2]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[2]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  TEST(grapheme, iterator_08_49_fwd)
  {
      // ÷ AC00 × 0308 × 0300 ÷	
      // ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3]
      {
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x0300 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_49_rev)
  {
      {
          // reverse
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x0300 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 3);
      }
  }
  TEST(grapheme, iterator_08_49_fab)
  {
      {
          // forth and back
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x0300 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 3);
      }
  }
  TEST(grapheme, iterator_08_49_baf)
  {
      {
          // back and forth
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x0300 };
          boost::text::grapheme_iterator<uint32_t const *> it(cps, cps + 3, cps + 3);
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
  
          --it;
  
          EXPECT_EQ(it.base(), cps + 0);
          EXPECT_EQ((*it).begin(), cps + 0);
          EXPECT_EQ((*it).end(), cps + 3);
  
          ++it;
  
          EXPECT_EQ(it.base(), cps + 3);
          EXPECT_EQ((*it).begin(), (*it).end());
      }
  }
  TEST(grapheme, iterator_08_49_utf8)
  {
      {
          // from UTF8
          uint32_t const cps[] = { 0xAC00, 0x0308, 0x0300 };
          char cus[1024] = { 0 };
          int cp_indices[1024] = { 0 };
  
          std::copy(
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps, cps + 3),
              boost::text::utf_32_to_8_iterator<uint32_t const *>(cps, cps + 3, cps + 3),
              cus);
  
          boost::text::null_sentinel sentinel;
          int * index_it = cp_indices;
          for (boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel> it(cus, cus, boost::text::null_sentinel{}); ; ++it) {
              *index_it++ = it.base() - cus;
              if (it == sentinel)
                  break;
          }
  
          using iter_t = boost::text::utf_8_to_32_iterator<char const *, boost::text::null_sentinel>;
          boost::text::grapheme_iterator<iter_t, boost::text::null_sentinel> it(
              iter_t{cus, cus, boost::text::null_sentinel{}}, iter_t{cus, cus, boost::text::null_sentinel{}}, sentinel);
  
          EXPECT_EQ(*it.base(), cps[0]);
          EXPECT_EQ(*it->begin(), cps[0]);
          EXPECT_EQ(it.base().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->begin().base(), cus + cp_indices[0]);
          EXPECT_EQ(it->end().base(), cus + cp_indices[3]);
  
          ++it;
  
          EXPECT_EQ(it.base().base(), cus + cp_indices[3]);
          EXPECT_EQ(it->begin(), (*it).end());
      }
  }
  
  