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