1 /* stringhelp.c - standard string helper functions
2 * Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005,
3 * 2006, 2007, 2008 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/>.
26 #ifdef HAVE_W32_SYSTEM
30 #include "libjnlib-config.h"
32 #include "stringhelp.h"
35 #define tohex_lower(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'a'))
37 /* Sometimes we want to avoid mixing slashes and backslashes on W32
38 and prefer backslashes. There is usual no problem with mixing
39 them, however a very few W32 API calls can't grok plain slashes.
40 Printing filenames with mixed slashes also looks a bit strange.
41 This function has no effext on POSIX. */
43 change_slashes (char *name
)
45 #ifdef HAVE_DRIVE_LETTERS
48 if (strchr (name
, '\\'))
54 #endif /*HAVE_DRIVE_LETTERS*/
60 * Look for the substring SUB in buffer and return a pointer to that
61 * substring in BUFFER or NULL if not found.
62 * Comparison is case-insensitive.
65 memistr (const void *buffer
, size_t buflen
, const char *sub
)
67 const unsigned char *buf
= buffer
;
68 const unsigned char *t
= (const unsigned char *)buffer
;
69 const unsigned char *s
= (const unsigned char *)sub
;
72 for ( ; n
; t
++, n
-- )
74 if ( toupper (*t
) == toupper (*s
) )
76 for ( buf
=t
++, buflen
= n
--, s
++;
77 n
&& toupper (*t
) == toupper (*s
); t
++, s
++, n
-- )
80 return (const char*)buf
;
82 s
= (const unsigned char *)sub
;
90 ascii_memistr ( const void *buffer
, size_t buflen
, const char *sub
)
92 const unsigned char *buf
= buffer
;
93 const unsigned char *t
= (const unsigned char *)buf
;
94 const unsigned char *s
= (const unsigned char *)sub
;
97 for ( ; n
; t
++, n
-- )
99 if (ascii_toupper (*t
) == ascii_toupper (*s
) )
101 for ( buf
=t
++, buflen
= n
--, s
++;
102 n
&& ascii_toupper (*t
) == ascii_toupper (*s
); t
++, s
++, n
-- )
105 return (const char*)buf
;
106 t
= (const unsigned char *)buf
;
107 s
= (const unsigned char *)sub
;
114 /* This function is similar to strncpy(). However it won't copy more
115 than N - 1 characters and makes sure that a '\0' is appended. With
116 N given as 0, nothing will happen. With DEST given as NULL, memory
117 will be allocated using jnlib_xmalloc (i.e. if it runs out of core
118 the function terminates). Returns DES or a pointer to the
122 mem2str( char *dest
, const void *src
, size_t n
)
129 dest
= jnlib_xmalloc( n
) ;
132 for(n
--; n
&& *s
; n
-- )
142 * remove leading and trailing white spaces
145 trim_spaces( char *str
)
147 char *string
, *p
, *mark
;
150 /* find first non space character */
151 for( p
=string
; *p
&& isspace( *(byte
*)p
) ; p
++ )
153 /* move characters */
154 for( (mark
= NULL
); (*string
= *p
); string
++, p
++ )
155 if( isspace( *(byte
*)p
) ) {
162 *mark
= '\0' ; /* remove trailing spaces */
168 * remove trailing white spaces
171 trim_trailing_spaces( char *string
)
175 for( mark
= NULL
, p
= string
; *p
; p
++ ) {
176 if( isspace( *(byte
*)p
) ) {
191 trim_trailing_chars( byte
*line
, unsigned len
, const char *trimchars
)
196 for(mark
=NULL
, p
=line
, n
=0; n
< len
; n
++, p
++ ) {
197 if( strchr(trimchars
, *p
) ) {
213 * remove trailing white spaces and return the length of the buffer
216 trim_trailing_ws( byte
*line
, unsigned len
)
218 return trim_trailing_chars( line
, len
, " \t\r\n" );
222 length_sans_trailing_chars (const unsigned char *line
, size_t len
,
223 const char *trimchars
)
225 const unsigned char *p
, *mark
;
228 for( mark
=NULL
, p
=line
, n
=0; n
< len
; n
++, p
++ )
230 if (strchr (trimchars
, *p
))
245 * Return the length of line ignoring trailing white-space.
248 length_sans_trailing_ws (const unsigned char *line
, size_t len
)
250 return length_sans_trailing_chars (line
, len
, " \t\r\n");
256 * Extract from a given path the filename component.
260 make_basename(const char *filepath
, const char *inputpath
)
263 return riscos_make_basename(filepath
, inputpath
);
267 (void)inputpath
; /* Only required for riscos. */
269 if ( !(p
=strrchr(filepath
, '/')) )
270 #ifdef HAVE_DRIVE_LETTERS
271 if ( !(p
=strrchr(filepath
, '\\')) )
272 if ( !(p
=strrchr(filepath
, ':')) )
275 return jnlib_xstrdup(filepath
);
278 return jnlib_xstrdup(p
+1);
285 * Extract from a given filename the path prepended to it.
286 * If their isn't a path prepended to the filename, a dot
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 will never fail. */
351 make_filename (const char *first_part
, ... )
354 name
= jnlib_xmalloc (n
);
358 /* Construct a filename from the NULL terminated list of parts. Tilde
359 expansion is done here. This function may return NULL on error. */
361 make_filename_try (const char *first_part
, ... )
364 name
= jnlib_xmalloc (n
);
369 #undef MAKE_FILENAME_PART1
370 #undef MAKE_FILENAME_PART2
374 /* Compare whether the filenames are identical. This is a
375 special version of strcmp() taking the semantics of filenames in
376 account. Note that this function works only on the supplied names
377 without considereing any context like the current directory. See
378 also same_file_p(). */
380 compare_filenames (const char *a
, const char *b
)
382 #ifdef HAVE_DRIVE_LETTERS
383 for ( ; *a
&& *b
; a
++, b
++ )
386 && (toupper (*(const unsigned char*)a
)
387 != toupper (*(const unsigned char*)b
) )
388 && !((*a
== '/' && *b
== '\\') || (*a
== '\\' && *b
== '/')))
391 if ((*a
== '/' && *b
== '\\') || (*a
== '\\' && *b
== '/'))
394 return (toupper (*(const unsigned char*)a
)
395 - toupper (*(const unsigned char*)b
));
402 /* Convert 2 hex characters at S to a byte value. Return this value
403 or -1 if there is an error. */
405 hextobyte (const char *s
)
409 if ( *s
>= '0' && *s
<= '9' )
411 else if ( *s
>= 'A' && *s
<= 'F' )
412 c
= 16 * (10 + *s
- 'A');
413 else if ( *s
>= 'a' && *s
<= 'f' )
414 c
= 16 * (10 + *s
- 'a');
418 if ( *s
>= '0' && *s
<= '9' )
420 else if ( *s
>= 'A' && *s
<= 'F' )
422 else if ( *s
>= 'a' && *s
<= 'f' )
430 /* Print a BUFFER to stream FP while replacing all control characters
431 and the characters DELIM and DELIM2 with standard C escape
432 sequences. Returns the number of characters printed. */
434 print_sanitized_buffer2 (FILE *fp
, const void *buffer
, size_t length
,
435 int delim
, int delim2
)
437 const unsigned char *p
= buffer
;
440 for (; length
; length
--, p
++, count
++)
446 || ((delim
|| delim2
) && *p
=='\\'))
482 fprintf (fp
, "x%02x", *p
);
496 /* Same as print_sanitized_buffer2 but with just one delimiter. */
498 print_sanitized_buffer (FILE *fp
, const void *buffer
, size_t length
,
501 return print_sanitized_buffer2 (fp
, buffer
, length
, delim
, 0);
506 print_sanitized_utf8_buffer (FILE *fp
, const void *buffer
,
507 size_t length
, int delim
)
509 const char *p
= buffer
;
512 /* We can handle plain ascii simpler, so check for it first. */
513 for (i
=0; i
< length
; i
++ )
520 char *buf
= utf8_to_native (p
, length
, delim
);
521 /*(utf8 conversion already does the control character quoting)*/
528 return print_sanitized_buffer (fp
, p
, length
, delim
);
533 print_sanitized_string2 (FILE *fp
, const char *string
, int delim
, int delim2
)
535 return string
? print_sanitized_buffer2 (fp
, string
, strlen (string
),
540 print_sanitized_string (FILE *fp
, const char *string
, int delim
)
542 return string
? print_sanitized_buffer (fp
, string
, strlen (string
), delim
):0;
546 print_sanitized_utf8_string (FILE *fp
, const char *string
, int delim
)
548 return string
? print_sanitized_utf8_buffer (fp
,
549 string
, strlen (string
),
553 /* Create a string from the buffer P_ARG of length N which is suitable for
554 printing. Caller must release the created string using xfree. */
556 sanitize_buffer (const void *p_arg
, size_t n
, int delim
)
558 const unsigned char *p
= p_arg
;
559 size_t save_n
, buflen
;
560 const unsigned char *save_p
;
563 /* First count length. */
564 for (save_n
= n
, save_p
= p
, buflen
=1 ; n
; n
--, p
++ )
566 if ( *p
< 0x20 || *p
== 0x7f || *p
== delim
|| (delim
&& *p
=='\\'))
568 if ( *p
=='\n' || *p
=='\r' || *p
=='\f'
569 || *p
=='\v' || *p
=='\b' || !*p
)
579 /* And now make the string */
580 d
= buffer
= jnlib_xmalloc( buflen
);
581 for ( ; n
; n
--, p
++ )
583 if (*p
< 0x20 || *p
== 0x7f || *p
== delim
|| (delim
&& *p
=='\\')) {
587 else if( *p
== '\r' )
589 else if( *p
== '\f' )
591 else if( *p
== '\v' )
593 else if( *p
== '\b' )
598 sprintf(d
, "x%02x", *p
);
610 /* Given a string containing an UTF-8 encoded text, return the number
611 of characters in this string. It differs from strlen in that it
612 only counts complete UTF-8 characters. Note, that this function
613 does not take combined characters into account. */
615 utf8_charcount (const char *s
)
620 if ( (*s
&0xc0) != 0x80 ) /* Exclude continuation bytes: 10xxxxxx */
627 /****************************************************
628 ********** W32 specific functions ****************
629 ****************************************************/
631 #ifdef HAVE_W32_SYSTEM
633 w32_strerror (int ec
)
635 static char strerr
[256];
638 ec
= (int)GetLastError ();
639 FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
, NULL
, ec
,
640 MAKELANGID (LANG_NEUTRAL
, SUBLANG_DEFAULT
),
641 strerr
, DIM (strerr
)-1, NULL
);
644 #endif /*HAVE_W32_SYSTEM*/
647 /****************************************************
648 ******** Locale insensitive ctype functions ********
649 ****************************************************/
650 /* FIXME: replace them by a table lookup and macros */
652 ascii_isupper (int c
)
654 return c
>= 'A' && c
<= 'Z';
658 ascii_islower (int c
)
660 return c
>= 'a' && c
<= 'z';
664 ascii_toupper (int c
)
666 if (c
>= 'a' && c
<= 'z')
672 ascii_tolower (int c
)
674 if (c
>= 'A' && c
<= 'Z')
681 ascii_strcasecmp( const char *a
, const char *b
)
686 for (; *a
&& *b
; a
++, b
++) {
687 if (*a
!= *b
&& ascii_toupper(*a
) != ascii_toupper(*b
))
690 return *a
== *b
? 0 : (ascii_toupper (*a
) - ascii_toupper (*b
));
694 ascii_strncasecmp (const char *a
, const char *b
, size_t n
)
696 const unsigned char *p1
= (const unsigned char *)a
;
697 const unsigned char *p2
= (const unsigned char *)b
;
698 unsigned char c1
, c2
;
705 c1
= ascii_tolower (*p1
);
706 c2
= ascii_tolower (*p2
);
708 if ( !--n
|| c1
== '\0')
721 ascii_memcasecmp (const void *a_arg
, const void *b_arg
, size_t n
)
723 const char *a
= a_arg
;
724 const char *b
= b_arg
;
728 for ( ; n
; n
--, a
++, b
++ )
730 if( *a
!= *b
&& ascii_toupper (*a
) != ascii_toupper (*b
) )
731 return *a
== *b
? 0 : (ascii_toupper (*a
) - ascii_toupper (*b
));
737 ascii_strcmp( const char *a
, const char *b
)
742 for (; *a
&& *b
; a
++, b
++) {
746 return *a
== *b
? 0 : (*(signed char *)a
- *(signed char *)b
);
751 ascii_memcasemem (const void *haystack
, size_t nhaystack
,
752 const void *needle
, size_t nneedle
)
756 return (void*)haystack
; /* finding an empty needle is really easy */
757 if (nneedle
<= nhaystack
)
759 const char *a
= haystack
;
760 const char *b
= a
+ nhaystack
- nneedle
;
764 if ( !ascii_memcasecmp (a
, needle
, nneedle
) )
771 /*********************************************
772 ********** missing string functions *********
773 *********************************************/
777 stpcpy(char *a
,const char *b
)
788 /* Code taken from glibc-2.2.1/sysdeps/generic/strsep.c. */
790 strsep (char **stringp
, const char *delim
)
798 /* A frequent case is when the delimiter string contains only one
799 character. Here we don't need to call the expensive `strpbrk'
800 function and instead work using `strchr'. */
801 if (delim
[0] == '\0' || delim
[1] == '\0')
811 else if (*begin
== '\0')
814 end
= strchr (begin
+ 1, ch
);
818 /* Find the end of the token. */
819 end
= strpbrk (begin
, delim
);
823 /* Terminate the token and set *STRINGP past NUL character. */
828 /* No more delimiters; this is the last token. */
833 #endif /*HAVE_STRSEP*/
848 #ifndef HAVE_STRCASECMP
850 strcasecmp( const char *a
, const char *b
)
852 for( ; *a
&& *b
; a
++, b
++ ) {
853 if( *a
!= *b
&& toupper(*a
) != toupper(*b
) )
856 return *(const byte
*)a
- *(const byte
*)b
;
862 * mingw32/cpd has a memicmp()
866 memicmp( const char *a
, const char *b
, size_t n
)
868 for( ; n
; n
--, a
++, b
++ )
869 if( *a
!= *b
&& toupper(*(const byte
*)a
) != toupper(*(const byte
*)b
) )
870 return *(const byte
*)a
- *(const byte
*)b
;
878 memrchr (const void *buffer
, int c
, size_t n
)
880 const unsigned char *p
= buffer
;
882 for (p
+= n
; n
; n
--)
887 #endif /*HAVE_MEMRCHR*/
890 /* Percent-escape the string STR by replacing colons with '%3a'. If
891 EXTRA is not NULL all characters in EXTRA are also escaped. */
893 do_percent_escape (const char *str
, const char *extra
, int die
)
901 for (i
=j
=0; str
[i
]; i
++)
902 if (str
[i
] == ':' || str
[i
] == '%' || (extra
&& strchr (extra
, str
[i
])))
905 ptr
= jnlib_xmalloc (i
+ 2 * j
+ 1);
908 ptr
= jnlib_malloc (i
+ 2 * j
+ 1);
921 else if (*str
== '%')
927 else if (extra
&& strchr (extra
, *str
))
930 ptr
[i
++] = tohex_lower ((*str
>>4)&15);
931 ptr
[i
++] = tohex_lower (*str
&15);
942 /* Percent-escape the string STR by replacing colons with '%3a'. If
943 EXTRA is not NULL all characters in EXTRA are also escaped. */
945 percent_escape (const char *str
, const char *extra
)
947 return do_percent_escape (str
, extra
, 1);
950 /* Same as percent_escape but return NULL instead of exiting on memory
953 try_percent_escape (const char *str
, const char *extra
)
955 return do_percent_escape (str
, extra
, 0);