Add threshold for file size.
[midnight-commander.git] / lib / strutil.h
blob8b66c1e58c906d3aff6f2f2c2c4710813b590e2b
1 #ifndef MC_STRUTIL_H
2 #define MC_STRUTIL_H
4 #include "lib/global.h" /* include glib.h */
6 #include <sys/types.h>
7 #include <inttypes.h>
8 #include <string.h>
9 #ifdef HAVE_ASSERT_H
10 #include <assert.h> /* assert() */
11 #endif
13 /* Header file for strutil.c, strutilascii.c, strutil8bit.c, strutilutf8.c.
14 * There are two sort of functions:
15 * 1. functions for working with growing strings and conversion strings between
16 * different encodings.
17 * (implemented directly in strutil.c)
18 * 2. functions, that hide differences between encodings derived from ASCII.
19 * (implemented separately in strutilascii.c, strutil8bit.c, strutilutf8.c)
20 * documentation is made for UTF-8 version of functions.
23 /* invalid strings
24 * function, that works with invalid strings are marked with "I"
25 * in documentation
26 * invalid bytes of string are handled as one byte characters with width 1, they
27 * are displayed as questionmarks, I-maked comparing functions try to keep
28 * the original value of these bytes.
31 /* combining characters
32 * displaynig: all handled as zero with characters, expect combing character
33 * at the begin of string, this character has with one (space add before),
34 * so str_term_width is not good for computing width of singles characters
35 * (never return zero, expect emtpy string)
36 * for compatibility are strings composed before displaynig
37 * comparing: comparing decompose all string before comparing, n-compare
38 * functions do not work as is usual, because same strings do not have to be
39 * same length in UTF-8. So they return 0 if one string is prefix of the other
40 * one.
41 * str_prefix is used to determine, how many characters from one string are
42 * prefix in second string. However, str_prefix return number of characters in
43 * decompose form. (used in do_search (screen.c))
46 /*** typedefs(not structures) and defined constants **********************************************/
48 #define IS_FIT(x) ((x) & 0x0010)
49 #define MAKE_FIT(x) ((x) | 0x0010)
50 #define HIDE_FIT(x) ((x) & 0x000f)
52 #define INVALID_CONV ((GIConv) (-1))
54 /*** enums ***************************************************************************************/
56 /* results of conversion function
58 typedef enum
60 /* success means, that convertion has been finished successully
62 ESTR_SUCCESS = 0,
63 /* problem means, that not every characters was successfully converted (They are
64 * replaced with questionmark). So is impossible convert string back.
66 ESTR_PROBLEM = 1,
67 /* failure means, that conversion is not possible (example: wrong encoding
68 * of input string)
70 ESTR_FAILURE = 2
71 } estr_t;
73 /* alignment strings on terminal
75 typedef enum
77 J_LEFT = 0x01,
78 J_RIGHT = 0x02,
79 J_CENTER = 0x03,
80 /* if there is enough space for string on terminal,
81 * string is centered otherwise is aligned to left */
82 J_CENTER_LEFT = 0x04,
83 /* fit alignment, if string is to long, is truncated with '~' */
84 J_LEFT_FIT = 0x11,
85 J_RIGHT_FIT = 0x12,
86 J_CENTER_FIT = 0x13,
87 J_CENTER_LEFT_FIT = 0x14
88 } align_crt_t;
90 /* string-to-integer parsing results
92 typedef enum
94 LONGINT_OK = 0,
96 /* These two values can be ORed together, to indicate that both errors occurred. */
97 LONGINT_OVERFLOW = 1,
98 LONGINT_INVALID_SUFFIX_CHAR = 2,
100 LONGINT_INVALID_SUFFIX_CHAR_WITH_OVERFLOW = (LONGINT_INVALID_SUFFIX_CHAR | LONGINT_OVERFLOW),
101 LONGINT_INVALID = 4
102 } strtol_error_t;
104 /*** structures declarations (and typedefs of structures)*****************************************/
106 /* all functions in str_class must be defined for every encoding */
107 struct str_class
109 gchar *(*conv_gerror_message) (GError * error, const char *def_msg);
110 /*I*/ estr_t (*vfs_convert_to) (GIConv coder, const char *string, int size, GString * buffer);
111 /*I*/ void (*insert_replace_char) (GString * buffer);
112 int (*is_valid_string) (const char *);
113 /*I*/ int (*is_valid_char) (const char *, size_t);
114 /*I*/ void (*cnext_char) (const char **);
115 void (*cprev_char) (const char **);
116 void (*cnext_char_safe) (const char **);
117 /*I*/ void (*cprev_char_safe) (const char **);
118 /*I*/ int (*cnext_noncomb_char) (const char **text);
119 /*I*/ int (*cprev_noncomb_char) (const char **text, const char *begin);
120 /*I*/ int (*char_isspace) (const char *);
121 /*I*/ int (*char_ispunct) (const char *);
122 /*I*/ int (*char_isalnum) (const char *);
123 /*I*/ int (*char_isdigit) (const char *);
124 /*I*/ int (*char_isprint) (const char *);
125 /*I*/ gboolean (*char_iscombiningmark) (const char *);
126 /*I*/ int (*length) (const char *);
127 /*I*/ int (*length2) (const char *, int);
128 /*I*/ int (*length_noncomb) (const char *);
129 /*I*/ int (*char_toupper) (const char *, char **, size_t *);
130 int (*char_tolower) (const char *, char **, size_t *);
131 void (*fix_string) (char *);
132 /*I*/ const char *(*term_form) (const char *);
133 /*I*/ const char *(*fit_to_term) (const char *, int, align_crt_t);
134 /*I*/ const char *(*term_trim) (const char *text, int width);
135 /*I*/ const char *(*term_substring) (const char *, int, int);
136 /*I*/ int (*term_width1) (const char *);
137 /*I*/ int (*term_width2) (const char *, size_t);
138 /*I*/ int (*term_char_width) (const char *);
139 /*I*/ const char *(*trunc) (const char *, int);
140 /*I*/ int (*offset_to_pos) (const char *, size_t);
141 /*I*/ int (*column_to_pos) (const char *, size_t);
142 /*I*/ char *(*create_search_needle) (const char *, int);
143 void (*release_search_needle) (char *, int);
144 const char *(*search_first) (const char *, const char *, int);
145 const char *(*search_last) (const char *, const char *, int);
146 int (*compare) (const char *, const char *);
147 /*I*/ int (*ncompare) (const char *, const char *);
148 /*I*/ int (*casecmp) (const char *, const char *);
149 /*I*/ int (*ncasecmp) (const char *, const char *);
150 /*I*/ int (*prefix) (const char *, const char *);
151 /*I*/ int (*caseprefix) (const char *, const char *);
152 /*I*/ char *(*create_key) (const char *text, int case_sen);
153 /*I*/ char *(*create_key_for_filename) (const char *text, int case_sen);
154 /*I*/ int (*key_collate) (const char *t1, const char *t2, int case_sen);
155 /*I*/ void (*release_key) (char *key, int case_sen);
156 /*I*/};
158 /*** global variables defined in .c file *********************************************************/
160 /* standard convertors */
161 extern GIConv str_cnv_to_term;
162 extern GIConv str_cnv_from_term;
163 /* from terminal encoding to terminal encoding */
164 extern GIConv str_cnv_not_convert;
166 /*** declarations of public functions ************************************************************/
168 struct str_class str_utf8_init (void);
169 struct str_class str_8bit_init (void);
170 struct str_class str_ascii_init (void);
172 /* create convertor from "from_enc" to terminal encoding
173 * if "from_enc" is not supported return INVALID_CONV
175 GIConv str_crt_conv_from (const char *);
177 /* create convertor from terminal encoding to "to_enc"
178 * if "to_enc" is not supported return INVALID_CONV
180 GIConv str_crt_conv_to (const char *);
182 /* close convertor, do not close str_cnv_to_term, str_cnv_from_term,
183 * str_cnv_not_convert
185 void str_close_conv (GIConv);
187 /* return on of not used buffers (.used == 0) or create new
188 * returned buffer has set .used to 1
191 /* convert string using coder, result of conversion is appended at end of buffer
192 * return ESTR_SUCCESS if there was no problem.
193 * otherwise return ESTR_PROBLEM or ESTR_FAILURE
195 estr_t str_convert (GIConv, const char *, GString *);
196 estr_t str_nconvert (GIConv, const char *, int, GString *);
198 /* convert GError message (which in UTF-8) to terminal charset
199 * def_char is used if result of error->str conversion if ESTR_FAILURE
200 * return new allocated null-terminated string, which is need to be freed
203 gchar *str_conv_gerror_message (GError * error, const char *def_msg);
205 /* return only ESTR_SUCCESS or ESTR_FAILURE, because vfs must be able to convert
206 * result to original string. (so no replace with questionmark)
207 * if coder is str_cnv_from_term or str_cnv_not_convert, string is only copied,
208 * so is possible to show file, that is not valid in terminal encoding
210 estr_t str_vfs_convert_from (GIConv, const char *, GString *);
212 /* if coder is str_cnv_to_term or str_cnv_not_convert, string is only copied,
213 * does replace with questionmark
216 estr_t str_vfs_convert_to (GIConv, const char *, int, GString *);
218 /* printf function for str_buffer, append result of printf at the end of buffer
220 void str_printf (GString *, const char *, ...);
222 /* add standard replacement character in terminal encoding
224 void str_insert_replace_char (GString *);
226 /* init strings and set terminal encoding,
227 * if is termenc NULL, detect terminal encoding
228 * create all str_cnv_* and set functions for terminal encoding
230 void str_init_strings (const char *termenc);
232 /* free all str_buffer and all str_cnv_*
234 void str_uninit_strings (void);
236 /* try convert characters in ch to output using conv
237 * ch_size is size of ch, can by (size_t)(-1) (-1 only for ASCII
238 * compatible encoding, for other must be set)
239 * return ESTR_SUCCESS if conversion was successfully,
240 * ESTR_PROBLEM if ch contains only part of characters,
241 * ESTR_FAILURE if conversion is not possible
243 estr_t str_translate_char (GIConv conv, const char *ch, size_t ch_size,
244 char *output, size_t out_size);
246 /* test, if text is valid in terminal encoding
249 int str_is_valid_string (const char *text);
251 /* test, if first char of ch is valid
252 * size, how many bytes characters occupied, could be (size_t)(-1)
253 * return 1 if it is valid, -1 if it is invalid or -2 if it is only part of
254 * multibyte character
257 int str_is_valid_char (const char *ch, size_t size);
259 /* return next characters after text, do not call on the end of string
261 char *str_get_next_char (char *text);
262 const char *str_cget_next_char (const char *text);
264 /* return previous characters before text, do not call on the start of strings
266 char *str_get_prev_char (char *text);
267 const char *str_cget_prev_char (const char *text);
269 /* set text to next characters, do not call on the end of string
271 void str_next_char (char **text);
272 void str_cnext_char (const char **text);
274 /* set text to previous characters, do not call on the start of strings
276 void str_prev_char (char **text);
277 void str_cprev_char (const char **text);
279 /* return next characters after text, do not call on the end of string
280 * works with invalid string
283 char *str_get_next_char_safe (char *text);
284 const char *str_cget_next_char_safe (const char *text);
286 /* return previous characters before text, do not call on the start of strings
287 * works with invalid string
290 char *str_get_prev_char_safe (char *text);
291 const char *str_cget_prev_char_safe (const char *text);
293 /* set text to next characters, do not call on the end of string
294 * works with invalid string
297 void str_next_char_safe (char **text);
298 void str_cnext_char_safe (const char **text);
300 /* set text to previous characters, do not call on the start of strings
301 * works with invalid string
304 void str_prev_char_safe (char **text);
305 void str_cprev_char_safe (const char **text);
307 /* set text to next noncombining characters, check the end of text
308 * return how many characters was skipped
309 * works with invalid string
312 int str_next_noncomb_char (char **text);
313 int str_cnext_noncomb_char (const char **text);
315 /* set text to previous noncombining characters, search stop at begin
316 * return how many characters was skipped
317 * works with invalid string
320 int str_prev_noncomb_char (char **text, const char *begin);
321 int str_cprev_noncomb_char (const char **text, const char *begin);
323 /* if first characters in ch is space, tabulator or new lines
326 int str_isspace (const char *ch);
328 /* if first characters in ch is punctuation or symbol
331 int str_ispunct (const char *ch);
333 /* if first characters in ch is alphanum
336 int str_isalnum (const char *ch);
338 /* if first characters in ch is digit
341 int str_isdigit (const char *ch);
343 /* if first characters in ch is printable
346 int str_isprint (const char *ch);
348 /* if first characters in ch is a combining mark (only in utf-8)
349 * combining makrs are assumed to be zero width
352 gboolean str_iscombiningmark (const char *ch);
354 /* write lower from of fisrt characters in ch into out
355 * decrase remain by size of returned characters
356 * if out is not big enough, do nothing
358 int str_toupper (const char *ch, char **out, size_t * remain);
360 /* write upper from of fisrt characters in ch into out
361 * decrase remain by size of returned characters
362 * if out is not big enough, do nothing
364 int str_tolower (const char *ch, char **out, size_t * remain);
366 /* return length of text in characters
369 int str_length (const char *text);
371 /* return length of text in characters, limit to size
374 int str_length2 (const char *text, int size);
376 /* return length of one char
379 int str_length_char (const char *);
381 /* return length of text in characters, count only noncombining characters
384 int str_length_noncomb (const char *text);
386 /* replace all invalid characters in text with questionmark
387 * after return, text is valid string in terminal encoding
390 void str_fix_string (char *text);
392 /* replace all invalid characters in text with questionmark
393 * replace all unprintable characters with '.'
394 * return static allocated string, "text" is not changed
395 * returned string do not need to be freed
398 const char *str_term_form (const char *text);
400 /* like str_term_form, but text can be alignment to width
401 * alignment is specified in just_mode (J_LEFT, J_LEFT_FIT, ...)
402 * result is completed with spaces to width
405 const char *str_fit_to_term (const char *text, int width, align_crt_t just_mode);
407 /* like str_term_form, but when text is wider than width, three dots are
408 * inserted at begin and result is completed with suffix of text
409 * no additional spaces are inserted
412 const char *str_term_trim (const char *text, int width);
415 /* like str_term_form, but return only specified substring
416 * start - column (position) on terminal, where substring begin
417 * result is completed with spaces to width
420 const char *str_term_substring (const char *text, int start, int width);
422 /* return width, that will be text occupied on terminal
425 int str_term_width1 (const char *text);
427 /* return width, that will be text occupied on terminal
428 * text is limited by length in characters
431 int str_term_width2 (const char *text, size_t length);
433 /* return width, that will be character occupied on terminal
434 * combining characters are always zero width
437 int str_term_char_width (const char *text);
439 /* convert position in characters to position in bytes
442 int str_offset_to_pos (const char *text, size_t length);
444 /* convert position on terminal to position in characters
447 int str_column_to_pos (const char *text, size_t pos);
449 /* like str_fit_to_term width just_mode = J_LEFT_FIT,
450 * but do not insert additional spaces
453 const char *str_trunc (const char *text, int width);
455 /* create needle, that will be searched in str_search_fist/last,
456 * so needle can be reused
457 * in UTF-8 return normalized form of needle
459 char *str_create_search_needle (const char *needle, int case_sen);
461 /* free needle returned by str_create_search_needle
463 void str_release_search_needle (char *needle, int case_sen);
465 /* search for first occurrence of search in text
467 const char *str_search_first (const char *text, const char *needle, int case_sen);
469 /* search for last occurrence of search in text
471 const char *str_search_last (const char *text, const char *needle, int case_sen);
473 /* case sensitive compare two strings
476 int str_compare (const char *t1, const char *t2);
478 /* case sensitive compare two strings
479 * if one string is prefix of the other string, return 0
482 int str_ncompare (const char *t1, const char *t2);
484 /* case insensitive compare two strings
487 int str_casecmp (const char *t1, const char *t2);
489 /* case insensitive compare two strings
490 * if one string is prefix of the other string, return 0
493 int str_ncasecmp (const char *t1, const char *t2);
495 /* return, how many bytes are are same from start in text and prefix
496 * both strings are decomposed befor comapring and return value is counted
497 * in decomposed form, too. caling with prefix, prefix, you get size in bytes
498 * of prefix in decomposed form,
501 int str_prefix (const char *text, const char *prefix);
503 /* case insensitive version of str_prefix
506 int str_caseprefix (const char *text, const char *prefix);
508 /* create a key that is used by str_key_collate
511 char *str_create_key (const char *text, int case_sen);
513 /* create a key that is used by str_key_collate
514 * should aware dot '.' in text
517 char *str_create_key_for_filename (const char *text, int case_sen);
519 /* compare two string using LC_COLLATE, if is possible
520 * if case_sen is set, comparing is case sensitive,
521 * case_sen must be same for str_create_key, str_key_collate and str_release_key
524 int str_key_collate (const char *t1, const char *t2, int case_sen);
526 /* release_key created by str_create_key, only rigth way to release key
529 void str_release_key (char *key, int case_sen);
531 /* return TRUE if codeset_name is utf8 or utf-8
534 gboolean str_isutf8 (const char *codeset_name);
536 const char *str_detect_termencoding (void);
538 int str_verscmp (const char *s1, const char *s2);
540 /* return how many lines and columns will text occupy on terminal
542 void str_msg_term_size (const char *text, int *lines, int *columns);
545 * skip first needle's in haystack
547 * @param haystack pointer to string
548 * @param needle pointer to string
549 * @param skip_count skip first bytes
551 * @return pointer to skip_count+1 needle (or NULL if not found).
554 char *strrstr_skip_count (const char *haystack, const char *needle, size_t skip_count);
556 char *str_replace_all (const char *haystack, const char *needle, const char *replacement);
558 strtol_error_t xstrtoumax (const char *s, char **ptr, int base, uintmax_t * val,
559 const char *valid_suffixes);
560 uintmax_t parse_integer (const char *str, gboolean * invalid);
562 /* --------------------------------------------------------------------------------------------- */
563 /*** inline functions ****************************************************************************/
564 /* --------------------------------------------------------------------------------------------- */
566 static inline void
567 str_replace (char *s, char from, char to)
569 for (; *s != '\0'; s++)
571 if (*s == from)
572 *s = to;
576 /* --------------------------------------------------------------------------------------------- */
578 * strcpy is unsafe on overlapping memory areas, so define memmove-alike
579 * string function.
580 * Have sense only when:
581 * * dest <= src
582 * AND
583 * * dest and str are pointers to one object (as Roland Illig pointed).
585 * We can't use str*cpy funs here:
586 * http://kerneltrap.org/mailarchive/openbsd-misc/2008/5/27/1951294
588 * @param dest pointer to string
589 * @param src pointer to string
591 * @return newly allocated string
595 static inline char *
596 str_move (char *dest, const char *src)
598 size_t n;
600 #ifdef HAVE_ASSERT_H
601 assert (dest <= src);
602 #endif
604 n = strlen (src) + 1; /* + '\0' */
606 return (char *) memmove (dest, src, n);
609 /* --------------------------------------------------------------------------------------------- */
611 #endif /* MC_STRUTIL_H */