This repository has been archived by the owner on Oct 15, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 123
/
keymetaformatting.c
162 lines (142 loc) · 4.5 KB
/
keymetaformatting.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/**
* @file
*
* @brief Utility functions for comment metakeys
*
* @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
*
*/
#include "keymetaformatting.h"
#include <ctype.h>
#include <kdbease.h>
#include <kdbhelper.h>
#include <kdbinternal.h>
#include <string.h>
/**
* @brief Set a formatted string
*
* @param key the key to set the string value
* @param format NULL-terminated text format string
* @param ... more arguments
*
* @return the size of the string as set (with including 0)
*/
ssize_t keySetStringF (Key * key, const char * format, ...)
{
va_list arg_list;
keySetMeta (key, "binary", 0);
va_start (arg_list, format);
char * p = elektraVFormat (format, arg_list);
va_end (arg_list);
if (!p)
{
return -1;
}
ssize_t ret = keySetRaw (key, p, elektraStrLen (p));
elektraFree (p);
return ret;
}
static void elektraAddCommentInfo (KeySet * comments, Key * commentBase, size_t spaces, const char * commentStart, const char * comment)
{
keySetString (commentBase, comment);
if (commentStart)
{
/* this comment contains actual comment data */
Key * commentStartKey = keyDup (commentBase, KEY_CP_ALL);
keyAddBaseName (commentStartKey, "start");
keySetString (commentStartKey, commentStart);
ksAppendKey (comments, commentStartKey);
}
ksAppendKey (comments, commentBase);
/* a space comment key is created for each common comment key
* and for each line that contains more than one space
*/
if (commentStart || spaces > 0)
{
Key * commentSpaceKey = keyDup (commentBase, KEY_CP_ALL);
keyAddBaseName (commentSpaceKey, "space");
keySetStringF (commentSpaceKey, "%d", spaces);
ksAppendKey (comments, commentSpaceKey);
}
}
/**
* Adds a line comment to the supplied comment keyset.
* The created comment key will always have an array index
* >= 1. This is because #0 is reserved for inline comments
*
* The following rules apply to the comment subkeys (i.e. space, start)
* - a space key is only omitted for newline comments that do not contain spaces
* each other line comment will have a space key (probably with the value 0)
* - the start key is only present if the comment start sequence is not NULL
*
* @param comments the keyset that should hold the created keys
* @param spaces the number of spaces in the comment
* @param commentStart the used comment start sequence
* @param comment the comment data (i.e. the actual comment)
*/
void elektraAddLineComment (KeySet * comments, size_t spaces, const char * commentStart, const char * comment)
{
Key * lineComment;
/* initialize the comment key */
if (ksGetSize (comments) == 0)
{
lineComment = keyNew ("meta:/comment/#", KEY_END);
elektraArrayIncName (lineComment);
ksAppendKey (comments, lineComment);
lineComment = elektraArrayGetNextKey (comments);
}
else
{
// TODO: doing all this every time is very inefficient. Arrayhandling
// definitely needs to be improved
Key * arrayBase = keyNew ("meta:/comment", KEY_END);
KeySet * array = elektraArrayGet (arrayBase, comments);
lineComment = elektraArrayGetNextKey (array);
keyDel (arrayBase);
ksDel (array);
}
elektraAddCommentInfo (comments, lineComment, spaces, commentStart, comment);
}
/**
* Adds an inline comment to the supplied comment keyset.
* The inline comment will always have the index #0. If an
* inline comment is already present in the supplied comment keyset
* it will be replaced.
*
* @param comments the keyset that should hold the created keys
* @param spaces the number of spaces in the comment
* @param commentStart the used comment start sequence
* @param comment the comment data (i.e. the actual comment)
*/
void elektraAddInlineComment (KeySet * comments, size_t spaces, const char * commentStart, const char * comment)
{
Key * inlineComment = keyNew ("meta:/comment/#", KEY_END);
elektraArrayIncName (inlineComment);
elektraAddCommentInfo (comments, inlineComment, spaces, commentStart, comment);
}
/**
* Counts the number of spaces at the beginning of a string.
* The function continues until the first non blank character is detected.
* This means that tabs are counted as normal spaces.
*
* @param line the string in which spaces are counted
* @return the number of spaces before the first non blank character
*/
size_t elektraCountStartSpaces (const char * line)
{
/* count the number of whitespace characters before the comment */
size_t spaces = 0;
size_t lineLen = strlen (line);
for (size_t i = 0; i < lineLen; i++)
{
if (isblank (line[i]))
{
spaces++;
}
else
{
break;
}
}
return spaces;
}