?: go back to numexpr
[nedit-bw.git] / macroJoin.diff
blob77d9374cfc9f7e6c31945c04219bcc2fbd6df24a
1 From: Tony Balinski <ajbj@free.fr>
2 Subject: join() macro
4 ---
6 source/macro.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7 1 file changed, 123 insertions(+)
9 diff --quilt old/source/macro.c new/source/macro.c
10 --- old/source/macro.c
11 +++ new/source/macro.c
12 @@ -276,6 +276,8 @@ static int stringCompareMS(WindowInfo *w
13 DataValue *result, char **errMsg);
14 static int splitMS(WindowInfo *window, DataValue *argList, int nArgs,
15 DataValue *result, char **errMsg);
16 +static int joinMS(WindowInfo *window, DataValue *argList, int nArgs,
17 + DataValue *result, char **errMsg);
18 /* DISASBLED for 5.4
19 static int setBacklightStringMS(WindowInfo *window, DataValue *argList,
20 int nArgs, DataValue *result, char **errMsg);
21 @@ -551,6 +553,7 @@ static const BuiltInSubrName MacroSubrs[
22 { "timer_remove", timerRemoveMS },
23 { "escape_literal", escapeLiteralMS },
24 { "full_file_name", fullFileNameMS },
25 + { "join", joinMS },
26 { NULL, NULL } /* sentinel */
29 @@ -4815,6 +4818,126 @@ static int splitMS(WindowInfo *window, D
33 +** This function is intended to concatenate values in an array of strings into a
34 +** single string. It acts as the inverse-operation to split().
35 +**
36 +** string = join(array, separator[, start[, end]]))
37 +**
38 +** It will only concatenate consecutive integer-indexed elements. If start and
39 +** end are given, these are the lower and upper bounds of the index range to
40 +** use; the element array[end] will not be accessed. By default, start is 0 and
41 +** end will be one beyond the last valid integer index of a contiguous sequence
42 +** starting at start.
43 +*/
44 +static int joinMS(WindowInfo *window, DataValue *argList, int nArgs,
45 + DataValue *result, char **errMsg)
47 + char stringStorage[TYPE_INT_STR_SIZE(int)];
48 + char *sepStr;
49 + int start, end, index;
50 + size_t size, sepLen, separatorLen;
51 + char indexStr[TYPE_INT_STR_SIZE(int)], *pos;
52 + DataValue *array, element;
54 + result->tag = STRING_TAG;
55 + result->val.str.rep = PERM_ALLOC_STR("");
56 + result->val.str.len = 0;
58 + if (nArgs < 1 || nArgs > 4) {
59 + return wrongNArgsErr(errMsg);
60 + }
61 + if (argList[0].tag != ARRAY_TAG) {
62 + M_FAILURE("first argument must be an array: %s");
63 + }
64 + array = &argList[0];
65 + if (nArgs >= 2) {
66 + if (!readStringArg(argList[1], &sepStr, stringStorage, errMsg)) {
67 + M_FAILURE("second argument (separator) must be scalar: %s");
68 + }
69 + }
70 + else {
71 + sepStr = stringStorage;
72 + *sepStr = '\0';
73 + }
74 + if (nArgs >= 3) {
75 + if (!readIntArg(argList[2], &start, errMsg))
76 + M_FAILURE("third argument (start index) must be numeric: %s");
77 + }
78 + else {
79 + start = 0;
80 + }
81 + if (nArgs >= 4) {
82 + if (!readIntArg(argList[3], &end, errMsg))
83 + M_FAILURE("fourth argument (end index) must be numeric: %s");
84 + if (end <= start)
85 + return True;
86 + }
87 + else {
88 + end = start - 1;
89 + }
91 + /* right: now for the real work */
92 + /* count the space we need to build the result string */
93 + size = 0;
94 + sepLen = 0;
95 + separatorLen = strlen(sepStr);
96 + for (index = start; index != end; ++index) {
97 + if (ArrayGet(array, longAsStr(index), &element)) {
98 + size += sepLen;
99 + sepLen = separatorLen;
101 + switch (element.tag) {
102 + case INT_TAG:
103 + size += strlen(longAsStr(element.val.n));
104 + break;
105 + case STRING_TAG:
106 + size += element.val.str.len;
107 + break;
108 + default:
109 + M_FAILURE("cannot append non-scalar element to string: %s");
112 + else
113 + break;
115 + if (size == 0)
116 + return True;
118 + /* allocate a string result */
119 + AllocNString(&result->val.str, size + 1);
120 + M_STR_ALLOC_ASSERT(*result);
121 + pos = result->val.str.rep;
123 + /* now fill it in */
124 + sepLen = 0;
125 + for (index = start; index != end; ++index) {
126 + if (ArrayGet(array, longAsStr(index), &element)) {
127 + memcpy(pos, sepStr, sepLen);
128 + pos += sepLen;
129 + sepLen = separatorLen;
131 + switch (element.tag) {
132 + case INT_TAG:
133 + strcpy(pos, longAsStr(element.val.n));
134 + pos += strlen(pos);
135 + break;
136 + case STRING_TAG:
137 + memcpy(pos, element.val.str.rep, element.val.str.len);
138 + pos += element.val.str.len;
139 + break;
140 + default:
141 + M_FAILURE("internal error - inaccessible code attained: %s");
144 + else
145 + break;
147 + *pos = '\0';
149 + return True;
153 ** Set the backlighting string resource for the current window. If no parameter
154 ** is passed or the value "default" is passed, it attempts to set the preference
155 ** value of the resource. If the empty string is passed, the backlighting string