Gentoo Archives: gentoo-commits

From: Sven Eden <sven.eden@×××.de>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/ufed:master commit in: /
Date: Fri, 01 Feb 2013 10:49:53
Message-Id: 1359554426.44916f41c4e7b65f5e8829f00ec101c7f52e4d72.yamakuzure@gentoo
1 commit: 44916f41c4e7b65f5e8829f00ec101c7f52e4d72
2 Author: Sven Eden <sven.eden <AT> gmx <DOT> de>
3 AuthorDate: Wed Jan 30 14:00:26 2013 +0000
4 Commit: Sven Eden <sven.eden <AT> gmx <DOT> de>
5 CommitDate: Wed Jan 30 14:00:26 2013 +0000
6 URL: http://git.overlays.gentoo.org/gitweb/?p=proj/ufed.git;a=commit;h=44916f41
7
8 Moved type declaration of enums and structs to a central ufed-types.h and specific functions to ufed-types.c. The new structs sFlag and sDesc are desinged to substitute struct item and struct flag. They can handle much more details. This move is necessary to not have the original data structure to grow into an unmaintainable mess, and is useful to remove all the cross-casting done throughout the code.
9
10 ---
11 ufed-types.c | 301 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12 ufed-types.h | 155 ++++++++++++++++++++++++++++++
13 2 files changed, 456 insertions(+), 0 deletions(-)
14
15 diff --git a/ufed-types.c b/ufed-types.c
16 new file mode 100644
17 index 0000000..694ea29
18 --- /dev/null
19 +++ b/ufed-types.c
20 @@ -0,0 +1,301 @@
21 +/*
22 + * ufed-types.c
23 + *
24 + * Created on: 28.01.2013
25 + * Author: Sven Eden
26 + */
27 +#include "ufed-types.h"
28 +#include "ufed-curses.h"
29 +#include <stdlib.h>
30 +#include <string.h>
31 +
32 +/* external members */
33 +extern eMask e_mask;
34 +extern eScope e_scope;
35 +extern eState e_state;
36 +
37 +/* function implementations */
38 +
39 +/** @brief create a new flag without description lines
40 + * As this is a crucial initialization task, the function will
41 + * terminate the program if an error occurs.
42 + * @param[in,out] root the new item will be *root if *root is null and its previous flag otherwise.
43 + * @param[in] name the name to set, must not be NULL.
44 + * @param[in] line the fixed line in the list this item starts.
45 + * @param[in] ndesc number of description lines to allocate and initialize.
46 + * @param[in] state '+','-',' ' for stateConf and stateDefault in that order.
47 + */
48 +sFlag* addFlag (sFlag** root, const char* name, int line, int ndesc, const char state[2])
49 +{
50 + sFlag* newFlag = NULL;
51 +
52 + // Exit early if root is NULL:
53 + if (!root)
54 + ERROR_EXIT(-1, "root must not be %s\n", "NULL")
55 +
56 + if (name) {
57 +
58 + // state is a byte mask. Check it first:
59 + for (int i = 0; i < 2; ++i) {
60 + if (('+' != state[i]) && ('-' != state[i]) && (' ' != state[i]))
61 + ERROR_EXIT(-1, "Illegal character '%c' in state string at position %d\n",
62 + state[i], i)
63 + }
64 +
65 + newFlag = (sFlag*)malloc(sizeof(sFlag));
66 + if (newFlag) {
67 + newFlag->currline = 0;
68 + newFlag->desc = (sDesc*)malloc(sizeof(sDesc) * ndesc);
69 +
70 + if (newFlag->desc) {
71 + for (int i = 0; i < ndesc; ++i) {
72 + newFlag->desc[i].desc = NULL;
73 + newFlag->desc[i].isGlobal = false;
74 + newFlag->desc[i].isInstalled = false;
75 + newFlag->desc[i].pkg = NULL;
76 + newFlag->desc[i].stateForced = ' ';
77 + newFlag->desc[i].stateMasked = ' ';
78 + newFlag->desc[i].statePackage = ' ';
79 + }
80 + } else
81 + ERROR_EXIT(-1, "Unable to allocate %lu bytes for %d sDesc_ structs\n",
82 + sizeof(sDesc) * ndesc, ndesc)
83 +
84 + newFlag->forced = false;
85 + newFlag->listline = line;
86 + newFlag->masked = false;
87 + newFlag->name = strdup(name);
88 + newFlag->ndesc = ndesc;
89 + newFlag->next = NULL;
90 + newFlag->prev = NULL;
91 + newFlag->stateConf = state[0];
92 + newFlag->stateDefault = state[1];
93 +
94 + // Eventually put the new flag into the doubly linked ring:
95 + if (*root) {
96 + newFlag->next = *root;
97 + newFlag->prev = (*root)->prev;
98 + (*root)->prev = newFlag;
99 + if (newFlag->prev)
100 + newFlag->prev->next = newFlag;
101 + } else {
102 + newFlag->next = newFlag;
103 + newFlag->prev = newFlag;
104 + *root = newFlag;
105 + }
106 +
107 + } else
108 + ERROR_EXIT(-1, "Unable to allocate %lu bytes for sFlag_ struct\n", sizeof(sFlag))
109 + } else
110 + ERROR_EXIT(-1, "The new flags must have a name, not %s\n", "NULL")
111 +
112 + return newFlag;
113 +}
114 +
115 +
116 +/** @brief add a flag description line to an existing flag
117 + * As this is a crucial initialization task, the function will
118 + * terminate the program if an error occurs.
119 + * @param[in,out] flag pointer to the flag to manipulate. Must not be NULL
120 + * @param[in] pkg list of affected packages or NULL if no packages are affected
121 + * @param[in] desc description line
122 + * @param[in] state '+','-',' ' for global, installed, forced, masked, package - in that order.
123 + * @return the full length of the description including package list and separators
124 +**/
125 +size_t addFlagDesc (sFlag* flag, const char* pkg, const char* desc, const char state[5])
126 +{
127 + size_t result = 3; // space and brackets.
128 + if (flag) {
129 + int idx = 0;
130 + for ( ; (idx < flag->ndesc) && flag->desc[idx].desc ; ++idx) ;
131 + if (idx < flag->ndesc) {
132 +
133 + // state is a byte mask. Check it first:
134 + for (int i = 0; i < 5; ++i) {
135 + if (('+' != state[i]) && ('-' != state[i]) && (' ' != state[i]))
136 + ERROR_EXIT(-1, "Illegal character '%c' in state string at position %d\n",
137 + state[i], i)
138 + }
139 +
140 + // Now apply.
141 + if (pkg) flag->desc[idx].pkg = strdup(pkg);
142 + if (desc) flag->desc[idx].desc = strdup(desc);
143 + if ('+' == state[0]) flag->desc[idx].isGlobal = true;
144 + if ('+' == state[1]) flag->desc[idx].isInstalled = true;
145 + flag->desc[idx].stateForced = state[2];
146 + flag->desc[idx].stateMasked = state[3];
147 + flag->desc[idx].statePackage = state[4];
148 +
149 + // Set flag mask and force status if this is a global and masked/forced description
150 + if (flag->desc[idx].isGlobal && ('+' == flag->desc[idx].stateMasked))
151 + flag->masked = true;
152 + if (flag->desc[idx].isGlobal && ('+' == flag->desc[idx].stateForced))
153 + flag->forced = true;
154 +
155 + // Determine width:
156 + result += (flag->desc[idx].pkg ? strlen(flag->desc[idx].pkg) : 0)
157 + + strlen(flag->desc[idx].desc);
158 + } else
159 + ERROR_EXIT(-1, "Too many lines for flag %s which is set to %d lines.\n desc: \"%s\"\n",
160 + flag->name, flag->ndesc, desc ? desc : "no description provided")
161 +
162 + } else
163 + ERROR_EXIT(-1, "flag is NULL for description\n \"%s\"\n", desc ? desc : "no description provided")
164 +
165 + return result;
166 +}
167 +
168 +
169 +/** @brief add statistics to @a stats according to the given flag stats
170 + * This function simply counts how many lines are added in which filter case.
171 + * @param[in] flag pointer to the flag to analyze.
172 + * @param[out] stats pointer to the sListStats struct to update.
173 + */
174 +void addLineStats (const sFlag* flag, sListStats* stats)
175 +{
176 + if (flag && stats) {
177 + for (int i = 0; i < flag->ndesc; ++i) {
178 + // Masked is true if the flag is globally masked/forced
179 + // and the description is not explicitly unmasked/unforced,
180 + // or if the description is explicitly masked/forced.
181 + if ( ('+' == flag->desc[i].stateMasked)
182 + || ('+' == flag->desc[i].stateForced)
183 + || ( (' ' == flag->desc[i].stateMasked)
184 + && flag->masked )
185 + || ( (' ' == flag->desc[i].stateForced)
186 + && flag->forced ) ) {
187 + if (flag->desc[i].isInstalled)
188 + ++stats->lineCountMaskedInstalled;
189 + else
190 + ++stats->lineCountMasked;
191 + } else if (flag->desc[i].isGlobal) {
192 + if (flag->desc[i].isInstalled)
193 + ++stats->lineCountGlobalInstalled;
194 + else
195 + ++stats->lineCountGlobal;
196 + } else {
197 + if (flag->desc[i].isInstalled)
198 + ++stats->lineCountLocalInstalled;
199 + else
200 + ++stats->lineCountLocal;
201 + }
202 + }
203 + }
204 +}
205 +
206 +
207 +/** @brief destroy a given flag and set its pointer to the next flag or NULL
208 + * This function never fails. It is completely safe to call it with
209 + * a NULL pointer or a pointer to NULL.
210 + * If the given @a flag is the last in the ring, @a root and @a flag
211 + * are both set to NULL after the flags destruction.
212 + * If @a flag equals @a root and there are items left in the
213 + * ring, @a root is set to its successor.
214 + * @param[in,out] root pointer to the root flag.
215 + * @param[in,out] flag pointer to an sFlag pointer.
216 +**/
217 +void destroyFlag (sFlag** root, sFlag** flag)
218 +{
219 + if (flag && *flag) {
220 + sFlag* xFlag = *flag;
221 + *flag = xFlag->next != xFlag ? xFlag->next : NULL;
222 +
223 + // a) determine whether the ring is closed:
224 + if (*root == xFlag)
225 + *root = *flag;
226 +
227 + // b) destroy description lines
228 + for (int i = 0; i < xFlag->ndesc; ++i) {
229 + if (xFlag->desc[i].pkg)
230 + free (xFlag->desc[i].pkg);
231 + if (xFlag->desc[i].desc)
232 + free (xFlag->desc[i].desc);
233 + }
234 + if (xFlag->desc)
235 + free (xFlag->desc);
236 +
237 + // c) Destroy name and detach from the ring
238 + if (xFlag->name)
239 + free (xFlag->name);
240 + if (xFlag->next && (xFlag->next != xFlag)) {
241 + if (xFlag->prev && (xFlag->prev != xFlag))
242 + xFlag->prev->next = xFlag->next;
243 + xFlag->next->prev = xFlag->prev;
244 + } else if (xFlag->prev && (xFlag->prev != xFlag))
245 + xFlag->prev->next = NULL;
246 + xFlag->next = NULL;
247 + xFlag->prev = NULL;
248 +
249 + // d) destroy remaining flag struct and set pointer to NULL
250 + free (xFlag);
251 + }
252 +}
253 +
254 +
255 +/** @brief determine the number of lines used by @a flag
256 + * This method checks the flag and its description line(s)
257 + * settings against the globally active filters.
258 + * If @a flag is NULL, the result will be 0.
259 + * @param[in] flag pointer to the flag to check.
260 + * @return number of lines needed to display the line *without* possible line wrapping.
261 +**/
262 +int getFlagHeight (const sFlag* flag)
263 +{
264 + int result = 0;
265 +
266 + if (flag) {
267 + for (int i = 0; i < flag->ndesc; ++i)
268 + result += isDescLegal(flag, i) ? 1 : 0;
269 + }
270 +
271 + return result;
272 +}
273 +
274 +
275 +/** @brief return true if the flag description @a idx is ok to display.
276 + * If @a flag is NULL, the result will be false.
277 + * @param[in] flag pointer to the flag to check.
278 + * @param[in] idx index of the description line to check.
279 + * @return true if at least one line has to be shown.
280 + */
281 +bool isDescLegal (const sFlag* flag, int idx)
282 +{
283 + bool result = false;
284 +
285 + if (flag && (idx < flag->ndesc)) {
286 + if ( // 1.: Check isGlobal versus e_scope
287 + ( ( flag->desc[idx].isGlobal && e_scope != eScope_local)
288 + || (!flag->desc[idx].isGlobal && e_scope != eScope_global) )
289 + // 2.: Check isInstalled versus e_state
290 + && ( ( flag->desc[idx].isInstalled && e_state != eState_notinstalled)
291 + || (!flag->desc[idx].isInstalled && e_state != eState_installed) )
292 + // 3.: Check stateMasked versus e_mask
293 + && ( (('+' == flag->desc[idx].stateMasked) && e_mask != eMask_unmasked)
294 + || (('+' != flag->desc[idx].stateMasked) && e_mask != eMask_masked) ) )
295 + result = true;
296 + }
297 +
298 + return result;
299 +}
300 +
301 +/** @brief return true if this flag has at least one line to display.
302 + * This method checks the flag and its description line(s)
303 + * settings against the globally active filters.
304 + * The function returns as soon as the first displayable line is
305 + * found and can be therefore faster than getFlagHeight().
306 + * If @a flag is NULL, the result will be false.
307 + * @param[in] flag pointer to the flag to check.
308 + * @return true if at least one line has to be shown.
309 + */
310 +bool isFlagLegal (const sFlag* flag)
311 +{
312 + bool result = false;
313 +
314 + if (flag) {
315 + for (int i = 0; !result && (i < flag->ndesc); ++i) {
316 + result = isDescLegal(flag, i);
317 + }
318 + }
319 +
320 + return result;
321 +}
322
323 diff --git a/ufed-types.h b/ufed-types.h
324 new file mode 100644
325 index 0000000..9953b6a
326 --- /dev/null
327 +++ b/ufed-types.h
328 @@ -0,0 +1,155 @@
329 +/*
330 + * ufed-types.h
331 + *
332 + * Created on: 28.01.2013
333 + * Author: Sven Eden
334 + */
335 +#pragma once
336 +#ifndef UFED_TYPES_H_INCLUDED
337 +#define UFED_TYPES_H_INCLUDED 1
338 +
339 +#ifdef HAVE_CONFIG_H
340 +#include "config.h"
341 +#endif
342 +
343 +#include <curses.h>
344 +#include "ufed-debug.h"
345 +
346 +/* =============
347 + * === enums ===
348 + * =============
349 + */
350 +
351 +/** @enum eMask_
352 + * @brief determine which flags are shown concerning masked status
353 +**/
354 +typedef enum eMask_ {
355 + eMask_unmasked,
356 + eMask_both,
357 + eMask_masked
358 +} eMask;
359 +
360 +
361 +/** @enum eOrder_
362 + * @brief determine whether package lists are shown left or right of the description
363 +**/
364 +typedef enum eOrder_ {
365 + eOrder_left,
366 + eOrder_right
367 +} eOrder;
368 +
369 +
370 +/** @enum eScope_
371 + * @brief determine whether global, local or all flags are listed
372 +**/
373 +typedef enum eScope_ {
374 + eScope_all,
375 + eScope_global,
376 + eScope_local
377 +} eScope;
378 +
379 +
380 +/** @enum eState_
381 + * @brief determine whether installed, not installed or all packages are listed
382 +**/
383 +typedef enum eState_ {
384 + eState_all,
385 + eState_installed,
386 + eState_notinstalled
387 +} eState;
388 +
389 +
390 +/** @enum eWin_
391 + * @brief list of used curses windows
392 +**/
393 +typedef enum eWin_ {
394 + Top = 0,
395 + Left, List, Input, Scrollbar, Right, Bottom,
396 + wCount // always last
397 +} eWin;
398 +
399 +
400 +/* ===============
401 + * === structs ===
402 + * ===============
403 + */
404 +
405 +/** @struct sDesc_
406 + * @brief Describe one description line
407 +**/
408 +typedef struct sDesc_ {
409 + char* desc; //!< The description line
410 + bool isGlobal; //!< true if this is the global description and setting
411 + bool isInstalled; //!< global: at least one pkg is installed, local: all in *pkg are installed.
412 + char* pkg; //!< affected packages
413 + char stateForced; //!< unforced '-', forced '+' or not set ' ' by *use.force
414 + char stateMasked; //!< unmasked '-', masked '+' or not sed ' ' by *use.mask
415 + char statePackage; //!< disabled '-', enabled '+' or not set ' ' by package.use
416 +} sDesc;
417 +
418 +
419 +/** @struct sFlag_
420 + * @brief Describe one flag and its make.conf setting in a doubly linked ring
421 +**/
422 +typedef struct sFlag_ {
423 + int currline; //!< The current line on the screen this flag starts
424 + sDesc* desc; //!< variable array of sDesc structs
425 + bool forced; //!< true if the first global description is force enabled.
426 + int listline; //!< The fixed line within the full list this flag starts
427 + bool masked; //!< true if the first global description is mask enabled.
428 + char* name; //!< Name of the flag or NULL for help lines
429 + int ndesc; //!< number of description lines
430 + struct
431 + sFlag_* next; //!< Next flag in the doubly linked ring
432 + struct
433 + sFlag_* prev; //!< Previous flag in the doubly linked ring
434 + char stateConf; //!< disabled '-', enabled '+' or not set ' ' by make.conf
435 + char stateDefault; //!< disabled '-', enabled '+' or not set ' ' by make.defaults
436 +} sFlag;
437 +
438 +
439 +/** @struct sListStats_
440 + * @brief hold stats of the flag list like line counts
441 +**/
442 +typedef struct sListStats_ {
443 + int lineCountGlobal;
444 + int lineCountGlobalInstalled;
445 + int lineCountLocal;
446 + int lineCountLocalInstalled;
447 + int lineCountMasked;
448 + int lineCountMaskedInstalled;
449 +} sListStats;
450 +
451 +
452 +/** @struct sKey_
453 + * @brief describe one main control key
454 +**/
455 +typedef struct sKey_ {
456 + int key; //!< curses key or -1 if no key shall be used
457 + const char *descr; //!< Help text to display
458 + size_t length; //!< length of the description
459 +} sKey;
460 +
461 +
462 +/** @struct sWindow_
463 + * @brief describe one curses window dimensions
464 +**/
465 +typedef struct sWindow_ {
466 + WINDOW *win;
467 + const int top, left, height, width;
468 +} sWindow;
469 +
470 +
471 +/* =======================================
472 + * === public functions handling types ===
473 + * =======================================
474 + */
475 +sFlag* addFlag (sFlag** root, const char* name, int line, int ndesc, const char state[2]);
476 +size_t addFlagDesc (sFlag* flag, const char* pkg, const char* desc, const char state[5]);
477 +void addLineStats (const sFlag* flag, sListStats* stats);
478 +void destroyFlag (sFlag** root, sFlag** flag);
479 +int getFlagHeight(const sFlag* flag);
480 +bool isDescLegal (const sFlag* flag, int idx);
481 +bool isFlagLegal (const sFlag* flag);
482 +
483 +#endif /* UFED_TYPES_H_INCLUDED */