Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 08:40:26

0001 #ifndef BOOST_PARSER_DETAIL_CASE_FOLD_HPP
0002 #define BOOST_PARSER_DETAIL_CASE_FOLD_HPP
0003 
0004 #include <boost/parser/config.hpp>
0005 #include <boost/parser/detail/text/transcode_iterator.hpp>
0006 #include <boost/parser/detail/case_fold_data_generated.hpp>
0007 
0008 #include <algorithm>
0009 
0010 
0011 namespace boost::parser::detail {
0012 
0013     template<typename I>
0014     std::optional<I> do_short_mapping(
0015         short_mapping_range const * first,
0016         short_mapping_range const * last,
0017         char32_t cp,
0018         I out)
0019     {
0020         auto it = std::lower_bound(
0021             first,
0022             last,
0023             cp,
0024             [](short_mapping_range const & range, char32_t cp) {
0025                 return range.cp_first_ < cp;
0026             });
0027         if (it != first) {
0028             auto const prev = it - 1;
0029             if (prev->cp_first_ <= cp && cp < prev->cp_last_)
0030                 it = prev;
0031         }
0032         if (it != last && it->cp_first_ <= cp && cp < it->cp_last_) {
0033             auto const offset = cp - it->cp_first_;
0034             if (offset % it->stride_ == 0) {
0035                 *out++ =
0036                     single_mapping_cps[it->first_idx_ + offset / it->stride_];
0037                 return out;
0038             }
0039         }
0040 
0041         return std::nullopt;
0042     }
0043 
0044     template<typename I>
0045     I case_fold(char32_t cp, I out)
0046     {
0047         // One-byte fast path.
0048         if (cp < 0x100) {
0049             // ASCII letter fast path.
0050             if (0x41 <= cp && cp < 0x5a) {
0051                 *out++ = cp + 0x20;
0052                 return out;
0053             } else if (cp == 0x00DF) {
0054                 // The lone multi-mapping below 0x100.
0055                 *out++ = 0x0073;
0056                 *out++ = 0x0073;
0057                 return out;
0058             } else {
0059                 // Skip [0x41, 0x5a), handled above.
0060                 auto const first = text::detail::begin(mapping_ranges) + 1;
0061                 // 7th entry starts with 0x100.
0062                 auto const last = text::detail::begin(mapping_ranges) + 7;
0063                 if (auto out_opt = do_short_mapping(first, last, cp, out))
0064                     return *out_opt;
0065             }
0066             *out++ = cp;
0067             return out;
0068         }
0069 
0070         // Single-cp-mapping path (next most common case).
0071         {
0072             auto const first = text::detail::begin(mapping_ranges);
0073             auto const last = text::detail::end(mapping_ranges);
0074             if (auto out_opt = do_short_mapping(first, last, cp, out))
0075                 return *out_opt;
0076         }
0077 
0078         // Multi-cp mapping path.
0079         {
0080             auto const last = detail::text::detail::end(long_mappings);
0081             auto const it = std::lower_bound(
0082                 detail::text::detail::begin(long_mappings),
0083                 last,
0084                 cp,
0085                 [](long_mapping const & mapping, char32_t cp) {
0086                     return mapping.cp_ < cp;
0087                 });
0088             if (it != last && it->cp_ == cp) {
0089 #if BOOST_PARSER_USE_CONCEPTS
0090                 return std::ranges::copy(it->mapping_, text::null_sentinel, out)
0091                     .out;
0092 #else
0093                 return std::copy(
0094                     it->mapping_,
0095                     std::find(
0096                         text::detail::begin(it->mapping_),
0097                         text::detail::end(it->mapping_),
0098                         0),
0099                     out);
0100 #endif
0101             }
0102         }
0103 
0104         *out++ = cp;
0105         return out;
0106     }
0107 }
0108 
0109 #endif