1
/* stringhelp.c - standard string helper functions
2
* Copyright (C) 1998, 1999, 2000, 2001, 2003,
3
* 2004 Free Software Foundation, Inc.
5
* This file is part of GnuPG.
7
* GnuPG is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation; either version 2 of the License, or
10
* (at your option) any later version.
12
* GnuPG is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software
19
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
27
#ifdef HAVE_W32_SYSTEM
31
#include "libjnlib-config.h"
33
#include "stringhelp.h"
37
* Look for the substring SUB in buffer and return a pointer to that
38
* substring in BUF or NULL if not found.
39
* Comparison is case-insensitive.
42
memistr( const char *buf, size_t buflen, const char *sub )
47
for( t=buf, n=buflen, s=sub ; n ; t++, n-- )
48
if( toupper(*t) == toupper(*s) ) {
49
for( buf=t++, buflen = n--, s++;
50
n && toupper(*t) == toupper(*s); t++, s++, n-- )
54
t = buf; n = buflen; s = sub ;
61
ascii_memistr( const char *buf, size_t buflen, const char *sub )
66
for( t=buf, n=buflen, s=sub ; n ; t++, n-- )
67
if( ascii_toupper(*t) == ascii_toupper(*s) ) {
68
for( buf=t++, buflen = n--, s++;
69
n && ascii_toupper(*t) == ascii_toupper(*s); t++, s++, n-- )
73
t = buf; n = buflen; s = sub ;
79
/* This function is similar to strncpy(). However it won't copy more
80
than N - 1 characters and makes sure that a '\0' is appended. With
81
N given as 0, nothing will happen. With DEST given as NULL, memory
82
will be allocated using jnlib_xmalloc (i.e. if it runs out of core
83
the function terminates). Returns DES or a pointer to the
87
mem2str( char *dest , const void *src , size_t n )
94
dest = jnlib_xmalloc( n ) ;
97
for(n--; n && *s; n-- )
107
* remove leading and trailing white spaces
110
trim_spaces( char *str )
112
char *string, *p, *mark;
115
/* find first non space character */
116
for( p=string; *p && isspace( *(byte*)p ) ; p++ )
118
/* move characters */
119
for( (mark = NULL); (*string = *p); string++, p++ )
120
if( isspace( *(byte*)p ) ) {
127
*mark = '\0' ; /* remove trailing spaces */
133
* remove trailing white spaces
136
trim_trailing_spaces( char *string )
140
for( mark = NULL, p = string; *p; p++ ) {
141
if( isspace( *(byte*)p ) ) {
156
trim_trailing_chars( byte *line, unsigned len, const char *trimchars )
161
for(mark=NULL, p=line, n=0; n < len; n++, p++ ) {
162
if( strchr(trimchars, *p ) ) {
178
* remove trailing white spaces and return the length of the buffer
181
trim_trailing_ws( byte *line, unsigned len )
183
return trim_trailing_chars( line, len, " \t\r\n" );
187
length_sans_trailing_chars (const unsigned char *line, size_t len,
188
const char *trimchars )
190
const unsigned char *p, *mark;
193
for( mark=NULL, p=line, n=0; n < len; n++, p++ )
195
if (strchr (trimchars, *p ))
210
* remove trailing white spaces and return the length of the buffer
213
length_sans_trailing_ws (const unsigned char *line, size_t len)
215
return length_sans_trailing_chars (line, len, " \t\r\n");
221
* Extract from a given path the filename component.
225
make_basename(const char *filepath)
229
if ( !(p=strrchr(filepath, '/')) )
230
#ifdef HAVE_DRIVE_LETTERS
231
if ( !(p=strrchr(filepath, '\\')) )
232
if ( !(p=strrchr(filepath, ':')) )
235
return jnlib_xstrdup(filepath);
238
return jnlib_xstrdup(p+1);
244
* Extract from a given filename the path prepended to it.
245
* If their isn't a path prepended to the filename, a dot
250
make_dirname(const char *filepath)
256
if ( !(p=strrchr(filepath, '/')) )
257
#ifdef HAVE_DRIVE_LETTERS
258
if ( !(p=strrchr(filepath, '\\')) )
259
if ( !(p=strrchr(filepath, ':')) )
262
return jnlib_xstrdup(".");
265
dirname_length = p-filepath;
266
dirname = jnlib_xmalloc(dirname_length+1);
267
strncpy(dirname, filepath, dirname_length);
268
dirname[dirname_length] = 0;
276
* Construct a filename from the NULL terminated list of parts.
277
* Tilde expansion is done here.
280
make_filename( const char *first_part, ... )
285
char *name, *home, *p;
287
va_start( arg_ptr, first_part ) ;
288
n = strlen(first_part)+1;
289
while( (s=va_arg(arg_ptr, const char *)) )
294
if( *first_part == '~' && first_part[1] == '/'
295
&& (home = getenv("HOME")) && *home )
298
name = jnlib_xmalloc(n);
299
p = home ? stpcpy(stpcpy(name,home), first_part+1)
300
: stpcpy(name, first_part);
301
va_start( arg_ptr, first_part ) ;
302
while( (s=va_arg(arg_ptr, const char *)) )
303
p = stpcpy(stpcpy(p,"/"), s);
311
compare_filenames( const char *a, const char *b )
313
/* ? check whether this is an absolute filename and
316
#ifdef HAVE_DRIVE_LETTERS
323
/* Print a BUFFER to stream FP while replacing all control characters
324
and the character DELIM with standard C escape sequences. Returns
325
the number of characters printed. */
327
print_sanitized_buffer (FILE *fp, const void *buffer, size_t length,
330
const unsigned char *p = buffer;
333
for (; length; length--, p++, count++)
335
if (*p < 0x20 || *p == 0x7f || *p == delim)
353
fprintf (fp, "x%02x", *p);
365
print_sanitized_utf8_buffer (FILE *fp, const void *buffer,
366
size_t length, int delim)
368
const char *p = buffer;
371
/* We can handle plain ascii simpler, so check for it first. */
372
for (i=0; i < length; i++ )
379
char *buf = utf8_to_native (p, length, delim);
380
/*(utf8 conversion already does the control character quoting)*/
387
return print_sanitized_buffer (fp, p, length, delim);
392
print_sanitized_string (FILE *fp, const char *string, int delim)
394
return string? print_sanitized_buffer (fp, string, strlen (string), delim):0;
398
print_sanitized_utf8_string (FILE *fp, const char *string, int delim)
400
return string? print_sanitized_utf8_buffer (fp,
401
string, strlen (string),
405
/* Create a string from the buffer P of length N which is suitable for
406
printing. Caller must release the created string using xfree. */
408
sanitize_buffer (const unsigned char *p, size_t n, int delim)
410
size_t save_n, buflen;
414
/* first count length */
415
for (save_n = n, save_p = p, buflen=1 ; n; n--, p++ )
417
if ( *p < 0x20 || *p == 0x7f || *p == delim || (delim && *p=='\\'))
419
if ( *p=='\n' || *p=='\r' || *p=='\f'
420
|| *p=='\v' || *p=='\b' || !*p )
430
/* and now make the string */
431
d = buffer = jnlib_xmalloc( buflen );
432
for ( ; n; n--, p++ )
434
if (*p < 0x20 || *p == 0x7f || *p == delim || (delim && *p=='\\')) {
438
else if( *p == '\r' )
440
else if( *p == '\f' )
442
else if( *p == '\v' )
444
else if( *p == '\b' )
449
sprintf(d, "x%02x", *p );
461
/****************************************************
462
********** W32 specific functions ****************
463
****************************************************/
465
#ifdef HAVE_W32_SYSTEM
467
w32_strerror (int ec)
469
static char strerr[256];
472
ec = (int)GetLastError ();
473
FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, ec,
474
MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
475
strerr, DIM (strerr)-1, NULL);
478
#endif /*HAVE_W32_SYSTEM*/
481
/****************************************************
482
******** Locale insensitive ctype functions ********
483
****************************************************/
484
/* FIXME: replace them by a table lookup and macros */
486
ascii_isupper (int c)
488
return c >= 'A' && c <= 'Z';
492
ascii_islower (int c)
494
return c >= 'a' && c <= 'z';
498
ascii_toupper (int c)
500
if (c >= 'a' && c <= 'z')
506
ascii_tolower (int c)
508
if (c >= 'A' && c <= 'Z')
515
ascii_strcasecmp( const char *a, const char *b )
520
for (; *a && *b; a++, b++) {
521
if (*a != *b && ascii_toupper(*a) != ascii_toupper(*b))
524
return *a == *b? 0 : (ascii_toupper (*a) - ascii_toupper (*b));
528
ascii_strncasecmp (const char *a, const char *b, size_t n)
530
const unsigned char *p1 = (const unsigned char *)a;
531
const unsigned char *p2 = (const unsigned char *)b;
532
unsigned char c1, c2;
539
c1 = ascii_tolower (*p1);
540
c2 = ascii_tolower (*p2);
542
if ( !--n || c1 == '\0')
555
ascii_memcasecmp( const char *a, const char *b, size_t n )
559
for ( ; n; n--, a++, b++ ) {
560
if( *a != *b && ascii_toupper (*a) != ascii_toupper (*b) )
561
return *a == *b? 0 : (ascii_toupper (*a) - ascii_toupper (*b));
567
ascii_strcmp( const char *a, const char *b )
572
for (; *a && *b; a++, b++) {
576
return *a == *b? 0 : (*(signed char *)a - *(signed char *)b);
581
ascii_memcasemem (const void *haystack, size_t nhaystack,
582
const void *needle, size_t nneedle)
586
return (void*)haystack; /* finding an empty needle is really easy */
587
if (nneedle <= nhaystack)
589
const unsigned char *a = haystack;
590
const unsigned char *b = a + nhaystack - nneedle;
594
if ( !ascii_memcasecmp (a, needle, nneedle) )
601
/*********************************************
602
********** missing string functions *********
603
*********************************************/
607
stpcpy(char *a,const char *b)
629
#ifndef HAVE_STRCASECMP
631
strcasecmp( const char *a, const char *b )
633
for( ; *a && *b; a++, b++ ) {
634
if( *a != *b && toupper(*a) != toupper(*b) )
637
return *(const byte*)a - *(const byte*)b;
643
* mingw32/cpd has a memicmp()
647
memicmp( const char *a, const char *b, size_t n )
649
for( ; n; n--, a++, b++ )
650
if( *a != *b && toupper(*(const byte*)a) != toupper(*(const byte*)b) )
651
return *(const byte *)a - *(const byte*)b;