• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -*- mode: C; c-file-style: "gnu" -*- */
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  *
6  * Licensed under the Academic Free License version 2.1
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  */
23 
24 #include "dbus-internals.h"
25 #include "dbus-string.h"
26 #define DBUS_CAN_USE_DBUS_STRING_PRIVATE 1
27 #include "dbus-string-private.h"
28 
29 /**
30  * @addtogroup DBusString
31  * @{
32  */
33 
34 /**
35  * Returns whether a string ends with the given suffix
36  *
37  * @todo memcmp might make this faster.
38  *
39  * @param a the string
40  * @param c_str the C-style string
41  * @returns #TRUE if the string ends with the suffix
42  */
43 dbus_bool_t
_dbus_string_ends_with_c_str(const DBusString * a,const char * c_str)44 _dbus_string_ends_with_c_str (const DBusString *a,
45                               const char       *c_str)
46 {
47   const unsigned char *ap;
48   const unsigned char *bp;
49   const unsigned char *a_end;
50   unsigned long c_str_len;
51   const DBusRealString *real_a = (const DBusRealString*) a;
52   DBUS_GENERIC_STRING_PREAMBLE (real_a);
53   _dbus_assert (c_str != NULL);
54 
55   c_str_len = strlen (c_str);
56   if (((unsigned long)real_a->len) < c_str_len)
57     return FALSE;
58 
59   ap = real_a->str + (real_a->len - c_str_len);
60   bp = (const unsigned char*) c_str;
61   a_end = real_a->str + real_a->len;
62   while (ap != a_end)
63     {
64       if (*ap != *bp)
65         return FALSE;
66 
67       ++ap;
68       ++bp;
69     }
70 
71   _dbus_assert (*ap == '\0');
72   _dbus_assert (*bp == '\0');
73 
74   return TRUE;
75 }
76 
77 /**
78  * Find the given byte scanning backward from the given start.
79  * Sets *found to -1 if the byte is not found.
80  *
81  * @param str the string
82  * @param start the place to start scanning (will not find the byte at this point)
83  * @param byte the byte to find
84  * @param found return location for where it was found
85  * @returns #TRUE if found
86  */
87 dbus_bool_t
_dbus_string_find_byte_backward(const DBusString * str,int start,unsigned char byte,int * found)88 _dbus_string_find_byte_backward (const DBusString  *str,
89                                  int                start,
90                                  unsigned char      byte,
91                                  int               *found)
92 {
93   int i;
94   DBUS_CONST_STRING_PREAMBLE (str);
95   _dbus_assert (start <= real->len);
96   _dbus_assert (start >= 0);
97   _dbus_assert (found != NULL);
98 
99   i = start - 1;
100   while (i >= 0)
101     {
102       if (real->str[i] == byte)
103         break;
104 
105       --i;
106     }
107 
108   if (found)
109     *found = i;
110 
111   return i >= 0;
112 }
113 
114 /** @} */
115 
116 #ifdef DBUS_BUILD_TESTS
117 #include "dbus-test.h"
118 #include <stdio.h>
119 
120 static void
test_max_len(DBusString * str,int max_len)121 test_max_len (DBusString *str,
122               int         max_len)
123 {
124   if (max_len > 0)
125     {
126       if (!_dbus_string_set_length (str, max_len - 1))
127         _dbus_assert_not_reached ("setting len to one less than max should have worked");
128     }
129 
130   if (!_dbus_string_set_length (str, max_len))
131     _dbus_assert_not_reached ("setting len to max len should have worked");
132 
133   if (_dbus_string_set_length (str, max_len + 1))
134     _dbus_assert_not_reached ("setting len to one more than max len should not have worked");
135 
136   if (!_dbus_string_set_length (str, 0))
137     _dbus_assert_not_reached ("setting len to zero should have worked");
138 }
139 
140 static void
test_hex_roundtrip(const unsigned char * data,int len)141 test_hex_roundtrip (const unsigned char *data,
142                     int                  len)
143 {
144   DBusString orig;
145   DBusString encoded;
146   DBusString decoded;
147   int end;
148 
149   if (len < 0)
150     len = strlen (data);
151 
152   if (!_dbus_string_init (&orig))
153     _dbus_assert_not_reached ("could not init string");
154 
155   if (!_dbus_string_init (&encoded))
156     _dbus_assert_not_reached ("could not init string");
157 
158   if (!_dbus_string_init (&decoded))
159     _dbus_assert_not_reached ("could not init string");
160 
161   if (!_dbus_string_append_len (&orig, data, len))
162     _dbus_assert_not_reached ("couldn't append orig data");
163 
164   if (!_dbus_string_hex_encode (&orig, 0, &encoded, 0))
165     _dbus_assert_not_reached ("could not encode");
166 
167   if (!_dbus_string_hex_decode (&encoded, 0, &end, &decoded, 0))
168     _dbus_assert_not_reached ("could not decode");
169 
170   _dbus_assert (_dbus_string_get_length (&encoded) == end);
171 
172   if (!_dbus_string_equal (&orig, &decoded))
173     {
174       const char *s;
175 
176       printf ("Original string %d bytes encoded %d bytes decoded %d bytes\n",
177               _dbus_string_get_length (&orig),
178               _dbus_string_get_length (&encoded),
179               _dbus_string_get_length (&decoded));
180       printf ("Original: %s\n", data);
181       s = _dbus_string_get_const_data (&decoded);
182       printf ("Decoded: %s\n", s);
183       _dbus_assert_not_reached ("original string not the same as string decoded from hex");
184     }
185 
186   _dbus_string_free (&orig);
187   _dbus_string_free (&encoded);
188   _dbus_string_free (&decoded);
189 }
190 
191 typedef void (* TestRoundtripFunc) (const unsigned char *data,
192                                     int                  len);
193 static void
test_roundtrips(TestRoundtripFunc func)194 test_roundtrips (TestRoundtripFunc func)
195 {
196   (* func) ("Hello this is a string\n", -1);
197   (* func) ("Hello this is a string\n1", -1);
198   (* func) ("Hello this is a string\n12", -1);
199   (* func) ("Hello this is a string\n123", -1);
200   (* func) ("Hello this is a string\n1234", -1);
201   (* func) ("Hello this is a string\n12345", -1);
202   (* func) ("", 0);
203   (* func) ("1", 1);
204   (* func) ("12", 2);
205   (* func) ("123", 3);
206   (* func) ("1234", 4);
207   (* func) ("12345", 5);
208   (* func) ("", 1);
209   (* func) ("1", 2);
210   (* func) ("12", 3);
211   (* func) ("123", 4);
212   (* func) ("1234", 5);
213   (* func) ("12345", 6);
214   {
215     unsigned char buf[512];
216     int i;
217 
218     i = 0;
219     while (i < _DBUS_N_ELEMENTS (buf))
220       {
221         buf[i] = i;
222         ++i;
223       }
224     i = 0;
225     while (i < _DBUS_N_ELEMENTS (buf))
226       {
227         (* func) (buf, i);
228         ++i;
229       }
230   }
231 }
232 
233 #ifdef DBUS_BUILD_TESTS
234 /* The max length thing is sort of a historical artifact
235  * from a feature that turned out to be dumb; perhaps
236  * we should purge it entirely. The problem with
237  * the feature is that it looks like memory allocation
238  * failure, but is not a transient or resolvable failure.
239  */
240 static void
set_max_length(DBusString * str,int max_length)241 set_max_length (DBusString *str,
242                 int         max_length)
243 {
244   DBusRealString *real;
245 
246   real = (DBusRealString*) str;
247 
248   real->max_length = max_length;
249 }
250 #endif /* DBUS_BUILD_TESTS */
251 
252 /**
253  * @ingroup DBusStringInternals
254  * Unit test for DBusString.
255  *
256  * @todo Need to write tests for _dbus_string_copy() and
257  * _dbus_string_move() moving to/from each of start/middle/end of a
258  * string. Also need tests for _dbus_string_move_len ()
259  *
260  * @returns #TRUE on success.
261  */
262 dbus_bool_t
_dbus_string_test(void)263 _dbus_string_test (void)
264 {
265   DBusString str;
266   DBusString other;
267   int i, end;
268   long v;
269   double d;
270   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 };
271   char *s;
272   dbus_unichar_t ch;
273 
274   i = 0;
275   while (i < _DBUS_N_ELEMENTS (lens))
276     {
277       if (!_dbus_string_init (&str))
278         _dbus_assert_not_reached ("failed to init string");
279 
280       set_max_length (&str, lens[i]);
281 
282       test_max_len (&str, lens[i]);
283       _dbus_string_free (&str);
284 
285       ++i;
286     }
287 
288   /* Test shortening and setting length */
289   i = 0;
290   while (i < _DBUS_N_ELEMENTS (lens))
291     {
292       int j;
293 
294       if (!_dbus_string_init (&str))
295         _dbus_assert_not_reached ("failed to init string");
296 
297       set_max_length (&str, lens[i]);
298 
299       if (!_dbus_string_set_length (&str, lens[i]))
300         _dbus_assert_not_reached ("failed to set string length");
301 
302       j = lens[i];
303       while (j > 0)
304         {
305           _dbus_assert (_dbus_string_get_length (&str) == j);
306           if (j > 0)
307             {
308               _dbus_string_shorten (&str, 1);
309               _dbus_assert (_dbus_string_get_length (&str) == (j - 1));
310             }
311           --j;
312         }
313 
314       _dbus_string_free (&str);
315 
316       ++i;
317     }
318 
319   /* Test equality */
320   if (!_dbus_string_init (&str))
321     _dbus_assert_not_reached ("oom");
322 
323   if (!_dbus_string_append (&str, "Hello World"))
324     _dbus_assert_not_reached ("oom");
325 
326   _dbus_string_init_const (&other, "H");
327   _dbus_assert (_dbus_string_equal_substring (&str, 0, 1, &other, 0));
328   _dbus_assert (_dbus_string_equal_substring (&str, 1, 0, &other, 1));
329   _dbus_string_init_const (&other, "Hello");
330   _dbus_assert (_dbus_string_equal_substring (&str, 0, 5, &other, 0));
331   _dbus_assert (_dbus_string_equal_substring (&str, 1, 4, &other, 1));
332   _dbus_assert (_dbus_string_equal_substring (&str, 2, 3, &other, 2));
333   _dbus_assert (_dbus_string_equal_substring (&str, 3, 2, &other, 3));
334   _dbus_assert (_dbus_string_equal_substring (&str, 4, 1, &other, 4));
335   _dbus_assert (_dbus_string_equal_substring (&str, 5, 0, &other, 5));
336 
337   _dbus_assert (_dbus_string_equal_substring (&other, 0, 5, &str, 0));
338   _dbus_assert (_dbus_string_equal_substring (&other, 1, 4, &str, 1));
339   _dbus_assert (_dbus_string_equal_substring (&other, 2, 3, &str, 2));
340   _dbus_assert (_dbus_string_equal_substring (&other, 3, 2, &str, 3));
341   _dbus_assert (_dbus_string_equal_substring (&other, 4, 1, &str, 4));
342   _dbus_assert (_dbus_string_equal_substring (&other, 5, 0, &str, 5));
343 
344 
345   _dbus_string_init_const (&other, "World");
346   _dbus_assert (_dbus_string_equal_substring (&str, 6,  5, &other, 0));
347   _dbus_assert (_dbus_string_equal_substring (&str, 7,  4, &other, 1));
348   _dbus_assert (_dbus_string_equal_substring (&str, 8,  3, &other, 2));
349   _dbus_assert (_dbus_string_equal_substring (&str, 9,  2, &other, 3));
350   _dbus_assert (_dbus_string_equal_substring (&str, 10, 1, &other, 4));
351   _dbus_assert (_dbus_string_equal_substring (&str, 11, 0, &other, 5));
352 
353   _dbus_assert (_dbus_string_equal_substring (&other, 0, 5, &str, 6));
354   _dbus_assert (_dbus_string_equal_substring (&other, 1, 4, &str, 7));
355   _dbus_assert (_dbus_string_equal_substring (&other, 2, 3, &str, 8));
356   _dbus_assert (_dbus_string_equal_substring (&other, 3, 2, &str, 9));
357   _dbus_assert (_dbus_string_equal_substring (&other, 4, 1, &str, 10));
358   _dbus_assert (_dbus_string_equal_substring (&other, 5, 0, &str, 11));
359 
360   _dbus_string_free (&str);
361 
362   /* Test appending data */
363   if (!_dbus_string_init (&str))
364     _dbus_assert_not_reached ("failed to init string");
365 
366   i = 0;
367   while (i < 10)
368     {
369       if (!_dbus_string_append (&str, "a"))
370         _dbus_assert_not_reached ("failed to append string to string\n");
371 
372       _dbus_assert (_dbus_string_get_length (&str) == i * 2 + 1);
373 
374       if (!_dbus_string_append_byte (&str, 'b'))
375         _dbus_assert_not_reached ("failed to append byte to string\n");
376 
377       _dbus_assert (_dbus_string_get_length (&str) == i * 2 + 2);
378 
379       ++i;
380     }
381 
382   _dbus_string_free (&str);
383 
384   /* Check steal_data */
385 
386   if (!_dbus_string_init (&str))
387     _dbus_assert_not_reached ("failed to init string");
388 
389   if (!_dbus_string_append (&str, "Hello World"))
390     _dbus_assert_not_reached ("could not append to string");
391 
392   i = _dbus_string_get_length (&str);
393 
394   if (!_dbus_string_steal_data (&str, &s))
395     _dbus_assert_not_reached ("failed to steal data");
396 
397   _dbus_assert (_dbus_string_get_length (&str) == 0);
398   _dbus_assert (((int)strlen (s)) == i);
399 
400   dbus_free (s);
401 
402   /* Check move */
403 
404   if (!_dbus_string_append (&str, "Hello World"))
405     _dbus_assert_not_reached ("could not append to string");
406 
407   i = _dbus_string_get_length (&str);
408 
409   if (!_dbus_string_init (&other))
410     _dbus_assert_not_reached ("could not init string");
411 
412   if (!_dbus_string_move (&str, 0, &other, 0))
413     _dbus_assert_not_reached ("could not move");
414 
415   _dbus_assert (_dbus_string_get_length (&str) == 0);
416   _dbus_assert (_dbus_string_get_length (&other) == i);
417 
418   if (!_dbus_string_append (&str, "Hello World"))
419     _dbus_assert_not_reached ("could not append to string");
420 
421   if (!_dbus_string_move (&str, 0, &other, _dbus_string_get_length (&other)))
422     _dbus_assert_not_reached ("could not move");
423 
424   _dbus_assert (_dbus_string_get_length (&str) == 0);
425   _dbus_assert (_dbus_string_get_length (&other) == i * 2);
426 
427     if (!_dbus_string_append (&str, "Hello World"))
428     _dbus_assert_not_reached ("could not append to string");
429 
430   if (!_dbus_string_move (&str, 0, &other, _dbus_string_get_length (&other) / 2))
431     _dbus_assert_not_reached ("could not move");
432 
433   _dbus_assert (_dbus_string_get_length (&str) == 0);
434   _dbus_assert (_dbus_string_get_length (&other) == i * 3);
435 
436   _dbus_string_free (&other);
437 
438   /* Check copy */
439 
440   if (!_dbus_string_append (&str, "Hello World"))
441     _dbus_assert_not_reached ("could not append to string");
442 
443   i = _dbus_string_get_length (&str);
444 
445   if (!_dbus_string_init (&other))
446     _dbus_assert_not_reached ("could not init string");
447 
448   if (!_dbus_string_copy (&str, 0, &other, 0))
449     _dbus_assert_not_reached ("could not copy");
450 
451   _dbus_assert (_dbus_string_get_length (&str) == i);
452   _dbus_assert (_dbus_string_get_length (&other) == i);
453 
454   if (!_dbus_string_copy (&str, 0, &other, _dbus_string_get_length (&other)))
455     _dbus_assert_not_reached ("could not copy");
456 
457   _dbus_assert (_dbus_string_get_length (&str) == i);
458   _dbus_assert (_dbus_string_get_length (&other) == i * 2);
459   _dbus_assert (_dbus_string_equal_c_str (&other,
460                                           "Hello WorldHello World"));
461 
462   if (!_dbus_string_copy (&str, 0, &other, _dbus_string_get_length (&other) / 2))
463     _dbus_assert_not_reached ("could not copy");
464 
465   _dbus_assert (_dbus_string_get_length (&str) == i);
466   _dbus_assert (_dbus_string_get_length (&other) == i * 3);
467   _dbus_assert (_dbus_string_equal_c_str (&other,
468                                           "Hello WorldHello WorldHello World"));
469 
470   _dbus_string_free (&str);
471   _dbus_string_free (&other);
472 
473   /* Check replace */
474 
475   if (!_dbus_string_init (&str))
476     _dbus_assert_not_reached ("failed to init string");
477 
478   if (!_dbus_string_append (&str, "Hello World"))
479     _dbus_assert_not_reached ("could not append to string");
480 
481   i = _dbus_string_get_length (&str);
482 
483   if (!_dbus_string_init (&other))
484     _dbus_assert_not_reached ("could not init string");
485 
486   if (!_dbus_string_replace_len (&str, 0, _dbus_string_get_length (&str),
487                                  &other, 0, _dbus_string_get_length (&other)))
488     _dbus_assert_not_reached ("could not replace");
489 
490   _dbus_assert (_dbus_string_get_length (&str) == i);
491   _dbus_assert (_dbus_string_get_length (&other) == i);
492   _dbus_assert (_dbus_string_equal_c_str (&other, "Hello World"));
493 
494   if (!_dbus_string_replace_len (&str, 0, _dbus_string_get_length (&str),
495                                  &other, 5, 1))
496     _dbus_assert_not_reached ("could not replace center space");
497 
498   _dbus_assert (_dbus_string_get_length (&str) == i);
499   _dbus_assert (_dbus_string_get_length (&other) == i * 2 - 1);
500   _dbus_assert (_dbus_string_equal_c_str (&other,
501                                           "HelloHello WorldWorld"));
502 
503 
504   if (!_dbus_string_replace_len (&str, 1, 1,
505                                  &other,
506                                  _dbus_string_get_length (&other) - 1,
507                                  1))
508     _dbus_assert_not_reached ("could not replace end character");
509 
510   _dbus_assert (_dbus_string_get_length (&str) == i);
511   _dbus_assert (_dbus_string_get_length (&other) == i * 2 - 1);
512   _dbus_assert (_dbus_string_equal_c_str (&other,
513                                           "HelloHello WorldWorle"));
514 
515   _dbus_string_free (&str);
516   _dbus_string_free (&other);
517 
518   /* Check append/get unichar */
519 
520   if (!_dbus_string_init (&str))
521     _dbus_assert_not_reached ("failed to init string");
522 
523   ch = 0;
524   if (!_dbus_string_append_unichar (&str, 0xfffc))
525     _dbus_assert_not_reached ("failed to append unichar");
526 
527   _dbus_string_get_unichar (&str, 0, &ch, &i);
528 
529   _dbus_assert (ch == 0xfffc);
530   _dbus_assert (i == _dbus_string_get_length (&str));
531 
532   _dbus_string_free (&str);
533 
534   /* Check insert/set/get byte */
535 
536   if (!_dbus_string_init (&str))
537     _dbus_assert_not_reached ("failed to init string");
538 
539   if (!_dbus_string_append (&str, "Hello"))
540     _dbus_assert_not_reached ("failed to append Hello");
541 
542   _dbus_assert (_dbus_string_get_byte (&str, 0) == 'H');
543   _dbus_assert (_dbus_string_get_byte (&str, 1) == 'e');
544   _dbus_assert (_dbus_string_get_byte (&str, 2) == 'l');
545   _dbus_assert (_dbus_string_get_byte (&str, 3) == 'l');
546   _dbus_assert (_dbus_string_get_byte (&str, 4) == 'o');
547 
548   _dbus_string_set_byte (&str, 1, 'q');
549   _dbus_assert (_dbus_string_get_byte (&str, 1) == 'q');
550 
551   if (!_dbus_string_insert_bytes (&str, 0, 1, 255))
552     _dbus_assert_not_reached ("can't insert byte");
553 
554   if (!_dbus_string_insert_bytes (&str, 2, 4, 'Z'))
555     _dbus_assert_not_reached ("can't insert byte");
556 
557   if (!_dbus_string_insert_bytes (&str, _dbus_string_get_length (&str), 1, 'W'))
558     _dbus_assert_not_reached ("can't insert byte");
559 
560   _dbus_assert (_dbus_string_get_byte (&str, 0) == 255);
561   _dbus_assert (_dbus_string_get_byte (&str, 1) == 'H');
562   _dbus_assert (_dbus_string_get_byte (&str, 2) == 'Z');
563   _dbus_assert (_dbus_string_get_byte (&str, 3) == 'Z');
564   _dbus_assert (_dbus_string_get_byte (&str, 4) == 'Z');
565   _dbus_assert (_dbus_string_get_byte (&str, 5) == 'Z');
566   _dbus_assert (_dbus_string_get_byte (&str, 6) == 'q');
567   _dbus_assert (_dbus_string_get_byte (&str, 7) == 'l');
568   _dbus_assert (_dbus_string_get_byte (&str, 8) == 'l');
569   _dbus_assert (_dbus_string_get_byte (&str, 9) == 'o');
570   _dbus_assert (_dbus_string_get_byte (&str, 10) == 'W');
571 
572   _dbus_string_free (&str);
573 
574   /* Check append/parse int/double */
575 
576   if (!_dbus_string_init (&str))
577     _dbus_assert_not_reached ("failed to init string");
578 
579   if (!_dbus_string_append_int (&str, 27))
580     _dbus_assert_not_reached ("failed to append int");
581 
582   i = _dbus_string_get_length (&str);
583 
584   if (!_dbus_string_parse_int (&str, 0, &v, &end))
585     _dbus_assert_not_reached ("failed to parse int");
586 
587   _dbus_assert (v == 27);
588   _dbus_assert (end == i);
589 
590   _dbus_string_free (&str);
591 
592   if (!_dbus_string_init (&str))
593     _dbus_assert_not_reached ("failed to init string");
594 
595   if (!_dbus_string_append_double (&str, 50.3))
596     _dbus_assert_not_reached ("failed to append float");
597 
598   i = _dbus_string_get_length (&str);
599 
600   if (!_dbus_string_parse_double (&str, 0, &d, &end))
601     _dbus_assert_not_reached ("failed to parse float");
602 
603   _dbus_assert (d > (50.3 - 1e-6) && d < (50.3 + 1e-6));
604   _dbus_assert (end == i);
605 
606   _dbus_string_free (&str);
607 
608   /* Test find */
609   if (!_dbus_string_init (&str))
610     _dbus_assert_not_reached ("failed to init string");
611 
612   if (!_dbus_string_append (&str, "Hello"))
613     _dbus_assert_not_reached ("couldn't append to string");
614 
615   if (!_dbus_string_find (&str, 0, "He", &i))
616     _dbus_assert_not_reached ("didn't find 'He'");
617   _dbus_assert (i == 0);
618 
619   if (!_dbus_string_find (&str, 0, "Hello", &i))
620     _dbus_assert_not_reached ("didn't find 'Hello'");
621   _dbus_assert (i == 0);
622 
623   if (!_dbus_string_find (&str, 0, "ello", &i))
624     _dbus_assert_not_reached ("didn't find 'ello'");
625   _dbus_assert (i == 1);
626 
627   if (!_dbus_string_find (&str, 0, "lo", &i))
628     _dbus_assert_not_reached ("didn't find 'lo'");
629   _dbus_assert (i == 3);
630 
631   if (!_dbus_string_find (&str, 2, "lo", &i))
632     _dbus_assert_not_reached ("didn't find 'lo'");
633   _dbus_assert (i == 3);
634 
635   if (_dbus_string_find (&str, 4, "lo", &i))
636     _dbus_assert_not_reached ("did find 'lo'");
637 
638   if (!_dbus_string_find (&str, 0, "l", &i))
639     _dbus_assert_not_reached ("didn't find 'l'");
640   _dbus_assert (i == 2);
641 
642   if (!_dbus_string_find (&str, 0, "H", &i))
643     _dbus_assert_not_reached ("didn't find 'H'");
644   _dbus_assert (i == 0);
645 
646   if (!_dbus_string_find (&str, 0, "", &i))
647     _dbus_assert_not_reached ("didn't find ''");
648   _dbus_assert (i == 0);
649 
650   if (_dbus_string_find (&str, 0, "Hello!", NULL))
651     _dbus_assert_not_reached ("Did find 'Hello!'");
652 
653   if (_dbus_string_find (&str, 0, "Oh, Hello", NULL))
654     _dbus_assert_not_reached ("Did find 'Oh, Hello'");
655 
656   if (_dbus_string_find (&str, 0, "ill", NULL))
657     _dbus_assert_not_reached ("Did find 'ill'");
658 
659   if (_dbus_string_find (&str, 0, "q", NULL))
660     _dbus_assert_not_reached ("Did find 'q'");
661 
662   if (!_dbus_string_find_to (&str, 0, 2, "He", NULL))
663     _dbus_assert_not_reached ("Didn't find 'He'");
664 
665   if (_dbus_string_find_to (&str, 0, 2, "Hello", NULL))
666     _dbus_assert_not_reached ("Did find 'Hello'");
667 
668   if (!_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str), 'H', &i))
669     _dbus_assert_not_reached ("Did not find 'H'");
670   _dbus_assert (i == 0);
671 
672   if (!_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str), 'o', &i))
673     _dbus_assert_not_reached ("Did not find 'o'");
674   _dbus_assert (i == _dbus_string_get_length (&str) - 1);
675 
676   if (_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str) - 1, 'o', &i))
677     _dbus_assert_not_reached ("Did find 'o'");
678   _dbus_assert (i == -1);
679 
680   if (_dbus_string_find_byte_backward (&str, 1, 'e', &i))
681     _dbus_assert_not_reached ("Did find 'e'");
682   _dbus_assert (i == -1);
683 
684   if (!_dbus_string_find_byte_backward (&str, 2, 'e', &i))
685     _dbus_assert_not_reached ("Didn't find 'e'");
686   _dbus_assert (i == 1);
687 
688   _dbus_string_free (&str);
689 
690   /* Hex encoding */
691   _dbus_string_init_const (&str, "cafebabe, this is a bogus hex string");
692   if (!_dbus_string_init (&other))
693     _dbus_assert_not_reached ("could not init string");
694 
695   if (!_dbus_string_hex_decode (&str, 0, &end, &other, 0))
696     _dbus_assert_not_reached ("deccoded bogus hex string with no error");
697 
698   _dbus_assert (end == 8);
699 
700   _dbus_string_free (&other);
701 
702   test_roundtrips (test_hex_roundtrip);
703 
704   _dbus_string_free (&str);
705 
706   return TRUE;
707 }
708 
709 #endif /* DBUS_BUILD_TESTS */
710