Line data Source code
1 : #include "xdiff.h"
2 :
3 : /**
4 : * @brief Structure for storing output buffer
5 : */
6 : typedef struct {
7 : char *buffer; /**< Pointer to data buffer */
8 : size_t size; /**< Current size of data in buffer */
9 : size_t capacity; /**< Total buffer capacity */
10 : } output_buffer_t;
11 :
12 : /**
13 : * @brief Initializes output buffer for storing comparison results
14 : *
15 : * @return output_buffer_t* Pointer to created buffer or NULL on error
16 : */
17 8 : static output_buffer_t *init_output_buffer(void)
18 : {
19 8 : Return status = SUCCESS;
20 8 : output_buffer_t *buf = NULL;
21 :
22 : /* Allocate memory for buffer structure */
23 8 : buf = (output_buffer_t *)malloc(sizeof(output_buffer_t));
24 :
25 8 : if(NULL == buf)
26 : {
27 0 : status = FAILURE;
28 : }
29 :
30 8 : if(SUCCESS == status)
31 : {
32 : /* Set initial size */
33 8 : buf->capacity = 1024;
34 8 : buf->buffer = (char *)malloc(buf->capacity);
35 :
36 8 : if(NULL == buf->buffer)
37 : {
38 0 : free(buf);
39 0 : buf = NULL;
40 0 : status = FAILURE;
41 : }
42 : }
43 :
44 8 : if(SUCCESS == status)
45 : {
46 8 : buf->size = 0;
47 8 : buf->buffer[0] = '\0';
48 : }
49 :
50 8 : return buf;
51 : }
52 :
53 : /**
54 : * @brief Appends data to output buffer
55 : *
56 : * @param priv Pointer to buffer (output_buffer_t*)
57 : * @param mb Array of buffers with data
58 : * @param nbuf Number of buffers
59 : * @return Return Operation status
60 : */
61 114 : static int append_to_buffer(
62 : void *priv,
63 : mmbuffer_t *mb,
64 : int nbuf)
65 : {
66 114 : int status = SUCCESS;
67 114 : output_buffer_t *buf = (output_buffer_t *)priv;
68 114 : size_t total_size = 0;
69 114 : size_t new_capacity = 0;
70 114 : char *new_buffer = NULL;
71 :
72 : /* Check input parameters */
73 114 : if(NULL == buf || NULL == mb)
74 : {
75 0 : return(1);
76 : }
77 :
78 : /* Calculate total size to append */
79 114 : if(SUCCESS == status)
80 : {
81 342 : for(int i = 0; i < nbuf; i++)
82 : {
83 228 : total_size += mb[i].size;
84 : }
85 : }
86 :
87 : /* Check if buffer needs to be enlarged */
88 114 : if(SUCCESS == status)
89 : {
90 114 : if(buf->size + total_size + 1 > buf->capacity)
91 : {
92 4 : new_capacity = buf->capacity;
93 :
94 8 : while(new_capacity < buf->size + total_size + 1)
95 : {
96 4 : new_capacity *= 2;
97 : }
98 :
99 4 : new_buffer = (char *)realloc(buf->buffer,new_capacity);
100 :
101 4 : if(NULL == new_buffer)
102 : {
103 0 : status = FAILURE;
104 : } else {
105 4 : buf->buffer = new_buffer;
106 4 : buf->capacity = new_capacity;
107 : }
108 : }
109 : }
110 :
111 : /* Copy data */
112 114 : if(SUCCESS == status)
113 : {
114 342 : for(int i = 0; i < nbuf; i++)
115 : {
116 228 : memcpy(buf->buffer + buf->size,mb[i].ptr,mb[i].size);
117 228 : buf->size += mb[i].size;
118 : }
119 114 : buf->buffer[buf->size] = '\0';
120 : }
121 :
122 114 : return(status);
123 : }
124 :
125 : /**
126 : * @brief Creates mmfile from string
127 : *
128 : * @param mmf Pointer to mmfile_t structure to fill
129 : * @param content Source string
130 : * @return Return Operation status
131 : */
132 16 : static Return create_mmfile(
133 : mmfile_t *mmf,
134 : const char *content)
135 : {
136 16 : Return status = SUCCESS;
137 16 : size_t size = 0;
138 16 : void *data = NULL;
139 :
140 16 : if(NULL == mmf || NULL == content)
141 : {
142 0 : return(FAILURE);
143 : }
144 :
145 16 : size = strlen(content);
146 :
147 : /* Initialize mmfile */
148 16 : if(SUCCESS == status)
149 : {
150 16 : if(xdl_init_mmfile(mmf,size + 1,XDL_MMF_ATOMIC) < 0)
151 : {
152 0 : status = FAILURE;
153 : }
154 : }
155 :
156 : /* Allocate memory and copy data */
157 16 : if(SUCCESS == status)
158 : {
159 16 : data = xdl_mmfile_writeallocate(mmf,size);
160 :
161 16 : if(NULL == data)
162 : {
163 0 : xdl_free_mmfile(mmf);
164 0 : status = FAILURE;
165 : }
166 : }
167 :
168 16 : if(SUCCESS == status)
169 : {
170 16 : memcpy(data,content,size);
171 : }
172 :
173 16 : if(SUCCESS != status)
174 : {
175 0 : serp("Failed to create mmfile");
176 : }
177 :
178 16 : return(status);
179 : }
180 :
181 : /**
182 : * @brief Compares two strings and generates diff in unified format
183 : *
184 : * @param[out] diff Pointer to string with comparison result
185 : * @param[in] string1 First string to compare
186 : * @param[in] string2 Second string to compare
187 : * @return Return Operation status
188 : */
189 8 : Return compare_strings(
190 : char **diff,
191 : const char *string1,
192 : const char *string2)
193 : {
194 8 : Return status = SUCCESS;
195 : mmfile_t mf1,mf2;
196 : xpparam_t xpp;
197 : xdemitconf_t xecfg;
198 : xdemitcb_t ecb;
199 8 : output_buffer_t *output = NULL;
200 :
201 : /* Validate input parameters */
202 8 : if(NULL == diff || NULL == string1 || NULL == string2)
203 : {
204 0 : return(FAILURE);
205 : }
206 :
207 : /* Create output buffer */
208 8 : output = init_output_buffer();
209 :
210 8 : if(NULL == output || output->buffer == NULL)
211 : {
212 0 : serp("Failed to initialize output buffer");
213 0 : status = FAILURE;
214 : }
215 :
216 : /* Initialize parameters */
217 8 : if(SUCCESS == status)
218 : {
219 8 : memset(&xpp,0,sizeof(xpp));
220 8 : xpp.flags |= XDF_NEED_MINIMAL;
221 8 : xecfg.ctxlen = 0;
222 8 : xecfg.str_meta = 0;
223 8 : ecb.priv = output;
224 8 : ecb.outf = append_to_buffer;
225 : }
226 :
227 : /* Create mmfile structures from input strings */
228 8 : if(SUCCESS == status)
229 : {
230 8 : status = create_mmfile(&mf1,string1);
231 : }
232 :
233 8 : if(SUCCESS == status)
234 : {
235 8 : status = create_mmfile(&mf2,string2);
236 : }
237 :
238 : /* Perform comparison */
239 8 : if(SUCCESS == status)
240 : {
241 8 : if(xdl_diff(&mf1,&mf2,&xpp,&xecfg,&ecb) < 0)
242 : {
243 0 : serp("Diff failed");
244 0 : status = FAILURE;
245 : }
246 : }
247 :
248 : /* Save result */
249 8 : if(SUCCESS == status)
250 : {
251 8 : *diff = strdup(output->buffer);
252 :
253 8 : if(NULL == *diff)
254 : {
255 0 : status = FAILURE;
256 : }
257 : }
258 :
259 : /* Free resources */
260 8 : xdl_free_mmfile(&mf1);
261 8 : xdl_free_mmfile(&mf2);
262 :
263 8 : if(output != NULL)
264 : {
265 8 : if(output->buffer != NULL)
266 : {
267 8 : free(output->buffer);
268 : }
269 :
270 8 : free(output);
271 : }
272 :
273 8 : return(status);
274 : }
|