1/* GLIB - Library of useful routines for C programming 2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public 6 * License as published by the Free Software Foundation; either 7 * version 2 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public 15 * License along with this library; if not, write to the 16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 17 * Boston, MA 02111-1307, USA. 18 */ 19 20/* 21 * Modified by the GLib Team and others 1997-2000. See the AUTHORS 22 * file for a list of people on the GLib Team. See the ChangeLog 23 * files for a list of changes. These files are distributed with 24 * GLib at ftp://ftp.gtk.org/pub/gtk/. 25 */ 26 27/* 28 * Modified by Bruno Haible for use as a gnulib module. 29 */ 30 31/* 32 * MT safe 33 */ 34 35#include "config.h" 36 37#ifdef HAVE_UNISTD_H 38#include <unistd.h> 39#endif 40#include <stdarg.h> 41#include <stdlib.h> 42#include <stdio.h> 43#include <string.h> 44#include <ctype.h> 45 46#include "glib.h" 47#if 0 48#include "gprintf.h" 49 50#include "galias.h" 51 52struct _GStringChunk 53{ 54 GHashTable *const_table; 55 GSList *storage_list; 56 gsize storage_next; 57 gsize this_size; 58 gsize default_size; 59}; 60#endif 61 62/* Hash Functions. 63 */ 64 65/** 66 * g_str_equal: 67 * @v1: a key. 68 * @v2: a key to compare with @v1. 69 * 70 * Compares two strings and returns %TRUE if they are equal. 71 * It can be passed to g_hash_table_new() as the @key_equal_func 72 * parameter, when using strings as keys in a #GHashTable. 73 * 74 * Returns: %TRUE if the two keys match. 75 */ 76gboolean 77g_str_equal (gconstpointer v1, 78 gconstpointer v2) 79{ 80 const gchar *string1 = v1; 81 const gchar *string2 = v2; 82 83 return strcmp (string1, string2) == 0; 84} 85 86/** 87 * g_str_hash: 88 * @v: a string key. 89 * 90 * Converts a string to a hash value. 91 * It can be passed to g_hash_table_new() as the @hash_func parameter, 92 * when using strings as keys in a #GHashTable. 93 * 94 * Returns: a hash value corresponding to the key. 95 */ 96guint 97g_str_hash (gconstpointer v) 98{ 99 /* 31 bit hash function */ 100 const signed char *p = v; 101 guint32 h = *p; 102 103 if (h) 104 for (p += 1; *p != '\0'; p++) 105 h = (h << 5) - h + *p; 106 107 return h; 108} 109 110#define MY_MAXSIZE ((gsize)-1) 111 112static inline gsize 113nearest_power (gsize base, gsize num) 114{ 115 if (num > MY_MAXSIZE / 2) 116 { 117 return MY_MAXSIZE; 118 } 119 else 120 { 121 gsize n = base; 122 123 while (n < num) 124 n <<= 1; 125 126 return n; 127 } 128} 129 130#if 0 131 132/* String Chunks. 133 */ 134 135GStringChunk* 136g_string_chunk_new (gsize default_size) 137{ 138 GStringChunk *new_chunk = g_new (GStringChunk, 1); 139 gsize size = 1; 140 141 size = nearest_power (1, default_size); 142 143 new_chunk->const_table = NULL; 144 new_chunk->storage_list = NULL; 145 new_chunk->storage_next = size; 146 new_chunk->default_size = size; 147 new_chunk->this_size = size; 148 149 return new_chunk; 150} 151 152void 153g_string_chunk_free (GStringChunk *chunk) 154{ 155 GSList *tmp_list; 156 157 g_return_if_fail (chunk != NULL); 158 159 if (chunk->storage_list) 160 { 161 for (tmp_list = chunk->storage_list; tmp_list; tmp_list = tmp_list->next) 162 g_free (tmp_list->data); 163 164 g_slist_free (chunk->storage_list); 165 } 166 167 if (chunk->const_table) 168 g_hash_table_destroy (chunk->const_table); 169 170 g_free (chunk); 171} 172 173gchar* 174g_string_chunk_insert (GStringChunk *chunk, 175 const gchar *string) 176{ 177 g_return_val_if_fail (chunk != NULL, NULL); 178 179 return g_string_chunk_insert_len (chunk, string, -1); 180} 181 182gchar* 183g_string_chunk_insert_const (GStringChunk *chunk, 184 const gchar *string) 185{ 186 char* lookup; 187 188 g_return_val_if_fail (chunk != NULL, NULL); 189 190 if (!chunk->const_table) 191 chunk->const_table = g_hash_table_new (g_str_hash, g_str_equal); 192 193 lookup = (char*) g_hash_table_lookup (chunk->const_table, (gchar *)string); 194 195 if (!lookup) 196 { 197 lookup = g_string_chunk_insert (chunk, string); 198 g_hash_table_insert (chunk->const_table, lookup, lookup); 199 } 200 201 return lookup; 202} 203 204/** 205 * g_string_chunk_insert_len: 206 * @chunk: a #GStringChunk 207 * @string: bytes to insert 208 * @len: number of bytes of @string to insert, or -1 to insert a 209 * nul-terminated string. 210 * 211 * Adds a copy of the first @len bytes of @string to the #GStringChunk. The 212 * copy is nul-terminated. 213 * 214 * The characters in the string can be changed, if necessary, though you 215 * should not change anything after the end of the string. 216 * 217 * Return value: a pointer to the copy of @string within the #GStringChunk 218 * 219 * Since: 2.4 220 **/ 221gchar* 222g_string_chunk_insert_len (GStringChunk *chunk, 223 const gchar *string, 224 gssize len) 225{ 226 gssize size; 227 gchar* pos; 228 229 g_return_val_if_fail (chunk != NULL, NULL); 230 231 if (len < 0) 232 size = strlen (string); 233 else 234 size = len; 235 236 if ((chunk->storage_next + size + 1) > chunk->this_size) 237 { 238 gsize new_size = nearest_power (chunk->default_size, size + 1); 239 240 chunk->storage_list = g_slist_prepend (chunk->storage_list, 241 g_new (gchar, new_size)); 242 243 chunk->this_size = new_size; 244 chunk->storage_next = 0; 245 } 246 247 pos = ((gchar *) chunk->storage_list->data) + chunk->storage_next; 248 249 *(pos + size) = '\0'; 250 251 strncpy (pos, string, size); 252 if (len > 0) 253 size = strlen (pos); 254 255 chunk->storage_next += size + 1; 256 257 return pos; 258} 259 260#endif 261 262/* Strings. 263 */ 264static void 265g_string_maybe_expand (GString* string, 266 gsize len) 267{ 268 if (string->len + len >= string->allocated_len) 269 { 270 string->allocated_len = nearest_power (1, string->len + len + 1); 271 string->str = g_realloc (string->str, string->allocated_len); 272 } 273} 274 275GString* 276g_string_sized_new (gsize dfl_size) 277{ 278 GString *string = g_slice_new (GString); 279 280 string->allocated_len = 0; 281 string->len = 0; 282 string->str = NULL; 283 284 g_string_maybe_expand (string, MAX (dfl_size, 2)); 285 string->str[0] = 0; 286 287 return string; 288} 289 290GString* 291g_string_new (const gchar *init) 292{ 293 GString *string; 294 295 if (init == NULL || *init == '\0') 296 string = g_string_sized_new (2); 297 else 298 { 299 gint len; 300 301 len = strlen (init); 302 string = g_string_sized_new (len + 2); 303 304 g_string_append_len (string, init, len); 305 } 306 307 return string; 308} 309 310GString* 311g_string_new_len (const gchar *init, 312 gssize len) 313{ 314 GString *string; 315 316 if (len < 0) 317 return g_string_new (init); 318 else 319 { 320 string = g_string_sized_new (len); 321 322 if (init) 323 g_string_append_len (string, init, len); 324 325 return string; 326 } 327} 328 329gchar* 330g_string_free (GString *string, 331 gboolean free_segment) 332{ 333 gchar *segment; 334 335 g_return_val_if_fail (string != NULL, NULL); 336 337 if (free_segment) 338 { 339 g_free (string->str); 340 segment = NULL; 341 } 342 else 343 segment = string->str; 344 345 g_slice_free (GString, string); 346 347 return segment; 348} 349 350#if 0 351 352gboolean 353g_string_equal (const GString *v, 354 const GString *v2) 355{ 356 gchar *p, *q; 357 GString *string1 = (GString *) v; 358 GString *string2 = (GString *) v2; 359 gsize i = string1->len; 360 361 if (i != string2->len) 362 return FALSE; 363 364 p = string1->str; 365 q = string2->str; 366 while (i) 367 { 368 if (*p != *q) 369 return FALSE; 370 p++; 371 q++; 372 i--; 373 } 374 return TRUE; 375} 376 377/* 31 bit hash function */ 378guint 379g_string_hash (const GString *str) 380{ 381 const gchar *p = str->str; 382 gsize n = str->len; 383 guint h = 0; 384 385 while (n--) 386 { 387 h = (h << 5) - h + *p; 388 p++; 389 } 390 391 return h; 392} 393 394GString* 395g_string_assign (GString *string, 396 const gchar *rval) 397{ 398 g_return_val_if_fail (string != NULL, NULL); 399 g_return_val_if_fail (rval != NULL, string); 400 401 /* Make sure assigning to itself doesn't corrupt the string. */ 402 if (string->str != rval) 403 { 404 /* Assigning from substring should be ok since g_string_truncate 405 does not realloc. */ 406 g_string_truncate (string, 0); 407 g_string_append (string, rval); 408 } 409 410 return string; 411} 412 413GString* 414g_string_truncate (GString *string, 415 gsize len) 416{ 417 g_return_val_if_fail (string != NULL, NULL); 418 419 string->len = MIN (len, string->len); 420 string->str[string->len] = 0; 421 422 return string; 423} 424 425/** 426 * g_string_set_size: 427 * @string: a #GString 428 * @len: the new length 429 * 430 * Sets the length of a #GString. If the length is less than 431 * the current length, the string will be truncated. If the 432 * length is greater than the current length, the contents 433 * of the newly added area are undefined. (However, as 434 * always, string->str[string->len] will be a nul byte.) 435 * 436 * Return value: @string 437 **/ 438GString* 439g_string_set_size (GString *string, 440 gsize len) 441{ 442 g_return_val_if_fail (string != NULL, NULL); 443 444 if (len >= string->allocated_len) 445 g_string_maybe_expand (string, len - string->len); 446 447 string->len = len; 448 string->str[len] = 0; 449 450 return string; 451} 452 453#endif 454 455GString* 456g_string_insert_len (GString *string, 457 gssize pos, 458 const gchar *val, 459 gssize len) 460{ 461 g_return_val_if_fail (string != NULL, NULL); 462 g_return_val_if_fail (val != NULL, string); 463 464 if (len < 0) 465 len = strlen (val); 466 467 if (pos < 0) 468 pos = string->len; 469 else 470 g_return_val_if_fail (pos <= string->len, string); 471 472 /* Check whether val represents a substring of string. This test 473 probably violates chapter and verse of the C standards, since 474 ">=" and "<=" are only valid when val really is a substring. 475 In practice, it will work on modern archs. */ 476 if (val >= string->str && val <= string->str + string->len) 477 { 478 gsize offset = val - string->str; 479 gsize precount = 0; 480 481 g_string_maybe_expand (string, len); 482 val = string->str + offset; 483 /* At this point, val is valid again. */ 484 485 /* Open up space where we are going to insert. */ 486 if (pos < string->len) 487 g_memmove (string->str + pos + len, string->str + pos, string->len - pos); 488 489 /* Move the source part before the gap, if any. */ 490 if (offset < pos) 491 { 492 precount = MIN (len, pos - offset); 493 memcpy (string->str + pos, val, precount); 494 } 495 496 /* Move the source part after the gap, if any. */ 497 if (len > precount) 498 memcpy (string->str + pos + precount, 499 val + /* Already moved: */ precount + /* Space opened up: */ len, 500 len - precount); 501 } 502 else 503 { 504 g_string_maybe_expand (string, len); 505 506 /* If we aren't appending at the end, move a hunk 507 * of the old string to the end, opening up space 508 */ 509 if (pos < string->len) 510 g_memmove (string->str + pos + len, string->str + pos, string->len - pos); 511 512 /* insert the new string */ 513 if (len == 1) 514 string->str[pos] = *val; 515 else 516 memcpy (string->str + pos, val, len); 517 } 518 519 string->len += len; 520 521 string->str[string->len] = 0; 522 523 return string; 524} 525 526GString* 527g_string_append (GString *string, 528 const gchar *val) 529{ 530 g_return_val_if_fail (string != NULL, NULL); 531 g_return_val_if_fail (val != NULL, string); 532 533 return g_string_insert_len (string, -1, val, -1); 534} 535 536GString* 537g_string_append_len (GString *string, 538 const gchar *val, 539 gssize len) 540{ 541 g_return_val_if_fail (string != NULL, NULL); 542 g_return_val_if_fail (val != NULL, string); 543 544 return g_string_insert_len (string, -1, val, len); 545} 546 547#undef g_string_append_c 548GString* 549g_string_append_c (GString *string, 550 gchar c) 551{ 552 g_return_val_if_fail (string != NULL, NULL); 553 554 return g_string_insert_c (string, -1, c); 555} 556 557/** 558 * g_string_append_unichar: 559 * @string: a #GString 560 * @wc: a Unicode character 561 * 562 * Converts a Unicode character into UTF-8, and appends it 563 * to the string. 564 * 565 * Return value: @string 566 **/ 567GString* 568g_string_append_unichar (GString *string, 569 gunichar wc) 570{ 571 g_return_val_if_fail (string != NULL, NULL); 572 573 return g_string_insert_unichar (string, -1, wc); 574} 575 576#if 0 577 578GString* 579g_string_prepend (GString *string, 580 const gchar *val) 581{ 582 g_return_val_if_fail (string != NULL, NULL); 583 g_return_val_if_fail (val != NULL, string); 584 585 return g_string_insert_len (string, 0, val, -1); 586} 587 588GString* 589g_string_prepend_len (GString *string, 590 const gchar *val, 591 gssize len) 592{ 593 g_return_val_if_fail (string != NULL, NULL); 594 g_return_val_if_fail (val != NULL, string); 595 596 return g_string_insert_len (string, 0, val, len); 597} 598 599GString* 600g_string_prepend_c (GString *string, 601 gchar c) 602{ 603 g_return_val_if_fail (string != NULL, NULL); 604 605 return g_string_insert_c (string, 0, c); 606} 607 608/** 609 * g_string_prepend_unichar: 610 * @string: a #GString. 611 * @wc: a Unicode character. 612 * 613 * Converts a Unicode character into UTF-8, and prepends it 614 * to the string. 615 * 616 * Return value: @string. 617 **/ 618GString* 619g_string_prepend_unichar (GString *string, 620 gunichar wc) 621{ 622 g_return_val_if_fail (string != NULL, NULL); 623 624 return g_string_insert_unichar (string, 0, wc); 625} 626 627GString* 628g_string_insert (GString *string, 629 gssize pos, 630 const gchar *val) 631{ 632 g_return_val_if_fail (string != NULL, NULL); 633 g_return_val_if_fail (val != NULL, string); 634 if (pos >= 0) 635 g_return_val_if_fail (pos <= string->len, string); 636 637 return g_string_insert_len (string, pos, val, -1); 638} 639 640#endif 641 642GString* 643g_string_insert_c (GString *string, 644 gssize pos, 645 gchar c) 646{ 647 g_return_val_if_fail (string != NULL, NULL); 648 649 g_string_maybe_expand (string, 1); 650 651 if (pos < 0) 652 pos = string->len; 653 else 654 g_return_val_if_fail (pos <= string->len, string); 655 656 /* If not just an append, move the old stuff */ 657 if (pos < string->len) 658 g_memmove (string->str + pos + 1, string->str + pos, string->len - pos); 659 660 string->str[pos] = c; 661 662 string->len += 1; 663 664 string->str[string->len] = 0; 665 666 return string; 667} 668 669/** 670 * g_string_insert_unichar: 671 * @string: a #GString 672 * @pos: the position at which to insert character, or -1 to 673 * append at the end of the string. 674 * @wc: a Unicode character 675 * 676 * Converts a Unicode character into UTF-8, and insert it 677 * into the string at the given position. 678 * 679 * Return value: @string 680 **/ 681GString* 682g_string_insert_unichar (GString *string, 683 gssize pos, 684 gunichar wc) 685{ 686 gint charlen, first, i; 687 gchar *dest; 688 689 g_return_val_if_fail (string != NULL, NULL); 690 691 /* Code copied from g_unichar_to_utf() */ 692 if (wc < 0x80) 693 { 694 first = 0; 695 charlen = 1; 696 } 697 else if (wc < 0x800) 698 { 699 first = 0xc0; 700 charlen = 2; 701 } 702 else if (wc < 0x10000) 703 { 704 first = 0xe0; 705 charlen = 3; 706 } 707 else if (wc < 0x200000) 708 { 709 first = 0xf0; 710 charlen = 4; 711 } 712 else if (wc < 0x4000000) 713 { 714 first = 0xf8; 715 charlen = 5; 716 } 717 else 718 { 719 first = 0xfc; 720 charlen = 6; 721 } 722 /* End of copied code */ 723 724 g_string_maybe_expand (string, charlen); 725 726 if (pos < 0) 727 pos = string->len; 728 else 729 g_return_val_if_fail (pos <= string->len, string); 730 731 /* If not just an append, move the old stuff */ 732 if (pos < string->len) 733 g_memmove (string->str + pos + charlen, string->str + pos, string->len - pos); 734 735 dest = string->str + pos; 736 /* Code copied from g_unichar_to_utf() */ 737 for (i = charlen - 1; i > 0; --i) 738 { 739 dest[i] = (wc & 0x3f) | 0x80; 740 wc >>= 6; 741 } 742 dest[0] = wc | first; 743 /* End of copied code */ 744 745 string->len += charlen; 746 747 string->str[string->len] = 0; 748 749 return string; 750} 751 752#if 0 753 754GString* 755g_string_erase (GString *string, 756 gssize pos, 757 gssize len) 758{ 759 g_return_val_if_fail (string != NULL, NULL); 760 g_return_val_if_fail (pos >= 0, string); 761 g_return_val_if_fail (pos <= string->len, string); 762 763 if (len < 0) 764 len = string->len - pos; 765 else 766 { 767 g_return_val_if_fail (pos + len <= string->len, string); 768 769 if (pos + len < string->len) 770 g_memmove (string->str + pos, string->str + pos + len, string->len - (pos + len)); 771 } 772 773 string->len -= len; 774 775 string->str[string->len] = 0; 776 777 return string; 778} 779 780/** 781 * g_string_ascii_down: 782 * @string: a GString 783 * 784 * Converts all upper case ASCII letters to lower case ASCII letters. 785 * 786 * Return value: passed-in @string pointer, with all the upper case 787 * characters converted to lower case in place, with 788 * semantics that exactly match g_ascii_tolower. 789 **/ 790GString* 791g_string_ascii_down (GString *string) 792{ 793 gchar *s; 794 gint n; 795 796 g_return_val_if_fail (string != NULL, NULL); 797 798 n = string->len; 799 s = string->str; 800 801 while (n) 802 { 803 *s = g_ascii_tolower (*s); 804 s++; 805 n--; 806 } 807 808 return string; 809} 810 811/** 812 * g_string_ascii_up: 813 * @string: a GString 814 * 815 * Converts all lower case ASCII letters to upper case ASCII letters. 816 * 817 * Return value: passed-in @string pointer, with all the lower case 818 * characters converted to upper case in place, with 819 * semantics that exactly match g_ascii_toupper. 820 **/ 821GString* 822g_string_ascii_up (GString *string) 823{ 824 gchar *s; 825 gint n; 826 827 g_return_val_if_fail (string != NULL, NULL); 828 829 n = string->len; 830 s = string->str; 831 832 while (n) 833 { 834 *s = g_ascii_toupper (*s); 835 s++; 836 n--; 837 } 838 839 return string; 840} 841 842/** 843 * g_string_down: 844 * @string: a #GString 845 * 846 * Converts a #GString to lowercase. 847 * 848 * Returns: the #GString. 849 * 850 * Deprecated:2.2: This function uses the locale-specific tolower() function, 851 * which is almost never the right thing. Use g_string_ascii_down() or 852 * g_utf8_strdown() instead. 853 */ 854GString* 855g_string_down (GString *string) 856{ 857 guchar *s; 858 glong n; 859 860 g_return_val_if_fail (string != NULL, NULL); 861 862 n = string->len; 863 s = (guchar *) string->str; 864 865 while (n) 866 { 867 if (isupper (*s)) 868 *s = tolower (*s); 869 s++; 870 n--; 871 } 872 873 return string; 874} 875 876/** 877 * g_string_up: 878 * @string: a #GString 879 * 880 * Converts a #GString to uppercase. 881 * 882 * Return value: the #GString 883 * 884 * Deprecated:2.2: This function uses the locale-specific toupper() function, 885 * which is almost never the right thing. Use g_string_ascii_up() or 886 * g_utf8_strup() instead. 887 **/ 888GString* 889g_string_up (GString *string) 890{ 891 guchar *s; 892 glong n; 893 894 g_return_val_if_fail (string != NULL, NULL); 895 896 n = string->len; 897 s = (guchar *) string->str; 898 899 while (n) 900 { 901 if (islower (*s)) 902 *s = toupper (*s); 903 s++; 904 n--; 905 } 906 907 return string; 908} 909 910#endif 911 912static void 913g_string_append_printf_internal (GString *string, 914 const gchar *fmt, 915 va_list args) 916{ 917 gchar *buffer; 918 gint length; 919 920 length = g_vasprintf (&buffer, fmt, args); 921 g_string_append_len (string, buffer, length); 922 g_free (buffer); 923} 924 925#if 0 926 927void 928g_string_printf (GString *string, 929 const gchar *fmt, 930 ...) 931{ 932 va_list args; 933 934 g_string_truncate (string, 0); 935 936 va_start (args, fmt); 937 g_string_append_printf_internal (string, fmt, args); 938 va_end (args); 939} 940 941#endif 942 943void 944g_string_append_printf (GString *string, 945 const gchar *fmt, 946 ...) 947{ 948 va_list args; 949 950 va_start (args, fmt); 951 g_string_append_printf_internal (string, fmt, args); 952 va_end (args); 953} 954 955#if 0 956#define __G_STRING_C__ 957#include "galiasdef.c" 958#endif 959