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