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