root/maint/gnulib/lib/unistr/u8-prev.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. u8_prev

   1 /* Iterate over previous character in UTF-8 string.
   2    Copyright (C) 2002, 2006-2007, 2009-2021 Free Software Foundation, Inc.
   3    Written by Bruno Haible <bruno@clisp.org>, 2002.
   4 
   5    This file is free software: you can redistribute it and/or modify
   6    it under the terms of the GNU Lesser General Public License as
   7    published by the Free Software Foundation; either version 2.1 of the
   8    License, or (at your option) any later version.
   9 
  10    This file is distributed in the hope that it will be useful,
  11    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13    GNU Lesser General Public License for more details.
  14 
  15    You should have received a copy of the GNU Lesser General Public License
  16    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
  17 
  18 #include <config.h>
  19 
  20 /* Specification.  */
  21 #include "unistr.h"
  22 
  23 const uint8_t *
  24 u8_prev (ucs4_t *puc, const uint8_t *s, const uint8_t *start)
     /* [previous][next][first][last][top][bottom][index][help] */
  25 {
  26   /* Keep in sync with unistr.h and u8-mbtouc-aux.c.  */
  27   if (s != start)
  28     {
  29       uint8_t c_1 = s[-1];
  30 
  31       if (c_1 < 0x80)
  32         {
  33           *puc = c_1;
  34           return s - 1;
  35         }
  36       if ((c_1 ^ 0x80) < 0x40)
  37         if (s - 1 != start)
  38           {
  39             uint8_t c_2 = s[-2];
  40 
  41             if (c_2 >= 0xc2 && c_2 < 0xe0)
  42               {
  43                 *puc = ((unsigned int) (c_2 & 0x1f) << 6)
  44                        | (unsigned int) (c_1 ^ 0x80);
  45                 return s - 2;
  46               }
  47             if ((c_2 ^ 0x80) < 0x40)
  48               if (s - 2 != start)
  49                 {
  50                   uint8_t c_3 = s[-3];
  51 
  52                   if (c_3 >= 0xe0 && c_3 < 0xf0
  53                       && (c_3 >= 0xe1 || c_2 >= 0xa0)
  54                       && (c_3 != 0xed || c_2 < 0xa0))
  55                     {
  56                       *puc = ((unsigned int) (c_3 & 0x0f) << 12)
  57                              | ((unsigned int) (c_2 ^ 0x80) << 6)
  58                              | (unsigned int) (c_1 ^ 0x80);
  59                       return s - 3;
  60                     }
  61                   if ((c_3 ^ 0x80) < 0x40)
  62                     if (s - 3 != start)
  63                       {
  64                         uint8_t c_4 = s[-4];
  65 
  66                         if (c_4 >= 0xf0 && c_4 < 0xf8
  67                             && (c_4 >= 0xf1 || c_3 >= 0x90)
  68                             && (c_4 < 0xf4 || (c_4 == 0xf4 && c_3 < 0x90)))
  69                           {
  70                             *puc = ((unsigned int) (c_4 & 0x07) << 18)
  71                                    | ((unsigned int) (c_3 ^ 0x80) << 12)
  72                                    | ((unsigned int) (c_2 ^ 0x80) << 6)
  73                                    | (unsigned int) (c_1 ^ 0x80);
  74                             return s - 4;
  75                           }
  76                       }
  77                 }
  78           }
  79     }
  80   return NULL;
  81 }

/* [previous][next][first][last][top][bottom][index][help] */