[build] Skips RemoteExecuted bases tests on monodroid
[mono-project.git] / mono / eglib / gstr.c
blobdc2346cc9958f903b0885bab268375234096880e
1 /*
2 * gstr.c: String Utility Functions.
4 * Author:
5 * Miguel de Icaza (miguel@novell.com)
6 * Aaron Bockover (abockover@novell.com)
8 * (C) 2006 Novell, Inc.
10 * Permission is hereby granted, free of charge, to any person obtaining
11 * a copy of this software and associated documentation files (the
12 * "Software"), to deal in the Software without restriction, including
13 * without limitation the rights to use, copy, modify, merge, publish,
14 * distribute, sublicense, and/or sell copies of the Software, and to
15 * permit persons to whom the Software is furnished to do so, subject to
16 * the following conditions:
18 * The above copyright notice and this permission notice shall be
19 * included in all copies or substantial portions of the Software.
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 #include <config.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <ctype.h>
33 #include <glib.h>
35 #ifndef G_OS_WIN32
36 #include <pthread.h>
37 #endif
39 #include <errno.h>
41 /*
42 * g_strndup and g_vasprintf need to allocate memory with g_malloc if
43 * ENABLE_OVERRIDABLE_ALLOCATORS is defined so that it can be safely freed with g_free
44 * rather than free.
47 /* This is not a macro, because I dont want to put _GNU_SOURCE in the glib.h header */
48 gchar *
49 g_strndup (const gchar *str, gsize n)
51 #if defined (HAVE_STRNDUP) && !defined (ENABLE_OVERRIDABLE_ALLOCATORS)
52 return strndup (str, n);
53 #else
54 if (str) {
55 char *retval = g_malloc(n+1);
56 if (retval) {
57 strncpy(retval, str, n)[n] = 0;
59 return retval;
61 return NULL;
62 #endif
65 gint g_vasprintf (gchar **ret, const gchar *fmt, va_list ap)
67 #if defined (HAVE_VASPRINTF) && !defined (ENABLE_OVERRIDABLE_ALLOCATORS)
68 return vasprintf (ret, fmt, ap);
69 #else
70 char *buf;
71 int len;
72 size_t buflen;
73 va_list ap2;
75 #if defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR)
76 ap2 = ap;
77 len = _vscprintf(fmt, ap2); // NOTE MS specific extension ( :-( )
78 #else
79 va_copy(ap2, ap);
80 len = vsnprintf(NULL, 0, fmt, ap2);
81 #endif
83 if (len >= 0 && (buf = g_malloc ((buflen = (size_t) (len + 1)))) != NULL) {
84 len = vsnprintf(buf, buflen, fmt, ap);
85 *ret = buf;
86 } else {
87 *ret = NULL;
88 len = -1;
91 va_end(ap2);
92 return len;
93 #endif
96 void
97 g_strfreev (gchar **str_array)
99 gchar **orig = str_array;
100 if (str_array == NULL)
101 return;
102 while (*str_array != NULL){
103 g_free (*str_array);
104 str_array++;
106 g_free (orig);
109 gchar **
110 g_strdupv (gchar **str_array)
112 guint length;
113 gchar **ret;
114 guint i;
116 if (!str_array)
117 return NULL;
119 length = g_strv_length(str_array);
120 ret = g_new0(gchar *, length + 1);
121 for (i = 0; str_array[i]; i++) {
122 ret[i] = g_strdup(str_array[i]);
124 ret[length] = NULL;
125 return ret;
128 guint
129 g_strv_length(gchar **str_array)
131 gint length = 0;
132 g_return_val_if_fail(str_array != NULL, 0);
133 for(length = 0; str_array[length] != NULL; length++);
134 return length;
137 gboolean
138 g_str_has_suffix(const gchar *str, const gchar *suffix)
140 size_t str_length;
141 size_t suffix_length;
143 g_return_val_if_fail(str != NULL, FALSE);
144 g_return_val_if_fail(suffix != NULL, FALSE);
146 str_length = strlen(str);
147 suffix_length = strlen(suffix);
149 return suffix_length <= str_length ?
150 strncmp(str + str_length - suffix_length, suffix, suffix_length) == 0 :
151 FALSE;
154 gboolean
155 g_str_has_prefix(const gchar *str, const gchar *prefix)
157 size_t str_length;
158 size_t prefix_length;
160 g_return_val_if_fail(str != NULL, FALSE);
161 g_return_val_if_fail(prefix != NULL, FALSE);
163 str_length = strlen(str);
164 prefix_length = strlen(prefix);
166 return prefix_length <= str_length ?
167 strncmp(str, prefix, prefix_length) == 0 :
168 FALSE;
171 gchar *
172 g_strdup_vprintf (const gchar *format, va_list args)
174 int n;
175 char *ret;
177 n = g_vasprintf (&ret, format, args);
178 if (n == -1)
179 return NULL;
181 return ret;
184 gchar *
185 g_strdup_printf (const gchar *format, ...)
187 gchar *ret;
188 va_list args;
189 int n;
191 va_start (args, format);
192 n = g_vasprintf (&ret, format, args);
193 va_end (args);
194 if (n == -1)
195 return NULL;
197 return ret;
202 Max error number we support. It's empirically found by looking at our target OS.
204 Last this was checked was June-2017.
206 Apple is at 106.
207 Android is at 133.
209 #define MONO_ERRNO_MAX 200
210 #define str(s) #s
212 #ifndef G_OS_WIN32
213 static pthread_mutex_t strerror_lock = PTHREAD_MUTEX_INITIALIZER;
214 #endif
216 static char *error_messages [MONO_ERRNO_MAX];
218 const gchar *
219 g_strerror (gint errnum)
221 if (errnum < 0)
222 errnum = -errnum;
223 if (errnum >= MONO_ERRNO_MAX)
224 return ("Error number higher than " str (MONO_ERRNO_MAX));
226 if (!error_messages [errnum]) {
227 #ifndef G_OS_WIN32
228 pthread_mutex_lock (&strerror_lock);
229 #endif
231 #ifdef HAVE_STRERROR_R
232 char tmp_buff [128]; //Quite arbitrary, should be large enough
233 char *buff = tmp_buff;
234 size_t buff_len = sizeof (tmp_buff);
235 buff [0] = 0;
237 #ifndef STRERROR_R_CHAR_P
238 int r;
239 while ((r = strerror_r (errnum, buff, buff_len - 1))) {
240 if (r != ERANGE) {
241 buff = g_strdup_printf ("Invalid Error code '%d'", errnum);
242 break;
244 if (buff == tmp_buff)
245 buff = g_malloc (buff_len * 2);
246 else
247 buff = g_realloc (buff, buff_len * 2);
248 buff_len *= 2;
249 //Spec is not clean on whether size argument includes space for null terminator or not
251 if (!error_messages [errnum])
252 error_messages [errnum] = g_strdup (buff);
253 if (buff != tmp_buff)
254 g_free (buff);
255 #else /* STRERROR_R_CHAR_P */
256 buff = strerror_r (errnum, buff, buff_len);
257 if (!error_messages [errnum])
258 error_messages [errnum] = g_strdup (buff);
259 #endif /* STRERROR_R_CHAR_P */
261 #else /* HAVE_STRERROR_R */
262 if (!error_messages [errnum])
263 error_messages [errnum] = g_strdup_printf ("Error code '%d'", errnum);
264 #endif /* HAVE_STRERROR_R */
267 #ifndef G_OS_WIN32
268 pthread_mutex_unlock (&strerror_lock);
269 #endif
272 return error_messages [errnum];
275 gchar *
276 g_strconcat (const gchar *first, ...)
278 va_list args;
279 size_t total = 0;
280 char *s, *ret;
281 g_return_val_if_fail (first != NULL, NULL);
283 total += strlen (first);
284 va_start (args, first);
285 for (s = va_arg (args, char *); s != NULL; s = va_arg(args, char *)){
286 total += strlen (s);
288 va_end (args);
290 ret = g_malloc (total + 1);
291 if (ret == NULL)
292 return NULL;
294 ret [total] = 0;
295 strcpy (ret, first);
296 va_start (args, first);
297 for (s = va_arg (args, char *); s != NULL; s = va_arg(args, char *)){
298 strcat (ret, s);
300 va_end (args);
302 return ret;
305 static void
306 add_to_vector (gchar ***vector, int size, gchar *token)
308 *vector = *vector == NULL ?
309 (gchar **)g_malloc(2 * sizeof(*vector)) :
310 (gchar **)g_realloc(*vector, (size + 1) * sizeof(*vector));
312 (*vector)[size - 1] = token;
315 gchar **
316 g_strsplit (const gchar *string, const gchar *delimiter, gint max_tokens)
318 const gchar *c;
319 gchar *token, **vector;
320 gint size = 1;
322 g_return_val_if_fail (string != NULL, NULL);
323 g_return_val_if_fail (delimiter != NULL, NULL);
324 g_return_val_if_fail (delimiter[0] != 0, NULL);
326 if (strncmp (string, delimiter, strlen (delimiter)) == 0) {
327 vector = (gchar **)g_malloc (2 * sizeof(vector));
328 vector[0] = g_strdup ("");
329 size++;
330 string += strlen (delimiter);
331 } else {
332 vector = NULL;
335 while (*string && !(max_tokens > 0 && size >= max_tokens)) {
336 c = string;
337 if (strncmp (string, delimiter, strlen (delimiter)) == 0) {
338 token = g_strdup ("");
339 string += strlen (delimiter);
340 } else {
341 while (*string && strncmp (string, delimiter, strlen (delimiter)) != 0) {
342 string++;
345 if (*string) {
346 gsize toklen = (string - c);
347 token = g_strndup (c, toklen);
349 /* Need to leave a trailing empty
350 * token if the delimiter is the last
351 * part of the string
353 if (strcmp (string, delimiter) != 0) {
354 string += strlen (delimiter);
356 } else {
357 token = g_strdup (c);
361 add_to_vector (&vector, size, token);
362 size++;
365 if (*string) {
366 if (strcmp (string, delimiter) == 0)
367 add_to_vector (&vector, size, g_strdup (""));
368 else {
369 /* Add the rest of the string as the last element */
370 add_to_vector (&vector, size, g_strdup (string));
372 size++;
375 if (vector == NULL) {
376 vector = (gchar **) g_malloc (2 * sizeof (vector));
377 vector [0] = NULL;
378 } else if (size > 0) {
379 vector[size - 1] = NULL;
382 return vector;
385 static gboolean
386 charcmp (gchar testchar, const gchar *compare)
388 while(*compare) {
389 if (*compare == testchar) {
390 return TRUE;
392 compare++;
395 return FALSE;
398 gchar **
399 g_strsplit_set (const gchar *string, const gchar *delimiter, gint max_tokens)
401 const gchar *c;
402 gchar *token, **vector;
403 gint size = 1;
405 g_return_val_if_fail (string != NULL, NULL);
406 g_return_val_if_fail (delimiter != NULL, NULL);
407 g_return_val_if_fail (delimiter[0] != 0, NULL);
409 if (charcmp (*string, delimiter)) {
410 vector = (gchar **)g_malloc (2 * sizeof(vector));
411 vector[0] = g_strdup ("");
412 size++;
413 string++;
414 } else {
415 vector = NULL;
418 c = string;
419 while (*string && !(max_tokens > 0 && size >= max_tokens)) {
420 if (charcmp (*string, delimiter)) {
421 gsize toklen = (string - c);
422 if (toklen == 0) {
423 token = g_strdup ("");
424 } else {
425 token = g_strndup (c, toklen);
428 c = string + 1;
430 add_to_vector (&vector, size, token);
431 size++;
434 string++;
437 if (max_tokens > 0 && size >= max_tokens) {
438 if (*string) {
439 /* Add the rest of the string as the last element */
440 add_to_vector (&vector, size, g_strdup (string));
441 size++;
443 } else {
444 if (*c) {
445 /* Fill in the trailing last token */
446 add_to_vector (&vector, size, g_strdup (c));
447 size++;
448 } else {
449 /* Need to leave a trailing empty token if the
450 * delimiter is the last part of the string
452 add_to_vector (&vector, size, g_strdup (""));
453 size++;
457 if (vector == NULL) {
458 vector = (gchar **) g_malloc (2 * sizeof (vector));
459 vector [0] = NULL;
460 } else if (size > 0) {
461 vector[size - 1] = NULL;
464 return vector;
467 gchar *
468 g_strreverse (gchar *str)
470 size_t i, j;
471 gchar c;
473 if (str == NULL)
474 return NULL;
476 if (*str == 0)
477 return str;
479 for (i = 0, j = strlen (str) - 1; i < j; i++, j--) {
480 c = str [i];
481 str [i] = str [j];
482 str [j] = c;
485 return str;
488 gchar *
489 g_strjoin (const gchar *separator, ...)
491 va_list args;
492 char *res, *s, *r;
493 size_t len, slen;
495 if (separator != NULL)
496 slen = strlen (separator);
497 else
498 slen = 0;
500 len = 0;
501 va_start (args, separator);
502 for (s = va_arg (args, char *); s != NULL; s = va_arg (args, char *)){
503 len += strlen (s);
504 len += slen;
506 va_end (args);
508 if (len == 0)
509 return g_strdup ("");
511 /* Remove the last separator */
512 if (slen > 0 && len > 0)
513 len -= slen;
515 res = g_malloc (len + 1);
516 va_start (args, separator);
517 s = va_arg (args, char *);
518 r = g_stpcpy (res, s);
519 for (s = va_arg (args, char *); s != NULL; s = va_arg (args, char *)){
520 if (separator != NULL)
521 r = g_stpcpy (r, separator);
522 r = g_stpcpy (r, s);
524 va_end (args);
526 return res;
529 gchar *
530 g_strjoinv (const gchar *separator, gchar **str_array)
532 char *res, *r;
533 size_t slen, len, i;
535 if (separator != NULL)
536 slen = strlen (separator);
537 else
538 slen = 0;
540 len = 0;
541 for (i = 0; str_array [i] != NULL; i++){
542 len += strlen (str_array [i]);
543 len += slen;
546 if (len == 0)
547 return g_strdup ("");
549 if (slen > 0 && len > 0)
550 len -= slen;
552 res = g_malloc (len + 1);
553 r = g_stpcpy (res, str_array [0]);
554 for (i = 1; str_array [i] != NULL; i++){
555 if (separator != NULL)
556 r = g_stpcpy (r, separator);
557 r = g_stpcpy (r, str_array [i]);
560 return res;
563 gchar *
564 g_strchug (gchar *str)
566 size_t len;
567 gchar *tmp;
569 if (str == NULL)
570 return NULL;
572 tmp = str;
573 while (*tmp && isspace (*tmp)) tmp++;
574 if (str != tmp) {
575 len = strlen (str) - (tmp - str - 1);
576 memmove (str, tmp, len);
578 return str;
581 gchar *
582 g_strchomp (gchar *str)
584 gchar *tmp;
586 if (str == NULL)
587 return NULL;
589 tmp = str + strlen (str) - 1;
590 while (*tmp && isspace (*tmp)) tmp--;
591 *(tmp + 1) = '\0';
592 return str;
595 gint
596 g_printf(gchar const *format, ...)
598 va_list args;
599 gint ret;
601 va_start(args, format);
602 ret = vprintf(format, args);
603 va_end(args);
605 return ret;
608 gint
609 g_fprintf(FILE *file, gchar const *format, ...)
611 va_list args;
612 gint ret;
614 va_start(args, format);
615 ret = vfprintf(file, format, args);
616 va_end(args);
618 return ret;
621 gint
622 g_sprintf(gchar *string, gchar const *format, ...)
624 va_list args;
625 gint ret;
627 va_start(args, format);
628 ret = vsprintf(string, format, args);
629 va_end(args);
631 return ret;
634 gint
635 g_snprintf(gchar *string, gulong n, gchar const *format, ...)
637 va_list args;
638 gint ret;
640 va_start(args, format);
641 ret = vsnprintf(string, n, format, args);
642 va_end(args);
644 return ret;
647 static const char hx [] = { '0', '1', '2', '3', '4', '5', '6', '7',
648 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
650 static gboolean
651 char_needs_encoding (char c)
653 if (((unsigned char)c) >= 0x80)
654 return TRUE;
656 if ((c >= '@' && c <= 'Z') ||
657 (c >= 'a' && c <= 'z') ||
658 (c >= '&' && c < 0x3b) ||
659 (c == '!') || (c == '$') || (c == '_') || (c == '=') || (c == '~'))
660 return FALSE;
661 return TRUE;
664 gchar *
665 g_filename_to_uri (const gchar *filename, const gchar *hostname, GError **gerror)
667 size_t n;
668 char *ret, *rp;
669 const char *p;
670 #ifdef G_OS_WIN32
671 const char *uriPrefix = "file:///";
672 #else
673 const char *uriPrefix = "file://";
674 #endif
676 g_return_val_if_fail (filename != NULL, NULL);
678 if (hostname != NULL)
679 g_warning ("%s", "eglib: g_filename_to_uri: hostname not handled");
681 if (!g_path_is_absolute (filename)){
682 if (gerror != NULL)
683 *gerror = g_error_new (NULL, 2, "Not an absolute filename");
685 return NULL;
688 n = strlen (uriPrefix) + 1;
689 for (p = filename; *p; p++){
690 #ifdef G_OS_WIN32
691 if (*p == '\\') {
692 n++;
693 continue;
695 #endif
696 if (char_needs_encoding (*p))
697 n += 3;
698 else
699 n++;
701 ret = g_malloc (n);
702 strcpy (ret, uriPrefix);
703 for (p = filename, rp = ret + strlen (ret); *p; p++){
704 #ifdef G_OS_WIN32
705 if (*p == '\\') {
706 *rp++ = '/';
707 continue;
709 #endif
710 if (char_needs_encoding (*p)){
711 *rp++ = '%';
712 *rp++ = hx [((unsigned char)(*p)) >> 4];
713 *rp++ = hx [((unsigned char)(*p)) & 0xf];
714 } else
715 *rp++ = *p;
717 *rp = 0;
718 return ret;
721 static int
722 decode (char p)
724 if (p >= '0' && p <= '9')
725 return p - '0';
726 if (p >= 'A' && p <= 'F')
727 return p - 'A';
728 if (p >= 'a' && p <= 'f')
729 return p - 'a';
730 g_assert_not_reached ();
731 return 0;
734 gchar *
735 g_filename_from_uri (const gchar *uri, gchar **hostname, GError **gerror)
737 const char *p;
738 char *r, *result;
739 int flen = 0;
741 g_return_val_if_fail (uri != NULL, NULL);
743 if (hostname != NULL)
744 g_warning ("%s", "eglib: g_filename_from_uri: hostname not handled");
746 if (strncmp (uri, "file:///", 8) != 0){
747 if (gerror != NULL)
748 *gerror = g_error_new (NULL, 2, "URI does not start with the file: scheme");
749 return NULL;
752 for (p = uri + 8; *p; p++){
753 if (*p == '%'){
754 if (p [1] && p [2] && isxdigit (p [1]) && isxdigit (p [2])){
755 p += 2;
756 } else {
757 if (gerror != NULL)
758 *gerror = g_error_new (NULL, 2, "URI contains an invalid escape sequence");
759 return NULL;
762 flen++;
764 #ifndef G_OS_WIN32
765 flen++;
766 #endif
768 result = g_malloc (flen + 1);
769 result [flen] = 0;
771 #ifndef G_OS_WIN32
772 *result = '/';
773 r = result + 1;
774 #else
775 r = result;
776 #endif
778 for (p = uri + 8; *p; p++){
779 if (*p == '%'){
780 *r++ = (char)((decode (p [1]) << 4) | decode (p [2]));
781 p += 2;
782 } else
783 *r++ = *p;
784 flen++;
786 return result;
789 void
790 g_strdown (gchar *string)
792 g_return_if_fail (string != NULL);
794 while (*string){
795 *string = (gchar)tolower (*string);
796 string++;
800 gchar
801 g_ascii_tolower (gchar c)
803 return c >= 'A' && c <= 'Z' ? c + ('a' - 'A') : c;
806 gchar *
807 g_ascii_strdown (const gchar *str, gssize len)
809 char *ret;
810 int i;
812 g_return_val_if_fail (str != NULL, NULL);
814 if (len == -1)
815 len = strlen (str);
817 ret = g_malloc (len + 1);
818 for (i = 0; i < len; i++)
819 ret [i] = (guchar) g_ascii_tolower (str [i]);
820 ret [i] = 0;
822 return ret;
825 gchar
826 g_ascii_toupper (gchar c)
828 return c >= 'a' && c <= 'z' ? c + ('A' - 'a') : c;
831 gchar *
832 g_ascii_strup (const gchar *str, gssize len)
834 char *ret;
835 int i;
837 g_return_val_if_fail (str != NULL, NULL);
839 if (len == -1)
840 len = strlen (str);
842 ret = g_malloc (len + 1);
843 for (i = 0; i < len; i++)
844 ret [i] = (guchar) g_ascii_toupper (str [i]);
845 ret [i] = 0;
847 return ret;
850 gint
851 g_ascii_strncasecmp (const gchar *s1, const gchar *s2, gsize n)
853 gsize i;
855 g_return_val_if_fail (s1 != NULL, 0);
856 g_return_val_if_fail (s2 != NULL, 0);
858 for (i = 0; i < n; i++) {
859 gchar c1 = g_ascii_tolower (*s1++);
860 gchar c2 = g_ascii_tolower (*s2++);
862 if (c1 != c2)
863 return c1 - c2;
866 return 0;
869 gint
870 g_ascii_strcasecmp (const gchar *s1, const gchar *s2)
872 const char *sp1 = s1;
873 const char *sp2 = s2;
875 g_return_val_if_fail (s1 != NULL, 0);
876 g_return_val_if_fail (s2 != NULL, 0);
878 while (*sp1 != '\0') {
879 char c1 = g_ascii_tolower (*sp1++);
880 char c2 = g_ascii_tolower (*sp2++);
882 if (c1 != c2)
883 return c1 - c2;
886 return (*sp1) - (*sp2);
889 gboolean
890 g_utf16_ascii_equal (const gunichar2 *utf16, size_t ulen, const char *ascii, size_t alen)
892 size_t i;
893 if (ulen != alen)
894 return FALSE;
895 for (i = 0; i < ulen; ++i) {
896 if (utf16[i] != ascii[i])
897 return FALSE;
899 return TRUE;
902 gboolean
903 g_utf16_asciiz_equal (const gunichar2 *utf16, const char *ascii)
904 // z for zero means null terminated
906 while (1)
908 char a = *ascii++;
909 gunichar2 u = *utf16++;
910 if (a != u)
911 return FALSE;
912 if (a == 0)
913 return TRUE;
917 gchar *
918 g_strdelimit (gchar *string, const gchar *delimiters, gchar new_delimiter)
920 gchar *ptr;
922 g_return_val_if_fail (string != NULL, NULL);
924 if (delimiters == NULL)
925 delimiters = G_STR_DELIMITERS;
927 for (ptr = string; *ptr; ptr++) {
928 if (strchr (delimiters, *ptr))
929 *ptr = new_delimiter;
932 return string;
935 gsize
936 g_strlcpy (gchar *dest, const gchar *src, gsize dest_size)
938 #ifdef HAVE_STRLCPY
939 return strlcpy (dest, src, dest_size);
940 #else
941 gchar *d;
942 const gchar *s;
943 gchar c;
944 gsize len;
946 g_return_val_if_fail (src != NULL, 0);
947 g_return_val_if_fail (dest != NULL, 0);
949 len = dest_size;
950 if (len == 0)
951 return 0;
953 s = src;
954 d = dest;
955 while (--len) {
956 c = *s++;
957 *d++ = c;
958 if (c == '\0')
959 return (dest_size - len - 1);
962 /* len is 0 i we get here */
963 *d = '\0';
964 /* we need to return the length of src here */
965 while (*s++) ; /* instead of a plain strlen, we use 's' */
966 return s - src - 1;
967 #endif
970 gchar *
971 g_stpcpy (gchar *dest, const char *src)
973 g_return_val_if_fail (dest != NULL, dest);
974 g_return_val_if_fail (src != NULL, dest);
976 #if HAVE_STPCPY
977 return stpcpy (dest, src);
978 #else
979 while (*src)
980 *dest++ = *src++;
982 *dest = '\0';
984 return dest;
985 #endif
988 static const gchar escaped_dflt [256] = {
989 1, 1, 1, 1, 1, 1, 1, 1, 'b', 't', 'n', 1, 'f', 'r', 1, 1,
990 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
991 0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
992 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
993 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
994 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '\\', 0, 0, 0,
995 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
996 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
997 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
998 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
999 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1000 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1001 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1002 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1003 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1004 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
1007 gchar *
1008 g_strescape (const gchar *source, const gchar *exceptions)
1010 gchar escaped [256];
1011 const gchar *ptr;
1012 gchar c;
1013 gchar op;
1014 gchar *result;
1015 gchar *res_ptr;
1017 g_return_val_if_fail (source != NULL, NULL);
1019 memcpy (escaped, escaped_dflt, 256);
1020 if (exceptions != NULL) {
1021 for (ptr = exceptions; *ptr; ptr++)
1022 escaped [(int) *ptr] = 0;
1024 result = g_malloc (strlen (source) * 4 + 1); /* Worst case: everything octal. */
1025 res_ptr = result;
1026 for (ptr = source; *ptr; ptr++) {
1027 c = *ptr;
1028 op = escaped [(int) c];
1029 if (op == 0) {
1030 *res_ptr++ = c;
1031 } else {
1032 *res_ptr++ = '\\';
1033 if (op != 1) {
1034 *res_ptr++ = op;
1035 } else {
1036 *res_ptr++ = '0' + ((c >> 6) & 3);
1037 *res_ptr++ = '0' + ((c >> 3) & 7);
1038 *res_ptr++ = '0' + (c & 7);
1042 *res_ptr = '\0';
1043 return result;
1046 gint
1047 g_ascii_xdigit_value (gchar c)
1049 return ((isxdigit (c) == 0) ? -1 :
1050 ((c >= '0' && c <= '9') ? (c - '0') :
1051 ((c >= 'a' && c <= 'f') ? (c - 'a' + 10) :
1052 (c - 'A' + 10))));
1055 gchar *
1056 g_strnfill (gsize length, gchar fill_char)
1058 gchar *ret = g_new (gchar, length + 1);
1060 memset (ret, fill_char, length);
1061 ret [length] = 0;
1062 return ret;