(root)/
gettext-0.22.4/
gettext-runtime/
gnulib-lib/
trim.c
       1  /* Removes leading and/or trailing whitespaces
       2     Copyright (C) 2006-2023 Free Software Foundation, Inc.
       3  
       4     This program is free software: you can redistribute it and/or modify
       5     it under the terms of the GNU General Public License as published by
       6     the Free Software Foundation, either version 3 of the License, or
       7     (at your option) any later version.
       8  
       9     This program is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12     GNU General Public License for more details.
      13  
      14     You should have received a copy of the GNU General Public License
      15     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      16  
      17  /* Written by Davide Angelocola <davide.angelocola@gmail.com> */
      18  
      19  #include <config.h>
      20  
      21  /* Specification.  */
      22  #include "trim.h"
      23  
      24  #include <ctype.h>
      25  #include <string.h>
      26  #include <stddef.h>
      27  #include <stdlib.h>
      28  
      29  #if GNULIB_MCEL_PREFER
      30  # include "mcel.h"
      31  #else
      32  # include "mbchar.h"
      33  # include "mbuiterf.h"
      34  #endif
      35  #include "xalloc.h"
      36  
      37  char *
      38  trim2 (const char *s, int how)
      39  {
      40    const char *start = s;
      41    const char *end;
      42  
      43    if (MB_CUR_MAX > 1)
      44      {
      45  #if GNULIB_MCEL_PREFER
      46        /* Skip leading whitespace. */
      47        if (how != TRIM_TRAILING)
      48          for (mcel_t g; *start; start += g.len)
      49            {
      50              g = mcel_scanz (start);
      51              if (!c32isspace (g.ch))
      52                break;
      53            }
      54  
      55        /* Find start of any trailing whitespace.  */
      56        if (how != TRIM_LEADING)
      57          for (const char *p = end = start; *p; )
      58            {
      59              mcel_t g = mcel_scanz (p);
      60              p += g.len;
      61              if (!c32isspace (g.ch))
      62                end = p;
      63            }
      64  #else
      65        mbuif_state_t state;
      66        mbuif_init (state);
      67  
      68        /* Skip leading whitespace. */
      69        if (how != TRIM_TRAILING)
      70          while (mbuif_avail (state, start))
      71            {
      72              mbchar_t cur = mbuif_next (state, start);
      73              if (!mb_isspace (cur))
      74                break;
      75              start += mb_len (cur);
      76            }
      77  
      78        /* Find start of any trailing whitespace.  */
      79        if (how != TRIM_LEADING)
      80          for (const char *p = end = start; mbuif_avail (state, p); )
      81            {
      82              mbchar_t cur = mbuif_next (state, p);
      83              p += mb_len (cur);
      84              if (!mb_isspace (cur))
      85                end = p;
      86            }
      87  #endif
      88      }
      89    else
      90      {
      91        /* Skip leading whitespace. */
      92        if (how != TRIM_TRAILING)
      93          while (isspace ((unsigned char) *start))
      94            start++;
      95  
      96        /* Find start of any trailing whitespace.  */
      97        if (how != TRIM_LEADING)
      98          for (const char *p = end = start; *p; )
      99            if (!isspace ((unsigned char) *p++))
     100              end = p;
     101      }
     102  
     103    /* Create trimmed copy.  */
     104    size_t dlen = how == TRIM_LEADING ? strlen (start) : end - start;
     105    char *d = malloc (dlen + 1);
     106    if (!d)
     107      xalloc_die ();
     108    char *d_end = mempcpy (d, start, dlen);
     109    *d_end = '\0';
     110  
     111    return d;
     112  }