Merge branch 'dbus-1.2'
[platform/upstream/dbus.git] / dbus / dbus-string-util.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-string-util.c Would be in dbus-string.c, but not used in libdbus
3  * 
4  * Copyright (C) 2002, 2003, 2004, 2005 Red Hat, Inc.
5  * Copyright (C) 2006 Ralf Habacker <ralf.habacker@freenet.de>
6  *
7  * Licensed under the Academic Free License version 2.1
8  * 
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  * 
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22  *
23  */
24
25 #include "dbus-internals.h"
26 #include "dbus-string.h"
27 #define DBUS_CAN_USE_DBUS_STRING_PRIVATE 1
28 #include "dbus-string-private.h"
29
30 /**
31  * @addtogroup DBusString
32  * @{
33  */
34
35 /**
36  * Returns whether a string ends with the given suffix
37  *
38  * @todo memcmp might make this faster.
39  * 
40  * @param a the string
41  * @param c_str the C-style string
42  * @returns #TRUE if the string ends with the suffix
43  */
44 dbus_bool_t
45 _dbus_string_ends_with_c_str (const DBusString *a,
46                               const char       *c_str)
47 {
48   const unsigned char *ap;
49   const unsigned char *bp;
50   const unsigned char *a_end;
51   unsigned long c_str_len;
52   const DBusRealString *real_a = (const DBusRealString*) a;
53   DBUS_GENERIC_STRING_PREAMBLE (real_a);
54   _dbus_assert (c_str != NULL);
55   
56   c_str_len = strlen (c_str);
57   if (((unsigned long)real_a->len) < c_str_len)
58     return FALSE;
59   
60   ap = real_a->str + (real_a->len - c_str_len);
61   bp = (const unsigned char*) c_str;
62   a_end = real_a->str + real_a->len;
63   while (ap != a_end)
64     {
65       if (*ap != *bp)
66         return FALSE;
67       
68       ++ap;
69       ++bp;
70     }
71
72   _dbus_assert (*ap == '\0');
73   _dbus_assert (*bp == '\0');
74   
75   return TRUE;
76 }
77
78 /**
79  * Find the given byte scanning backward from the given start.
80  * Sets *found to -1 if the byte is not found.
81  *
82  * @param str the string
83  * @param start the place to start scanning (will not find the byte at this point)
84  * @param byte the byte to find
85  * @param found return location for where it was found
86  * @returns #TRUE if found
87  */
88 dbus_bool_t
89 _dbus_string_find_byte_backward (const DBusString  *str,
90                                  int                start,
91                                  unsigned char      byte,
92                                  int               *found)
93 {
94   int i;
95   DBUS_CONST_STRING_PREAMBLE (str);
96   _dbus_assert (start <= real->len);
97   _dbus_assert (start >= 0);
98   _dbus_assert (found != NULL);
99
100   i = start - 1;
101   while (i >= 0)
102     {
103       if (real->str[i] == byte)
104         break;
105       
106       --i;
107     }
108
109   if (found)
110     *found = i;
111
112   return i >= 0;
113 }
114
115 /** @} */
116
117 #ifdef DBUS_BUILD_TESTS
118 #include "dbus-test.h"
119 #include <stdio.h>
120
121 static void
122 test_max_len (DBusString *str,
123               int         max_len)
124 {
125   if (max_len > 0)
126     {
127       if (!_dbus_string_set_length (str, max_len - 1))
128         _dbus_assert_not_reached ("setting len to one less than max should have worked");
129     }
130
131   if (!_dbus_string_set_length (str, max_len))
132     _dbus_assert_not_reached ("setting len to max len should have worked");
133
134   if (_dbus_string_set_length (str, max_len + 1))
135     _dbus_assert_not_reached ("setting len to one more than max len should not have worked");
136
137   if (!_dbus_string_set_length (str, 0))
138     _dbus_assert_not_reached ("setting len to zero should have worked");
139 }
140
141 static void
142 test_hex_roundtrip (const unsigned char *data,
143                     int                  len)
144 {
145   DBusString orig;
146   DBusString encoded;
147   DBusString decoded;
148   int end;
149
150   if (len < 0)
151     len = strlen (data);
152   
153   if (!_dbus_string_init (&orig))
154     _dbus_assert_not_reached ("could not init string");
155
156   if (!_dbus_string_init (&encoded))
157     _dbus_assert_not_reached ("could not init string");
158   
159   if (!_dbus_string_init (&decoded))
160     _dbus_assert_not_reached ("could not init string");
161
162   if (!_dbus_string_append_len (&orig, data, len))
163     _dbus_assert_not_reached ("couldn't append orig data");
164
165   if (!_dbus_string_hex_encode (&orig, 0, &encoded, 0))
166     _dbus_assert_not_reached ("could not encode");
167
168   if (!_dbus_string_hex_decode (&encoded, 0, &end, &decoded, 0))
169     _dbus_assert_not_reached ("could not decode");
170     
171   _dbus_assert (_dbus_string_get_length (&encoded) == end);
172
173   if (!_dbus_string_equal (&orig, &decoded))
174     {
175       const char *s;
176       
177       printf ("Original string %d bytes encoded %d bytes decoded %d bytes\n",
178               _dbus_string_get_length (&orig),
179               _dbus_string_get_length (&encoded),
180               _dbus_string_get_length (&decoded));
181       printf ("Original: %s\n", data);
182       s = _dbus_string_get_const_data (&decoded);
183       printf ("Decoded: %s\n", s);
184       _dbus_assert_not_reached ("original string not the same as string decoded from hex");
185     }
186   
187   _dbus_string_free (&orig);
188   _dbus_string_free (&encoded);
189   _dbus_string_free (&decoded);  
190 }
191
192 typedef void (* TestRoundtripFunc) (const unsigned char *data,
193                                     int                  len);
194 static void
195 test_roundtrips (TestRoundtripFunc func)
196 {
197   (* func) ("Hello this is a string\n", -1);
198   (* func) ("Hello this is a string\n1", -1);
199   (* func) ("Hello this is a string\n12", -1);
200   (* func) ("Hello this is a string\n123", -1);
201   (* func) ("Hello this is a string\n1234", -1);
202   (* func) ("Hello this is a string\n12345", -1);
203   (* func) ("", 0);
204   (* func) ("1", 1);
205   (* func) ("12", 2);
206   (* func) ("123", 3);
207   (* func) ("1234", 4);
208   (* func) ("12345", 5);
209   (* func) ("", 1);
210   (* func) ("1", 2);
211   (* func) ("12", 3);
212   (* func) ("123", 4);
213   (* func) ("1234", 5);
214   (* func) ("12345", 6);
215   {
216     unsigned char buf[512];
217     int i;
218     
219     i = 0;
220     while (i < _DBUS_N_ELEMENTS (buf))
221       {
222         buf[i] = i;
223         ++i;
224       }
225     i = 0;
226     while (i < _DBUS_N_ELEMENTS (buf))
227       {
228         (* func) (buf, i);
229         ++i;
230       }
231   }
232 }
233
234 #ifdef DBUS_BUILD_TESTS
235 /* The max length thing is sort of a historical artifact
236  * from a feature that turned out to be dumb; perhaps
237  * we should purge it entirely. The problem with
238  * the feature is that it looks like memory allocation
239  * failure, but is not a transient or resolvable failure.
240  */
241 static void
242 set_max_length (DBusString *str,
243                 int         max_length)
244 {
245   DBusRealString *real;
246   
247   real = (DBusRealString*) str;
248
249   real->max_length = max_length;
250 }
251 #endif /* DBUS_BUILD_TESTS */
252
253 /**
254  * @ingroup DBusStringInternals
255  * Unit test for DBusString.
256  *
257  * @todo Need to write tests for _dbus_string_copy() and
258  * _dbus_string_move() moving to/from each of start/middle/end of a
259  * string. Also need tests for _dbus_string_move_len ()
260  * 
261  * @returns #TRUE on success.
262  */
263 dbus_bool_t
264 _dbus_string_test (void)
265 {
266   DBusString str;
267   DBusString other;
268   int i, end;
269   long v;
270   double d;
271   int lens[] = { 0, 1, 2, 3, 4, 5, 10, 16, 17, 18, 25, 31, 32, 33, 34, 35, 63, 64, 65, 66, 67, 68, 69, 70, 71, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136 };
272   char *s;
273   dbus_unichar_t ch;
274   
275   i = 0;
276   while (i < _DBUS_N_ELEMENTS (lens))
277     {
278       if (!_dbus_string_init (&str))
279         _dbus_assert_not_reached ("failed to init string");
280
281       set_max_length (&str, lens[i]);
282       
283       test_max_len (&str, lens[i]);
284       _dbus_string_free (&str);
285
286       ++i;
287     }
288
289   /* Test shortening and setting length */
290   i = 0;
291   while (i < _DBUS_N_ELEMENTS (lens))
292     {
293       int j;
294       
295       if (!_dbus_string_init (&str))
296         _dbus_assert_not_reached ("failed to init string");
297
298       set_max_length (&str, lens[i]);
299       
300       if (!_dbus_string_set_length (&str, lens[i]))
301         _dbus_assert_not_reached ("failed to set string length");
302
303       j = lens[i];
304       while (j > 0)
305         {
306           _dbus_assert (_dbus_string_get_length (&str) == j);
307           if (j > 0)
308             {
309               _dbus_string_shorten (&str, 1);
310               _dbus_assert (_dbus_string_get_length (&str) == (j - 1));
311             }
312           --j;
313         }
314       
315       _dbus_string_free (&str);
316
317       ++i;
318     }
319
320   /* Test equality */
321   if (!_dbus_string_init (&str))
322     _dbus_assert_not_reached ("oom");
323
324   if (!_dbus_string_append (&str, "Hello World"))
325     _dbus_assert_not_reached ("oom");
326
327   _dbus_string_init_const (&other, "H");
328   _dbus_assert (_dbus_string_equal_substring (&str, 0, 1, &other, 0));
329   _dbus_assert (_dbus_string_equal_substring (&str, 1, 0, &other, 1));
330   _dbus_string_init_const (&other, "Hello");
331   _dbus_assert (_dbus_string_equal_substring (&str, 0, 5, &other, 0));
332   _dbus_assert (_dbus_string_equal_substring (&str, 1, 4, &other, 1));
333   _dbus_assert (_dbus_string_equal_substring (&str, 2, 3, &other, 2));
334   _dbus_assert (_dbus_string_equal_substring (&str, 3, 2, &other, 3));
335   _dbus_assert (_dbus_string_equal_substring (&str, 4, 1, &other, 4));
336   _dbus_assert (_dbus_string_equal_substring (&str, 5, 0, &other, 5));
337
338   _dbus_assert (_dbus_string_equal_substring (&other, 0, 5, &str, 0));
339   _dbus_assert (_dbus_string_equal_substring (&other, 1, 4, &str, 1));
340   _dbus_assert (_dbus_string_equal_substring (&other, 2, 3, &str, 2));
341   _dbus_assert (_dbus_string_equal_substring (&other, 3, 2, &str, 3));
342   _dbus_assert (_dbus_string_equal_substring (&other, 4, 1, &str, 4));
343   _dbus_assert (_dbus_string_equal_substring (&other, 5, 0, &str, 5));
344
345   
346   _dbus_string_init_const (&other, "World");
347   _dbus_assert (_dbus_string_equal_substring (&str, 6,  5, &other, 0));
348   _dbus_assert (_dbus_string_equal_substring (&str, 7,  4, &other, 1));
349   _dbus_assert (_dbus_string_equal_substring (&str, 8,  3, &other, 2));
350   _dbus_assert (_dbus_string_equal_substring (&str, 9,  2, &other, 3));
351   _dbus_assert (_dbus_string_equal_substring (&str, 10, 1, &other, 4));
352   _dbus_assert (_dbus_string_equal_substring (&str, 11, 0, &other, 5));
353
354   _dbus_assert (_dbus_string_equal_substring (&other, 0, 5, &str, 6));
355   _dbus_assert (_dbus_string_equal_substring (&other, 1, 4, &str, 7));
356   _dbus_assert (_dbus_string_equal_substring (&other, 2, 3, &str, 8));
357   _dbus_assert (_dbus_string_equal_substring (&other, 3, 2, &str, 9));
358   _dbus_assert (_dbus_string_equal_substring (&other, 4, 1, &str, 10));
359   _dbus_assert (_dbus_string_equal_substring (&other, 5, 0, &str, 11));
360   
361   _dbus_string_free (&str);
362   
363   /* Test appending data */
364   if (!_dbus_string_init (&str))
365     _dbus_assert_not_reached ("failed to init string");
366
367   i = 0;
368   while (i < 10)
369     {
370       if (!_dbus_string_append (&str, "a"))
371         _dbus_assert_not_reached ("failed to append string to string\n");
372
373       _dbus_assert (_dbus_string_get_length (&str) == i * 2 + 1);
374
375       if (!_dbus_string_append_byte (&str, 'b'))
376         _dbus_assert_not_reached ("failed to append byte to string\n");
377
378       _dbus_assert (_dbus_string_get_length (&str) == i * 2 + 2);
379                     
380       ++i;
381     }
382
383   _dbus_string_free (&str);
384
385   /* Check steal_data */
386   
387   if (!_dbus_string_init (&str))
388     _dbus_assert_not_reached ("failed to init string");
389
390   if (!_dbus_string_append (&str, "Hello World"))
391     _dbus_assert_not_reached ("could not append to string");
392
393   i = _dbus_string_get_length (&str);
394   
395   if (!_dbus_string_steal_data (&str, &s))
396     _dbus_assert_not_reached ("failed to steal data");
397
398   _dbus_assert (_dbus_string_get_length (&str) == 0);
399   _dbus_assert (((int)strlen (s)) == i);
400
401   dbus_free (s);
402
403   /* Check move */
404   
405   if (!_dbus_string_append (&str, "Hello World"))
406     _dbus_assert_not_reached ("could not append to string");
407
408   i = _dbus_string_get_length (&str);
409
410   if (!_dbus_string_init (&other))
411     _dbus_assert_not_reached ("could not init string");
412   
413   if (!_dbus_string_move (&str, 0, &other, 0))
414     _dbus_assert_not_reached ("could not move");
415
416   _dbus_assert (_dbus_string_get_length (&str) == 0);
417   _dbus_assert (_dbus_string_get_length (&other) == i);
418
419   if (!_dbus_string_append (&str, "Hello World"))
420     _dbus_assert_not_reached ("could not append to string");
421   
422   if (!_dbus_string_move (&str, 0, &other, _dbus_string_get_length (&other)))
423     _dbus_assert_not_reached ("could not move");
424
425   _dbus_assert (_dbus_string_get_length (&str) == 0);
426   _dbus_assert (_dbus_string_get_length (&other) == i * 2);
427
428     if (!_dbus_string_append (&str, "Hello World"))
429     _dbus_assert_not_reached ("could not append to string");
430   
431   if (!_dbus_string_move (&str, 0, &other, _dbus_string_get_length (&other) / 2))
432     _dbus_assert_not_reached ("could not move");
433
434   _dbus_assert (_dbus_string_get_length (&str) == 0);
435   _dbus_assert (_dbus_string_get_length (&other) == i * 3);
436   
437   _dbus_string_free (&other);
438
439   /* Check copy */
440   
441   if (!_dbus_string_append (&str, "Hello World"))
442     _dbus_assert_not_reached ("could not append to string");
443
444   i = _dbus_string_get_length (&str);
445   
446   if (!_dbus_string_init (&other))
447     _dbus_assert_not_reached ("could not init string");
448   
449   if (!_dbus_string_copy (&str, 0, &other, 0))
450     _dbus_assert_not_reached ("could not copy");
451
452   _dbus_assert (_dbus_string_get_length (&str) == i);
453   _dbus_assert (_dbus_string_get_length (&other) == i);
454
455   if (!_dbus_string_copy (&str, 0, &other, _dbus_string_get_length (&other)))
456     _dbus_assert_not_reached ("could not copy");
457
458   _dbus_assert (_dbus_string_get_length (&str) == i);
459   _dbus_assert (_dbus_string_get_length (&other) == i * 2);
460   _dbus_assert (_dbus_string_equal_c_str (&other,
461                                           "Hello WorldHello World"));
462
463   if (!_dbus_string_copy (&str, 0, &other, _dbus_string_get_length (&other) / 2))
464     _dbus_assert_not_reached ("could not copy");
465
466   _dbus_assert (_dbus_string_get_length (&str) == i);
467   _dbus_assert (_dbus_string_get_length (&other) == i * 3);
468   _dbus_assert (_dbus_string_equal_c_str (&other,
469                                           "Hello WorldHello WorldHello World"));
470   
471   _dbus_string_free (&str);
472   _dbus_string_free (&other);
473
474   /* Check replace */
475
476   if (!_dbus_string_init (&str))
477     _dbus_assert_not_reached ("failed to init string");
478   
479   if (!_dbus_string_append (&str, "Hello World"))
480     _dbus_assert_not_reached ("could not append to string");
481
482   i = _dbus_string_get_length (&str);
483   
484   if (!_dbus_string_init (&other))
485     _dbus_assert_not_reached ("could not init string");
486   
487   if (!_dbus_string_replace_len (&str, 0, _dbus_string_get_length (&str),
488                                  &other, 0, _dbus_string_get_length (&other)))
489     _dbus_assert_not_reached ("could not replace");
490
491   _dbus_assert (_dbus_string_get_length (&str) == i);
492   _dbus_assert (_dbus_string_get_length (&other) == i);
493   _dbus_assert (_dbus_string_equal_c_str (&other, "Hello World"));
494   
495   if (!_dbus_string_replace_len (&str, 0, _dbus_string_get_length (&str),
496                                  &other, 5, 1))
497     _dbus_assert_not_reached ("could not replace center space");
498
499   _dbus_assert (_dbus_string_get_length (&str) == i);
500   _dbus_assert (_dbus_string_get_length (&other) == i * 2 - 1);
501   _dbus_assert (_dbus_string_equal_c_str (&other,
502                                           "HelloHello WorldWorld"));
503
504   
505   if (!_dbus_string_replace_len (&str, 1, 1,
506                                  &other,
507                                  _dbus_string_get_length (&other) - 1,
508                                  1))
509     _dbus_assert_not_reached ("could not replace end character");
510   
511   _dbus_assert (_dbus_string_get_length (&str) == i);
512   _dbus_assert (_dbus_string_get_length (&other) == i * 2 - 1);
513   _dbus_assert (_dbus_string_equal_c_str (&other,
514                                           "HelloHello WorldWorle"));
515   
516   _dbus_string_free (&str);
517   _dbus_string_free (&other);
518   
519   /* Check append/get unichar */
520   
521   if (!_dbus_string_init (&str))
522     _dbus_assert_not_reached ("failed to init string");
523
524   ch = 0;
525   if (!_dbus_string_append_unichar (&str, 0xfffc))
526     _dbus_assert_not_reached ("failed to append unichar");
527
528   _dbus_string_get_unichar (&str, 0, &ch, &i);
529
530   _dbus_assert (ch == 0xfffc);
531   _dbus_assert (i == _dbus_string_get_length (&str));
532
533   _dbus_string_free (&str);
534
535   /* Check insert/set/get byte */
536   
537   if (!_dbus_string_init (&str))
538     _dbus_assert_not_reached ("failed to init string");
539
540   if (!_dbus_string_append (&str, "Hello"))
541     _dbus_assert_not_reached ("failed to append Hello");
542
543   _dbus_assert (_dbus_string_get_byte (&str, 0) == 'H');
544   _dbus_assert (_dbus_string_get_byte (&str, 1) == 'e');
545   _dbus_assert (_dbus_string_get_byte (&str, 2) == 'l');
546   _dbus_assert (_dbus_string_get_byte (&str, 3) == 'l');
547   _dbus_assert (_dbus_string_get_byte (&str, 4) == 'o');
548
549   _dbus_string_set_byte (&str, 1, 'q');
550   _dbus_assert (_dbus_string_get_byte (&str, 1) == 'q');
551
552   if (!_dbus_string_insert_bytes (&str, 0, 1, 255))
553     _dbus_assert_not_reached ("can't insert byte");
554
555   if (!_dbus_string_insert_bytes (&str, 2, 4, 'Z'))
556     _dbus_assert_not_reached ("can't insert byte");
557
558   if (!_dbus_string_insert_bytes (&str, _dbus_string_get_length (&str), 1, 'W'))
559     _dbus_assert_not_reached ("can't insert byte");
560   
561   _dbus_assert (_dbus_string_get_byte (&str, 0) == 255);
562   _dbus_assert (_dbus_string_get_byte (&str, 1) == 'H');
563   _dbus_assert (_dbus_string_get_byte (&str, 2) == 'Z');
564   _dbus_assert (_dbus_string_get_byte (&str, 3) == 'Z');
565   _dbus_assert (_dbus_string_get_byte (&str, 4) == 'Z');
566   _dbus_assert (_dbus_string_get_byte (&str, 5) == 'Z');
567   _dbus_assert (_dbus_string_get_byte (&str, 6) == 'q');
568   _dbus_assert (_dbus_string_get_byte (&str, 7) == 'l');
569   _dbus_assert (_dbus_string_get_byte (&str, 8) == 'l');
570   _dbus_assert (_dbus_string_get_byte (&str, 9) == 'o');
571   _dbus_assert (_dbus_string_get_byte (&str, 10) == 'W');
572
573   _dbus_string_free (&str);
574   
575   /* Check append/parse int/double */
576   
577   if (!_dbus_string_init (&str))
578     _dbus_assert_not_reached ("failed to init string");
579
580   if (!_dbus_string_append_int (&str, 27))
581     _dbus_assert_not_reached ("failed to append int");
582
583   i = _dbus_string_get_length (&str);
584
585   if (!_dbus_string_parse_int (&str, 0, &v, &end))
586     _dbus_assert_not_reached ("failed to parse int");
587
588   _dbus_assert (v == 27);
589   _dbus_assert (end == i);
590
591   _dbus_string_free (&str);
592   
593   if (!_dbus_string_init (&str))
594     _dbus_assert_not_reached ("failed to init string");
595   
596   if (!_dbus_string_append_double (&str, 50.3))
597     _dbus_assert_not_reached ("failed to append float");
598
599   i = _dbus_string_get_length (&str);
600
601   if (!_dbus_string_parse_double (&str, 0, &d, &end))
602     _dbus_assert_not_reached ("failed to parse float");
603
604   _dbus_assert (d > (50.3 - 1e-6) && d < (50.3 + 1e-6));
605   _dbus_assert (end == i);
606
607   _dbus_string_free (&str);
608
609   /* Test find */
610   if (!_dbus_string_init (&str))
611     _dbus_assert_not_reached ("failed to init string");
612
613   if (!_dbus_string_append (&str, "Hello"))
614     _dbus_assert_not_reached ("couldn't append to string");
615   
616   if (!_dbus_string_find (&str, 0, "He", &i))
617     _dbus_assert_not_reached ("didn't find 'He'");
618   _dbus_assert (i == 0);
619
620   if (!_dbus_string_find (&str, 0, "Hello", &i))
621     _dbus_assert_not_reached ("didn't find 'Hello'");
622   _dbus_assert (i == 0);
623   
624   if (!_dbus_string_find (&str, 0, "ello", &i))
625     _dbus_assert_not_reached ("didn't find 'ello'");
626   _dbus_assert (i == 1);
627
628   if (!_dbus_string_find (&str, 0, "lo", &i))
629     _dbus_assert_not_reached ("didn't find 'lo'");
630   _dbus_assert (i == 3);
631
632   if (!_dbus_string_find (&str, 2, "lo", &i))
633     _dbus_assert_not_reached ("didn't find 'lo'");
634   _dbus_assert (i == 3);
635
636   if (_dbus_string_find (&str, 4, "lo", &i))
637     _dbus_assert_not_reached ("did find 'lo'");
638   
639   if (!_dbus_string_find (&str, 0, "l", &i))
640     _dbus_assert_not_reached ("didn't find 'l'");
641   _dbus_assert (i == 2);
642
643   if (!_dbus_string_find (&str, 0, "H", &i))
644     _dbus_assert_not_reached ("didn't find 'H'");
645   _dbus_assert (i == 0);
646
647   if (!_dbus_string_find (&str, 0, "", &i))
648     _dbus_assert_not_reached ("didn't find ''");
649   _dbus_assert (i == 0);
650   
651   if (_dbus_string_find (&str, 0, "Hello!", NULL))
652     _dbus_assert_not_reached ("Did find 'Hello!'");
653
654   if (_dbus_string_find (&str, 0, "Oh, Hello", NULL))
655     _dbus_assert_not_reached ("Did find 'Oh, Hello'");
656   
657   if (_dbus_string_find (&str, 0, "ill", NULL))
658     _dbus_assert_not_reached ("Did find 'ill'");
659
660   if (_dbus_string_find (&str, 0, "q", NULL))
661     _dbus_assert_not_reached ("Did find 'q'");
662
663   if (!_dbus_string_find_to (&str, 0, 2, "He", NULL))
664     _dbus_assert_not_reached ("Didn't find 'He'");
665
666   if (_dbus_string_find_to (&str, 0, 2, "Hello", NULL))
667     _dbus_assert_not_reached ("Did find 'Hello'");
668
669   if (!_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str), 'H', &i))
670     _dbus_assert_not_reached ("Did not find 'H'");
671   _dbus_assert (i == 0);
672
673   if (!_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str), 'o', &i))
674     _dbus_assert_not_reached ("Did not find 'o'");
675   _dbus_assert (i == _dbus_string_get_length (&str) - 1);
676
677   if (_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str) - 1, 'o', &i))
678     _dbus_assert_not_reached ("Did find 'o'");
679   _dbus_assert (i == -1);
680
681   if (_dbus_string_find_byte_backward (&str, 1, 'e', &i))
682     _dbus_assert_not_reached ("Did find 'e'");
683   _dbus_assert (i == -1);
684
685   if (!_dbus_string_find_byte_backward (&str, 2, 'e', &i))
686     _dbus_assert_not_reached ("Didn't find 'e'");
687   _dbus_assert (i == 1);
688   
689   _dbus_string_free (&str);
690
691   /* Hex encoding */
692   _dbus_string_init_const (&str, "cafebabe, this is a bogus hex string");
693   if (!_dbus_string_init (&other))
694     _dbus_assert_not_reached ("could not init string");
695
696   if (!_dbus_string_hex_decode (&str, 0, &end, &other, 0))
697     _dbus_assert_not_reached ("deccoded bogus hex string with no error");
698
699   _dbus_assert (end == 8);
700
701   _dbus_string_free (&other);
702
703   test_roundtrips (test_hex_roundtrip);
704   
705   _dbus_string_free (&str);
706
707   {                                                                                           
708     int found, found_len;  
709
710     _dbus_string_init_const (&str, "012\r\n567\n90");
711     
712     if (!_dbus_string_find_eol (&str, 0, &found, &found_len) || found != 3 || found_len != 2)
713       _dbus_assert_not_reached ("Did not find '\\r\\n'");                                       
714     if (found != 3 || found_len != 2)                                                           
715       _dbus_assert_not_reached ("invalid return values");                                       
716     
717     if (!_dbus_string_find_eol (&str, 5, &found, &found_len))                                    
718       _dbus_assert_not_reached ("Did not find '\\n'");                                          
719     if (found != 8 || found_len != 1)                                                           
720       _dbus_assert_not_reached ("invalid return values");                                       
721     
722     if (_dbus_string_find_eol (&str, 9, &found, &found_len))                                     
723       _dbus_assert_not_reached ("Found not expected '\\n'");                                    
724     else if (found != 11 || found_len != 0)                                                     
725       _dbus_assert_not_reached ("invalid return values '\\n'");                                 
726
727     found = -1;
728     found_len = -1;
729     _dbus_string_init_const (&str, "");
730     if (_dbus_string_find_eol (&str, 0, &found, &found_len))
731       _dbus_assert_not_reached ("found an eol in an empty string");
732     _dbus_assert (found == 0);
733     _dbus_assert (found_len == 0);
734     
735     found = -1;
736     found_len = -1;
737     _dbus_string_init_const (&str, "foobar");
738     if (_dbus_string_find_eol (&str, 0, &found, &found_len))
739       _dbus_assert_not_reached ("found eol in string that lacks one");
740     _dbus_assert (found == 6);
741     _dbus_assert (found_len == 0);
742
743     found = -1;
744     found_len = -1;
745     _dbus_string_init_const (&str, "foobar\n");
746     if (!_dbus_string_find_eol (&str, 0, &found, &found_len))
747       _dbus_assert_not_reached ("did not find eol in string that has one at end");
748     _dbus_assert (found == 6);
749     _dbus_assert (found_len == 1);
750   }
751
752   {
753     DBusString line;
754
755 #define FIRST_LINE "this is a line"
756 #define SECOND_LINE "this is a second line"
757     /* third line is empty */
758 #define THIRD_LINE ""
759 #define FOURTH_LINE "this is a fourth line"
760     
761     if (!_dbus_string_init (&str))
762       _dbus_assert_not_reached ("no memory");
763
764     if (!_dbus_string_append (&str, FIRST_LINE "\n" SECOND_LINE "\r\n" THIRD_LINE "\n" FOURTH_LINE))
765       _dbus_assert_not_reached ("no memory");
766     
767     if (!_dbus_string_init (&line))
768       _dbus_assert_not_reached ("no memory");
769     
770     if (!_dbus_string_pop_line (&str, &line))
771       _dbus_assert_not_reached ("failed to pop first line");
772
773     _dbus_assert (_dbus_string_equal_c_str (&line, FIRST_LINE));
774     
775     if (!_dbus_string_pop_line (&str, &line))
776       _dbus_assert_not_reached ("failed to pop second line");
777
778     _dbus_assert (_dbus_string_equal_c_str (&line, SECOND_LINE));
779     
780     if (!_dbus_string_pop_line (&str, &line))
781       _dbus_assert_not_reached ("failed to pop third line");
782
783     _dbus_assert (_dbus_string_equal_c_str (&line, THIRD_LINE));
784     
785     if (!_dbus_string_pop_line (&str, &line))
786       _dbus_assert_not_reached ("failed to pop fourth line");
787
788     _dbus_assert (_dbus_string_equal_c_str (&line, FOURTH_LINE));
789     
790     _dbus_string_free (&str);
791     _dbus_string_free (&line);
792   }
793
794   {
795     if (!_dbus_string_init (&str))
796       _dbus_assert_not_reached ("no memory");
797
798     for (i = 0; i < 10000; i++)
799       if (!_dbus_string_append (&str, "abcdefghijklmnopqrstuvwxyz"))
800         _dbus_assert_not_reached ("no memory");
801
802     if (!_dbus_string_set_length (&str, 10))
803       _dbus_assert_not_reached ("failed to set length");
804
805     /* actually compact */
806     if (!_dbus_string_compact (&str, 2048))
807       _dbus_assert_not_reached ("failed to compact after set_length");
808
809     /* peek inside to make sure it worked */
810     if (((DBusRealString *)&str)->allocated > 30)
811       _dbus_assert_not_reached ("compacting string didn't do anything");
812
813     if (!_dbus_string_equal_c_str (&str, "abcdefghij"))
814       _dbus_assert_not_reached ("unexpected content after compact");
815
816     /* compact nothing */
817     if (!_dbus_string_compact (&str, 2048))
818       _dbus_assert_not_reached ("failed to compact 2nd time");
819
820     if (!_dbus_string_equal_c_str (&str, "abcdefghij"))
821       _dbus_assert_not_reached ("unexpected content after 2nd compact");
822
823     /* and make sure it still works...*/
824     if (!_dbus_string_append (&str, "123456"))
825       _dbus_assert_not_reached ("failed to append after compact");
826
827     if (!_dbus_string_equal_c_str (&str, "abcdefghij123456"))
828       _dbus_assert_not_reached ("unexpected content after append");
829
830     /* after growing automatically, this should do nothing */
831     if (!_dbus_string_compact (&str, 20000))
832       _dbus_assert_not_reached ("failed to compact after grow");
833
834     /* but this one will do something */
835     if (!_dbus_string_compact (&str, 0))
836       _dbus_assert_not_reached ("failed to compact after grow");
837
838     if (!_dbus_string_equal_c_str (&str, "abcdefghij123456"))
839       _dbus_assert_not_reached ("unexpected content");
840
841     if (!_dbus_string_append (&str, "!@#$%"))
842       _dbus_assert_not_reached ("failed to append after compact");
843
844     if (!_dbus_string_equal_c_str (&str, "abcdefghij123456!@#$%"))
845       _dbus_assert_not_reached ("unexpected content");
846
847     _dbus_string_free (&str);
848   }
849
850   {
851     const char two_strings[] = "one\ttwo";
852
853     if (!_dbus_string_init (&str))
854       _dbus_assert_not_reached ("no memory");
855
856     if (!_dbus_string_init (&other))
857       _dbus_assert_not_reached ("no memory");
858
859     if (!_dbus_string_append (&str, two_strings))
860       _dbus_assert_not_reached ("no memory");
861
862     if (!_dbus_string_split_on_byte (&str, '\t', &other))
863       _dbus_assert_not_reached ("no memory or delimiter not found");
864
865     if (strcmp (_dbus_string_get_data (&str), "one") != 0)
866       _dbus_assert_not_reached ("left side after split on tab is wrong");
867
868     if (strcmp (_dbus_string_get_data (&other), "two") != 0)
869       _dbus_assert_not_reached ("right side after split on tab is wrong");
870
871     _dbus_string_free (&str);
872     _dbus_string_free (&other);
873   }
874
875   {
876     const char upper_string[] = "TOUPPERSTRING";
877     const char lower_string[] = "toupperstring";
878     const char lower2_string[] = "toupperSTRING";
879
880     if (!_dbus_string_init (&str))
881       _dbus_assert_not_reached ("no memory");
882
883     if (!_dbus_string_append (&str, upper_string))
884       _dbus_assert_not_reached ("no memory");
885
886     _dbus_string_tolower_ascii (&str, 0, _dbus_string_get_length(&str));
887
888     if (!_dbus_string_equal_c_str (&str, lower_string))
889       _dbus_assert_not_reached ("_dbus_string_tolower_ascii failed");
890
891     _dbus_string_free (&str);
892
893     if (!_dbus_string_init (&str))
894       _dbus_assert_not_reached ("no memory");
895
896     if (!_dbus_string_append (&str, upper_string))
897       _dbus_assert_not_reached ("no memory");
898
899     _dbus_string_tolower_ascii (&str, 0, 7);
900
901     if (!_dbus_string_equal_c_str (&str, lower2_string))
902       _dbus_assert_not_reached ("_dbus_string_tolower_ascii failed in partial conversion");
903
904     _dbus_string_free (&str);
905   }
906
907   {
908     const char lower_string[] = "toupperstring";
909     const char upper_string[] = "TOUPPERSTRING";
910     const char upper2_string[] = "TOUPPERstring";
911
912     if (!_dbus_string_init (&str))
913       _dbus_assert_not_reached ("no memory");
914
915     if (!_dbus_string_append (&str, lower_string))
916       _dbus_assert_not_reached ("no memory");
917
918     _dbus_string_toupper_ascii (&str, 0, _dbus_string_get_length(&str));
919
920     if (!_dbus_string_equal_c_str (&str, upper_string))
921       _dbus_assert_not_reached ("_dbus_string_toupper_ascii failed");
922
923     _dbus_string_free (&str);
924
925     if (!_dbus_string_init (&str))
926       _dbus_assert_not_reached ("no memory");
927
928     if (!_dbus_string_append (&str, lower_string))
929       _dbus_assert_not_reached ("no memory");
930
931     _dbus_string_toupper_ascii (&str, 0, 7);
932
933     if (!_dbus_string_equal_c_str (&str, upper2_string))
934       _dbus_assert_not_reached ("_dbus_string_toupper_ascii failed in partial conversion");
935
936     _dbus_string_free (&str);
937   }
938
939   return TRUE;
940 }
941
942 #endif /* DBUS_BUILD_TESTS */