1 #include "smartcolsP.h"
2
3 /**
4 * scola_table_print_range:
5 * @tb: table
6 * @start: first printed line or NULL to print from the begin of the table
7 * @end: last printed line or NULL to print all from start.
8 *
9 * If the start is the first line in the table than prints table header too.
10 * The header is printed only once. This does not work for trees.
11 *
12 * Returns: 0, a negative value in case of an error.
13 */
14 int scols_table_print_range( struct libscols_table *tb,
15 struct libscols_line *start,
16 struct libscols_line *end)
17 {
18 struct ul_buffer buf = UL_INIT_BUFFER;
19 struct libscols_iter itr;
20 int rc;
21
22 if (scols_table_is_tree(tb))
23 return -EINVAL;
24
25 DBG(TAB, ul_debugobj(tb, "printing range from API"));
26
27 rc = __scols_initialize_printing(tb, &buf);
28 if (rc)
29 return rc;
30
31 if (start) {
32 itr.direction = SCOLS_ITER_FORWARD;
33 itr.head = &tb->tb_lines;
34 itr.p = &start->ln_lines;
35 } else
36 scols_reset_iter(&itr, SCOLS_ITER_FORWARD);
37
38 if (!start || itr.p == tb->tb_lines.next) {
39 rc = __scols_print_header(tb, &buf);
40 if (rc)
41 goto done;
42 }
43
44 rc = __scols_print_range(tb, &buf, &itr, end);
45 done:
46 __scols_cleanup_printing(tb, &buf);
47 return rc;
48 }
49
50 /**
51 * scols_table_print_range_to_string:
52 * @tb: table
53 * @start: first printed line or NULL to print from the beginning of the table
54 * @end: last printed line or NULL to print all from start.
55 * @data: pointer to the beginning of a memory area to print to
56 *
57 * The same as scols_table_print_range(), but prints to @data instead of
58 * stream.
59 *
60 * Returns: 0, a negative value in case of an error.
61 */
62 #ifdef HAVE_OPEN_MEMSTREAM
63 int scols_table_print_range_to_string( struct libscols_table *tb,
64 struct libscols_line *start,
65 struct libscols_line *end,
66 char **data)
67 {
68 FILE *stream, *old_stream;
69 size_t sz;
70 int rc;
71
72 if (!tb)
73 return -EINVAL;
74
75 DBG(TAB, ul_debugobj(tb, "printing range to string"));
76
77 /* create a stream for output */
78 stream = open_memstream(data, &sz);
79 if (!stream)
80 return -ENOMEM;
81
82 old_stream = scols_table_get_stream(tb);
83 scols_table_set_stream(tb, stream);
84 rc = scols_table_print_range(tb, start, end);
85 fclose(stream);
86 scols_table_set_stream(tb, old_stream);
87
88 return rc;
89 }
90 #else
91 int scols_table_print_range_to_string(
92 struct libscols_table *tb __attribute__((__unused__)),
93 struct libscols_line *start __attribute__((__unused__)),
94 struct libscols_line *end __attribute__((__unused__)),
95 char **data __attribute__((__unused__)))
96 {
97 return -ENOSYS;
98 }
99 #endif
100
101 static int do_print_table(struct libscols_table *tb, int *is_empty)
102 {
103 int rc = 0;
104 struct ul_buffer buf = UL_INIT_BUFFER;
105
106 if (!tb)
107 return -EINVAL;
108
109 DBG(TAB, ul_debugobj(tb, "printing"));
110 if (is_empty)
111 *is_empty = 0;
112
113 if (list_empty(&tb->tb_columns)) {
114 DBG(TAB, ul_debugobj(tb, "error -- no columns"));
115 return -EINVAL;
116 }
117 if (list_empty(&tb->tb_lines)) {
118 DBG(TAB, ul_debugobj(tb, "ignore -- no lines"));
119 if (scols_table_is_json(tb)) {
120 ul_jsonwrt_init(&tb->json, tb->out, 0);
121 ul_jsonwrt_root_open(&tb->json);
122 ul_jsonwrt_array_open(&tb->json, tb->name ? tb->name : "");
123 ul_jsonwrt_array_close(&tb->json);
124 ul_jsonwrt_root_close(&tb->json);
125 } else if (is_empty)
126 *is_empty = 1;
127 return 0;
128 }
129
130 tb->header_printed = 0;
131 rc = __scols_initialize_printing(tb, &buf);
132 if (rc)
133 return rc;
134
135 if (scols_table_is_json(tb)) {
136 ul_jsonwrt_root_open(&tb->json);
137 ul_jsonwrt_array_open(&tb->json, tb->name ? tb->name : "");
138 }
139
140 if (tb->format == SCOLS_FMT_HUMAN)
141 __scols_print_title(tb);
142
143 rc = __scols_print_header(tb, &buf);
144 if (rc)
145 goto done;
146
147 if (scols_table_is_tree(tb))
148 rc = __scols_print_tree(tb, &buf);
149 else
150 rc = __scols_print_table(tb, &buf);
151
152 if (scols_table_is_json(tb)) {
153 ul_jsonwrt_array_close(&tb->json);
154 ul_jsonwrt_root_close(&tb->json);
155 }
156 done:
157 __scols_cleanup_printing(tb, &buf);
158 return rc;
159 }
160
161 /**
162 * scols_print_table:
163 * @tb: table
164 *
165 * Prints the table to the output stream and terminate by \n.
166 *
167 * Returns: 0, a negative value in case of an error.
168 */
169 int scols_print_table(struct libscols_table *tb)
170 {
171 int empty = 0;
172 int rc = do_print_table(tb, &empty);
173
174 if (rc == 0 && !empty && !scols_table_is_json(tb))
175 fputc('\n', tb->out);
176 return rc;
177 }
178
179 /**
180 * scols_print_table_to_string:
181 * @tb: table
182 * @data: pointer to the beginning of a memory area to print to
183 *
184 * Prints the table to @data.
185 *
186 * Returns: 0, a negative value in case of an error.
187 */
188 #ifdef HAVE_OPEN_MEMSTREAM
189 int scols_print_table_to_string(struct libscols_table *tb, char **data)
190 {
191 FILE *stream, *old_stream;
192 size_t sz;
193 int rc;
194
195 if (!tb)
196 return -EINVAL;
197
198 DBG(TAB, ul_debugobj(tb, "printing to string"));
199
200 /* create a stream for output */
201 stream = open_memstream(data, &sz);
202 if (!stream)
203 return -ENOMEM;
204
205 old_stream = scols_table_get_stream(tb);
206 scols_table_set_stream(tb, stream);
207 rc = do_print_table(tb, NULL);
208 fclose(stream);
209 scols_table_set_stream(tb, old_stream);
210
211 return rc;
212 }
213 #else
214 int scols_print_table_to_string(
215 struct libscols_table *tb __attribute__((__unused__)),
216 char **data __attribute__((__unused__)))
217 {
218 return -ENOSYS;
219 }
220 #endif