Imported Upstream version 0.18.1.1
[platform/upstream/gettext.git] / gettext-tools / gnulib-lib / glib / gstring.c
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 3 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
52 struct _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  */
76 gboolean
77 g_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  */
96 guint
97 g_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
112 static inline gsize
113 nearest_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
135 GStringChunk*
136 g_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
152 void
153 g_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
173 gchar*
174 g_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
182 gchar*
183 g_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  **/
221 gchar*
222 g_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  */
264 static void
265 g_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
275 GString*
276 g_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
290 GString*
291 g_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
310 GString*
311 g_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
329 gchar*
330 g_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
352 gboolean
353 g_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 */
378 guint
379 g_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
394 GString*
395 g_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
413 GString*
414 g_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  **/
438 GString*
439 g_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
455 GString*
456 g_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
526 GString*
527 g_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
536 GString*
537 g_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
548 GString*
549 g_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  **/
567 GString*
568 g_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
578 GString*
579 g_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
588 GString*
589 g_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
599 GString*
600 g_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  **/
618 GString*
619 g_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
627 GString*
628 g_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
642 GString*
643 g_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  **/
681 GString*
682 g_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
754 GString*
755 g_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  **/
790 GString*
791 g_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  **/
821 GString*
822 g_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  */
854 GString*
855 g_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  **/
888 GString*
889 g_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
912 static void
913 g_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
927 void
928 g_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
943 void
944 g_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