J
John Kelly
/*
Define author
John Kelly, August 20, 2010
Define copyright
Copyright John Kelly, 2010. All rights reserved.
Define license
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this work except in compliance with the License.
You may obtain a copy of the License at:
http://www.apache.org/licenses/LICENSE-2.0
Define symbols and (words)
exam ......... temporary char *
hast ......... temporary char * to alpha !isspace
keep ......... temporary char * to omega !isspace
strlen ....... string length
trimlen ...... trimmed string length
ts ........... temporary string
tu ........... temporary size_t
xu ........... fail safe size_t
Define ideas
Trim leading and trailing whitespace from any null terminated string
found in memory, no matter whether data or garbage. Reports failure
and quits if null terminator not found within system defined limit.
Parameters
char * to string
NULL, or size_t * for trimlen result
On success returns 0
On failure returns -1 and after setting errno to one of
EINVAL
EOVERFLOW
*/
# if __STDC_VERSION__ >= 199901L
# include <stdint.h>
# endif
# include <stddef.h>
# include <stdlib.h>
# include <limits.h>
# include <ctype.h>
# include <errno.h>
# include <stdio.h>
# include <string.h>
# include <malloc.h>
# ifndef SIZE_MAX
# define SIZE_MAX ((size_t)-1)
# endif
ptrdiff_t
ptrdiff_max_ (void)
{
ptrdiff_t last, next;
for (last = 32767; (next = 2 * (double) last + 1) > last {
last = next;
}
return last;
}
static int
trim (char *const ts, size_t *trimlen)
{
size_t tu;
unsigned char *exam;
unsigned char *hast;
unsigned char *keep;
# ifdef PTRDIFF_MAX
ptrdiff_t const ptrdiff_max = PTRDIFF_MAX;
# else
ptrdiff_t const ptrdiff_max = ptrdiff_max_ ();
# endif
size_t const xu = ptrdiff_max < SIZE_MAX ? ptrdiff_max : SIZE_MAX;
if (!ts) {
errno = EINVAL;
return -1;
}
tu = 0;
exam = (unsigned char *) ts;
while (++tu < xu && isspace (*exam)) {
++exam;
}
if (tu == xu) {
errno = EOVERFLOW;
return -1;
}
tu = 0;
hast = keep = exam;
while (++tu < xu && *exam) {
if (!isspace (*exam)) {
keep = exam;
}
++exam;
}
if (tu == xu) {
errno = EOVERFLOW;
return -1;
}
if (*keep) {
*++keep = '\0';
}
tu = keep - hast;
if (hast != (unsigned char *) ts) {
(void) memmove (ts, hast, tu + 1);
}
if (trimlen) {
*trimlen = tu;
}
return 0;
}
/*
Test code courtesy c.l.c contributors
*/
static char s0[] = " I need trimming on both ends. ";
static char s1[] = "I need trimming on far end. ";
static char s2[] = " I need trimming on near end.";
static char s3[] = " I need more trimming on both ends. ";
static char s4[] = "\n\t\rI need special trimming on both ends.\n\t\r";
static char s5[] = " \n\t\r I need special trimming on near end.";
static char s6[] = "I need special trimming on far end. \n\t\r ";
static char s7[] = "I need no trimming";
static char s8[] = " ";
static char s9[] = "";
static char *strings[12] = {
s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, NULL,
};
# define CHUNK 100000
int
main (void)
{
int i;
char *cp;
size_t length;
for (i = 0; i < 11; i++) {
printf ("Original string:[%s]\n", strings);
trim (strings, &length);
printf ("Trimmed string:[%s]\n", strings);
puts ("---------------------------------------");
}
/* insanity tests */
printf ("trim returned: %i\n", trim (NULL, NULL));
printf ("trim returned: %i\n", trim (NULL, &length));
cp = malloc (CHUNK);
if (cp) {
memset (cp, 'x', CHUNK);
memset (cp + CHUNK - 3, ' ', 1);
memset (cp + CHUNK - 2, ' ', 1);
memset (cp + CHUNK - 1, '\0', 1);
} else {
printf ("malloc failed\n");
return (1);
}
printf ("Original big string length %u\n", strlen (cp));
printf ("trim returned: %i\n", trim (cp, &length));
printf ("New string length %u\n", strlen (cp));
printf ("Double check length returned %u\n", length);
free (cp);
printf ("trim returned %i on a freed block!\n", trim (cp, &length));
printf ("The length returned was %d\n", length);
puts ("\nSUCCESS testing trim function");
return 0;
}
Define author
John Kelly, August 20, 2010
Define copyright
Copyright John Kelly, 2010. All rights reserved.
Define license
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this work except in compliance with the License.
You may obtain a copy of the License at:
http://www.apache.org/licenses/LICENSE-2.0
Define symbols and (words)
exam ......... temporary char *
hast ......... temporary char * to alpha !isspace
keep ......... temporary char * to omega !isspace
strlen ....... string length
trimlen ...... trimmed string length
ts ........... temporary string
tu ........... temporary size_t
xu ........... fail safe size_t
Define ideas
Trim leading and trailing whitespace from any null terminated string
found in memory, no matter whether data or garbage. Reports failure
and quits if null terminator not found within system defined limit.
Parameters
char * to string
NULL, or size_t * for trimlen result
On success returns 0
On failure returns -1 and after setting errno to one of
EINVAL
EOVERFLOW
*/
# if __STDC_VERSION__ >= 199901L
# include <stdint.h>
# endif
# include <stddef.h>
# include <stdlib.h>
# include <limits.h>
# include <ctype.h>
# include <errno.h>
# include <stdio.h>
# include <string.h>
# include <malloc.h>
# ifndef SIZE_MAX
# define SIZE_MAX ((size_t)-1)
# endif
ptrdiff_t
ptrdiff_max_ (void)
{
ptrdiff_t last, next;
for (last = 32767; (next = 2 * (double) last + 1) > last {
last = next;
}
return last;
}
static int
trim (char *const ts, size_t *trimlen)
{
size_t tu;
unsigned char *exam;
unsigned char *hast;
unsigned char *keep;
# ifdef PTRDIFF_MAX
ptrdiff_t const ptrdiff_max = PTRDIFF_MAX;
# else
ptrdiff_t const ptrdiff_max = ptrdiff_max_ ();
# endif
size_t const xu = ptrdiff_max < SIZE_MAX ? ptrdiff_max : SIZE_MAX;
if (!ts) {
errno = EINVAL;
return -1;
}
tu = 0;
exam = (unsigned char *) ts;
while (++tu < xu && isspace (*exam)) {
++exam;
}
if (tu == xu) {
errno = EOVERFLOW;
return -1;
}
tu = 0;
hast = keep = exam;
while (++tu < xu && *exam) {
if (!isspace (*exam)) {
keep = exam;
}
++exam;
}
if (tu == xu) {
errno = EOVERFLOW;
return -1;
}
if (*keep) {
*++keep = '\0';
}
tu = keep - hast;
if (hast != (unsigned char *) ts) {
(void) memmove (ts, hast, tu + 1);
}
if (trimlen) {
*trimlen = tu;
}
return 0;
}
/*
Test code courtesy c.l.c contributors
*/
static char s0[] = " I need trimming on both ends. ";
static char s1[] = "I need trimming on far end. ";
static char s2[] = " I need trimming on near end.";
static char s3[] = " I need more trimming on both ends. ";
static char s4[] = "\n\t\rI need special trimming on both ends.\n\t\r";
static char s5[] = " \n\t\r I need special trimming on near end.";
static char s6[] = "I need special trimming on far end. \n\t\r ";
static char s7[] = "I need no trimming";
static char s8[] = " ";
static char s9[] = "";
static char *strings[12] = {
s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, NULL,
};
# define CHUNK 100000
int
main (void)
{
int i;
char *cp;
size_t length;
for (i = 0; i < 11; i++) {
printf ("Original string:[%s]\n", strings);
trim (strings, &length);
printf ("Trimmed string:[%s]\n", strings);
puts ("---------------------------------------");
}
/* insanity tests */
printf ("trim returned: %i\n", trim (NULL, NULL));
printf ("trim returned: %i\n", trim (NULL, &length));
cp = malloc (CHUNK);
if (cp) {
memset (cp, 'x', CHUNK);
memset (cp + CHUNK - 3, ' ', 1);
memset (cp + CHUNK - 2, ' ', 1);
memset (cp + CHUNK - 1, '\0', 1);
} else {
printf ("malloc failed\n");
return (1);
}
printf ("Original big string length %u\n", strlen (cp));
printf ("trim returned: %i\n", trim (cp, &length));
printf ("New string length %u\n", strlen (cp));
printf ("Double check length returned %u\n", length);
free (cp);
printf ("trim returned %i on a freed block!\n", trim (cp, &length));
printf ("The length returned was %d\n", length);
puts ("\nSUCCESS testing trim function");
return 0;
}