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/>.
31 #include <sys/types.h>
32 #ifdef HAVE_W32_SYSTEM
36 #include "libjnlib-config.h"
38 #include "stringhelp.h"
41 #define tohex_lower(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'a'))
43 /* Sometimes we want to avoid mixing slashes and backslashes on W32
44 and prefer backslashes. There is usual no problem with mixing
45 them, however a very few W32 API calls can't grok plain slashes.
46 Printing filenames with mixed slashes also looks a bit strange.
47 This function has no effext on POSIX. */
49 change_slashes (char *name
)
51 #ifdef HAVE_DRIVE_LETTERS
54 if (strchr (name
, '\\'))
60 #endif /*HAVE_DRIVE_LETTERS*/
66 * Look for the substring SUB in buffer and return a pointer to that
67 * substring in BUFFER or NULL if not found.
68 * Comparison is case-insensitive.
71 memistr (const void *buffer
, size_t buflen
, const char *sub
)
73 const unsigned char *buf
= buffer
;
74 const unsigned char *t
= (const unsigned char *)buffer
;
75 const unsigned char *s
= (const unsigned char *)sub
;
78 for ( ; n
; t
++, n
-- )
80 if ( toupper (*t
) == toupper (*s
) )
82 for ( buf
=t
++, buflen
= n
--, s
++;
83 n
&& toupper (*t
) == toupper (*s
); t
++, s
++, n
-- )
86 return (const char*)buf
;
88 s
= (const unsigned char *)sub
;
96 ascii_memistr ( const void *buffer
, size_t buflen
, const char *sub
)
98 const unsigned char *buf
= buffer
;
99 const unsigned char *t
= (const unsigned char *)buf
;
100 const unsigned char *s
= (const unsigned char *)sub
;
103 for ( ; n
; t
++, n
-- )
105 if (ascii_toupper (*t
) == ascii_toupper (*s
) )
107 for ( buf
=t
++, buflen
= n
--, s
++;
108 n
&& ascii_toupper (*t
) == ascii_toupper (*s
); t
++, s
++, n
-- )
111 return (const char*)buf
;
112 t
= (const unsigned char *)buf
;
113 s
= (const unsigned char *)sub
;
120 /* This function is similar to strncpy(). However it won't copy more
121 than N - 1 characters and makes sure that a '\0' is appended. With
122 N given as 0, nothing will happen. With DEST given as NULL, memory
123 will be allocated using jnlib_xmalloc (i.e. if it runs out of core
124 the function terminates). Returns DES or a pointer to the
128 mem2str( char *dest
, const void *src
, size_t n
)
135 dest
= jnlib_xmalloc( n
) ;
138 for(n
--; n
&& *s
; n
-- )
148 * remove leading and trailing white spaces
151 trim_spaces( char *str
)
153 char *string
, *p
, *mark
;
156 /* find first non space character */
157 for( p
=string
; *p
&& isspace( *(byte
*)p
) ; p
++ )
159 /* move characters */
160 for( (mark
= NULL
); (*string
= *p
); string
++, p
++ )
161 if( isspace( *(byte
*)p
) ) {
168 *mark
= '\0' ; /* remove trailing spaces */
174 * remove trailing white spaces
177 trim_trailing_spaces( char *string
)
181 for( mark
= NULL
, p
= string
; *p
; p
++ ) {
182 if( isspace( *(byte
*)p
) ) {
197 trim_trailing_chars( byte
*line
, unsigned len
, const char *trimchars
)
202 for(mark
=NULL
, p
=line
, n
=0; n
< len
; n
++, p
++ ) {
203 if( strchr(trimchars
, *p
) ) {
219 * remove trailing white spaces and return the length of the buffer
222 trim_trailing_ws( byte
*line
, unsigned len
)
224 return trim_trailing_chars( line
, len
, " \t\r\n" );
228 length_sans_trailing_chars (const unsigned char *line
, size_t len
,
229 const char *trimchars
)
231 const unsigned char *p
, *mark
;
234 for( mark
=NULL
, p
=line
, n
=0; n
< len
; n
++, p
++ )
236 if (strchr (trimchars
, *p
))
251 * Return the length of line ignoring trailing white-space.
254 length_sans_trailing_ws (const unsigned char *line
, size_t len
)
256 return length_sans_trailing_chars (line
, len
, " \t\r\n");
262 * Extract from a given path the filename component. This function
263 * terminates the process on memory shortage.
266 make_basename(const char *filepath
, const char *inputpath
)
269 return riscos_make_basename(filepath
, inputpath
);
273 (void)inputpath
; /* Only required for riscos. */
275 if ( !(p
=strrchr(filepath
, '/')) )
276 #ifdef HAVE_DRIVE_LETTERS
277 if ( !(p
=strrchr(filepath
, '\\')) )
278 if ( !(p
=strrchr(filepath
, ':')) )
281 return jnlib_xstrdup(filepath
);
284 return jnlib_xstrdup(p
+1);
291 * Extract from a given filename the path prepended to it. If there
292 * isn't a path prepended to the filename, a dot is returned ('.').
293 * This function terminates the process on memory shortage.
296 make_dirname(const char *filepath
)
302 if ( !(p
=strrchr(filepath
, '/')) )
303 #ifdef HAVE_DRIVE_LETTERS
304 if ( !(p
=strrchr(filepath
, '\\')) )
305 if ( !(p
=strrchr(filepath
, ':')) )
308 return jnlib_xstrdup(".");
311 dirname_length
= p
-filepath
;
312 dirname
= jnlib_xmalloc(dirname_length
+1);
313 strncpy(dirname
, filepath
, dirname_length
);
314 dirname
[dirname_length
] = 0;
322 get_pwdir (int xmode
, const char *name
)
326 struct passwd
*pwd
= NULL
;
331 /* Fixme: We should use getpwnam_r if available. */
332 pwd
= getpwnam (name
);
338 /* Fixme: We should use getpwuid_r if available. */
339 pwd
= getpwuid (getuid());
345 result
= jnlib_xstrdup (pwd
->pw_dir
);
347 result
= jnlib_strdup (pwd
->pw_dir
);
349 #endif /*HAVE_PWD_H*/
354 do_make_filename (int xmode
, const char *first_part
, va_list arg_ptr
)
356 const char *argv
[32];
360 char *home_buffer
= NULL
;
361 char *name
, *home
, *p
;
363 n
= strlen (first_part
) + 1;
365 while ( (argv
[argc
] = va_arg (arg_ptr
, const char *)) )
367 n
+= strlen (argv
[argc
]) + 1;
368 if (argc
>= DIM (argv
)-1)
380 if (*first_part
== '~')
382 if (first_part
[1] == '/' || !first_part
[1])
384 /* This is the "~/" or "~" case. */
385 home
= getenv("HOME");
387 home
= home_buffer
= get_pwdir (xmode
, NULL
);
393 /* This is the "~username/" or "~username" case. */
397 user
= jnlib_xstrdup (first_part
+1);
400 user
= jnlib_strdup (first_part
+1);
404 p
= strchr (user
, '/');
407 skip
= 1 + strlen (user
);
409 home
= home_buffer
= get_pwdir (xmode
, user
);
419 name
= jnlib_xmalloc (n
);
422 name
= jnlib_malloc (n
);
425 jnlib_free (home_buffer
);
431 p
= stpcpy (stpcpy (name
, home
), first_part
+ skip
);
433 p
= stpcpy (name
, first_part
);
435 jnlib_free (home_buffer
);
437 for (argc
=0; argv
[argc
]; argc
++)
438 p
= stpcpy (stpcpy (p
, "/"), argv
[argc
]);
440 return change_slashes (name
);
443 /* Construct a filename from the NULL terminated list of parts. Tilde
444 expansion is done for the first argument. This function terminates
445 the process on memory shortage. */
447 make_filename (const char *first_part
, ... )
452 va_start (arg_ptr
, first_part
);
453 result
= do_make_filename (1, first_part
, arg_ptr
);
458 /* Construct a filename from the NULL terminated list of parts. Tilde
459 expansion is done for the first argument. This function may return
462 make_filename_try (const char *first_part
, ... )
467 va_start (arg_ptr
, first_part
);
468 result
= do_make_filename (0, first_part
, arg_ptr
);
475 /* Compare whether the filenames are identical. This is a
476 special version of strcmp() taking the semantics of filenames in
477 account. Note that this function works only on the supplied names
478 without considereing any context like the current directory. See
479 also same_file_p(). */
481 compare_filenames (const char *a
, const char *b
)
483 #ifdef HAVE_DRIVE_LETTERS
484 for ( ; *a
&& *b
; a
++, b
++ )
487 && (toupper (*(const unsigned char*)a
)
488 != toupper (*(const unsigned char*)b
) )
489 && !((*a
== '/' && *b
== '\\') || (*a
== '\\' && *b
== '/')))
492 if ((*a
== '/' && *b
== '\\') || (*a
== '\\' && *b
== '/'))
495 return (toupper (*(const unsigned char*)a
)
496 - toupper (*(const unsigned char*)b
));
503 /* Convert 2 hex characters at S to a byte value. Return this value
504 or -1 if there is an error. */
506 hextobyte (const char *s
)
510 if ( *s
>= '0' && *s
<= '9' )
512 else if ( *s
>= 'A' && *s
<= 'F' )
513 c
= 16 * (10 + *s
- 'A');
514 else if ( *s
>= 'a' && *s
<= 'f' )
515 c
= 16 * (10 + *s
- 'a');
519 if ( *s
>= '0' && *s
<= '9' )
521 else if ( *s
>= 'A' && *s
<= 'F' )
523 else if ( *s
>= 'a' && *s
<= 'f' )
531 /* Print a BUFFER to stream FP while replacing all control characters
532 and the characters DELIM and DELIM2 with standard C escape
533 sequences. Returns the number of characters printed. */
535 print_sanitized_buffer2 (FILE *fp
, const void *buffer
, size_t length
,
536 int delim
, int delim2
)
538 const unsigned char *p
= buffer
;
541 for (; length
; length
--, p
++, count
++)
547 || ((delim
|| delim2
) && *p
=='\\'))
583 fprintf (fp
, "x%02x", *p
);
597 /* Same as print_sanitized_buffer2 but with just one delimiter. */
599 print_sanitized_buffer (FILE *fp
, const void *buffer
, size_t length
,
602 return print_sanitized_buffer2 (fp
, buffer
, length
, delim
, 0);
607 print_sanitized_utf8_buffer (FILE *fp
, const void *buffer
,
608 size_t length
, int delim
)
610 const char *p
= buffer
;
613 /* We can handle plain ascii simpler, so check for it first. */
614 for (i
=0; i
< length
; i
++ )
621 char *buf
= utf8_to_native (p
, length
, delim
);
622 /*(utf8 conversion already does the control character quoting)*/
629 return print_sanitized_buffer (fp
, p
, length
, delim
);
634 print_sanitized_string2 (FILE *fp
, const char *string
, int delim
, int delim2
)
636 return string
? print_sanitized_buffer2 (fp
, string
, strlen (string
),
641 print_sanitized_string (FILE *fp
, const char *string
, int delim
)
643 return string
? print_sanitized_buffer (fp
, string
, strlen (string
), delim
):0;
647 print_sanitized_utf8_string (FILE *fp
, const char *string
, int delim
)
649 return string
? print_sanitized_utf8_buffer (fp
,
650 string
, strlen (string
),
654 /* Create a string from the buffer P_ARG of length N which is suitable
655 for printing. Caller must release the created string using xfree.
656 This function terminates the process on memory shortage. */
658 sanitize_buffer (const void *p_arg
, size_t n
, int delim
)
660 const unsigned char *p
= p_arg
;
661 size_t save_n
, buflen
;
662 const unsigned char *save_p
;
665 /* First count length. */
666 for (save_n
= n
, save_p
= p
, buflen
=1 ; n
; n
--, p
++ )
668 if ( *p
< 0x20 || *p
== 0x7f || *p
== delim
|| (delim
&& *p
=='\\'))
670 if ( *p
=='\n' || *p
=='\r' || *p
=='\f'
671 || *p
=='\v' || *p
=='\b' || !*p
)
681 /* And now make the string */
682 d
= buffer
= jnlib_xmalloc( buflen
);
683 for ( ; n
; n
--, p
++ )
685 if (*p
< 0x20 || *p
== 0x7f || *p
== delim
|| (delim
&& *p
=='\\')) {
689 else if( *p
== '\r' )
691 else if( *p
== '\f' )
693 else if( *p
== '\v' )
695 else if( *p
== '\b' )
700 sprintf(d
, "x%02x", *p
);
712 /* Given a string containing an UTF-8 encoded text, return the number
713 of characters in this string. It differs from strlen in that it
714 only counts complete UTF-8 characters. Note, that this function
715 does not take combined characters into account. */
717 utf8_charcount (const char *s
)
722 if ( (*s
&0xc0) != 0x80 ) /* Exclude continuation bytes: 10xxxxxx */
729 /****************************************************
730 ********** W32 specific functions ****************
731 ****************************************************/
733 #ifdef HAVE_W32_SYSTEM
735 w32_strerror (int ec
)
737 static char strerr
[256];
740 ec
= (int)GetLastError ();
741 FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
, NULL
, ec
,
742 MAKELANGID (LANG_NEUTRAL
, SUBLANG_DEFAULT
),
743 strerr
, DIM (strerr
)-1, NULL
);
746 #endif /*HAVE_W32_SYSTEM*/
749 /****************************************************
750 ******** Locale insensitive ctype functions ********
751 ****************************************************/
752 /* FIXME: replace them by a table lookup and macros */
754 ascii_isupper (int c
)
756 return c
>= 'A' && c
<= 'Z';
760 ascii_islower (int c
)
762 return c
>= 'a' && c
<= 'z';
766 ascii_toupper (int c
)
768 if (c
>= 'a' && c
<= 'z')
774 ascii_tolower (int c
)
776 if (c
>= 'A' && c
<= 'Z')
783 ascii_strcasecmp( const char *a
, const char *b
)
788 for (; *a
&& *b
; a
++, b
++) {
789 if (*a
!= *b
&& ascii_toupper(*a
) != ascii_toupper(*b
))
792 return *a
== *b
? 0 : (ascii_toupper (*a
) - ascii_toupper (*b
));
796 ascii_strncasecmp (const char *a
, const char *b
, size_t n
)
798 const unsigned char *p1
= (const unsigned char *)a
;
799 const unsigned char *p2
= (const unsigned char *)b
;
800 unsigned char c1
, c2
;
807 c1
= ascii_tolower (*p1
);
808 c2
= ascii_tolower (*p2
);
810 if ( !--n
|| c1
== '\0')
823 ascii_memcasecmp (const void *a_arg
, const void *b_arg
, size_t n
)
825 const char *a
= a_arg
;
826 const char *b
= b_arg
;
830 for ( ; n
; n
--, a
++, b
++ )
832 if( *a
!= *b
&& ascii_toupper (*a
) != ascii_toupper (*b
) )
833 return *a
== *b
? 0 : (ascii_toupper (*a
) - ascii_toupper (*b
));
839 ascii_strcmp( const char *a
, const char *b
)
844 for (; *a
&& *b
; a
++, b
++) {
848 return *a
== *b
? 0 : (*(signed char *)a
- *(signed char *)b
);
853 ascii_memcasemem (const void *haystack
, size_t nhaystack
,
854 const void *needle
, size_t nneedle
)
858 return (void*)haystack
; /* finding an empty needle is really easy */
859 if (nneedle
<= nhaystack
)
861 const char *a
= haystack
;
862 const char *b
= a
+ nhaystack
- nneedle
;
866 if ( !ascii_memcasecmp (a
, needle
, nneedle
) )
873 /*********************************************
874 ********** missing string functions *********
875 *********************************************/
879 stpcpy(char *a
,const char *b
)
890 /* Code taken from glibc-2.2.1/sysdeps/generic/strsep.c. */
892 strsep (char **stringp
, const char *delim
)
900 /* A frequent case is when the delimiter string contains only one
901 character. Here we don't need to call the expensive `strpbrk'
902 function and instead work using `strchr'. */
903 if (delim
[0] == '\0' || delim
[1] == '\0')
913 else if (*begin
== '\0')
916 end
= strchr (begin
+ 1, ch
);
920 /* Find the end of the token. */
921 end
= strpbrk (begin
, delim
);
925 /* Terminate the token and set *STRINGP past NUL character. */
930 /* No more delimiters; this is the last token. */
935 #endif /*HAVE_STRSEP*/
950 #ifndef HAVE_STRCASECMP
952 strcasecmp( const char *a
, const char *b
)
954 for( ; *a
&& *b
; a
++, b
++ ) {
955 if( *a
!= *b
&& toupper(*a
) != toupper(*b
) )
958 return *(const byte
*)a
- *(const byte
*)b
;
964 * mingw32/cpd has a memicmp()
968 memicmp( const char *a
, const char *b
, size_t n
)
970 for( ; n
; n
--, a
++, b
++ )
971 if( *a
!= *b
&& toupper(*(const byte
*)a
) != toupper(*(const byte
*)b
) )
972 return *(const byte
*)a
- *(const byte
*)b
;
980 memrchr (const void *buffer
, int c
, size_t n
)
982 const unsigned char *p
= buffer
;
984 for (p
+= n
; n
; n
--)
989 #endif /*HAVE_MEMRCHR*/
992 /* Percent-escape the string STR by replacing colons with '%3a'. If
993 EXTRA is not NULL all characters in EXTRA are also escaped. */
995 do_percent_escape (const char *str
, const char *extra
, int die
)
1003 for (i
=j
=0; str
[i
]; i
++)
1004 if (str
[i
] == ':' || str
[i
] == '%' || (extra
&& strchr (extra
, str
[i
])))
1007 ptr
= jnlib_xmalloc (i
+ 2 * j
+ 1);
1010 ptr
= jnlib_malloc (i
+ 2 * j
+ 1);
1023 else if (*str
== '%')
1029 else if (extra
&& strchr (extra
, *str
))
1032 ptr
[i
++] = tohex_lower ((*str
>>4)&15);
1033 ptr
[i
++] = tohex_lower (*str
&15);
1044 /* Percent-escape the string STR by replacing colons with '%3a'. If
1045 EXTRA is not NULL all characters in EXTRA are also escaped. This
1046 function terminates the process on memory shortage. */
1048 percent_escape (const char *str
, const char *extra
)
1050 return do_percent_escape (str
, extra
, 1);
1053 /* Same as percent_escape but return NULL instead of exiting on memory
1056 try_percent_escape (const char *str
, const char *extra
)
1058 return do_percent_escape (str
, extra
, 0);
1064 do_strconcat (const char *s1
, va_list arg_ptr
)
1066 const char *argv
[48];
1073 needed
= strlen (s1
);
1074 while (((argv
[argc
] = va_arg (arg_ptr
, const char *))))
1076 needed
+= strlen (argv
[argc
]);
1077 if (argc
>= DIM (argv
)-1)
1085 buffer
= jnlib_malloc (needed
);
1088 for (p
= buffer
, argc
=0; argv
[argc
]; argc
++)
1089 p
= stpcpy (p
, argv
[argc
]);
1095 /* Concatenate the string S1 with all the following strings up to a
1096 NULL. Returns a malloced buffer with the new string or NULL on a
1097 malloc error or if too many arguments are given. */
1099 strconcat (const char *s1
, ...)
1105 result
= jnlib_strdup ("");
1108 va_start (arg_ptr
, s1
);
1109 result
= do_strconcat (s1
, arg_ptr
);
1115 /* Same as strconcat but terminate the process with an error message
1116 if something goes wrong. */
1118 xstrconcat (const char *s1
, ...)
1124 result
= jnlib_xstrdup ("");
1127 va_start (arg_ptr
, s1
);
1128 result
= do_strconcat (s1
, arg_ptr
);
1133 if (errno
== EINVAL
)
1134 fputs ("\nfatal: too many args for xstrconcat\n", stderr
);
1136 fputs ("\nfatal: out of memory\n", stderr
);