This source file includes following definitions.
- str_test_not_convert
- _str_convert
- str_test_encoding_class
- str_choose_str_functions
- str_crt_conv_to
- str_crt_conv_from
- str_close_conv
- str_convert
- str_nconvert
- str_conv_gerror_message
- str_vfs_convert_from
- str_vfs_convert_to
- str_printf
- str_insert_replace_char
- str_translate_char
- str_detect_termencoding
- str_isutf8
- str_init_strings
- str_uninit_strings
- str_term_form
- str_fit_to_term
- str_term_trim
- str_term_substring
- str_get_next_char
- str_cget_next_char
- str_next_char
- str_cnext_char
- str_get_prev_char
- str_cget_prev_char
- str_prev_char
- str_cprev_char
- str_get_next_char_safe
- str_cget_next_char_safe
- str_next_char_safe
- str_cnext_char_safe
- str_get_prev_char_safe
- str_cget_prev_char_safe
- str_prev_char_safe
- str_cprev_char_safe
- str_next_noncomb_char
- str_cnext_noncomb_char
- str_prev_noncomb_char
- str_cprev_noncomb_char
- str_is_valid_char
- str_term_width1
- str_term_width2
- str_term_char_width
- str_offset_to_pos
- str_length
- str_length_char
- str_length2
- str_length_noncomb
- str_column_to_pos
- str_isspace
- str_ispunct
- str_isalnum
- str_isdigit
- str_toupper
- str_tolower
- str_isprint
- str_iscombiningmark
- str_trunc
- str_create_search_needle
- str_release_search_needle
- str_search_first
- str_search_last
- str_is_valid_string
- str_compare
- str_ncompare
- str_casecmp
- str_ncasecmp
- str_prefix
- str_caseprefix
- str_fix_string
- str_create_key
- str_create_key_for_filename
- str_key_collate
- str_release_key
- str_msg_term_size
- strrstr_skip_count
- parse_integer
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 #include <config.h>
27
28 #include <stdlib.h>
29 #include <langinfo.h>
30 #include <string.h>
31 #include <errno.h>
32
33 #include "lib/global.h"
34 #include "lib/util.h"
35 #include "lib/strutil.h"
36
37
38
39 GIConv str_cnv_to_term;
40 GIConv str_cnv_from_term;
41 GIConv str_cnv_not_convert = INVALID_CONV;
42
43
44
45
46
47
48
49
50 static const char *const str_utf8_encodings[] = {
51 "utf-8",
52 "utf8",
53 NULL
54 };
55
56
57 static const char *const str_8bit_encodings[] = {
58
59 #ifdef __sun
60 "ansi-1251",
61 "ansi1251",
62 #else
63 "cp-1251",
64 "cp1251",
65 #endif
66 "cp-1250",
67 "cp1250",
68 "cp-866",
69 "cp866",
70 "ibm-866",
71 "ibm866",
72 "cp-850",
73 "cp850",
74 "cp-852",
75 "cp852",
76 "iso-8859",
77 "iso8859",
78 "koi8",
79 NULL
80 };
81
82
83 static char *codeset = NULL;
84 static char *term_encoding = NULL;
85
86 static struct str_class used_class;
87
88
89
90
91
92
93 static int
94 str_test_not_convert (const char *enc)
95 {
96 return g_ascii_strcasecmp (enc, codeset) == 0;
97 }
98
99
100
101 static estr_t
102 _str_convert (GIConv coder, const char *string, int size, GString * buffer)
103 {
104 estr_t state = ESTR_SUCCESS;
105 gssize left;
106 gsize bytes_read = 0;
107 gsize bytes_written = 0;
108
109 errno = 0;
110
111 if (coder == INVALID_CONV)
112 return ESTR_FAILURE;
113
114 if (string == NULL || buffer == NULL)
115 return ESTR_FAILURE;
116
117
118
119
120
121
122
123 if (size < 0)
124 size = strlen (string);
125 else
126 {
127 left = strlen (string);
128 if (left < size)
129 size = left;
130 }
131
132 left = size;
133 g_iconv (coder, NULL, NULL, NULL, NULL);
134
135 while (left != 0)
136 {
137 gchar *tmp_buff;
138 GError *mcerror = NULL;
139
140 tmp_buff = g_convert_with_iconv ((const gchar *) string,
141 left, coder, &bytes_read, &bytes_written, &mcerror);
142 if (mcerror != NULL)
143 {
144 int code = mcerror->code;
145
146 g_error_free (mcerror);
147 mcerror = NULL;
148
149 switch (code)
150 {
151 case G_CONVERT_ERROR_NO_CONVERSION:
152
153 g_free (tmp_buff);
154 tmp_buff = g_strnfill (strlen (string), '?');
155 g_string_append (buffer, tmp_buff);
156 g_free (tmp_buff);
157 return ESTR_FAILURE;
158
159 case G_CONVERT_ERROR_ILLEGAL_SEQUENCE:
160
161 if ((tmp_buff == NULL) && (bytes_read != 0))
162
163 tmp_buff = g_convert_with_iconv ((const gchar *) string,
164 bytes_read, coder, NULL, NULL, NULL);
165
166 if (tmp_buff != NULL)
167 {
168 g_string_append (buffer, tmp_buff);
169 g_free (tmp_buff);
170 }
171
172 if ((int) bytes_read >= left)
173 return ESTR_PROBLEM;
174
175 string += bytes_read + 1;
176 size -= (bytes_read + 1);
177 left -= (bytes_read + 1);
178 g_string_append_c (buffer, *(string - 1));
179 state = ESTR_PROBLEM;
180 break;
181
182 case G_CONVERT_ERROR_PARTIAL_INPUT:
183
184 g_string_append (buffer, tmp_buff);
185 g_free (tmp_buff);
186 if ((int) bytes_read < left)
187 {
188 left = left - bytes_read;
189 tmp_buff = g_strnfill (left, '?');
190 g_string_append (buffer, tmp_buff);
191 g_free (tmp_buff);
192 }
193 return ESTR_PROBLEM;
194
195 case G_CONVERT_ERROR_BAD_URI:
196 case G_CONVERT_ERROR_NOT_ABSOLUTE_PATH:
197 case G_CONVERT_ERROR_FAILED:
198 default:
199 g_free (tmp_buff);
200 return ESTR_FAILURE;
201 }
202 }
203 else if (tmp_buff == NULL)
204 {
205 g_string_append (buffer, string);
206 return ESTR_PROBLEM;
207 }
208 else if (*tmp_buff == '\0')
209 {
210 g_free (tmp_buff);
211 g_string_append (buffer, string);
212 return state;
213 }
214 else
215 {
216 g_string_append (buffer, tmp_buff);
217 g_free (tmp_buff);
218 string += bytes_read;
219 left -= bytes_read;
220 }
221 }
222
223 return state;
224 }
225
226
227
228 static int
229 str_test_encoding_class (const char *encoding, const char *const *table)
230 {
231 int result = 0;
232
233 if (encoding != NULL)
234 {
235 int t;
236
237 for (t = 0; table[t] != NULL; t++)
238 if (g_ascii_strncasecmp (encoding, table[t], strlen (table[t])) == 0)
239 result++;
240 }
241
242 return result;
243 }
244
245
246
247 static void
248 str_choose_str_functions (void)
249 {
250 if (str_test_encoding_class (codeset, str_utf8_encodings))
251 used_class = str_utf8_init ();
252 else if (str_test_encoding_class (codeset, str_8bit_encodings))
253 used_class = str_8bit_init ();
254 else
255 used_class = str_ascii_init ();
256 }
257
258
259
260
261
262 GIConv
263 str_crt_conv_to (const char *to_enc)
264 {
265 return (!str_test_not_convert (to_enc)) ? g_iconv_open (to_enc, codeset) : str_cnv_not_convert;
266 }
267
268
269
270 GIConv
271 str_crt_conv_from (const char *from_enc)
272 {
273 return (!str_test_not_convert (from_enc))
274 ? g_iconv_open (codeset, from_enc) : str_cnv_not_convert;
275 }
276
277
278
279 void
280 str_close_conv (GIConv conv)
281 {
282 if (conv != str_cnv_not_convert)
283 g_iconv_close (conv);
284 }
285
286
287
288 estr_t
289 str_convert (GIConv coder, const char *string, GString * buffer)
290 {
291 return _str_convert (coder, string, -1, buffer);
292 }
293
294
295
296 estr_t
297 str_nconvert (GIConv coder, const char *string, int size, GString * buffer)
298 {
299 return _str_convert (coder, string, size, buffer);
300 }
301
302
303
304 gchar *
305 str_conv_gerror_message (GError * mcerror, const char *def_msg)
306 {
307 return used_class.conv_gerror_message (mcerror, def_msg);
308 }
309
310
311
312 estr_t
313 str_vfs_convert_from (GIConv coder, const char *string, GString * buffer)
314 {
315 estr_t result = ESTR_SUCCESS;
316
317 if (coder == str_cnv_not_convert)
318 g_string_append (buffer, string != NULL ? string : "");
319 else
320 result = _str_convert (coder, string, -1, buffer);
321
322 return result;
323 }
324
325
326
327 estr_t
328 str_vfs_convert_to (GIConv coder, const char *string, int size, GString * buffer)
329 {
330 return used_class.vfs_convert_to (coder, string, size, buffer);
331 }
332
333
334
335 void
336 str_printf (GString * buffer, const char *format, ...)
337 {
338 va_list ap;
339 va_start (ap, format);
340
341 g_string_append_vprintf (buffer, format, ap);
342 va_end (ap);
343 }
344
345
346
347 void
348 str_insert_replace_char (GString * buffer)
349 {
350 used_class.insert_replace_char (buffer);
351 }
352
353
354
355 estr_t
356 str_translate_char (GIConv conv, const char *keys, size_t ch_size, char *output, size_t out_size)
357 {
358 size_t left;
359 size_t cnv;
360
361 g_iconv (conv, NULL, NULL, NULL, NULL);
362
363 left = (ch_size == (size_t) (-1)) ? strlen (keys) : ch_size;
364
365 cnv = g_iconv (conv, (gchar **) & keys, &left, &output, &out_size);
366 if (cnv == (size_t) (-1))
367 return (errno == EINVAL) ? ESTR_PROBLEM : ESTR_FAILURE;
368
369 output[0] = '\0';
370 return ESTR_SUCCESS;
371 }
372
373
374
375 const char *
376 str_detect_termencoding (void)
377 {
378 if (term_encoding == NULL)
379 {
380
381
382
383
384 term_encoding = g_ascii_strup (nl_langinfo (CODESET), -1);
385 }
386
387 return term_encoding;
388 }
389
390
391
392 gboolean
393 str_isutf8 (const char *codeset_name)
394 {
395 return (str_test_encoding_class (codeset_name, str_utf8_encodings) != 0);
396 }
397
398
399
400 void
401 str_init_strings (const char *termenc)
402 {
403 codeset = termenc != NULL ? g_ascii_strup (termenc, -1) : g_strdup (str_detect_termencoding ());
404
405 str_cnv_not_convert = g_iconv_open (codeset, codeset);
406 if (str_cnv_not_convert == INVALID_CONV)
407 {
408 if (termenc != NULL)
409 {
410 g_free (codeset);
411 codeset = g_strdup (str_detect_termencoding ());
412 str_cnv_not_convert = g_iconv_open (codeset, codeset);
413 }
414
415 if (str_cnv_not_convert == INVALID_CONV)
416 {
417 g_free (codeset);
418 codeset = g_strdup (DEFAULT_CHARSET);
419 str_cnv_not_convert = g_iconv_open (codeset, codeset);
420 }
421 }
422
423 str_cnv_to_term = str_cnv_not_convert;
424 str_cnv_from_term = str_cnv_not_convert;
425
426 str_choose_str_functions ();
427 }
428
429
430
431 void
432 str_uninit_strings (void)
433 {
434 if (str_cnv_not_convert != INVALID_CONV)
435 g_iconv_close (str_cnv_not_convert);
436
437 MC_PTR_FREE (term_encoding);
438 MC_PTR_FREE (codeset);
439 }
440
441
442
443 const char *
444 str_term_form (const char *text)
445 {
446 return used_class.term_form (text);
447 }
448
449
450
451 const char *
452 str_fit_to_term (const char *text, int width, align_crt_t just_mode)
453 {
454 return used_class.fit_to_term (text, width, just_mode);
455 }
456
457
458
459 const char *
460 str_term_trim (const char *text, int width)
461 {
462 return used_class.term_trim (text, width);
463 }
464
465
466
467 const char *
468 str_term_substring (const char *text, int start, int width)
469 {
470 return used_class.term_substring (text, start, width);
471 }
472
473
474
475 char *
476 str_get_next_char (char *text)
477 {
478
479 used_class.cnext_char ((const char **) &text);
480 return text;
481 }
482
483
484
485 const char *
486 str_cget_next_char (const char *text)
487 {
488 used_class.cnext_char (&text);
489 return text;
490 }
491
492
493
494 void
495 str_next_char (char **text)
496 {
497 used_class.cnext_char ((const char **) text);
498 }
499
500
501
502 void
503 str_cnext_char (const char **text)
504 {
505 used_class.cnext_char (text);
506 }
507
508
509
510 char *
511 str_get_prev_char (char *text)
512 {
513 used_class.cprev_char ((const char **) &text);
514 return text;
515 }
516
517
518
519 const char *
520 str_cget_prev_char (const char *text)
521 {
522 used_class.cprev_char (&text);
523 return text;
524 }
525
526
527
528 void
529 str_prev_char (char **text)
530 {
531 used_class.cprev_char ((const char **) text);
532 }
533
534
535
536 void
537 str_cprev_char (const char **text)
538 {
539 used_class.cprev_char (text);
540 }
541
542
543
544 char *
545 str_get_next_char_safe (char *text)
546 {
547 used_class.cnext_char_safe ((const char **) &text);
548 return text;
549 }
550
551
552
553 const char *
554 str_cget_next_char_safe (const char *text)
555 {
556 used_class.cnext_char_safe (&text);
557 return text;
558 }
559
560
561
562 void
563 str_next_char_safe (char **text)
564 {
565 used_class.cnext_char_safe ((const char **) text);
566 }
567
568
569
570 void
571 str_cnext_char_safe (const char **text)
572 {
573 used_class.cnext_char_safe (text);
574 }
575
576
577
578 char *
579 str_get_prev_char_safe (char *text)
580 {
581 used_class.cprev_char_safe ((const char **) &text);
582 return text;
583 }
584
585
586
587 const char *
588 str_cget_prev_char_safe (const char *text)
589 {
590 used_class.cprev_char_safe (&text);
591 return text;
592 }
593
594
595
596 void
597 str_prev_char_safe (char **text)
598 {
599 used_class.cprev_char_safe ((const char **) text);
600 }
601
602
603
604 void
605 str_cprev_char_safe (const char **text)
606 {
607 used_class.cprev_char_safe (text);
608 }
609
610
611
612 int
613 str_next_noncomb_char (char **text)
614 {
615 return used_class.cnext_noncomb_char ((const char **) text);
616 }
617
618
619
620 int
621 str_cnext_noncomb_char (const char **text)
622 {
623 return used_class.cnext_noncomb_char (text);
624 }
625
626
627
628 int
629 str_prev_noncomb_char (char **text, const char *begin)
630 {
631 return used_class.cprev_noncomb_char ((const char **) text, begin);
632 }
633
634
635
636 int
637 str_cprev_noncomb_char (const char **text, const char *begin)
638 {
639 return used_class.cprev_noncomb_char (text, begin);
640 }
641
642
643
644 int
645 str_is_valid_char (const char *ch, size_t size)
646 {
647 return used_class.is_valid_char (ch, size);
648 }
649
650
651
652 int
653 str_term_width1 (const char *text)
654 {
655 return used_class.term_width1 (text);
656 }
657
658
659
660 int
661 str_term_width2 (const char *text, size_t length)
662 {
663 return used_class.term_width2 (text, length);
664 }
665
666
667
668 int
669 str_term_char_width (const char *text)
670 {
671 return used_class.term_char_width (text);
672 }
673
674
675
676 int
677 str_offset_to_pos (const char *text, size_t length)
678 {
679 return used_class.offset_to_pos (text, length);
680 }
681
682
683
684 int
685 str_length (const char *text)
686 {
687 return used_class.length (text);
688 }
689
690
691
692 int
693 str_length_char (const char *text)
694 {
695 return str_cget_next_char_safe (text) - text;
696 }
697
698
699
700 int
701 str_length2 (const char *text, int size)
702 {
703 return used_class.length2 (text, size);
704 }
705
706
707
708 int
709 str_length_noncomb (const char *text)
710 {
711 return used_class.length_noncomb (text);
712 }
713
714
715
716 int
717 str_column_to_pos (const char *text, size_t pos)
718 {
719 return used_class.column_to_pos (text, pos);
720 }
721
722
723
724 gboolean
725 str_isspace (const char *ch)
726 {
727 return used_class.char_isspace (ch);
728 }
729
730
731
732 gboolean
733 str_ispunct (const char *ch)
734 {
735 return used_class.char_ispunct (ch);
736 }
737
738
739
740 gboolean
741 str_isalnum (const char *ch)
742 {
743 return used_class.char_isalnum (ch);
744 }
745
746
747
748 gboolean
749 str_isdigit (const char *ch)
750 {
751 return used_class.char_isdigit (ch);
752 }
753
754
755
756 gboolean
757 str_toupper (const char *ch, char **out, size_t * remain)
758 {
759 return used_class.char_toupper (ch, out, remain);
760 }
761
762
763
764 gboolean
765 str_tolower (const char *ch, char **out, size_t * remain)
766 {
767 return used_class.char_tolower (ch, out, remain);
768 }
769
770
771
772 gboolean
773 str_isprint (const char *ch)
774 {
775 return used_class.char_isprint (ch);
776 }
777
778
779
780 gboolean
781 str_iscombiningmark (const char *ch)
782 {
783 return used_class.char_iscombiningmark (ch);
784 }
785
786
787
788 const char *
789 str_trunc (const char *text, int width)
790 {
791 return used_class.trunc (text, width);
792 }
793
794
795
796 char *
797 str_create_search_needle (const char *needle, gboolean case_sen)
798 {
799 return used_class.create_search_needle (needle, case_sen);
800 }
801
802
803
804 void
805 str_release_search_needle (char *needle, gboolean case_sen)
806 {
807 used_class.release_search_needle (needle, case_sen);
808 }
809
810
811
812 const char *
813 str_search_first (const char *text, const char *search, gboolean case_sen)
814 {
815 return used_class.search_first (text, search, case_sen);
816 }
817
818
819
820 const char *
821 str_search_last (const char *text, const char *search, gboolean case_sen)
822 {
823 return used_class.search_last (text, search, case_sen);
824 }
825
826
827
828 gboolean
829 str_is_valid_string (const char *text)
830 {
831 return used_class.is_valid_string (text);
832 }
833
834
835
836 int
837 str_compare (const char *t1, const char *t2)
838 {
839 return used_class.compare (t1, t2);
840 }
841
842
843
844 int
845 str_ncompare (const char *t1, const char *t2)
846 {
847 return used_class.ncompare (t1, t2);
848 }
849
850
851
852 int
853 str_casecmp (const char *t1, const char *t2)
854 {
855 return used_class.casecmp (t1, t2);
856 }
857
858
859
860 int
861 str_ncasecmp (const char *t1, const char *t2)
862 {
863 return used_class.ncasecmp (t1, t2);
864 }
865
866
867
868 int
869 str_prefix (const char *text, const char *prefix)
870 {
871 return used_class.prefix (text, prefix);
872 }
873
874
875
876 int
877 str_caseprefix (const char *text, const char *prefix)
878 {
879 return used_class.caseprefix (text, prefix);
880 }
881
882
883
884 void
885 str_fix_string (char *text)
886 {
887 used_class.fix_string (text);
888 }
889
890
891
892 char *
893 str_create_key (const char *text, gboolean case_sen)
894 {
895 return used_class.create_key (text, case_sen);
896 }
897
898
899
900 char *
901 str_create_key_for_filename (const char *text, gboolean case_sen)
902 {
903 return used_class.create_key_for_filename (text, case_sen);
904 }
905
906
907
908 int
909 str_key_collate (const char *t1, const char *t2, gboolean case_sen)
910 {
911 return used_class.key_collate (t1, t2, case_sen);
912 }
913
914
915
916 void
917 str_release_key (char *key, gboolean case_sen)
918 {
919 used_class.release_key (key, case_sen);
920 }
921
922
923
924 void
925 str_msg_term_size (const char *text, int *lines, int *columns)
926 {
927 char *p, *tmp;
928 char *q;
929 char c = '\0';
930
931 *lines = 1;
932 *columns = 0;
933
934 tmp = g_strdup (text);
935 p = tmp;
936
937 while (TRUE)
938 {
939 int width;
940
941 q = strchr (p, '\n');
942 if (q != NULL)
943 {
944 c = q[0];
945 q[0] = '\0';
946 }
947
948 width = str_term_width1 (p);
949 if (width > *columns)
950 *columns = width;
951
952 if (q == NULL)
953 break;
954
955 q[0] = c;
956 p = q + 1;
957 (*lines)++;
958 }
959
960 g_free (tmp);
961 }
962
963
964
965 char *
966 strrstr_skip_count (const char *haystack, const char *needle, size_t skip_count)
967 {
968 char *semi;
969 ssize_t len;
970
971 len = strlen (haystack);
972
973 do
974 {
975 semi = g_strrstr_len (haystack, len, needle);
976 if (semi == NULL)
977 return NULL;
978 len = semi - haystack - 1;
979 }
980 while (skip_count-- != 0);
981
982 return semi;
983 }
984
985
986
987
988
989
990
991
992
993
994 uintmax_t
995 parse_integer (const char *str, gboolean * invalid)
996 {
997 uintmax_t n;
998 char *suffix;
999 strtol_error_t e;
1000
1001 e = xstrtoumax (str, &suffix, 10, &n, "bcEGkKMPTwYZ0");
1002 if (e == LONGINT_INVALID_SUFFIX_CHAR && *suffix == 'x')
1003 {
1004 uintmax_t multiplier;
1005
1006 multiplier = parse_integer (suffix + 1, invalid);
1007 if (multiplier != 0 && n * multiplier / multiplier != n)
1008 {
1009 *invalid = TRUE;
1010 return 0;
1011 }
1012
1013 n *= multiplier;
1014 }
1015 else if (e != LONGINT_OK)
1016 {
1017 *invalid = TRUE;
1018 n = 0;
1019 }
1020
1021 return n;
1022 }
1023
1024