HiveBrain v1.2.0
Get Started
← Back to all entries
patterncMinor

String trim functions with destination size limitation

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
destinationtrimwithsizelimitationfunctionsstring

Problem

3 string trimming functions:

Trim whitespace from the beginning of a string.

Trim whitespace from the end of a string.

Trim whitespace from both ends of a string.

Looking to improve code for:

-
Correctness (tested code - but so far no holes) - especially overlapping src/dest cases.

-
Design

-
Portability (3 tried: MS, *nix, embedded)

-
Efficiency

Note: (unsigned char) used as unless x==EOF, isspace(x) is not defined when x < 0.

/* String trim functions
 * 
 * Result is sized limited.
 * Overlapping source and destination is OK.
 * Pointer parameters are assumed to point to valid strings spaces.
 */

#include 
#include 
#include 

// Return string beginning with first non-white-space in string `src`
// Return NULL when destination is too small, `dest` unchanged.

char *trim_begin(char *dest, size_t dest_size, const char *src) {
  while (isspace((unsigned char) *src)) {
    src++;
  }
  size_t src_size = strlen(src) + 1;
  if (src_size > dest_size) {
    return NULL;
  }
  return memmove(dest, src, src_size);
}

// Return string beginning string `src` but not including any of its trailing 
//   white-spaces.
// Return NULL when destination is too small, `dest` unchanged.

char *trim_end(char *dest, size_t dest_size, const char *src) {
  size_t len = strlen(src);
  while (len > 0 && isspace((unsigned char) src[len - 1])) {
    len--;
  }
  size_t src_size = len + 1;
  if (src_size > dest_size) {
    return NULL;
  }
  memmove(dest, src, len);
  dest[len] = 0;
  return dest;
}

// Return string beginning with first non-white-space in string `src` but not 
//   including any of its trailing white-spaces.
// Return NULL when destination is too small, `dest` unchanged.

char *trim(char *dest, size_t dest_size, const char *src) {
  while (isspace((unsigned char) *src)) {
    src++;
  }
  return trim_end(dest, dest_size, src);
}

Solution

-
Repeated code

size_t src_size = strlen(src) + 1;
if (src_size > dest_size) {
  return NULL;
}
return memmove(dest, src, src_size);


is a good candidate for a function (safe_memmove or something similar).

  • Optimistic loops while (isspace((unsigned char) *src)) may never stop: '\0' is not a white space. Test for end of string explicitly:



while (*src && isspace((unsigned char) *src))


Red face above. I don't know what I was thinking.

-
Portability. A free-standing environment doesn't have to provide memmove or strlen or isspace. Only features confined in , , , , , , and are mandatory. I am afraid that to claim embedded portability you need to implement optional features yourself.

Sorry for nitpicking.

Code Snippets

size_t src_size = strlen(src) + 1;
if (src_size > dest_size) {
  return NULL;
}
return memmove(dest, src, src_size);
while (*src && isspace((unsigned char) *src))

Context

StackExchange Code Review Q#88818, answer score: 4

Revisions (0)

No revisions yet.