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. This function
257 * terminates the process on memory shortage.
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. If there
286 * isn't a path prepended to the filename, a dot is returned ('.').
287 * This function terminates the process on memory shortage.
290 make_dirname(const char *filepath
)
296 if ( !(p
=strrchr(filepath
, '/')) )
297 #ifdef HAVE_DRIVE_LETTERS
298 if ( !(p
=strrchr(filepath
, '\\')) )
299 if ( !(p
=strrchr(filepath
, ':')) )
302 return jnlib_xstrdup(".");
305 dirname_length
= p
-filepath
;
306 dirname
= jnlib_xmalloc(dirname_length
+1);
307 strncpy(dirname
, filepath
, dirname_length
);
308 dirname
[dirname_length
] = 0;
315 /* Implementation of make_filename and make_filename_try. We need to
316 use macros here to avoid the use of the sometimes problematic
317 va_copy function which is not available on all systems. */
318 #define MAKE_FILENAME_PART1 \
322 char *name, *home, *p; \
324 va_start (arg_ptr, first_part); \
325 n = strlen (first_part) + 1; \
326 while ( (s = va_arg (arg_ptr, const char *)) ) \
327 n += strlen(s) + 1; \
331 if ( *first_part == '~' && first_part[1] == '/' \
332 && (home = getenv("HOME")) && *home ) \
335 #define MAKE_FILENAME_PART2 \
337 ? stpcpy (stpcpy (name,home), first_part + 1)\
338 : stpcpy(name, first_part)); \
340 va_start (arg_ptr, first_part); \
341 while ( (s = va_arg(arg_ptr, const char *)) ) \
342 p = stpcpy (stpcpy (p,"/"), s); \
344 return change_slashes (name);
347 /* Construct a filename from the NULL terminated list of parts. Tilde
348 expansion is done here. This function terminates the process on
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_malloc (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
554 for printing. Caller must release the created string using xfree.
555 This function terminates the process on memory shortage. */
557 sanitize_buffer (const void *p_arg
, size_t n
, int delim
)
559 const unsigned char *p
= p_arg
;
560 size_t save_n
, buflen
;
561 const unsigned char *save_p
;
564 /* First count length. */
565 for (save_n
= n
, save_p
= p
, buflen
=1 ; n
; n
--, p
++ )
567 if ( *p
< 0x20 || *p
== 0x7f || *p
== delim
|| (delim
&& *p
=='\\'))
569 if ( *p
=='\n' || *p
=='\r' || *p
=='\f'
570 || *p
=='\v' || *p
=='\b' || !*p
)
580 /* And now make the string */
581 d
= buffer
= jnlib_xmalloc( buflen
);
582 for ( ; n
; n
--, p
++ )
584 if (*p
< 0x20 || *p
== 0x7f || *p
== delim
|| (delim
&& *p
=='\\')) {
588 else if( *p
== '\r' )
590 else if( *p
== '\f' )
592 else if( *p
== '\v' )
594 else if( *p
== '\b' )
599 sprintf(d
, "x%02x", *p
);
611 /* Given a string containing an UTF-8 encoded text, return the number
612 of characters in this string. It differs from strlen in that it
613 only counts complete UTF-8 characters. Note, that this function
614 does not take combined characters into account. */
616 utf8_charcount (const char *s
)
621 if ( (*s
&0xc0) != 0x80 ) /* Exclude continuation bytes: 10xxxxxx */
628 /****************************************************
629 ********** W32 specific functions ****************
630 ****************************************************/
632 #ifdef HAVE_W32_SYSTEM
634 w32_strerror (int ec
)
636 static char strerr
[256];
639 ec
= (int)GetLastError ();
640 FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
, NULL
, ec
,
641 MAKELANGID (LANG_NEUTRAL
, SUBLANG_DEFAULT
),
642 strerr
, DIM (strerr
)-1, NULL
);
645 #endif /*HAVE_W32_SYSTEM*/
648 /****************************************************
649 ******** Locale insensitive ctype functions ********
650 ****************************************************/
651 /* FIXME: replace them by a table lookup and macros */
653 ascii_isupper (int c
)
655 return c
>= 'A' && c
<= 'Z';
659 ascii_islower (int c
)
661 return c
>= 'a' && c
<= 'z';
665 ascii_toupper (int c
)
667 if (c
>= 'a' && c
<= 'z')
673 ascii_tolower (int c
)
675 if (c
>= 'A' && c
<= 'Z')
682 ascii_strcasecmp( const char *a
, const char *b
)
687 for (; *a
&& *b
; a
++, b
++) {
688 if (*a
!= *b
&& ascii_toupper(*a
) != ascii_toupper(*b
))
691 return *a
== *b
? 0 : (ascii_toupper (*a
) - ascii_toupper (*b
));
695 ascii_strncasecmp (const char *a
, const char *b
, size_t n
)
697 const unsigned char *p1
= (const unsigned char *)a
;
698 const unsigned char *p2
= (const unsigned char *)b
;
699 unsigned char c1
, c2
;
706 c1
= ascii_tolower (*p1
);
707 c2
= ascii_tolower (*p2
);
709 if ( !--n
|| c1
== '\0')
722 ascii_memcasecmp (const void *a_arg
, const void *b_arg
, size_t n
)
724 const char *a
= a_arg
;
725 const char *b
= b_arg
;
729 for ( ; n
; n
--, a
++, b
++ )
731 if( *a
!= *b
&& ascii_toupper (*a
) != ascii_toupper (*b
) )
732 return *a
== *b
? 0 : (ascii_toupper (*a
) - ascii_toupper (*b
));
738 ascii_strcmp( const char *a
, const char *b
)
743 for (; *a
&& *b
; a
++, b
++) {
747 return *a
== *b
? 0 : (*(signed char *)a
- *(signed char *)b
);
752 ascii_memcasemem (const void *haystack
, size_t nhaystack
,
753 const void *needle
, size_t nneedle
)
757 return (void*)haystack
; /* finding an empty needle is really easy */
758 if (nneedle
<= nhaystack
)
760 const char *a
= haystack
;
761 const char *b
= a
+ nhaystack
- nneedle
;
765 if ( !ascii_memcasecmp (a
, needle
, nneedle
) )
772 /*********************************************
773 ********** missing string functions *********
774 *********************************************/
778 stpcpy(char *a
,const char *b
)
789 /* Code taken from glibc-2.2.1/sysdeps/generic/strsep.c. */
791 strsep (char **stringp
, const char *delim
)
799 /* A frequent case is when the delimiter string contains only one
800 character. Here we don't need to call the expensive `strpbrk'
801 function and instead work using `strchr'. */
802 if (delim
[0] == '\0' || delim
[1] == '\0')
812 else if (*begin
== '\0')
815 end
= strchr (begin
+ 1, ch
);
819 /* Find the end of the token. */
820 end
= strpbrk (begin
, delim
);
824 /* Terminate the token and set *STRINGP past NUL character. */
829 /* No more delimiters; this is the last token. */
834 #endif /*HAVE_STRSEP*/
849 #ifndef HAVE_STRCASECMP
851 strcasecmp( const char *a
, const char *b
)
853 for( ; *a
&& *b
; a
++, b
++ ) {
854 if( *a
!= *b
&& toupper(*a
) != toupper(*b
) )
857 return *(const byte
*)a
- *(const byte
*)b
;
863 * mingw32/cpd has a memicmp()
867 memicmp( const char *a
, const char *b
, size_t n
)
869 for( ; n
; n
--, a
++, b
++ )
870 if( *a
!= *b
&& toupper(*(const byte
*)a
) != toupper(*(const byte
*)b
) )
871 return *(const byte
*)a
- *(const byte
*)b
;
879 memrchr (const void *buffer
, int c
, size_t n
)
881 const unsigned char *p
= buffer
;
883 for (p
+= n
; n
; n
--)
888 #endif /*HAVE_MEMRCHR*/
891 /* Percent-escape the string STR by replacing colons with '%3a'. If
892 EXTRA is not NULL all characters in EXTRA are also escaped. */
894 do_percent_escape (const char *str
, const char *extra
, int die
)
902 for (i
=j
=0; str
[i
]; i
++)
903 if (str
[i
] == ':' || str
[i
] == '%' || (extra
&& strchr (extra
, str
[i
])))
906 ptr
= jnlib_xmalloc (i
+ 2 * j
+ 1);
909 ptr
= jnlib_malloc (i
+ 2 * j
+ 1);
922 else if (*str
== '%')
928 else if (extra
&& strchr (extra
, *str
))
931 ptr
[i
++] = tohex_lower ((*str
>>4)&15);
932 ptr
[i
++] = tohex_lower (*str
&15);
943 /* Percent-escape the string STR by replacing colons with '%3a'. If
944 EXTRA is not NULL all characters in EXTRA are also escaped. This
945 function terminates the process on memory shortage. */
947 percent_escape (const char *str
, const char *extra
)
949 return do_percent_escape (str
, extra
, 1);
952 /* Same as percent_escape but return NULL instead of exiting on memory
955 try_percent_escape (const char *str
, const char *extra
)
957 return do_percent_escape (str
, extra
, 0);