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