Line data Source code
1 : /*
2 : svg_badge.c
3 : Created by Danny Goossen, Gioxa Ltd on 6/3/17.
4 :
5 : MIT License
6 :
7 : Copyright (c) 2017 deployctl, Gioxa Ltd.
8 :
9 : Permission is hereby granted, free of charge, to any person obtaining a copy
10 : of this software and associated documentation files (the "Software"), to deal
11 : in the Software without restriction, including without limitation the rights
12 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 : copies of the Software, and to permit persons to whom the Software is
14 : furnished to do so, subject to the following conditions:
15 :
16 : The above copyright notice and this permission notice shall be included in all
17 : copies or substantial portions of the Software.
18 :
19 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 : SOFTWARE.
26 :
27 : */
28 :
29 : #include "deployd.h"
30 :
31 :
32 :
33 : static const char * svg= "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"@@c@@\" height=\"20\"> <linearGradient id=\"b\" x2=\"0\" y2=\"100%\">" \
34 : "<stop offset=\"0\" stop-color=\"#bbb\" stop-opacity=\".1\"/> <stop offset=\"1\" stop-opacity=\".1\"/>" \
35 : " </linearGradient><mask id=\"a\"> <rect width=\"@@c@@\" height=\"20\" rx=\"3\" fill=\"#fff\"/> </mask> <g mask=\"url(#a)\"> " \
36 : " <path fill=\"#555\" d=\"M0 0 h@@a@@ v20 H0 z\"/> <path fill=\"#4c1\" d=\"M@@a@@ 0 h@@b@@ v20 H@@a@@ z\"/> <path fill=\"url(#b)\"" \
37 : " d=\"M0 0 h@@c@@ v20 H0 z\"/> </g> <g fill=\"#fff\" text-anchor=\"middle\"> <g font-family=\"DejaVu Sans,Verdana,Geneva,sans-serif\" font-size=\"11\"> " \
38 : " <text x=\"@@d@@\" y=\"15\" fill=\"#010101\" fill-opacity=\".3\">@@f@@</text><text x=\"@@d@@\" y=\"14\">@@f@@</text> " \
39 : " <text x=\"@@e@@\" y=\"15\" fill=\"#010101\" fill-opacity=\".3\">@@g@@</text> <text x=\"@@e@@\" y=\"14\">@@g@@</text> </g> </g></svg>";
40 :
41 :
42 : /*
43 : svg placements_stubs:
44 :
45 : @@a@@ = strlen(@@f@@) * 7 + 3
46 : @@b@@ = strlen(@@g@@) * 7 + 5
47 : @@c@@ = @@a@@ + @@b@@
48 :
49 : @@d@@ = @@a@@ / 2
50 : @@e@@ = @@a@@ + @@b@@ / 2
51 :
52 : @@f@@ = "TAG"
53 : @@g@@ = "0.0.1"
54 :
55 : */
56 :
57 : /*------------------------------------------------------------------------
58 : * Creates a release badge
59 : +-------+-------+
60 : | str_a | str_b |
61 : +-------+-------+
62 : * auto calculates the witdh
63 : * returns 1 on success
64 : * caller need to free *badge_str
65 : *------------------------------------------------------------------------*/
66 :
67 6 : int make_svg_badge(char * str_a, char * str_b, char ** badge_str) {
68 :
69 : struct MemoryStruct output;
70 6 : init_dynamicbuf( &output);
71 6 : *badge_str=NULL;
72 :
73 : //Calculate size of badge according the str_a and str_b size
74 6 : size_t len_a= strlen(str_a)*9+3; // @@a@@
75 6 : size_t len_b= strlen(str_b)*9+3; // @@b@@
76 6 : size_t len_c= len_a+len_b; // @@c@@
77 6 : size_t pos_a= len_a/2; //@@d@@
78 6 : size_t pos_b= len_a+len_b/2; //@@e@@
79 :
80 : regex_t regex;
81 : int reti;
82 6 : size_t prev_end=0;
83 6 : char regex_str[]= "@@([a-z])@@";
84 :
85 6 : int regex_match_cnt=2+1; // ( 2 matches in above expression: from @@..@@ and inbtween the @@, and 1 position to store the -1 for end.)
86 6 : char * subject=(char*)svg;
87 :
88 : regmatch_t ovector[3];
89 : //regmatch_t * ovector= calloc(sizeof(regoff_t)*2,regex_match_cnt);
90 :
91 : /* Compile regular expression */
92 6 : debug("make tag badge %s:%s\n",str_a,str_b);
93 : //reti =
94 6 : regcomp(®ex, regex_str, REG_EXTENDED);
95 : //if (reti) { // no need to test here, it'll fail later as well
96 : // error( "Could not compile regex\n");
97 : // return -1;
98 : //}
99 :
100 : /* Execute regular expression in loop */
101 : for (;;)
102 : {
103 96 : reti = regexec(®ex, subject+prev_end, regex_match_cnt, ovector, 0);
104 96 : if (!reti)
105 : {
106 : //puts("Match");
107 : int i=0;
108 : while (ovector[i].rm_so!=-1 && i<5)
109 : {
110 : // debug("found at %lld to %lld\n", ovector[i].rm_so+prev_end,ovector[i].rm_eo+prev_end);
111 : i++;
112 : }
113 90 : if (ovector[1].rm_eo !=-1 && ovector[0].rm_so !=-1 && (ovector[1].rm_eo-ovector[1].rm_so) == 1)
114 : {
115 90 : Writedynamicbuf_n((void *)(subject+ prev_end), ovector[0].rm_so, &output);
116 :
117 : // since we use here only 1 char as named substring, we'll have that in ovector[2]
118 90 : char stub_code=subject[prev_end+ovector[1].rm_so];
119 90 : prev_end=prev_end+ovector[0].rm_eo;
120 90 : switch (stub_code) {
121 : case 'a':
122 : {
123 : char tmp[20];
124 18 : sprintf(tmp,"%zu", len_a);
125 18 : Writedynamicbuf(tmp,&output);
126 : break;
127 : }
128 : case 'b':
129 : {
130 : char tmp[20];
131 6 : sprintf(tmp,"%zu", len_b);
132 6 : Writedynamicbuf(tmp,&output);
133 : break;
134 : }
135 : case 'c':
136 : {
137 : char tmp[20];
138 18 : sprintf(tmp,"%zu", len_c);
139 18 : Writedynamicbuf(tmp,&output);
140 : break;
141 : }
142 : case 'd':
143 : {
144 : char tmp[20];
145 12 : sprintf(tmp,"%zu", pos_a);
146 12 : Writedynamicbuf(tmp,&output);
147 : break;
148 : }
149 : case 'e':
150 : {
151 : char tmp[20];
152 12 : sprintf(tmp,"%zu", pos_b);
153 12 : Writedynamicbuf(tmp,&output);
154 : break;
155 : }
156 : case 'f':
157 : {
158 12 : Writedynamicbuf(str_a,&output);
159 12 : break;
160 : }
161 : case 'g':
162 : {
163 12 : Writedynamicbuf(str_b,&output);
164 12 : break;
165 : }
166 : default:
167 0 : error("svg, regex unknown stub code %c @ pos : %d",subject[prev_end+ovector[1].rm_so],prev_end+ovector[1].rm_so);break;
168 : }
169 : }
170 :
171 : }
172 6 : else if (reti == REG_NOMATCH) {
173 : // copy rest from lastmatch end to end of subject
174 6 : Writedynamicbuf_n((void *)(subject+ prev_end), strlen(subject)-prev_end, &output);
175 6 : break;
176 : }
177 : else { prev_end=0;break; }
178 : // no need to change, regex is not variable
179 : //regerror(reti, ®ex,errorbuf, 1024);
180 : //error( "Regex match failed: %s\n", errorbuf);
181 : }
182 :
183 : /* Free memory allocated to the pattern buffer by regcomp() */
184 6 : regfree(®ex);
185 6 : if (prev_end)
186 : {
187 6 : *badge_str=output.memory;
188 : //debug ("svg tag size %d >>>>>\n%s\n<<<<\n",output.size,output.memory);
189 6 : debug("success parsing tag.svg, len: %d \n",strlen(output.memory));
190 6 : return 0;
191 : }
192 : else
193 : {
194 0 : if (output.memory) {free(output.memory); *badge_str=NULL;}return -1;
195 : }
196 : }
|