+2023-08-26 Paul Eggert <eggert@cs.ucla.edu>
+
+ trim: do not over-allocate result
+ * lib/trim.c: Include mbuiterf.h, not mbiterf.h, since we no
+ longer compute strlen at first.
+ (trim2): Do not over-allocate result and then trim the parts we
+ don’t want. Instead, skip unwanted input before allocating,
+ so that the result is just the right size. Use mempcpy
+ instead of memmove. Simplify.
+ * modules/trim (Depends-on): Remove mbiterf, memmove, strdup, xalloc.
+ Add mbuiterf, mempcpy, xalloc-die.
+
2023-08-26 Paul Eggert <eggert@cs.ucla.edu>
propername: tune single-byte code
#include <stdlib.h>
#include "mbchar.h"
-#include "mbiterf.h"
+#include "mbuiterf.h"
#include "xalloc.h"
char *
trim2 (const char *s, int how)
{
- char *d;
-
- d = strdup (s);
-
- if (!d)
- xalloc_die ();
+ const char *start = s;
+ const char *end;
if (MB_CUR_MAX > 1)
{
- /* Trim leading whitespaces. */
- if (how != TRIM_TRAILING)
- {
- const char *d_end = d + strlen (d);
- mbif_state_t state;
- char *iter;
- for (mbif_init (state), iter = d; mbif_avail (state, iter, d_end); )
- {
- mbchar_t cur = mbif_next (state, iter, d_end);
+ mbuif_state_t state;
+ mbuif_init (state);
- if (!mb_isspace (cur))
- break;
-
- iter += mb_len (cur);
- }
-
- memmove (d, iter, strlen (iter) + 1);
- }
-
- /* Trim trailing whitespaces. */
+ /* Skip leading whitespace. */
+ if (how != TRIM_TRAILING)
+ while (mbuif_avail (state, start))
+ {
+ mbchar_t cur = mbuif_next (state, start);
+ if (!mb_isspace (cur))
+ break;
+ start += mb_len (cur);
+ }
+
+ /* Find start of any trailing whitespace. */
if (how != TRIM_LEADING)
- {
- char *start_of_spaces = NULL;
-
- const char *d_end = d + strlen (d);
- mbif_state_t state;
- char *iter;
- for (mbif_init (state), iter = d; mbif_avail (state, iter, d_end); )
- {
- mbchar_t cur = mbif_next (state, iter, d_end);
-
- if (mb_isspace (cur))
- {
- if (start_of_spaces == NULL)
- start_of_spaces = iter;
- }
- else
- start_of_spaces = NULL;
-
- iter += mb_len (cur);
- }
-
- if (start_of_spaces != NULL)
- *start_of_spaces = '\0';
- }
+ for (const char *p = end = start; mbuif_avail (state, p); )
+ {
+ mbchar_t cur = mbuif_next (state, p);
+ p += mb_len (cur);
+ if (!mb_isspace (cur))
+ end = p;
+ }
}
else
{
- char *p;
-
- /* Trim leading whitespaces. */
+ /* Skip leading whitespace. */
if (how != TRIM_TRAILING)
- {
- for (p = d; *p && isspace ((unsigned char) *p); p++)
- ;
+ while (isspace ((unsigned char) *start))
+ start++;
- memmove (d, p, strlen (p) + 1);
- }
-
- /* Trim trailing whitespaces. */
+ /* Find start of any trailing whitespace. */
if (how != TRIM_LEADING)
- {
- for (p = d + strlen (d) - 1;
- p >= d && isspace ((unsigned char) *p); p--)
- *p = '\0';
- }
+ for (const char *p = end = start; *p; )
+ if (!isspace ((unsigned char) *p++))
+ end = p;
}
+ /* Create trimmed copy. */
+ size_t dlen = how == TRIM_LEADING ? strlen (start) : end - start;
+ char *d = malloc (dlen + 1);
+ if (!d)
+ xalloc_die ();
+ char *d_end = mempcpy (d, start, dlen);
+ *d_end = '\0';
+
return d;
}