@@ -121,10 +121,17 @@ namespace sysstr
121121            SYS_STRING_FORCE_INLINE
122122            constexpr  void  operator ()(char32_t  value) noexcept (noexcept (sink(utf_char_of<To>())))
123123            {
124-                 utf_codepoint_encoder<To, false > encoder;
125-                 encoder.put (value);
126-                 for (auto  first = encoder.begin (), last = encoder.end (); first != last; ++first)
127-                     sink (*first);
124+                 if  constexpr  (To != utf32)
125+                 {
126+                     utf_codepoint_encoder<To, false > encoder;
127+                     encoder.put (value);
128+                     for (auto  first = encoder.begin (), last = encoder.end (); first != last; ++first)
129+                         sink (*first);
130+                 }
131+                 else  
132+                 {
133+                     sink (value);
134+                 }
128135            }
129136        };
130137        // Moronic GCC refuses to accept deduction guide not on namespace level
@@ -135,28 +142,6 @@ namespace sysstr
135142            { return  writer<Sink>(sink); }
136143    };
137144
138-     template <>
139-     struct  utf32_output <utf32>
140-     {
141-         template <class  Sink >
142-         struct  writer 
143-         {
144-             Sink sink;
145- 
146-             writer (Sink s) : sink(s) {}
147-             
148-             constexpr  void  operator ()(char32_t  value) noexcept (noexcept (sink(value)))
149-             {
150-                 sink (value);
151-             }
152-         };
153-         // Moronic GCC refuses to accept deduction guide not on namespace level
154-         // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79501
155-         // template<class Sink> writer(Sink sink) -> writer<Sink>;
156-         template <class  Sink > static  auto  make_writer (Sink sink) -> writer<Sink>
157-             { return  writer<Sink>(sink); }
158-     };
159- 
160145    template <utf_encoding From, utf_encoding To>
161146    template <std::ranges::forward_range Range, class  Func >
162147    SYS_STRING_FORCE_INLINE
@@ -167,141 +152,126 @@ namespace sysstr
167152    }
168153
169154
170-     // MARK:- UTF-16
171- 
172-     template <>
155+     template <utf_encoding From>
173156    template <std::forward_iterator It, std::sentinel_for<It> EndIt>
174157    SYS_STRING_FORCE_INLINE
175-     char32_t  utf32_input<utf16 >::read(It & first, EndIt last) noexcept (noexcept (reading(first,last)))
158+     char32_t  utf32_input<From >::read(It & first, EndIt last) noexcept (noexcept (reading(first,last)))
176159    {
177-         utf_codepoint_decoder<utf16> decoder;
160+         if  constexpr  (From == utf8) 
161+         {
162+             uint8_t  byte = uint8_t (*first);
163+             ++first;
164+             if  (byte <= 0x7f )
165+                 return  char32_t {byte};
178166
179-         decoder. put ( uint16_t (*first)) ;
180-         ++first ;
181-         if  (decoder.done () )
182-             return  char32_t {decoder. value () };
167+             utf_codepoint_decoder<utf8>  decoder;
168+             decoder. put (byte) ;
169+              if  (decoder.error () || first == last )
170+                  return  char32_t {U ' \uFFFD ' 
183171
184-         if  (decoder.error () || first == last)
185-             return  char32_t {U' \uFFFD ' 
172+             for  ( ; ; )
173+             {
174+                 byte = uint8_t (*first);
175+                 decoder.put (byte);
176+                 if  (decoder.error ())
177+                     return  char32_t {U' \uFFFD ' 
178+                 ++first;
179+                 if  (decoder.done ())
180+                     return  char32_t {decoder.value ()};
181+                 if  (first == last)
182+                     return  char32_t {U' \uFFFD ' 
183+             }
184+         }
185+         else  if  constexpr  (From == utf16) 
186+         {
187+             utf_codepoint_decoder<utf16> decoder;
186188
187-         decoder.put (uint16_t (*first));
188-         if  (!decoder. done ()) 
189-             return   char32_t {U ' \uFFFD ' }; 
190-         ++first ;
189+              decoder.put (uint16_t (*first));
190+             ++first; 
191+             if  (decoder. done ()) 
192+                  return   char32_t {decoder. value ()} ;
191193
192-         return   char32_t { decoder.value ()}; 
193-     } 
194+              if  ( decoder.error () || first == last) 
195+                  return   char32_t {U ' \uFFFD ' }; 
194196
195-     template <>
196-     template <std::forward_iterator It, std::sentinel_for<It> EndIt>
197-     SYS_STRING_FORCE_INLINE
198-     char32_t  utf32_input<utf16>::read_reversed(It & first, EndIt last) noexcept (noexcept (reading(first, last)))
199-     {
200-         utf_reverse_codepoint_decoder<utf16> decoder;
197+             decoder.put (uint16_t (*first));
198+             if  (!decoder.done ())
199+                 return  char32_t {U' \uFFFD ' 
200+             ++first;
201201
202-         decoder.put (uint16_t (*first));
203-         ++first;
204-         if  (decoder.done ())
205202            return  char32_t {decoder.value ()};
203+         } 
204+         else  if  constexpr  (From == utf32)
205+         {
206+             utf_codepoint_decoder<utf32> decoder;
207+             bool  res = decoder.put (uint32_t (*first));
208+             ++first;
209+             return  res ? char32_t {decoder.value ()} : U' \uFFFD ' 
210+         }
206211
207-         if  (decoder.error () || first == last)
208-             return  char32_t {U' \uFFFD ' 
209- 
210-         decoder.put (uint16_t (*first));
211-         if  (!decoder.done ())
212-             return  char32_t {U' \uFFFD ' 
213-         ++first;
214212
215-         return  char32_t {decoder.value ()};
216213    }
217214
218-     // MARK:- UTF-8
219- 
220-     template <>
215+     template <utf_encoding From>
221216    template <std::forward_iterator It, std::sentinel_for<It> EndIt>
222217    SYS_STRING_FORCE_INLINE
223-     char32_t  utf32_input<utf8 >::read (It & first, EndIt last) noexcept (noexcept (reading(first, last)))
218+     char32_t  utf32_input<From >::read_reversed (It & first, EndIt last) noexcept (noexcept (reading(first, last)))
224219    {
225-         uint8_t  byte = uint8_t (*first);
226-         ++first;
227-         if  (byte <= 0x7f )
228-             return  char32_t {byte};
229- 
230-         utf_codepoint_decoder<utf8> decoder;
231-         decoder.put (byte);
232-         if  (decoder.error () || first == last)
233-             return  char32_t {U' \uFFFD ' 
234- 
235-         for  ( ; ; )
220+         if  constexpr  (From == utf8)
236221        {
237-             byte = uint8_t (*first);
238-             decoder.put (byte);
239-             if  (decoder.error ())
240-                 return  char32_t {U' \uFFFD ' 
222+             uint8_t  byte = uint8_t (*first);
241223            ++first;
242-             if  (decoder.done ())
243-                 return  char32_t {decoder.value ()};
244-             if  (first == last)
224+             if  (byte <= 0x7f )
225+                 return  char32_t {byte};
226+             
227+             utf_reverse_codepoint_decoder<utf8> decoder;
228+             decoder.put (byte);
229+             if  (decoder.error () || first == last)
245230                return  char32_t {U' \uFFFD ' 
246-         }
247-     }
248- 
249-     template <>
250-     template <std::forward_iterator It, std::sentinel_for<It> EndIt>
251-     SYS_STRING_FORCE_INLINE
252-     char32_t  utf32_input<utf8>::read_reversed(It & first, EndIt last) noexcept (noexcept (reading(first, last)))
253-     {
254-         uint8_t  byte = uint8_t (*first);
255-         ++first;
256-         if  (byte <= 0x7f )
257-             return  char32_t {byte};
258-         
259-         utf_reverse_codepoint_decoder<utf8> decoder;
260-         decoder.put (byte);
261-         if  (decoder.error () || first == last)
262-             return  char32_t {U' \uFFFD ' 
263231
264-         It rewind_point = first;
265-         for  ( ; ; )
232+             It rewind_point = first;
233+             for  ( ; ; )
234+             {
235+                 byte = uint8_t (*first);
236+                 ++first;
237+                 decoder.put (byte);
238+ 
239+                 if  (decoder.done ())
240+                     return  char32_t {decoder.value ()};
241+                 
242+                 if  (decoder.error ())
243+                 { 
244+                     first = std::move (rewind_point);
245+                     return  char32_t {U' \uFFFD ' 
246+                 }
247+                 
248+                 if  (first == last)
249+                     return  char32_t {u' \uFFFD ' 
250+             }
251+         }
252+         else  if  constexpr  (From == utf16)
266253        {
267-             byte = uint8_t (*first);
268-             ++first;
269-             decoder.put (byte);
254+             utf_reverse_codepoint_decoder<utf16> decoder;
270255
256+             decoder.put (uint16_t (*first));
257+             ++first;
271258            if  (decoder.done ())
272259                return  char32_t {decoder.value ()};
273-             
274-             if  (decoder.error ())
275-             { 
276-                 first = std::move (rewind_point);
277-                 return  char32_t {U' \uFFFD ' 
278-             }
279-             
280-             if  (first == last)
281-                 return  char32_t {u' \uFFFD ' 
282-         }
283-     }
284260
285-     // MARK:- UTF-32
261+             if  (decoder.error () || first == last)
262+                 return  char32_t {U' \uFFFD ' 
286263
287-     
288-     template <>
289-     template <std::forward_iterator It, std::sentinel_for<It> EndIt>
290-     SYS_STRING_FORCE_INLINE
291-     char32_t  utf32_input<utf32>::read(It & first, EndIt last) noexcept (noexcept (reading(first, last)))
292-     {
293-         utf_codepoint_decoder<utf32> decoder;
294-         bool  res = decoder.put (uint32_t (*first));
295-         ++first;
296-         return  res ? char32_t {decoder.value ()} : U' \uFFFD ' 
297-     }
264+             decoder.put (uint16_t (*first));
265+             if  (!decoder.done ())
266+                 return  char32_t {U' \uFFFD ' 
267+             ++first;
298268
299-     template <> 
300-     template <std::forward_iterator It, std::sentinel_for<It> EndIt> 
301-     SYS_STRING_FORCE_INLINE 
302-     char32_t  utf32_input<utf32>::read_reversed(It & first, EndIt last)  noexcept ( noexcept (reading(first, last))) 
303-     { 
304-         return   utf32_input::read (first, last); 
269+              return   char32_t {decoder. value ()}; 
270+         } 
271+          else   if   constexpr  (From == utf32) 
272+         { 
273+              return   utf32_input::read (first, last); 
274+         } 
305275    }
306276}
307277
0 commit comments