1 /* stringhelp.c - standard string helper functions
2 * Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005,
3 * 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
5 * This file is part of JNLIB.
7 * JNLIB is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 3 of
10 * the License, or (at your option) any later version.
12 * JNLIB is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this program; if not, see <http://www.gnu.org/licenses/>.
27 #ifdef HAVE_W32_SYSTEM
31 #include "libjnlib-config.h"
33 #include "stringhelp.h"
36 #define tohex_lower(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'a'))
38 /* Sometimes we want to avoid mixing slashes and backslashes on W32
39 and prefer backslashes. There is usual no problem with mixing
40 them, however a very few W32 API calls can't grok plain slashes.
41 Printing filenames with mixed slashes also looks a bit strange.
42 This function has no effext on POSIX. */
44 change_slashes (char *name
)
46 #ifdef HAVE_DRIVE_LETTERS
49 if (strchr (name
, '\\'))
55 #endif /*HAVE_DRIVE_LETTERS*/
61 * Look for the substring SUB in buffer and return a pointer to that
62 * substring in BUFFER or NULL if not found.
63 * Comparison is case-insensitive.
66 memistr (const void *buffer
, size_t buflen
, const char *sub
)
68 const unsigned char *buf
= buffer
;
69 const unsigned char *t
= (const unsigned char *)buffer
;
70 const unsigned char *s
= (const unsigned char *)sub
;
73 for ( ; n
; t
++, n
-- )
75 if ( toupper (*t
) == toupper (*s
) )
77 for ( buf
=t
++, buflen
= n
--, s
++;
78 n
&& toupper (*t
) == toupper (*s
); t
++, s
++, n
-- )
81 return (const char*)buf
;
83 s
= (const unsigned char *)sub
;
91 ascii_memistr ( const void *buffer
, size_t buflen
, const char *sub
)
93 const unsigned char *buf
= buffer
;
94 const unsigned char *t
= (const unsigned char *)buf
;
95 const unsigned char *s
= (const unsigned char *)sub
;
98 for ( ; n
; t
++, n
-- )
100 if (ascii_toupper (*t
) == ascii_toupper (*s
) )
102 for ( buf
=t
++, buflen
= n
--, s
++;
103 n
&& ascii_toupper (*t
) == ascii_toupper (*s
); t
++, s
++, n
-- )
106 return (const char*)buf
;
107 t
= (const unsigned char *)buf
;
108 s
= (const unsigned char *)sub
;
115 /* This function is similar to strncpy(). However it won't copy more
116 than N - 1 characters and makes sure that a '\0' is appended. With
117 N given as 0, nothing will happen. With DEST given as NULL, memory
118 will be allocated using jnlib_xmalloc (i.e. if it runs out of core
119 the function terminates). Returns DES or a pointer to the
123 mem2str( char *dest
, const void *src
, size_t n
)
130 dest
= jnlib_xmalloc( n
) ;
133 for(n
--; n
&& *s
; n
-- )
143 * remove leading and trailing white spaces
146 trim_spaces( char *str
)
148 char *string
, *p
, *mark
;
151 /* find first non space character */
152 for( p
=string
; *p
&& isspace( *(byte
*)p
) ; p
++ )
154 /* move characters */
155 for( (mark
= NULL
); (*string
= *p
); string
++, p
++ )
156 if( isspace( *(byte
*)p
) ) {
163 *mark
= '\0' ; /* remove trailing spaces */
169 * remove trailing white spaces
172 trim_trailing_spaces( char *string
)
176 for( mark
= NULL
, p
= string
; *p
; p
++ ) {
177 if( isspace( *(byte
*)p
) ) {
192 trim_trailing_chars( byte
*line
, unsigned len
, const char *trimchars
)
197 for(mark
=NULL
, p
=line
, n
=0; n
< len
; n
++, p
++ ) {
198 if( strchr(trimchars
, *p
) ) {
214 * remove trailing white spaces and return the length of the buffer
217 trim_trailing_ws( byte
*line
, unsigned len
)
219 return trim_trailing_chars( line
, len
, " \t\r\n" );
223 length_sans_trailing_chars (const unsigned char *line
, size_t len
,
224 const char *trimchars
)
226 const unsigned char *p
, *mark
;
229 for( mark
=NULL
, p
=line
, n
=0; n
< len
; n
++, p
++ )
231 if (strchr (trimchars
, *p
))
246 * Return the length of line ignoring trailing white-space.
249 length_sans_trailing_ws (const unsigned char *line
, size_t len
)
251 return length_sans_trailing_chars (line
, len
, " \t\r\n");
257 * Extract from a given path the filename component. This function
258 * terminates the process on memory shortage.
261 make_basename(const char *filepath
, const char *inputpath
)
264 return riscos_make_basename(filepath
, inputpath
);
268 (void)inputpath
; /* Only required for riscos. */
270 if ( !(p
=strrchr(filepath
, '/')) )
271 #ifdef HAVE_DRIVE_LETTERS
272 if ( !(p
=strrchr(filepath
, '\\')) )
273 if ( !(p
=strrchr(filepath
, ':')) )
276 return jnlib_xstrdup(filepath
);
279 return jnlib_xstrdup(p
+1);
286 * Extract from a given filename the path prepended to it. If there
287 * isn't a path prepended to the filename, a dot is returned ('.').
288 * This function terminates the process on memory shortage.
291 make_dirname(const char *filepath
)
297 if ( !(p
=strrchr(filepath
, '/')) )
298 #ifdef HAVE_DRIVE_LETTERS
299 if ( !(p
=strrchr(filepath
, '\\')) )
300 if ( !(p
=strrchr(filepath
, ':')) )
303 return jnlib_xstrdup(".");
306 dirname_length
= p
-filepath
;
307 dirname
= jnlib_xmalloc(dirname_length
+1);
308 strncpy(dirname
, filepath
, dirname_length
);
309 dirname
[dirname_length
] = 0;
316 /* Implementation of make_filename and make_filename_try. We need to
317 use macros here to avoid the use of the sometimes problematic
318 va_copy function which is not available on all systems. */
319 #define MAKE_FILENAME_PART1 \
323 char *name, *home, *p; \
325 va_start (arg_ptr, first_part); \
326 n = strlen (first_part) + 1; \
327 while ( (s = va_arg (arg_ptr, const char *)) ) \
328 n += strlen(s) + 1; \
332 if ( *first_part == '~' && first_part[1] == '/' \
333 && (home = getenv("HOME")) && *home ) \
336 #define MAKE_FILENAME_PART2 \
338 ? stpcpy (stpcpy (name,home), first_part + 1)\
339 : stpcpy(name, first_part)); \
341 va_start (arg_ptr, first_part); \
342 while ( (s = va_arg(arg_ptr, const char *)) ) \
343 p = stpcpy (stpcpy (p,"/"), s); \
345 return change_slashes (name);
348 /* Construct a filename from the NULL terminated list of parts. Tilde
349 expansion is done here. This function terminates the process on
352 make_filename (const char *first_part
, ... )
355 name
= jnlib_xmalloc (n
);
359 /* Construct a filename from the NULL terminated list of parts. Tilde
360 expansion is done here. This function may return NULL on error. */
362 make_filename_try (const char *first_part
, ... )
365 name
= jnlib_malloc (n
);
370 #undef MAKE_FILENAME_PART1
371 #undef MAKE_FILENAME_PART2
375 /* Compare whether the filenames are identical. This is a
376 special version of strcmp() taking the semantics of filenames in
377 account. Note that this function works only on the supplied names
378 without considereing any context like the current directory. See
379 also same_file_p(). */
381 compare_filenames (const char *a
, const char *b
)
383 #ifdef HAVE_DRIVE_LETTERS
384 for ( ; *a
&& *b
; a
++, b
++ )
387 && (toupper (*(const unsigned char*)a
)
388 != toupper (*(const unsigned char*)b
) )
389 && !((*a
== '/' && *b
== '\\') || (*a
== '\\' && *b
== '/')))
392 if ((*a
== '/' && *b
== '\\') || (*a
== '\\' && *b
== '/'))
395 return (toupper (*(const unsigned char*)a
)
396 - toupper (*(const unsigned char*)b
));
403 /* Convert 2 hex characters at S to a byte value. Return this value
404 or -1 if there is an error. */
406 hextobyte (const char *s
)
410 if ( *s
>= '0' && *s
<= '9' )
412 else if ( *s
>= 'A' && *s
<= 'F' )
413 c
= 16 * (10 + *s
- 'A');
414 else if ( *s
>= 'a' && *s
<= 'f' )
415 c
= 16 * (10 + *s
- 'a');
419 if ( *s
>= '0' && *s
<= '9' )
421 else if ( *s
>= 'A' && *s
<= 'F' )
423 else if ( *s
>= 'a' && *s
<= 'f' )
431 /* Print a BUFFER to stream FP while replacing all control characters
432 and the characters DELIM and DELIM2 with standard C escape
433 sequences. Returns the number of characters printed. */
435 print_sanitized_buffer2 (FILE *fp
, const void *buffer
, size_t length
,
436 int delim
, int delim2
)
438 const unsigned char *p
= buffer
;
441 for (; length
; length
--, p
++, count
++)
447 || ((delim
|| delim2
) && *p
=='\\'))
483 fprintf (fp
, "x%02x", *p
);
497 /* Same as print_sanitized_buffer2 but with just one delimiter. */
499 print_sanitized_buffer (FILE *fp
, const void *buffer
, size_t length
,
502 return print_sanitized_buffer2 (fp
, buffer
, length
, delim
, 0);
507 print_sanitized_utf8_buffer (FILE *fp
, const void *buffer
,
508 size_t length
, int delim
)
510 const char *p
= buffer
;
513 /* We can handle plain ascii simpler, so check for it first. */
514 for (i
=0; i
< length
; i
++ )
521 char *buf
= utf8_to_native (p
, length
, delim
);
522 /*(utf8 conversion already does the control character quoting)*/
529 return print_sanitized_buffer (fp
, p
, length
, delim
);
534 print_sanitized_string2 (FILE *fp
, const char *string
, int delim
, int delim2
)
536 return string
? print_sanitized_buffer2 (fp
, string
, strlen (string
),
541 print_sanitized_string (FILE *fp
, const char *string
, int delim
)
543 return string
? print_sanitized_buffer (fp
, string
, strlen (string
), delim
):0;
547 print_sanitized_utf8_string (FILE *fp
, const char *string
, int delim
)
549 return string
? print_sanitized_utf8_buffer (fp
,
550 string
, strlen (string
),
554 /* Create a string from the buffer P_ARG of length N which is suitable
555 for printing. Caller must release the created string using xfree.
556 This function terminates the process on memory shortage. */
558 sanitize_buffer (const void *p_arg
, size_t n
, int delim
)
560 const unsigned char *p
= p_arg
;
561 size_t save_n
, buflen
;
562 const unsigned char *save_p
;
565 /* First count length. */
566 for (save_n
= n
, save_p
= p
, buflen
=1 ; n
; n
--, p
++ )
568 if ( *p
< 0x20 || *p
== 0x7f || *p
== delim
|| (delim
&& *p
=='\\'))
570 if ( *p
=='\n' || *p
=='\r' || *p
=='\f'
571 || *p
=='\v' || *p
=='\b' || !*p
)
581 /* And now make the string */
582 d
= buffer
= jnlib_xmalloc( buflen
);
583 for ( ; n
; n
--, p
++ )
585 if (*p
< 0x20 || *p
== 0x7f || *p
== delim
|| (delim
&& *p
=='\\')) {
589 else if( *p
== '\r' )
591 else if( *p
== '\f' )
593 else if( *p
== '\v' )
595 else if( *p
== '\b' )
600 sprintf(d
, "x%02x", *p
);
612 /* Given a string containing an UTF-8 encoded text, return the number
613 of characters in this string. It differs from strlen in that it
614 only counts complete UTF-8 characters. Note, that this function
615 does not take combined characters into account. */
617 utf8_charcount (const char *s
)
622 if ( (*s
&0xc0) != 0x80 ) /* Exclude continuation bytes: 10xxxxxx */
629 /****************************************************
630 ********** W32 specific functions ****************
631 ****************************************************/
633 #ifdef HAVE_W32_SYSTEM
635 w32_strerror (int ec
)
637 static char strerr
[256];
640 ec
= (int)GetLastError ();
641 FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
, NULL
, ec
,
642 MAKELANGID (LANG_NEUTRAL
, SUBLANG_DEFAULT
),
643 strerr
, DIM (strerr
)-1, NULL
);
646 #endif /*HAVE_W32_SYSTEM*/
649 /****************************************************
650 ******** Locale insensitive ctype functions ********
651 ****************************************************/
652 /* FIXME: replace them by a table lookup and macros */
654 ascii_isupper (int c
)
656 return c
>= 'A' && c
<= 'Z';
660 ascii_islower (int c
)
662 return c
>= 'a' && c
<= 'z';
666 ascii_toupper (int c
)
668 if (c
>= 'a' && c
<= 'z')
674 ascii_tolower (int c
)
676 if (c
>= 'A' && c
<= 'Z')
683 ascii_strcasecmp( const char *a
, const char *b
)
688 for (; *a
&& *b
; a
++, b
++) {
689 if (*a
!= *b
&& ascii_toupper(*a
) != ascii_toupper(*b
))
692 return *a
== *b
? 0 : (ascii_toupper (*a
) - ascii_toupper (*b
));
696 ascii_strncasecmp (const char *a
, const char *b
, size_t n
)
698 const unsigned char *p1
= (const unsigned char *)a
;
699 const unsigned char *p2
= (const unsigned char *)b
;
700 unsigned char c1
, c2
;
707 c1
= ascii_tolower (*p1
);
708 c2
= ascii_tolower (*p2
);
710 if ( !--n
|| c1
== '\0')
723 ascii_memcasecmp (const void *a_arg
, const void *b_arg
, size_t n
)
725 const char *a
= a_arg
;
726 const char *b
= b_arg
;
730 for ( ; n
; n
--, a
++, b
++ )
732 if( *a
!= *b
&& ascii_toupper (*a
) != ascii_toupper (*b
) )
733 return *a
== *b
? 0 : (ascii_toupper (*a
) - ascii_toupper (*b
));
739 ascii_strcmp( const char *a
, const char *b
)
744 for (; *a
&& *b
; a
++, b
++) {
748 return *a
== *b
? 0 : (*(signed char *)a
- *(signed char *)b
);
753 ascii_memcasemem (const void *haystack
, size_t nhaystack
,
754 const void *needle
, size_t nneedle
)
758 return (void*)haystack
; /* finding an empty needle is really easy */
759 if (nneedle
<= nhaystack
)
761 const char *a
= haystack
;
762 const char *b
= a
+ nhaystack
- nneedle
;
766 if ( !ascii_memcasecmp (a
, needle
, nneedle
) )
773 /*********************************************
774 ********** missing string functions *********
775 *********************************************/
779 stpcpy(char *a
,const char *b
)
790 /* Code taken from glibc-2.2.1/sysdeps/generic/strsep.c. */
792 strsep (char **stringp
, const char *delim
)
800 /* A frequent case is when the delimiter string contains only one
801 character. Here we don't need to call the expensive `strpbrk'
802 function and instead work using `strchr'. */
803 if (delim
[0] == '\0' || delim
[1] == '\0')
813 else if (*begin
== '\0')
816 end
= strchr (begin
+ 1, ch
);
820 /* Find the end of the token. */
821 end
= strpbrk (begin
, delim
);
825 /* Terminate the token and set *STRINGP past NUL character. */
830 /* No more delimiters; this is the last token. */
835 #endif /*HAVE_STRSEP*/
850 #ifndef HAVE_STRCASECMP
852 strcasecmp( const char *a
, const char *b
)
854 for( ; *a
&& *b
; a
++, b
++ ) {
855 if( *a
!= *b
&& toupper(*a
) != toupper(*b
) )
858 return *(const byte
*)a
- *(const byte
*)b
;
864 * mingw32/cpd has a memicmp()
868 memicmp( const char *a
, const char *b
, size_t n
)
870 for( ; n
; n
--, a
++, b
++ )
871 if( *a
!= *b
&& toupper(*(const byte
*)a
) != toupper(*(const byte
*)b
) )
872 return *(const byte
*)a
- *(const byte
*)b
;
880 memrchr (const void *buffer
, int c
, size_t n
)
882 const unsigned char *p
= buffer
;
884 for (p
+= n
; n
; n
--)
889 #endif /*HAVE_MEMRCHR*/
892 /* Percent-escape the string STR by replacing colons with '%3a'. If
893 EXTRA is not NULL all characters in EXTRA are also escaped. */
895 do_percent_escape (const char *str
, const char *extra
, int die
)
903 for (i
=j
=0; str
[i
]; i
++)
904 if (str
[i
] == ':' || str
[i
] == '%' || (extra
&& strchr (extra
, str
[i
])))
907 ptr
= jnlib_xmalloc (i
+ 2 * j
+ 1);
910 ptr
= jnlib_malloc (i
+ 2 * j
+ 1);
923 else if (*str
== '%')
929 else if (extra
&& strchr (extra
, *str
))
932 ptr
[i
++] = tohex_lower ((*str
>>4)&15);
933 ptr
[i
++] = tohex_lower (*str
&15);
944 /* Percent-escape the string STR by replacing colons with '%3a'. If
945 EXTRA is not NULL all characters in EXTRA are also escaped. This
946 function terminates the process on memory shortage. */
948 percent_escape (const char *str
, const char *extra
)
950 return do_percent_escape (str
, extra
, 1);
953 /* Same as percent_escape but return NULL instead of exiting on memory
956 try_percent_escape (const char *str
, const char *extra
)
958 return do_percent_escape (str
, extra
, 0);
964 do_strconcat (const char *s1
, va_list arg_ptr
)
966 const char *argv
[48];
973 needed
= strlen (s1
);
974 while (((argv
[argc
] = va_arg (arg_ptr
, const char *))))
976 needed
+= strlen (argv
[argc
]);
977 if (argc
>= DIM (argv
)-1)
985 buffer
= jnlib_malloc (needed
);
988 for (p
= buffer
, argc
=0; argv
[argc
]; argc
++)
989 p
= stpcpy (p
, argv
[argc
]);
995 /* Concatenate the string S1 with all the following strings up to a
996 NULL. Returns a malloced buffer with the new string or NULL on a
997 malloc error or if too many arguments are given. */
999 strconcat (const char *s1
, ...)
1005 result
= jnlib_strdup ("");
1008 va_start (arg_ptr
, s1
);
1009 result
= do_strconcat (s1
, arg_ptr
);
1015 /* Same as strconcat but terminate the process with an error message
1016 if something goes wrong. */
1018 xstrconcat (const char *s1
, ...)
1024 result
= jnlib_xstrdup ("");
1027 va_start (arg_ptr
, s1
);
1028 result
= do_strconcat (s1
, arg_ptr
);
1033 if (errno
== EINVAL
)
1034 fputs ("\nfatal: too many args for xstrconcat\n", stderr
);
1036 fputs ("\nfatal: out of memory\n", stderr
);