]> git.ipfire.org Git - thirdparty/util-linux.git/blame - libsmartcols/src/column.c
libsmartcols: don't calculate with encoding on scols_table_enable_noencoding()
[thirdparty/util-linux.git] / libsmartcols / src / column.c
CommitLineData
1577b259
KZ
1/*
2 * column.c - functions for table handling at the column level
3 *
4 * Copyright (C) 2014 Ondrej Oprala <ooprala@redhat.com>
5 * Copyright (C) 2014 Karel Zak <kzak@redhat.com>
6 *
7 * This file may be redistributed under the terms of the
8 * GNU Lesser General Public License.
9 */
10
1d90bcb1
OO
11/**
12 * SECTION: column
13 * @title: Column
2473b711 14 * @short_description: defines output columns formats, headers, etc.
1d90bcb1
OO
15 *
16 * An API to access and modify per-column data and information.
17 */
18
ce44112b 19
1577b259
KZ
20#include <stdlib.h>
21#include <unistd.h>
22#include <string.h>
35958d0c 23#include <ctype.h>
1577b259 24
949ea05f
KZ
25#include "mbsalign.h"
26
1577b259
KZ
27#include "smartcolsP.h"
28
1d90bcb1
OO
29/**
30 * scols_new_column:
31 *
32 * Allocates space for a new column.
33 *
bfc6941a 34 * Returns: a pointer to a new struct libscols_column instance, NULL in case of an ENOMEM error.
1d90bcb1 35 */
1577b259
KZ
36struct libscols_column *scols_new_column(void)
37{
38 struct libscols_column *cl;
39
40 cl = calloc(1, sizeof(*cl));
41 if (!cl)
42 return NULL;
710ed55d 43 DBG(COL, ul_debugobj(cl, "alloc"));
1577b259
KZ
44 cl->refcount = 1;
45 INIT_LIST_HEAD(&cl->cl_columns);
46 return cl;
47}
48
1d90bcb1
OO
49/**
50 * scols_ref_column:
51 * @cl: a pointer to a struct libscols_column instance
52 *
53 * Increases the refcount of @cl.
54 */
1577b259
KZ
55void scols_ref_column(struct libscols_column *cl)
56{
57 if (cl)
58 cl->refcount++;
59}
60
1d90bcb1
OO
61/**
62 * scols_unref_column:
63 * @cl: a pointer to a struct libscols_column instance
64 *
3175f035
KZ
65 * Decreases the refcount of @cl. When the count falls to zero, the instance
66 * is automatically deallocated.
1d90bcb1 67 */
1577b259
KZ
68void scols_unref_column(struct libscols_column *cl)
69{
70 if (cl && --cl->refcount <= 0) {
710ed55d 71 DBG(COL, ul_debugobj(cl, "dealloc"));
1577b259
KZ
72 list_del(&cl->cl_columns);
73 scols_reset_cell(&cl->header);
74 free(cl->color);
68a7f92b 75 free(cl->safechars);
d94c5198 76 free(cl->pending_data_buf);
1577b259
KZ
77 free(cl);
78 }
79}
80
1d90bcb1
OO
81/**
82 * scols_copy_column:
83 * @cl: a pointer to a struct libscols_column instance
84 *
710ed55d 85 * Creates a new column and copies @cl's data over to it.
1d90bcb1
OO
86 *
87 * Returns: a pointer to a new struct libscols_column instance.
88 */
1577b259
KZ
89struct libscols_column *scols_copy_column(const struct libscols_column *cl)
90{
91 struct libscols_column *ret;
92
1577b259
KZ
93 if (!cl)
94 return NULL;
95 ret = scols_new_column();
96 if (!ret)
97 return NULL;
1577b259 98
63c9c05d 99 DBG(COL, ul_debugobj(cl, "copy"));
710ed55d 100
74bd28ad 101 if (scols_column_set_color(ret, cl->color))
1577b259 102 goto err;
74bd28ad 103 if (scols_cell_copy_content(&ret->header, &cl->header))
1577b259
KZ
104 goto err;
105
106 ret->width = cl->width;
107 ret->width_min = cl->width_min;
108 ret->width_max = cl->width_max;
109 ret->width_avg = cl->width_avg;
110 ret->width_hint = cl->width_hint;
8b992cb5 111 ret->flags = cl->flags;
1577b259 112 ret->is_extreme = cl->is_extreme;
d52f5542 113 ret->is_groups = cl->is_groups;
1577b259
KZ
114
115 return ret;
116err:
117 scols_unref_column(ret);
118 return NULL;
119}
120
1d90bcb1
OO
121/**
122 * scols_column_set_whint:
123 * @cl: a pointer to a struct libscols_column instance
124 * @whint: a width hint
125 *
cbe3e495 126 * Sets the width hint of column @cl to @whint. See scols_table_new_column().
1d90bcb1
OO
127 *
128 * Returns: 0, a negative value in case of an error.
129 */
1577b259
KZ
130int scols_column_set_whint(struct libscols_column *cl, double whint)
131{
1577b259
KZ
132 if (!cl)
133 return -EINVAL;
134
135 cl->width_hint = whint;
136 return 0;
137}
138
1d90bcb1
OO
139/**
140 * scols_column_get_whint:
141 * @cl: a pointer to a struct libscols_column instance
142 *
143 * Returns: The width hint of column @cl, a negative value in case of an error.
144 */
f7a9ea28 145double scols_column_get_whint(const struct libscols_column *cl)
1577b259 146{
d4275a4b 147 return cl->width_hint;
1577b259
KZ
148}
149
1d90bcb1
OO
150/**
151 * scols_column_set_flags:
152 * @cl: a pointer to a struct libscols_column instance
153 * @flags: a flag mask
154 *
155 * Sets the flags of @cl to @flags.
156 *
157 * Returns: 0, a negative value in case of an error.
158 */
8b992cb5
OO
159int scols_column_set_flags(struct libscols_column *cl, int flags)
160{
8b992cb5
OO
161 if (!cl)
162 return -EINVAL;
163
d10fa7e6
IG
164 if (cl->table) {
165 if (!(cl->flags & SCOLS_FL_TREE) && (flags & SCOLS_FL_TREE))
166 cl->table->ntreecols++;
167 else if ((cl->flags & SCOLS_FL_TREE) && !(flags & SCOLS_FL_TREE))
168 cl->table->ntreecols--;
169 }
170
369be41b 171 DBG(COL, ul_debugobj(cl, "setting flags from 0%x to 0%x", cl->flags, flags));
8b992cb5
OO
172 cl->flags = flags;
173 return 0;
174}
175
b2c871f9
KZ
176/**
177 * scols_column_set_json_type:
178 * @cl: a pointer to a struct libscols_column instance
179 * @type: SCOLS_JSON_* type
180 *
181 * Sets the type used for JSON formatting, the default is SCOLS_JSON_STRING.
182 *
183 * Returns: 0, a negative value in case of an error.
184 *
185 * Since: 2.33
186 */
187int scols_column_set_json_type(struct libscols_column *cl, int type)
188{
189 if (!cl)
190 return -EINVAL;
191
192 cl->json_type = type;
193 return 0;
194
195}
196
197/**
198 * scols_column_get_json_type:
199 * @cl: a pointer to a struct libscols_column instance
200 *
201 * Note that SCOLS_JSON_BOOLEAN interprets NULL, empty strings, '0', 'N' and
202 * 'n' as "false"; and everything else as "true".
203 *
204 * Returns: JSON type used for formatting or a negative value in case of an error.
205 *
206 * Since: 2.33
207 */
208int scols_column_get_json_type(const struct libscols_column *cl)
209{
210 return cl ? cl->json_type : -EINVAL;
211}
212
213
949ea05f
KZ
214/**
215 * scols_column_get_table:
216 * @cl: a pointer to a struct libscols_column instance
217 *
218 * Returns: pointer to the table where columns is used
219 */
68a7f92b 220struct libscols_table *scols_column_get_table(const struct libscols_column *cl)
949ea05f
KZ
221{
222 return cl->table;
223}
224
1d90bcb1
OO
225/**
226 * scols_column_get_flags:
227 * @cl: a pointer to a struct libscols_column instance
228 *
229 * Returns: The flag mask of @cl, a negative value in case of an error.
230 */
f7a9ea28 231int scols_column_get_flags(const struct libscols_column *cl)
8b992cb5 232{
d4275a4b 233 return cl->flags;
8b992cb5
OO
234}
235
1d90bcb1 236/**
e2310281 237 * scols_column_get_header:
1d90bcb1
OO
238 * @cl: a pointer to a struct libscols_column instance
239 *
240 * Returns: A pointer to a struct libscols_cell instance, representing the
241 * header info of column @cl or NULL in case of an error.
242 */
74bd28ad 243struct libscols_cell *scols_column_get_header(struct libscols_column *cl)
1577b259 244{
d4275a4b 245 return &cl->header;
1577b259
KZ
246}
247
1d90bcb1
OO
248/**
249 * scols_column_set_color:
250 * @cl: a pointer to a struct libscols_column instance
618a1d6d 251 * @color: color name or ESC sequence
1d90bcb1 252 *
1577b259
KZ
253 * The default color for data cells and column header.
254 *
255 * If you want to set header specific color then use scols_column_get_header()
256 * and scols_cell_set_color().
257 *
258 * If you want to set data cell specific color the use scols_line_get_cell() +
259 * scols_cell_set_color().
1d90bcb1
OO
260 *
261 * Returns: 0, a negative value in case of an error.
1577b259 262 */
618a1d6d 263int scols_column_set_color(struct libscols_column *cl, const char *color)
1577b259 264{
618a1d6d
IG
265 if (color && isalpha(*color)) {
266 color = color_sequence_from_colorname(color);
267 if (!color)
8fcdce8f 268 return -EINVAL;
1577b259 269 }
618a1d6d 270 return strdup_to_struct_member(cl, color, color);
1577b259
KZ
271}
272
1d90bcb1
OO
273/**
274 * scols_column_get_color:
275 * @cl: a pointer to a struct libscols_column instance
276 *
277 * Returns: The current color setting of the column @cl.
278 */
f7a9ea28 279const char *scols_column_get_color(const struct libscols_column *cl)
1577b259 280{
d4275a4b 281 return cl->color;
1577b259
KZ
282}
283
949ea05f
KZ
284/**
285 * scols_wrapnl_nextchunk:
286 * @cl: a pointer to a struct libscols_column instance
287 * @data: string
81b176c4 288 * @userdata: callback private data
949ea05f 289 *
68a7f92b 290 * This is built-in function for scols_column_set_wrapfunc(). This function
949ea05f
KZ
291 * terminates the current chunk by \0 and returns pointer to the begin of
292 * the next chunk. The chunks are based on \n.
293 *
294 * For example for data "AAA\nBBB\nCCC" the next chunk is "BBB".
295 *
296 * Returns: next chunk
3f47320a
KZ
297 *
298 * Since: 2.29
949ea05f
KZ
299 */
300char *scols_wrapnl_nextchunk(const struct libscols_column *cl __attribute__((unused)),
301 char *data,
302 void *userdata __attribute__((unused)))
303{
304 char *p = data ? strchr(data, '\n') : NULL;
305
306 if (p) {
307 *p = '\0';
308 return p + 1;
309 }
310 return NULL;
311}
312
313/**
314 * scols_wrapnl_chunksize:
315 * @cl: a pointer to a struct libscols_column instance
316 * @data: string
81b176c4 317 * @userdata: callback private data
949ea05f
KZ
318 *
319 * Analyzes @data and returns size of the largest chunk. The chunks are based
320 * on \n. For example for data "AAA\nBBB\nCCCC" the largest chunk size is 4.
321 *
322 * Note that the size has to be based on number of terminal cells rather than
323 * bytes to support multu-byte output.
324 *
325 * Returns: size of the largest chunk.
3f47320a
KZ
326 *
327 * Since: 2.29
949ea05f
KZ
328 */
329size_t scols_wrapnl_chunksize(const struct libscols_column *cl __attribute__((unused)),
330 const char *data,
331 void *userdata __attribute__((unused)))
332{
333 size_t sum = 0;
334
335 while (data && *data) {
1b504263 336 const char *p;
949ea05f
KZ
337 size_t sz;
338
339 p = strchr(data, '\n');
340 if (p) {
2292d0ba
KZ
341 sz = cl->table && scols_table_is_noencoding(cl->table) ?
342 mbs_nwidth(data, p - data) :
343 mbs_safe_nwidth(data, p - data, NULL);
949ea05f 344 p++;
2292d0ba
KZ
345 } else {
346 sz = cl->table && scols_table_is_noencoding(cl->table) ?
347 mbs_width(data) :
348 mbs_safe_width(data);
349 }
949ea05f 350 sum = max(sum, sz);
f4d37838 351 data = p;
949ea05f
KZ
352 }
353
354 return sum;
355}
57a86f9b
KZ
356
357/**
358 * scols_column_set_cmpfunc:
359 * @cl: column
360 * @cmp: pointer to compare function
361 * @data: private data for cmp function
362 *
363 * Returns: 0, a negative value in case of an error.
364 */
365int scols_column_set_cmpfunc(struct libscols_column *cl,
366 int (*cmp)(struct libscols_cell *,
367 struct libscols_cell *,
368 void *),
369 void *data)
370{
57a86f9b
KZ
371 if (!cl)
372 return -EINVAL;
373
374 cl->cmpfunc = cmp;
375 cl->cmpfunc_data = data;
376 return 0;
377}
378
949ea05f
KZ
379/**
380 * scols_column_set_wrapfunc:
381 * @cl: a pointer to a struct libscols_column instance
382 * @wrap_chunksize: function to return size of the largest chink of data
383 * @wrap_nextchunk: function to return next zero terminated data
81b176c4 384 * @userdata: optional stuff for callbacks
949ea05f
KZ
385 *
386 * Extends SCOLS_FL_WRAP and allows to set custom wrap function. The default
387 * is to wrap by column size, but you can create functions to wrap for example
388 * after \n or after words, etc.
389 *
390 * Returns: 0, a negative value in case of an error.
3f47320a
KZ
391 *
392 * Since: 2.29
949ea05f
KZ
393 */
394int scols_column_set_wrapfunc(struct libscols_column *cl,
395 size_t (*wrap_chunksize)(const struct libscols_column *,
396 const char *,
397 void *),
398 char * (*wrap_nextchunk)(const struct libscols_column *,
399 char *,
400 void *),
81b176c4 401 void *userdata)
949ea05f
KZ
402{
403 if (!cl)
404 return -EINVAL;
405
406 cl->wrap_nextchunk = wrap_nextchunk;
407 cl->wrap_chunksize = wrap_chunksize;
81b176c4 408 cl->wrapfunc_data = userdata;
949ea05f
KZ
409 return 0;
410}
411
412/**
413 * scols_column_set_safechars:
414 * @cl: a pointer to a struct libscols_column instance
415 * @safe: safe characters (e.g. "\n\t")
416 *
417 * Use for bytes you don't want to encode on output. This is for example
418 * necessary if you want to use custom wrap function based on \n, in this case
419 * you have to set "\n" as a safe char.
420 *
421 * Returns: 0, a negative value in case of an error.
3f47320a
KZ
422 *
423 * Since: 2.29
949ea05f
KZ
424 */
425int scols_column_set_safechars(struct libscols_column *cl, const char *safe)
426{
68a7f92b 427 return strdup_to_struct_member(cl, safechars, safe);
949ea05f
KZ
428}
429
430/**
431 * scols_column_get_safechars:
432 * @cl: a pointer to a struct libscols_column instance
433 *
434 * Returns: safe chars
3f47320a
KZ
435 *
436 * Since: 2.29
949ea05f
KZ
437 */
438const char *scols_column_get_safechars(const struct libscols_column *cl)
439{
440 return cl->safechars;
441}
442
82053f5e
KZ
443/**
444 * scols_column_get_width:
445 * @cl: a pointer to a struct libscols_column instance
446 *
447 * Important note: the column width is unknown until library starts printing
448 * (width is calculated before printing). The function is usable for example in
449 * nextchunk() callback specified by scols_column_set_wrapfunc().
450 *
451 * See also scols_column_get_whint(), it returns wanted size (!= final size).
452 *
453 * Returns: column width
454 *
455 * Since: 2.29
456 */
457size_t scols_column_get_width(const struct libscols_column *cl)
458{
459 return cl->width;
460}
461
6d6b6d18
KZ
462/**
463 * scols_column_is_hidden:
464 * @cl: a pointer to a struct libscols_column instance
465 *
466 * Gets the value of @cl's flag hidden.
467 *
d4275a4b 468 * Returns: 0 or 1
982034c3
KZ
469 *
470 * Since: 2.27
6d6b6d18 471 */
f7a9ea28 472int scols_column_is_hidden(const struct libscols_column *cl)
6d6b6d18 473{
d4275a4b 474 return cl->flags & SCOLS_FL_HIDDEN ? 1 : 0;
6d6b6d18
KZ
475}
476
8a38a8d3
OO
477/**
478 * scols_column_is_trunc:
1d90bcb1 479 * @cl: a pointer to a struct libscols_column instance
8a38a8d3 480 *
1d90bcb1 481 * Gets the value of @cl's flag trunc.
8a38a8d3 482 *
d4275a4b 483 * Returns: 0 or 1
8a38a8d3 484 */
f7a9ea28 485int scols_column_is_trunc(const struct libscols_column *cl)
8a38a8d3 486{
d4275a4b 487 return cl->flags & SCOLS_FL_TRUNC ? 1 : 0;
8a38a8d3
OO
488}
489/**
490 * scols_column_is_tree:
1d90bcb1 491 * @cl: a pointer to a struct libscols_column instance
8a38a8d3 492 *
1d90bcb1 493 * Gets the value of @cl's flag tree.
8a38a8d3 494 *
d4275a4b 495 * Returns: 0 or 1
8a38a8d3 496 */
f7a9ea28 497int scols_column_is_tree(const struct libscols_column *cl)
8a38a8d3 498{
d4275a4b 499 return cl->flags & SCOLS_FL_TREE ? 1 : 0;
8a38a8d3
OO
500}
501/**
502 * scols_column_is_right:
1d90bcb1 503 * @cl: a pointer to a struct libscols_column instance
8a38a8d3 504 *
1d90bcb1 505 * Gets the value of @cl's flag right.
8a38a8d3 506 *
d4275a4b 507 * Returns: 0 or 1
8a38a8d3 508 */
f7a9ea28 509int scols_column_is_right(const struct libscols_column *cl)
8a38a8d3 510{
d4275a4b 511 return cl->flags & SCOLS_FL_RIGHT ? 1 : 0;
8a38a8d3
OO
512}
513/**
514 * scols_column_is_strict_width:
1d90bcb1 515 * @cl: a pointer to a struct libscols_column instance
8a38a8d3 516 *
1d90bcb1 517 * Gets the value of @cl's flag strict_width.
8a38a8d3 518 *
d4275a4b 519 * Returns: 0 or 1
8a38a8d3 520 */
f7a9ea28 521int scols_column_is_strict_width(const struct libscols_column *cl)
8a38a8d3 522{
d4275a4b 523 return cl->flags & SCOLS_FL_STRICTWIDTH ? 1 : 0;
8a38a8d3
OO
524}
525/**
0925a9dd 526 * scols_column_is_noextremes:
1d90bcb1 527 * @cl: a pointer to a struct libscols_column instance
8a38a8d3 528 *
1d90bcb1 529 * Gets the value of @cl's flag no_extremes.
8a38a8d3 530 *
d4275a4b 531 * Returns: 0 or 1
8a38a8d3 532 */
f7a9ea28 533int scols_column_is_noextremes(const struct libscols_column *cl)
8a38a8d3 534{
d4275a4b 535 return cl->flags & SCOLS_FL_NOEXTREMES ? 1 : 0;
8a38a8d3 536}
a6404093
IG
537/**
538 * scols_column_is_wrap:
539 * @cl: a pointer to a struct libscols_column instance
540 *
541 * Gets the value of @cl's flag wrap.
542 *
d4275a4b 543 * Returns: 0 or 1
2f09ae9d
KZ
544 *
545 * Since: 2.28
a6404093 546 */
f7a9ea28 547int scols_column_is_wrap(const struct libscols_column *cl)
a6404093 548{
d4275a4b 549 return cl->flags & SCOLS_FL_WRAP ? 1 : 0;
a6404093 550}
ff471d89 551/**
949ea05f 552 * scols_column_is_customwrap:
ff471d89
KZ
553 * @cl: a pointer to a struct libscols_column instance
554 *
d4275a4b 555 * Returns: 0 or 1
ff471d89
KZ
556 *
557 * Since: 2.29
558 */
949ea05f 559int scols_column_is_customwrap(const struct libscols_column *cl)
ff471d89 560{
949ea05f
KZ
561 return (cl->flags & SCOLS_FL_WRAP)
562 && cl->wrap_chunksize
563 && cl->wrap_nextchunk ? 1 : 0;
ff471d89 564}