nautilus-3.6.3/eel/eel-string.c

Location Tool Test ID Function Issue
eel-string.c:204:3 clang-analyzer Null pointer passed as an argument to a 'nonnull' parameter
  1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
  2 
  3    eel-string.c: String routines to augment <string.h>.
  4 
  5    Copyright (C) 2000 Eazel, Inc.
  6 
  7    The Gnome Library is free software; you can redistribute it and/or
  8    modify it under the terms of the GNU Library General Public License as
  9    published by the Free Software Foundation; either version 2 of the
 10    License, or (at your option) any later version.
 11 
 12    The Gnome Library is distributed in the hope that it will be useful,
 13    but WITHOUT ANY WARRANTY; without even the implied warranty of
 14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 15    Library General Public License for more details.
 16 
 17    You should have received a copy of the GNU Library General Public
 18    License along with the Gnome Library; see the file COPYING.LIB.  If not,
 19    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 20    Boston, MA 02111-1307, USA.
 21 
 22    Authors: Darin Adler <darin@eazel.com>
 23 */
 24 
 25 #include <config.h>
 26 #include "eel-string.h"
 27 
 28 #include <errno.h>
 29 #include <locale.h>
 30 #include <stdlib.h>
 31 #include <string.h>
 32 #include <eel-glib-extensions.h>
 33 
 34 #if !defined (EEL_OMIT_SELF_CHECK)
 35 #include "eel-lib-self-check-functions.h"
 36 #endif
 37 
 38 char *
 39 eel_str_double_underscores (const char *string)
 40 {
 41 	int underscores;
 42 	const char *p;
 43 	char *q;
 44 	char *escaped;
 45 	
 46 	if (string == NULL) {
 47 		return NULL;
 48 	}
 49 	
 50 	underscores = 0;
 51 	for (p = string; *p != '\0'; p++) {
 52 		underscores += (*p == '_');
 53 	}
 54 	
 55 	if (underscores == 0) {
 56 		return g_strdup (string);
 57 	}
 58 
 59 	escaped = g_new (char, strlen (string) + underscores + 1);
 60 	for (p = string, q = escaped; *p != '\0'; p++, q++) {
 61 		/* Add an extra underscore. */
 62 		if (*p == '_') {
 63 			*q++ = '_';
 64 		}
 65 		*q = *p;
 66 	}
 67 	*q = '\0';
 68 	
 69 	return escaped;
 70 }
 71 
 72 char *
 73 eel_str_capitalize (const char *string)
 74 {
 75 	char *capitalized;
 76 
 77 	if (string == NULL) {
 78 		return NULL;
 79 	}
 80 
 81 	capitalized = g_strdup (string);
 82 
 83 	capitalized[0] = g_ascii_toupper (capitalized[0]);
 84 
 85 	return capitalized;
 86 }
 87 
 88 /* Note: eel_string_ellipsize_* that use a length in pixels
 89  * rather than characters can be found in eel_gdk_extensions.h
 90  * 
 91  * FIXME bugzilla.eazel.com 5089: 
 92  * we should coordinate the names of eel_string_ellipsize_*
 93  * and eel_str_*_truncate so that they match better and reflect
 94  * their different behavior.
 95  */
 96 char *
 97 eel_str_middle_truncate (const char *string,
 98 			 guint truncate_length)
 99 {
100 	char *truncated;
101 	guint length;
102 	guint num_left_chars;
103 	guint num_right_chars;
104 
105 	const char delimter[] = "...";
106 	const guint delimter_length = strlen (delimter);
107 	const guint min_truncate_length = delimter_length + 2;
108 
109 	if (string == NULL) {
110 		return NULL;
111 	}
112 
113 	/* It doesnt make sense to truncate strings to less than
114 	 * the size of the delimiter plus 2 characters (one on each
115 	 * side)
116 	 */
117 	if (truncate_length < min_truncate_length) {
118 		return g_strdup (string);
119 	}
120 
121 	length = g_utf8_strlen (string, -1);
122 
123 	/* Make sure the string is not already small enough. */
124 	if (length <= truncate_length) {
125 		return g_strdup (string);
126 	}
127 
128 	/* Find the 'middle' where the truncation will occur. */
129 	num_left_chars = (truncate_length - delimter_length) / 2;
130 	num_right_chars = truncate_length - num_left_chars - delimter_length;
131 
132 	truncated = g_new (char, strlen (string) + 1);
133 
134 	g_utf8_strncpy (truncated, string, num_left_chars);
135 	strcat (truncated, delimter);
136 	strcat (truncated, g_utf8_offset_to_pointer  (string, length - num_right_chars));
137 	
138 	return truncated;
139 }
140 
141 char *
142 eel_str_strip_substring_and_after (const char *string,
143 					const char *substring)
144 {
145 	const char *substring_position;
146 
147 	g_return_val_if_fail (substring != NULL, g_strdup (string));
148 	g_return_val_if_fail (substring[0] != '\0', g_strdup (string));
149 
150 	if (string == NULL) {
151 		return NULL;
152 	}
153 
154 	substring_position = strstr (string, substring);
155 	if (substring_position == NULL) {
156 		return g_strdup (string);
157 	}
158 
159 	return g_strndup (string,
160 			  substring_position - string);
161 }
162 
163 char *
164 eel_str_replace_substring (const char *string,
165 				const char *substring,
166 				const char *replacement)
167 {
168 	int substring_length, replacement_length, result_length, remaining_length;
169 	const char *p, *substring_position;
170 	char *result, *result_position;
171 
172 	g_return_val_if_fail (substring != NULL, g_strdup (string));
173 	g_return_val_if_fail (substring[0] != '\0', g_strdup (string));
174 
175 	if (string == NULL) {
176 		return NULL;
177 	}
178 
179 	substring_length = substring ? strlen (substring) : 0;
180 	replacement_length = replacement ? strlen (replacement) : 0;
181 
182 	result_length = strlen (string);
183 	for (p = string; ; p = substring_position + substring_length) {
184 		substring_position = strstr (p, substring);
185 		if (substring_position == NULL) {
186 			break;
187 		}
188 		result_length += replacement_length - substring_length;
189 	}
190 
191 	result = g_malloc (result_length + 1);
192 
193 	result_position = result;
194 	for (p = string; ; p = substring_position + substring_length) {
195 		substring_position = strstr (p, substring);
196 		if (substring_position == NULL) {
197 			remaining_length = strlen (p);
198 			memcpy (result_position, p, remaining_length);
199 			result_position += remaining_length;
200 			break;
201 		}
202 		memcpy (result_position, p, substring_position - p);
203 		result_position += substring_position - p;
204 		memcpy (result_position, replacement, replacement_length);
Null pointer passed as an argument to a 'nonnull' parameter
(emitted by clang-analyzer)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

205 result_position += replacement_length; 206 } 207 g_assert (result_position - result == result_length); 208 result_position[0] = '\0'; 209 210 return result; 211 } 212 213 /**************** Custom printf ***********/ 214 215 typedef struct { 216 const char *start; 217 const char *end; 218 GString *format; 219 int arg_pos; 220 int width_pos; 221 int width_format_index; 222 int precision_pos; 223 int precision_format_index; 224 } ConversionInfo; 225 226 enum { 227 ARG_TYPE_INVALID, 228 ARG_TYPE_INT, 229 ARG_TYPE_LONG, 230 ARG_TYPE_LONG_LONG, 231 ARG_TYPE_SIZE, 232 ARG_TYPE_LONG_DOUBLE, 233 ARG_TYPE_DOUBLE, 234 ARG_TYPE_POINTER 235 }; 236 237 typedef int ArgType; /* An int, because custom are < 0 */ 238 239 240 static const char * 241 get_position (const char *format, int *i) 242 { 243 const char *p; 244 245 p = format; 246 247 if (g_ascii_isdigit (*p)) { 248 p++; 249 250 while (g_ascii_isdigit (*p)) { 251 p++; 252 } 253 254 if (*p == '$') { 255 if (i != NULL) { 256 *i = atoi (format) - 1; 257 } 258 return p + 1; 259 } 260 } 261 262 return format; 263 } 264 265 static gboolean 266 is_flag (char c) 267 { 268 return strchr ("#0- +'I", c) != NULL; 269 } 270 271 static gboolean 272 is_length_modifier (char c) 273 { 274 return strchr ("hlLjzt", c) != NULL; 275 } 276 277 278 static ArgType 279 get_arg_type_from_format (EelPrintfHandler *custom_handlers, 280 const char *format, 281 int len) 282 { 283 int i; 284 char c; 285 286 c = format[len-1]; 287 288 if (custom_handlers != NULL) { 289 for (i = 0; custom_handlers[i].character != 0; i++) { 290 if (custom_handlers[i].character == c) { 291 return -(i + 1); 292 } 293 } 294 } 295 296 switch (c) { 297 case 'd': 298 case 'i': 299 case 'o': 300 case 'u': 301 case 'x': 302 case 'X': 303 if (g_str_has_prefix (format, "ll")) { 304 return ARG_TYPE_LONG_LONG; 305 } 306 if (g_str_has_prefix (format, "l")) { 307 return ARG_TYPE_LONG; 308 } 309 if (g_str_has_prefix (format, "l")) { 310 return ARG_TYPE_LONG; 311 } 312 if (g_str_has_prefix (format, "z")) { 313 return ARG_TYPE_SIZE; 314 } 315 return ARG_TYPE_INT; 316 case 'e': 317 case 'E': 318 case 'f': 319 case 'F': 320 case 'g': 321 case 'G': 322 case 'a': 323 case 'A': 324 if (g_str_has_prefix (format, "L")) { 325 return ARG_TYPE_LONG_DOUBLE; 326 } 327 return ARG_TYPE_DOUBLE; 328 case 'c': 329 return ARG_TYPE_INT; 330 case 's': 331 case 'p': 332 case 'n': 333 return ARG_TYPE_POINTER; 334 } 335 return ARG_TYPE_INVALID; 336 } 337 338 static void 339 skip_argv (va_list *va, 340 ArgType type, 341 EelPrintfHandler *custom_handlers) 342 { 343 if (type < 0) { 344 custom_handlers[-type - 1].skip (va); 345 return; 346 } 347 348 switch (type) { 349 default: 350 case ARG_TYPE_INVALID: 351 return; 352 353 case ARG_TYPE_INT: 354 (void) va_arg (*va, int); 355 break; 356 case ARG_TYPE_LONG: 357 (void) va_arg (*va, long int); 358 break; 359 case ARG_TYPE_LONG_LONG: 360 (void) va_arg (*va, long long int); 361 break; 362 case ARG_TYPE_SIZE: 363 (void) va_arg (*va, gsize); 364 break; 365 case ARG_TYPE_LONG_DOUBLE: 366 (void) va_arg (*va, long double); 367 break; 368 case ARG_TYPE_DOUBLE: 369 (void) va_arg (*va, double); 370 break; 371 case ARG_TYPE_POINTER: 372 (void) va_arg (*va, void *); 373 break; 374 } 375 } 376 377 static void 378 skip_to_arg (va_list *va, 379 ArgType *types, 380 EelPrintfHandler *custom_handlers, 381 int n) 382 { 383 int i; 384 for (i = 0; i < n; i++) { 385 skip_argv (va, types[i], custom_handlers); 386 } 387 } 388 389 char * 390 eel_strdup_vprintf_with_custom (EelPrintfHandler *custom, 391 const char *format, 392 va_list va_orig) 393 { 394 va_list va; 395 const char *p; 396 int num_args, i, j; 397 ArgType *args; 398 ArgType type; 399 ConversionInfo *conversions; 400 GString *f, *str; 401 const char *flags, *width, *prec, *mod, *pos; 402 char *s; 403 404 num_args = 0; 405 for (p = format; *p != 0; p++) { 406 if (*p == '%') { 407 p++; 408 if (*p != '%') { 409 num_args++; 410 } 411 } 412 } 413 414 args = g_new0 (ArgType, num_args * 3 + 1); 415 conversions = g_new0 (ConversionInfo, num_args); 416 417 /* i indexes conversions, j indexes args */ 418 i = 0; j = 0; 419 p = format; 420 while (*p != 0) { 421 if (*p != '%') { 422 p++; 423 continue; 424 } 425 p++; 426 if (*p == '%') { 427 p++; 428 continue; 429 } 430 431 /* We got a real conversion: */ 432 f = g_string_new ("%"); 433 conversions[i].start = p - 1; 434 435 /* First comes the positional arg */ 436 437 pos = p; 438 p = get_position (p, NULL); 439 440 /* Then flags */ 441 flags = p; 442 while (is_flag (*p)) { 443 p++; 444 } 445 g_string_append_len (f, flags, p - flags); 446 447 /* Field width */ 448 449 if (*p == '*') { 450 p++; 451 p = get_position (p, &j); 452 args[j] = ARG_TYPE_INT; 453 conversions[i].width_pos = j++; 454 conversions[i].width_format_index = f->len; 455 } else { 456 conversions[i].width_pos = -1; 457 conversions[i].width_format_index = -1; 458 width = p; 459 while (g_ascii_isdigit (*p)) { 460 p++; 461 } 462 g_string_append_len (f, width, p - width); 463 } 464 465 /* Precision */ 466 conversions[i].precision_pos = -1; 467 conversions[i].precision_format_index = -1; 468 if (*p == '.') { 469 g_string_append_c (f, '.'); 470 p++; 471 472 if (*p == '*') { 473 p++; 474 p = get_position (p, &j); 475 args[j] = ARG_TYPE_INT; 476 conversions[i].precision_pos = j++; 477 conversions[i].precision_format_index = f->len; 478 } else { 479 prec = p; 480 while (g_ascii_isdigit (*p) || *p == '-') { 481 p++; 482 } 483 g_string_append_len (f, prec, p - prec); 484 } 485 } 486 487 /* length modifier */ 488 489 mod = p; 490 491 while (is_length_modifier (*p)) { 492 p++; 493 } 494 495 /* conversion specifier */ 496 if (*p != 0) 497 p++; 498 499 g_string_append_len (f, mod, p - mod); 500 501 get_position (pos, &j); 502 args[j] = get_arg_type_from_format (custom, mod, p - mod); 503 conversions[i].arg_pos = j++; 504 conversions[i].format = f; 505 conversions[i].end = p; 506 507 i++; 508 } 509 510 g_assert (i == num_args); 511 512 str = g_string_new (""); 513 514 p = format; 515 for (i = 0; i < num_args; i++) { 516 g_string_append_len (str, p, conversions[i].start - p); 517 p = conversions[i].end; 518 519 if (conversions[i].precision_pos != -1) { 520 char *val; 521 522 G_VA_COPY(va, va_orig); 523 skip_to_arg (&va, args, custom, conversions[i].precision_pos); 524 val = g_strdup_vprintf ("%d", va); 525 va_end (va); 526 527 g_string_insert (conversions[i].format, 528 conversions[i].precision_format_index, 529 val); 530 531 g_free (val); 532 } 533 534 if (conversions[i].width_pos != -1) { 535 char *val; 536 537 G_VA_COPY(va, va_orig); 538 skip_to_arg (&va, args, custom, conversions[i].width_pos); 539 val = g_strdup_vprintf ("%d", va); 540 va_end (va); 541 542 g_string_insert (conversions[i].format, 543 conversions[i].width_format_index, 544 val); 545 546 g_free (val); 547 } 548 549 G_VA_COPY(va, va_orig); 550 skip_to_arg (&va, args, custom, conversions[i].arg_pos); 551 type = args[conversions[i].arg_pos]; 552 if (type < 0) { 553 s = custom[-type - 1].to_string (conversions[i].format->str, va); 554 g_string_append (str, s); 555 g_free (s); 556 } else{ 557 g_string_append_vprintf (str, conversions[i].format->str, va); 558 } 559 va_end (va); 560 561 g_string_free (conversions[i].format, TRUE); 562 } 563 g_string_append (str, p); 564 565 g_free (args); 566 g_free (conversions); 567 568 return g_string_free (str, FALSE); 569 } 570 571 char * 572 eel_strdup_printf_with_custom (EelPrintfHandler *handlers, 573 const char *format, 574 ...) 575 { 576 va_list va; 577 char *res; 578 579 va_start (va, format); 580 res = eel_strdup_vprintf_with_custom (handlers, format, va); 581 va_end (va); 582 583 return res; 584 } 585 586 /*********** refcounted strings ****************/ 587 588 G_LOCK_DEFINE_STATIC (unique_ref_strs); 589 static GHashTable *unique_ref_strs = NULL; 590 591 static eel_ref_str 592 eel_ref_str_new_internal (const char *string, int start_count) 593 { 594 char *res; 595 volatile gint *count; 596 gsize len; 597 598 len = strlen (string); 599 res = g_malloc (sizeof (gint) + len + 1); 600 count = (volatile gint *)res; 601 *count = start_count; 602 res += sizeof(gint); 603 memcpy (res, string, len + 1); 604 return res; 605 } 606 607 eel_ref_str 608 eel_ref_str_new (const char *string) 609 { 610 if (string == NULL) { 611 return NULL; 612 } 613 614 return eel_ref_str_new_internal (string, 1); 615 } 616 617 eel_ref_str 618 eel_ref_str_get_unique (const char *string) 619 { 620 eel_ref_str res; 621 622 if (string == NULL) { 623 return NULL; 624 } 625 626 G_LOCK (unique_ref_strs); 627 if (unique_ref_strs == NULL) { 628 unique_ref_strs = 629 g_hash_table_new (g_str_hash, g_str_equal); 630 } 631 632 res = g_hash_table_lookup (unique_ref_strs, string); 633 if (res != NULL) { 634 eel_ref_str_ref (res); 635 } else { 636 res = eel_ref_str_new_internal (string, 0x80000001); 637 g_hash_table_insert (unique_ref_strs, res, res); 638 } 639 640 G_UNLOCK (unique_ref_strs); 641 642 return res; 643 } 644 645 eel_ref_str 646 eel_ref_str_ref (eel_ref_str str) 647 { 648 volatile gint *count; 649 650 count = (volatile gint *)((char *)str - sizeof (gint)); 651 g_atomic_int_add (count, 1); 652 653 return str; 654 } 655 656 void 657 eel_ref_str_unref (eel_ref_str str) 658 { 659 volatile gint *count; 660 gint old_ref; 661 662 if (str == NULL) 663 return; 664 665 count = (volatile gint *)((char *)str - sizeof (gint)); 666 667 retry_atomic_decrement: 668 old_ref = g_atomic_int_get (count); 669 if (old_ref == 1) { 670 g_free ((char *)count); 671 } else if (old_ref == 0x80000001) { 672 G_LOCK (unique_ref_strs); 673 /* Need to recheck after taking lock to avoid races with _get_unique() */ 674 if (g_atomic_int_add (count, -1) == 0x80000001) { 675 g_hash_table_remove (unique_ref_strs, (char *)str); 676 g_free ((char *)count); 677 } 678 G_UNLOCK (unique_ref_strs); 679 } else if (!g_atomic_int_compare_and_exchange (count, 680 old_ref, old_ref - 1)) { 681 goto retry_atomic_decrement; 682 } 683 } 684 685 686 #if !defined (EEL_OMIT_SELF_CHECK) 687 688 static void 689 verify_printf (const char *format, ...) 690 { 691 va_list va; 692 char *orig, *new; 693 694 va_start (va, format); 695 orig = g_strdup_vprintf (format, va); 696 va_end (va); 697 698 va_start (va, format); 699 new = eel_strdup_vprintf_with_custom (NULL, format, va); 700 va_end (va); 701 702 EEL_CHECK_STRING_RESULT (new, orig); 703 704 g_free (orig); 705 } 706 707 static char * 708 custom1_to_string (char *format, va_list va) 709 { 710 int i; 711 712 i = va_arg (va, int); 713 714 return g_strdup_printf ("c1-%d-", i); 715 } 716 717 static void 718 custom1_skip (va_list *va) 719 { 720 (void) va_arg (*va, int); 721 } 722 723 static char * 724 custom2_to_string (char *format, va_list va) 725 { 726 char *s; 727 728 s = va_arg (va, char *); 729 730 return g_strdup_printf ("c2-%s-", s); 731 } 732 733 static void 734 custom2_skip (va_list *va) 735 { 736 (void) va_arg (*va, char *); 737 } 738 739 static EelPrintfHandler handlers[] = { 740 { 'N', custom1_to_string, custom1_skip }, 741 { 'Y', custom2_to_string, custom2_skip }, 742 { 0 } 743 }; 744 745 static void 746 verify_custom (const char *orig, const char *format, ...) 747 { 748 char *new; 749 va_list va; 750 751 va_start (va, format); 752 new = eel_strdup_vprintf_with_custom (handlers, format, va); 753 va_end (va); 754 755 EEL_CHECK_STRING_RESULT (new, orig); 756 } 757 758 void 759 eel_self_check_string (void) 760 { 761 EEL_CHECK_STRING_RESULT (eel_str_double_underscores (NULL), NULL); 762 EEL_CHECK_STRING_RESULT (eel_str_double_underscores (""), ""); 763 EEL_CHECK_STRING_RESULT (eel_str_double_underscores ("_"), "__"); 764 EEL_CHECK_STRING_RESULT (eel_str_double_underscores ("foo"), "foo"); 765 EEL_CHECK_STRING_RESULT (eel_str_double_underscores ("foo_bar"), "foo__bar"); 766 EEL_CHECK_STRING_RESULT (eel_str_double_underscores ("foo_bar_2"), "foo__bar__2"); 767 EEL_CHECK_STRING_RESULT (eel_str_double_underscores ("_foo"), "__foo"); 768 EEL_CHECK_STRING_RESULT (eel_str_double_underscores ("foo_"), "foo__"); 769 770 EEL_CHECK_STRING_RESULT (eel_str_capitalize (NULL), NULL); 771 EEL_CHECK_STRING_RESULT (eel_str_capitalize (""), ""); 772 EEL_CHECK_STRING_RESULT (eel_str_capitalize ("foo"), "Foo"); 773 EEL_CHECK_STRING_RESULT (eel_str_capitalize ("Foo"), "Foo"); 774 775 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("foo", 0), "foo"); 776 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("foo", 1), "foo"); 777 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("foo", 3), "foo"); 778 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("foo", 4), "foo"); 779 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("foo", 5), "foo"); 780 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("foo", 6), "foo"); 781 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("foo", 7), "foo"); 782 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("a_much_longer_foo", 0), "a_much_longer_foo"); 783 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("a_much_longer_foo", 1), "a_much_longer_foo"); 784 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("a_much_longer_foo", 2), "a_much_longer_foo"); 785 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("a_much_longer_foo", 3), "a_much_longer_foo"); 786 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("a_much_longer_foo", 4), "a_much_longer_foo"); 787 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("a_much_longer_foo", 5), "a...o"); 788 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("a_much_longer_foo", 6), "a...oo"); 789 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("a_much_longer_foo", 7), "a_...oo"); 790 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("a_much_longer_foo", 8), "a_...foo"); 791 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("a_much_longer_foo", 9), "a_m...foo"); 792 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_even", 8), "so...ven"); 793 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_odd", 8), "so...odd"); 794 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_even", 9), "som...ven"); 795 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_odd", 9), "som...odd"); 796 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_even", 10), "som...even"); 797 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_odd", 10), "som..._odd"); 798 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_even", 11), "some...even"); 799 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_odd", 11), "some..._odd"); 800 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_even", 12), "some..._even"); 801 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_odd", 12), "some...g_odd"); 802 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_even", 13), "somet..._even"); 803 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_odd", 13), "something_odd"); 804 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_even", 14), "something_even"); 805 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_odd", 13), "something_odd"); 806 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("ääääääääää", 5), "ä...ä"); 807 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("あぃいぅうぇえぉ", 7), "あぃ...えぉ"); 808 809 EEL_CHECK_STRING_RESULT (eel_str_strip_substring_and_after (NULL, "bar"), NULL); 810 EEL_CHECK_STRING_RESULT (eel_str_strip_substring_and_after ("", "bar"), ""); 811 EEL_CHECK_STRING_RESULT (eel_str_strip_substring_and_after ("foo", "bar"), "foo"); 812 EEL_CHECK_STRING_RESULT (eel_str_strip_substring_and_after ("foo bar", "bar"), "foo "); 813 EEL_CHECK_STRING_RESULT (eel_str_strip_substring_and_after ("foo bar xxx", "bar"), "foo "); 814 EEL_CHECK_STRING_RESULT (eel_str_strip_substring_and_after ("bar", "bar"), ""); 815 816 EEL_CHECK_STRING_RESULT (eel_str_replace_substring (NULL, "foo", NULL), NULL); 817 EEL_CHECK_STRING_RESULT (eel_str_replace_substring (NULL, "foo", "bar"), NULL); 818 EEL_CHECK_STRING_RESULT (eel_str_replace_substring ("bar", "foo", NULL), "bar"); 819 EEL_CHECK_STRING_RESULT (eel_str_replace_substring ("", "foo", ""), ""); 820 EEL_CHECK_STRING_RESULT (eel_str_replace_substring ("", "foo", "bar"), ""); 821 EEL_CHECK_STRING_RESULT (eel_str_replace_substring ("bar", "foo", ""), "bar"); 822 EEL_CHECK_STRING_RESULT (eel_str_replace_substring ("xxx", "x", "foo"), "foofoofoo"); 823 EEL_CHECK_STRING_RESULT (eel_str_replace_substring ("fff", "f", "foo"), "foofoofoo"); 824 EEL_CHECK_STRING_RESULT (eel_str_replace_substring ("foofoofoo", "foo", "f"), "fff"); 825 EEL_CHECK_STRING_RESULT (eel_str_replace_substring ("foofoofoo", "f", ""), "oooooo"); 826 827 verify_printf ("%.*s", 2, "foo"); 828 verify_printf ("%*.*s", 2, 4, "foo"); 829 verify_printf ("before %5$*1$.*2$s between %6$*3$.*4$d after", 830 4, 5, 6, 7, "foo", G_PI); 831 verify_custom ("c1-42- c2-foo-","%N %Y", 42 ,"foo"); 832 verify_custom ("c1-42- bar c2-foo-","%N %s %Y", 42, "bar" ,"foo"); 833 verify_custom ("c1-42- bar c2-foo-","%3$N %2$s %1$Y","foo", "bar", 42); 834 835 } 836 837 #endif /* !EEL_OMIT_SELF_CHECK */