• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500v2-V1.0.0.60_1.0.38/ap/gpl/timemachine/gettext-0.17/gettext-tools/gnulib-lib/glib/
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