Coverage Report

Created: 2025-11-15 06:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/uriparser/src/UriRecompose.c
Line
Count
Source
1
/*
2
 * uriparser - RFC 3986 URI parsing library
3
 *
4
 * Copyright (C) 2007, Weijia Song <songweijia@gmail.com>
5
 * Copyright (C) 2007, Sebastian Pipping <sebastian@pipping.org>
6
 * All rights reserved.
7
 *
8
 * Redistribution and use in source  and binary forms, with or without
9
 * modification, are permitted provided  that the following conditions
10
 * are met:
11
 *
12
 *     1. Redistributions  of  source  code   must  retain  the  above
13
 *        copyright notice, this list  of conditions and the following
14
 *        disclaimer.
15
 *
16
 *     2. Redistributions  in binary  form  must  reproduce the  above
17
 *        copyright notice, this list  of conditions and the following
18
 *        disclaimer  in  the  documentation  and/or  other  materials
19
 *        provided with the distribution.
20
 *
21
 *     3. Neither the  name of the  copyright holder nor the  names of
22
 *        its contributors may be used  to endorse or promote products
23
 *        derived from  this software  without specific  prior written
24
 *        permission.
25
 *
26
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27
 * "AS IS" AND  ANY EXPRESS OR IMPLIED WARRANTIES,  INCLUDING, BUT NOT
28
 * LIMITED TO,  THE IMPLIED WARRANTIES OF  MERCHANTABILITY AND FITNESS
29
 * FOR  A  PARTICULAR  PURPOSE  ARE  DISCLAIMED.  IN  NO  EVENT  SHALL
30
 * THE  COPYRIGHT HOLDER  OR CONTRIBUTORS  BE LIABLE  FOR ANY  DIRECT,
31
 * INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL DAMAGES
32
 * (INCLUDING, BUT NOT LIMITED TO,  PROCUREMENT OF SUBSTITUTE GOODS OR
33
 * SERVICES; LOSS OF USE, DATA,  OR PROFITS; OR BUSINESS INTERRUPTION)
34
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
35
 * STRICT  LIABILITY,  OR  TORT (INCLUDING  NEGLIGENCE  OR  OTHERWISE)
36
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
37
 * OF THE POSSIBILITY OF SUCH DAMAGE.
38
 */
39
40
/* What encodings are enabled? */
41
#include <uriparser/UriDefsConfig.h>
42
#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE))
43
/* Include SELF twice */
44
#  ifdef URI_ENABLE_ANSI
45
#    define URI_PASS_ANSI 1
46
#    include "UriRecompose.c"
47
#    undef URI_PASS_ANSI
48
#  endif
49
#  ifdef URI_ENABLE_UNICODE
50
#    define URI_PASS_UNICODE 1
51
#    include "UriRecompose.c"
52
#    undef URI_PASS_UNICODE
53
#  endif
54
#else
55
#  ifdef URI_PASS_ANSI
56
#    include <uriparser/UriDefsAnsi.h>
57
#  else
58
#    include <uriparser/UriDefsUnicode.h>
59
#    include <wchar.h>
60
#  endif
61
62
#  ifndef URI_DOXYGEN
63
#    include <uriparser/Uri.h>
64
#    include "UriCommon.h"
65
#  endif
66
67
static int URI_FUNC(ToStringEngine)(URI_CHAR * dest, const URI_TYPE(Uri) * uri,
68
                                    int maxChars, int * charsWritten,
69
                                    int * charsRequired);
70
71
0
int URI_FUNC(ToStringCharsRequired)(const URI_TYPE(Uri) * uri, int * charsRequired) {
72
0
    const int MAX_CHARS = ((unsigned int)-1) >> 1;
73
0
    return URI_FUNC(ToStringEngine)(NULL, uri, MAX_CHARS, NULL, charsRequired);
74
0
}
Unexecuted instantiation: uriToStringCharsRequiredA
Unexecuted instantiation: uriToStringCharsRequiredW
75
76
int URI_FUNC(ToString)(URI_CHAR * dest, const URI_TYPE(Uri) * uri, int maxChars,
77
19.2k
                       int * charsWritten) {
78
19.2k
    return URI_FUNC(ToStringEngine)(dest, uri, maxChars, charsWritten, NULL);
79
19.2k
}
uriToStringA
Line
Count
Source
77
9.24k
                       int * charsWritten) {
78
9.24k
    return URI_FUNC(ToStringEngine)(dest, uri, maxChars, charsWritten, NULL);
79
9.24k
}
uriToStringW
Line
Count
Source
77
10.0k
                       int * charsWritten) {
78
10.0k
    return URI_FUNC(ToStringEngine)(dest, uri, maxChars, charsWritten, NULL);
79
10.0k
}
80
81
static URI_INLINE int URI_FUNC(ToStringEngine)(URI_CHAR * dest, const URI_TYPE(Uri) * uri,
82
                                               int maxChars, int * charsWritten,
83
19.2k
                                               int * charsRequired) {
84
19.2k
    int written = 0;
85
19.2k
    if ((uri == NULL) || ((dest == NULL) && (charsRequired == NULL))) {
86
0
        if (charsWritten != NULL) {
87
0
            *charsWritten = 0;
88
0
        }
89
0
        return URI_ERROR_NULL;
90
0
    }
91
92
19.2k
    if (maxChars < 1) {
93
0
        if (charsWritten != NULL) {
94
0
            *charsWritten = 0;
95
0
        }
96
0
        return URI_ERROR_TOSTRING_TOO_LONG;
97
0
    }
98
19.2k
    maxChars--; /* So we don't have to subtract 1 for '\0' all the time */
99
100
    /* NOTE: The curly brackets here force deeper indent (and that's all) */
101
19.2k
    {
102
19.2k
        {
103
19.2k
            {
104
                /* clang-format off */
105
    /* [01/19] result = "" */
106
                /* clang-format on */
107
19.2k
                if (dest != NULL) {
108
19.2k
                    dest[0] = _UT('\0');
109
19.2k
                } else {
110
0
                    (*charsRequired) = 0;
111
0
                }
112
                /* clang-format off */
113
    /* [02/19] if defined(scheme) then */
114
                /* clang-format on */
115
19.2k
                if (uri->scheme.first != NULL) {
116
                    /* clang-format off */
117
    /* [03/19]     append scheme to result; */
118
                    /* clang-format on */
119
952
                    const int charsToWrite =
120
952
                        (int)(uri->scheme.afterLast - uri->scheme.first);
121
952
                    if (dest != NULL) {
122
952
                        if (written + charsToWrite <= maxChars) {
123
937
                            memcpy(dest + written, uri->scheme.first,
124
937
                                   charsToWrite * sizeof(URI_CHAR));
125
937
                            written += charsToWrite;
126
937
                        } else {
127
15
                            dest[0] = _UT('\0');
128
15
                            if (charsWritten != NULL) {
129
15
                                *charsWritten = 0;
130
15
                            }
131
15
                            return URI_ERROR_TOSTRING_TOO_LONG;
132
15
                        }
133
952
                    } else {
134
0
                        (*charsRequired) += charsToWrite;
135
0
                    }
136
                    /* clang-format off */
137
    /* [04/19]     append ":" to result; */
138
                    /* clang-format on */
139
937
                    if (dest != NULL) {
140
937
                        if (written + 1 <= maxChars) {
141
935
                            memcpy(dest + written, _UT(":"), 1 * sizeof(URI_CHAR));
142
935
                            written += 1;
143
935
                        } else {
144
2
                            dest[0] = _UT('\0');
145
2
                            if (charsWritten != NULL) {
146
2
                                *charsWritten = 0;
147
2
                            }
148
2
                            return URI_ERROR_TOSTRING_TOO_LONG;
149
2
                        }
150
937
                    } else {
151
0
                        (*charsRequired) += 1;
152
0
                    }
153
                    /* clang-format off */
154
    /* [05/19] endif; */
155
                    /* clang-format on */
156
937
                }
157
                /* clang-format off */
158
    /* [06/19] if defined(authority) then */
159
                /* clang-format on */
160
19.2k
                if (URI_FUNC(HasHost)(uri)) {
161
                    /* clang-format off */
162
    /* [07/19]     append "//" to result; */
163
                    /* clang-format on */
164
2.41k
                    if (dest != NULL) {
165
2.41k
                        if (written + 2 <= maxChars) {
166
2.41k
                            memcpy(dest + written, _UT("//"), 2 * sizeof(URI_CHAR));
167
2.41k
                            written += 2;
168
2.41k
                        } else {
169
4
                            dest[0] = _UT('\0');
170
4
                            if (charsWritten != NULL) {
171
4
                                *charsWritten = 0;
172
4
                            }
173
4
                            return URI_ERROR_TOSTRING_TOO_LONG;
174
4
                        }
175
2.41k
                    } else {
176
0
                        (*charsRequired) += 2;
177
0
                    }
178
                    /* clang-format off */
179
    /* [08/19]     append authority to result; */
180
                    /* clang-format on */
181
                    /* UserInfo */
182
2.41k
                    if (uri->userInfo.first != NULL) {
183
676
                        const int charsToWrite =
184
676
                            (int)(uri->userInfo.afterLast - uri->userInfo.first);
185
676
                        if (dest != NULL) {
186
676
                            if (written + charsToWrite <= maxChars) {
187
651
                                memcpy(dest + written, uri->userInfo.first,
188
651
                                       charsToWrite * sizeof(URI_CHAR));
189
651
                                written += charsToWrite;
190
651
                            } else {
191
25
                                dest[0] = _UT('\0');
192
25
                                if (charsWritten != NULL) {
193
25
                                    *charsWritten = 0;
194
25
                                }
195
25
                                return URI_ERROR_TOSTRING_TOO_LONG;
196
25
                            }
197
198
651
                            if (written + 1 <= maxChars) {
199
649
                                memcpy(dest + written, _UT("@"), 1 * sizeof(URI_CHAR));
200
649
                                written += 1;
201
649
                            } else {
202
2
                                dest[0] = _UT('\0');
203
2
                                if (charsWritten != NULL) {
204
2
                                    *charsWritten = 0;
205
2
                                }
206
2
                                return URI_ERROR_TOSTRING_TOO_LONG;
207
2
                            }
208
651
                        } else {
209
0
                            (*charsRequired) += charsToWrite + 1;
210
0
                        }
211
676
                    }
212
213
                    /* Host */
214
2.38k
                    if (uri->hostData.ip4 != NULL) {
215
                        /* IPv4 */
216
95
                        int i = 0;
217
454
                        for (; i < 4; i++) {
218
367
                            const unsigned char value = uri->hostData.ip4->data[i];
219
367
                            const int charsToWrite =
220
367
                                (value > 99) ? 3 : ((value > 9) ? 2 : 1);
221
367
                            if (dest != NULL) {
222
367
                                if (written + charsToWrite <= maxChars) {
223
362
                                    URI_CHAR text[4];
224
362
                                    if (value > 99) {
225
39
                                        text[0] = _UT('0') + (value / 100);
226
39
                                        text[1] = _UT('0') + ((value % 100) / 10);
227
39
                                        text[2] = _UT('0') + (value % 10);
228
323
                                    } else if (value > 9) {
229
71
                                        text[0] = _UT('0') + (value / 10);
230
71
                                        text[1] = _UT('0') + (value % 10);
231
252
                                    } else {
232
252
                                        text[0] = _UT('0') + value;
233
252
                                    }
234
362
                                    text[charsToWrite] = _UT('\0');
235
362
                                    memcpy(dest + written, text,
236
362
                                           charsToWrite * sizeof(URI_CHAR));
237
362
                                    written += charsToWrite;
238
362
                                } else {
239
5
                                    dest[0] = _UT('\0');
240
5
                                    if (charsWritten != NULL) {
241
5
                                        *charsWritten = 0;
242
5
                                    }
243
5
                                    return URI_ERROR_TOSTRING_TOO_LONG;
244
5
                                }
245
362
                                if (i < 3) {
246
275
                                    if (written + 1 <= maxChars) {
247
272
                                        memcpy(dest + written, _UT("."),
248
272
                                               1 * sizeof(URI_CHAR));
249
272
                                        written += 1;
250
272
                                    } else {
251
3
                                        dest[0] = _UT('\0');
252
3
                                        if (charsWritten != NULL) {
253
3
                                            *charsWritten = 0;
254
3
                                        }
255
3
                                        return URI_ERROR_TOSTRING_TOO_LONG;
256
3
                                    }
257
275
                                }
258
362
                            } else {
259
0
                                (*charsRequired) += charsToWrite + ((i == 3) ? 0 : 1);
260
0
                            }
261
367
                        }
262
2.29k
                    } else if (uri->hostData.ip6 != NULL) {
263
                        /* IPv6 */
264
544
                        int i = 0;
265
544
                        if (dest != NULL) {
266
544
                            if (written + 1 <= maxChars) {
267
542
                                memcpy(dest + written, _UT("["), 1 * sizeof(URI_CHAR));
268
542
                                written += 1;
269
542
                            } else {
270
2
                                dest[0] = _UT('\0');
271
2
                                if (charsWritten != NULL) {
272
2
                                    *charsWritten = 0;
273
2
                                }
274
2
                                return URI_ERROR_TOSTRING_TOO_LONG;
275
2
                            }
276
544
                        } else {
277
0
                            (*charsRequired) += 1;
278
0
                        }
279
280
9.01k
                        for (; i < 16; i++) {
281
8.48k
                            const unsigned char value = uri->hostData.ip6->data[i];
282
8.48k
                            if (dest != NULL) {
283
8.48k
                                if (written + 2 <= maxChars) {
284
8.47k
                                    URI_CHAR text[3];
285
8.47k
                                    text[0] =
286
8.47k
                                        URI_FUNC(HexToLetterEx)(value / 16, URI_FALSE);
287
8.47k
                                    text[1] =
288
8.47k
                                        URI_FUNC(HexToLetterEx)(value % 16, URI_FALSE);
289
8.47k
                                    text[2] = _UT('\0');
290
8.47k
                                    memcpy(dest + written, text, 2 * sizeof(URI_CHAR));
291
8.47k
                                    written += 2;
292
8.47k
                                } else {
293
12
                                    dest[0] = _UT('\0');
294
12
                                    if (charsWritten != NULL) {
295
12
                                        *charsWritten = 0;
296
12
                                    }
297
12
                                    return URI_ERROR_TOSTRING_TOO_LONG;
298
12
                                }
299
8.48k
                            } else {
300
0
                                (*charsRequired) += 2;
301
0
                            }
302
8.47k
                            if (((i & 1) == 1) && (i < 15)) {
303
3.70k
                                if (dest != NULL) {
304
3.70k
                                    if (written + 1 <= maxChars) {
305
3.70k
                                        memcpy(dest + written, _UT(":"),
306
3.70k
                                               1 * sizeof(URI_CHAR));
307
3.70k
                                        written += 1;
308
3.70k
                                    } else {
309
5
                                        dest[0] = _UT('\0');
310
5
                                        if (charsWritten != NULL) {
311
5
                                            *charsWritten = 0;
312
5
                                        }
313
5
                                        return URI_ERROR_TOSTRING_TOO_LONG;
314
5
                                    }
315
3.70k
                                } else {
316
0
                                    (*charsRequired) += 1;
317
0
                                }
318
3.70k
                            }
319
8.47k
                        }
320
321
525
                        if (dest != NULL) {
322
525
                            if (written + 1 <= maxChars) {
323
523
                                memcpy(dest + written, _UT("]"), 1 * sizeof(URI_CHAR));
324
523
                                written += 1;
325
523
                            } else {
326
2
                                dest[0] = _UT('\0');
327
2
                                if (charsWritten != NULL) {
328
2
                                    *charsWritten = 0;
329
2
                                }
330
2
                                return URI_ERROR_TOSTRING_TOO_LONG;
331
2
                            }
332
525
                        } else {
333
0
                            (*charsRequired) += 1;
334
0
                        }
335
1.74k
                    } else if (uri->hostData.ipFuture.first != NULL) {
336
                        /* IPvFuture */
337
324
                        const int charsToWrite = (int)(uri->hostData.ipFuture.afterLast
338
324
                                                       - uri->hostData.ipFuture.first);
339
324
                        if (dest != NULL) {
340
324
                            if (written + 1 <= maxChars) {
341
322
                                memcpy(dest + written, _UT("["), 1 * sizeof(URI_CHAR));
342
322
                                written += 1;
343
322
                            } else {
344
2
                                dest[0] = _UT('\0');
345
2
                                if (charsWritten != NULL) {
346
2
                                    *charsWritten = 0;
347
2
                                }
348
2
                                return URI_ERROR_TOSTRING_TOO_LONG;
349
2
                            }
350
351
322
                            if (written + charsToWrite <= maxChars) {
352
270
                                memcpy(dest + written, uri->hostData.ipFuture.first,
353
270
                                       charsToWrite * sizeof(URI_CHAR));
354
270
                                written += charsToWrite;
355
270
                            } else {
356
52
                                dest[0] = _UT('\0');
357
52
                                if (charsWritten != NULL) {
358
52
                                    *charsWritten = 0;
359
52
                                }
360
52
                                return URI_ERROR_TOSTRING_TOO_LONG;
361
52
                            }
362
363
270
                            if (written + 1 <= maxChars) {
364
268
                                memcpy(dest + written, _UT("]"), 1 * sizeof(URI_CHAR));
365
268
                                written += 1;
366
268
                            } else {
367
2
                                dest[0] = _UT('\0');
368
2
                                if (charsWritten != NULL) {
369
2
                                    *charsWritten = 0;
370
2
                                }
371
2
                                return URI_ERROR_TOSTRING_TOO_LONG;
372
2
                            }
373
270
                        } else {
374
0
                            (*charsRequired) += 1 + charsToWrite + 1;
375
0
                        }
376
1.42k
                    } else if (uri->hostText.first != NULL) {
377
                        /* Regname */
378
1.42k
                        const int charsToWrite =
379
1.42k
                            (int)(uri->hostText.afterLast - uri->hostText.first);
380
1.42k
                        if (dest != NULL) {
381
1.42k
                            if (written + charsToWrite <= maxChars) {
382
1.37k
                                memcpy(dest + written, uri->hostText.first,
383
1.37k
                                       charsToWrite * sizeof(URI_CHAR));
384
1.37k
                                written += charsToWrite;
385
1.37k
                            } else {
386
48
                                dest[0] = _UT('\0');
387
48
                                if (charsWritten != NULL) {
388
48
                                    *charsWritten = 0;
389
48
                                }
390
48
                                return URI_ERROR_TOSTRING_TOO_LONG;
391
48
                            }
392
1.42k
                        } else {
393
0
                            (*charsRequired) += charsToWrite;
394
0
                        }
395
1.42k
                    }
396
397
                    /* Port */
398
2.25k
                    if (uri->portText.first != NULL) {
399
233
                        const int charsToWrite =
400
233
                            (int)(uri->portText.afterLast - uri->portText.first);
401
233
                        if (dest != NULL) {
402
                            /* Leading ':' */
403
233
                            if (written + 1 <= maxChars) {
404
231
                                memcpy(dest + written, _UT(":"), 1 * sizeof(URI_CHAR));
405
231
                                written += 1;
406
231
                            } else {
407
2
                                dest[0] = _UT('\0');
408
2
                                if (charsWritten != NULL) {
409
2
                                    *charsWritten = 0;
410
2
                                }
411
2
                                return URI_ERROR_TOSTRING_TOO_LONG;
412
2
                            }
413
414
                            /* Port number */
415
231
                            if (written + charsToWrite <= maxChars) {
416
200
                                memcpy(dest + written, uri->portText.first,
417
200
                                       charsToWrite * sizeof(URI_CHAR));
418
200
                                written += charsToWrite;
419
200
                            } else {
420
31
                                dest[0] = _UT('\0');
421
31
                                if (charsWritten != NULL) {
422
31
                                    *charsWritten = 0;
423
31
                                }
424
31
                                return URI_ERROR_TOSTRING_TOO_LONG;
425
31
                            }
426
231
                        } else {
427
0
                            (*charsRequired) += 1 + charsToWrite;
428
0
                        }
429
233
                    }
430
                    /* clang-format off */
431
    /* [09/19] endif; */
432
                    /* clang-format on */
433
2.25k
                }
434
                /* clang-format off */
435
    /* [10/19] append path to result; */
436
                /* clang-format on */
437
                /* Slash needed here? */
438
19.0k
                if (uri->absolutePath
439
18.4k
                    || ((uri->pathHead != NULL) && URI_FUNC(HasHost)(uri))) {
440
855
                    if (dest != NULL) {
441
855
                        if (written + 1 <= maxChars) {
442
852
                            memcpy(dest + written, _UT("/"), 1 * sizeof(URI_CHAR));
443
852
                            written += 1;
444
852
                        } else {
445
3
                            dest[0] = _UT('\0');
446
3
                            if (charsWritten != NULL) {
447
3
                                *charsWritten = 0;
448
3
                            }
449
3
                            return URI_ERROR_TOSTRING_TOO_LONG;
450
3
                        }
451
855
                    } else {
452
0
                        (*charsRequired) += 1;
453
0
                    }
454
855
                }
455
456
19.0k
                if (uri->pathHead != NULL) {
457
4.01k
                    URI_TYPE(PathSegment) * walker = uri->pathHead;
458
35.6k
                    do {
459
35.6k
                        const int charsToWrite =
460
35.6k
                            (int)(walker->text.afterLast - walker->text.first);
461
35.6k
                        if (dest != NULL) {
462
35.6k
                            if (written + charsToWrite <= maxChars) {
463
35.5k
                                memcpy(dest + written, walker->text.first,
464
35.5k
                                       charsToWrite * sizeof(URI_CHAR));
465
35.5k
                                written += charsToWrite;
466
35.5k
                            } else {
467
101
                                dest[0] = _UT('\0');
468
101
                                if (charsWritten != NULL) {
469
101
                                    *charsWritten = 0;
470
101
                                }
471
101
                                return URI_ERROR_TOSTRING_TOO_LONG;
472
101
                            }
473
35.6k
                        } else {
474
0
                            (*charsRequired) += charsToWrite;
475
0
                        }
476
477
                        /* Not last segment -> append slash */
478
35.5k
                        if (walker->next != NULL) {
479
31.6k
                            if (dest != NULL) {
480
31.6k
                                if (written + 1 <= maxChars) {
481
31.6k
                                    memcpy(dest + written, _UT("/"),
482
31.6k
                                           1 * sizeof(URI_CHAR));
483
31.6k
                                    written += 1;
484
31.6k
                                } else {
485
2
                                    dest[0] = _UT('\0');
486
2
                                    if (charsWritten != NULL) {
487
2
                                        *charsWritten = 0;
488
2
                                    }
489
2
                                    return URI_ERROR_TOSTRING_TOO_LONG;
490
2
                                }
491
31.6k
                            } else {
492
0
                                (*charsRequired) += 1;
493
0
                            }
494
31.6k
                        }
495
496
35.5k
                        walker = walker->next;
497
35.5k
                    } while (walker != NULL);
498
4.01k
                }
499
                /* clang-format off */
500
    /* [11/19] if defined(query) then */
501
                /* clang-format on */
502
18.9k
                if (uri->query.first != NULL) {
503
                    /* clang-format off */
504
    /* [12/19]     append "?" to result; */
505
                    /* clang-format on */
506
386
                    if (dest != NULL) {
507
386
                        if (written + 1 <= maxChars) {
508
384
                            memcpy(dest + written, _UT("?"), 1 * sizeof(URI_CHAR));
509
384
                            written += 1;
510
384
                        } else {
511
2
                            dest[0] = _UT('\0');
512
2
                            if (charsWritten != NULL) {
513
2
                                *charsWritten = 0;
514
2
                            }
515
2
                            return URI_ERROR_TOSTRING_TOO_LONG;
516
2
                        }
517
386
                    } else {
518
0
                        (*charsRequired) += 1;
519
0
                    }
520
                    /* clang-format off */
521
    /* [13/19]     append query to result; */
522
                    /* clang-format on */
523
384
                    const int charsToWrite =
524
384
                        (int)(uri->query.afterLast - uri->query.first);
525
384
                    if (dest != NULL) {
526
384
                        if (written + charsToWrite <= maxChars) {
527
330
                            memcpy(dest + written, uri->query.first,
528
330
                                   charsToWrite * sizeof(URI_CHAR));
529
330
                            written += charsToWrite;
530
330
                        } else {
531
54
                            dest[0] = _UT('\0');
532
54
                            if (charsWritten != NULL) {
533
54
                                *charsWritten = 0;
534
54
                            }
535
54
                            return URI_ERROR_TOSTRING_TOO_LONG;
536
54
                        }
537
384
                    } else {
538
0
                        (*charsRequired) += charsToWrite;
539
0
                    }
540
                    /* clang-format off */
541
    /* [14/19] endif; */
542
                    /* clang-format on */
543
384
                }
544
                /* clang-format off */
545
    /* [15/19] if defined(fragment) then */
546
                /* clang-format on */
547
18.8k
                if (uri->fragment.first != NULL) {
548
                    /* clang-format off */
549
    /* [16/19]     append "#" to result; */
550
                    /* clang-format on */
551
295
                    if (dest != NULL) {
552
295
                        if (written + 1 <= maxChars) {
553
290
                            memcpy(dest + written, _UT("#"), 1 * sizeof(URI_CHAR));
554
290
                            written += 1;
555
290
                        } else {
556
5
                            dest[0] = _UT('\0');
557
5
                            if (charsWritten != NULL) {
558
5
                                *charsWritten = 0;
559
5
                            }
560
5
                            return URI_ERROR_TOSTRING_TOO_LONG;
561
5
                        }
562
295
                    } else {
563
0
                        (*charsRequired) += 1;
564
0
                    }
565
                    /* clang-format off */
566
    /* [17/19]     append fragment to result; */
567
                    /* clang-format on */
568
290
                    const int charsToWrite =
569
290
                        (int)(uri->fragment.afterLast - uri->fragment.first);
570
290
                    if (dest != NULL) {
571
290
                        if (written + charsToWrite <= maxChars) {
572
238
                            memcpy(dest + written, uri->fragment.first,
573
238
                                   charsToWrite * sizeof(URI_CHAR));
574
238
                            written += charsToWrite;
575
238
                        } else {
576
52
                            dest[0] = _UT('\0');
577
52
                            if (charsWritten != NULL) {
578
52
                                *charsWritten = 0;
579
52
                            }
580
52
                            return URI_ERROR_TOSTRING_TOO_LONG;
581
52
                        }
582
290
                    } else {
583
0
                        (*charsRequired) += charsToWrite;
584
0
                    }
585
                    /* clang-format off */
586
    /* [18/19] endif; */
587
                    /* clang-format on */
588
290
                }
589
                /* clang-format off */
590
    /* [19/19] return result; */
591
                /* clang-format on */
592
18.8k
                if (dest != NULL) {
593
18.8k
                    dest[written++] = _UT('\0');
594
18.8k
                    if (charsWritten != NULL) {
595
18.8k
                        *charsWritten = written;
596
18.8k
                    }
597
18.8k
                }
598
18.8k
                return URI_SUCCESS;
599
18.8k
            }
600
18.8k
        }
601
18.8k
    }
602
18.8k
}
UriRecompose.c:uriToStringEngineA
Line
Count
Source
83
9.24k
                                               int * charsRequired) {
84
9.24k
    int written = 0;
85
9.24k
    if ((uri == NULL) || ((dest == NULL) && (charsRequired == NULL))) {
86
0
        if (charsWritten != NULL) {
87
0
            *charsWritten = 0;
88
0
        }
89
0
        return URI_ERROR_NULL;
90
0
    }
91
92
9.24k
    if (maxChars < 1) {
93
0
        if (charsWritten != NULL) {
94
0
            *charsWritten = 0;
95
0
        }
96
0
        return URI_ERROR_TOSTRING_TOO_LONG;
97
0
    }
98
9.24k
    maxChars--; /* So we don't have to subtract 1 for '\0' all the time */
99
100
    /* NOTE: The curly brackets here force deeper indent (and that's all) */
101
9.24k
    {
102
9.24k
        {
103
9.24k
            {
104
                /* clang-format off */
105
    /* [01/19] result = "" */
106
                /* clang-format on */
107
9.24k
                if (dest != NULL) {
108
9.24k
                    dest[0] = _UT('\0');
109
9.24k
                } else {
110
0
                    (*charsRequired) = 0;
111
0
                }
112
                /* clang-format off */
113
    /* [02/19] if defined(scheme) then */
114
                /* clang-format on */
115
9.24k
                if (uri->scheme.first != NULL) {
116
                    /* clang-format off */
117
    /* [03/19]     append scheme to result; */
118
                    /* clang-format on */
119
512
                    const int charsToWrite =
120
512
                        (int)(uri->scheme.afterLast - uri->scheme.first);
121
512
                    if (dest != NULL) {
122
512
                        if (written + charsToWrite <= maxChars) {
123
506
                            memcpy(dest + written, uri->scheme.first,
124
506
                                   charsToWrite * sizeof(URI_CHAR));
125
506
                            written += charsToWrite;
126
506
                        } else {
127
6
                            dest[0] = _UT('\0');
128
6
                            if (charsWritten != NULL) {
129
6
                                *charsWritten = 0;
130
6
                            }
131
6
                            return URI_ERROR_TOSTRING_TOO_LONG;
132
6
                        }
133
512
                    } else {
134
0
                        (*charsRequired) += charsToWrite;
135
0
                    }
136
                    /* clang-format off */
137
    /* [04/19]     append ":" to result; */
138
                    /* clang-format on */
139
506
                    if (dest != NULL) {
140
506
                        if (written + 1 <= maxChars) {
141
505
                            memcpy(dest + written, _UT(":"), 1 * sizeof(URI_CHAR));
142
505
                            written += 1;
143
505
                        } else {
144
1
                            dest[0] = _UT('\0');
145
1
                            if (charsWritten != NULL) {
146
1
                                *charsWritten = 0;
147
1
                            }
148
1
                            return URI_ERROR_TOSTRING_TOO_LONG;
149
1
                        }
150
506
                    } else {
151
0
                        (*charsRequired) += 1;
152
0
                    }
153
                    /* clang-format off */
154
    /* [05/19] endif; */
155
                    /* clang-format on */
156
506
                }
157
                /* clang-format off */
158
    /* [06/19] if defined(authority) then */
159
                /* clang-format on */
160
9.23k
                if (URI_FUNC(HasHost)(uri)) {
161
                    /* clang-format off */
162
    /* [07/19]     append "//" to result; */
163
                    /* clang-format on */
164
1.40k
                    if (dest != NULL) {
165
1.40k
                        if (written + 2 <= maxChars) {
166
1.40k
                            memcpy(dest + written, _UT("//"), 2 * sizeof(URI_CHAR));
167
1.40k
                            written += 2;
168
1.40k
                        } else {
169
2
                            dest[0] = _UT('\0');
170
2
                            if (charsWritten != NULL) {
171
2
                                *charsWritten = 0;
172
2
                            }
173
2
                            return URI_ERROR_TOSTRING_TOO_LONG;
174
2
                        }
175
1.40k
                    } else {
176
0
                        (*charsRequired) += 2;
177
0
                    }
178
                    /* clang-format off */
179
    /* [08/19]     append authority to result; */
180
                    /* clang-format on */
181
                    /* UserInfo */
182
1.40k
                    if (uri->userInfo.first != NULL) {
183
424
                        const int charsToWrite =
184
424
                            (int)(uri->userInfo.afterLast - uri->userInfo.first);
185
424
                        if (dest != NULL) {
186
424
                            if (written + charsToWrite <= maxChars) {
187
404
                                memcpy(dest + written, uri->userInfo.first,
188
404
                                       charsToWrite * sizeof(URI_CHAR));
189
404
                                written += charsToWrite;
190
404
                            } else {
191
20
                                dest[0] = _UT('\0');
192
20
                                if (charsWritten != NULL) {
193
20
                                    *charsWritten = 0;
194
20
                                }
195
20
                                return URI_ERROR_TOSTRING_TOO_LONG;
196
20
                            }
197
198
404
                            if (written + 1 <= maxChars) {
199
403
                                memcpy(dest + written, _UT("@"), 1 * sizeof(URI_CHAR));
200
403
                                written += 1;
201
403
                            } else {
202
1
                                dest[0] = _UT('\0');
203
1
                                if (charsWritten != NULL) {
204
1
                                    *charsWritten = 0;
205
1
                                }
206
1
                                return URI_ERROR_TOSTRING_TOO_LONG;
207
1
                            }
208
404
                        } else {
209
0
                            (*charsRequired) += charsToWrite + 1;
210
0
                        }
211
424
                    }
212
213
                    /* Host */
214
1.38k
                    if (uri->hostData.ip4 != NULL) {
215
                        /* IPv4 */
216
42
                        int i = 0;
217
199
                        for (; i < 4; i++) {
218
161
                            const unsigned char value = uri->hostData.ip4->data[i];
219
161
                            const int charsToWrite =
220
161
                                (value > 99) ? 3 : ((value > 9) ? 2 : 1);
221
161
                            if (dest != NULL) {
222
161
                                if (written + charsToWrite <= maxChars) {
223
159
                                    URI_CHAR text[4];
224
159
                                    if (value > 99) {
225
17
                                        text[0] = _UT('0') + (value / 100);
226
17
                                        text[1] = _UT('0') + ((value % 100) / 10);
227
17
                                        text[2] = _UT('0') + (value % 10);
228
142
                                    } else if (value > 9) {
229
35
                                        text[0] = _UT('0') + (value / 10);
230
35
                                        text[1] = _UT('0') + (value % 10);
231
107
                                    } else {
232
107
                                        text[0] = _UT('0') + value;
233
107
                                    }
234
159
                                    text[charsToWrite] = _UT('\0');
235
159
                                    memcpy(dest + written, text,
236
159
                                           charsToWrite * sizeof(URI_CHAR));
237
159
                                    written += charsToWrite;
238
159
                                } else {
239
2
                                    dest[0] = _UT('\0');
240
2
                                    if (charsWritten != NULL) {
241
2
                                        *charsWritten = 0;
242
2
                                    }
243
2
                                    return URI_ERROR_TOSTRING_TOO_LONG;
244
2
                                }
245
159
                                if (i < 3) {
246
121
                                    if (written + 1 <= maxChars) {
247
119
                                        memcpy(dest + written, _UT("."),
248
119
                                               1 * sizeof(URI_CHAR));
249
119
                                        written += 1;
250
119
                                    } else {
251
2
                                        dest[0] = _UT('\0');
252
2
                                        if (charsWritten != NULL) {
253
2
                                            *charsWritten = 0;
254
2
                                        }
255
2
                                        return URI_ERROR_TOSTRING_TOO_LONG;
256
2
                                    }
257
121
                                }
258
159
                            } else {
259
0
                                (*charsRequired) += charsToWrite + ((i == 3) ? 0 : 1);
260
0
                            }
261
161
                        }
262
1.33k
                    } else if (uri->hostData.ip6 != NULL) {
263
                        /* IPv6 */
264
313
                        int i = 0;
265
313
                        if (dest != NULL) {
266
313
                            if (written + 1 <= maxChars) {
267
312
                                memcpy(dest + written, _UT("["), 1 * sizeof(URI_CHAR));
268
312
                                written += 1;
269
312
                            } else {
270
1
                                dest[0] = _UT('\0');
271
1
                                if (charsWritten != NULL) {
272
1
                                    *charsWritten = 0;
273
1
                                }
274
1
                                return URI_ERROR_TOSTRING_TOO_LONG;
275
1
                            }
276
313
                        } else {
277
0
                            (*charsRequired) += 1;
278
0
                        }
279
280
5.21k
                        for (; i < 16; i++) {
281
4.91k
                            const unsigned char value = uri->hostData.ip6->data[i];
282
4.91k
                            if (dest != NULL) {
283
4.91k
                                if (written + 2 <= maxChars) {
284
4.90k
                                    URI_CHAR text[3];
285
4.90k
                                    text[0] =
286
4.90k
                                        URI_FUNC(HexToLetterEx)(value / 16, URI_FALSE);
287
4.90k
                                    text[1] =
288
4.90k
                                        URI_FUNC(HexToLetterEx)(value % 16, URI_FALSE);
289
4.90k
                                    text[2] = _UT('\0');
290
4.90k
                                    memcpy(dest + written, text, 2 * sizeof(URI_CHAR));
291
4.90k
                                    written += 2;
292
4.90k
                                } else {
293
5
                                    dest[0] = _UT('\0');
294
5
                                    if (charsWritten != NULL) {
295
5
                                        *charsWritten = 0;
296
5
                                    }
297
5
                                    return URI_ERROR_TOSTRING_TOO_LONG;
298
5
                                }
299
4.91k
                            } else {
300
0
                                (*charsRequired) += 2;
301
0
                            }
302
4.90k
                            if (((i & 1) == 1) && (i < 15)) {
303
2.14k
                                if (dest != NULL) {
304
2.14k
                                    if (written + 1 <= maxChars) {
305
2.14k
                                        memcpy(dest + written, _UT(":"),
306
2.14k
                                               1 * sizeof(URI_CHAR));
307
2.14k
                                        written += 1;
308
2.14k
                                    } else {
309
2
                                        dest[0] = _UT('\0');
310
2
                                        if (charsWritten != NULL) {
311
2
                                            *charsWritten = 0;
312
2
                                        }
313
2
                                        return URI_ERROR_TOSTRING_TOO_LONG;
314
2
                                    }
315
2.14k
                                } else {
316
0
                                    (*charsRequired) += 1;
317
0
                                }
318
2.14k
                            }
319
4.90k
                        }
320
321
305
                        if (dest != NULL) {
322
305
                            if (written + 1 <= maxChars) {
323
304
                                memcpy(dest + written, _UT("]"), 1 * sizeof(URI_CHAR));
324
304
                                written += 1;
325
304
                            } else {
326
1
                                dest[0] = _UT('\0');
327
1
                                if (charsWritten != NULL) {
328
1
                                    *charsWritten = 0;
329
1
                                }
330
1
                                return URI_ERROR_TOSTRING_TOO_LONG;
331
1
                            }
332
305
                        } else {
333
0
                            (*charsRequired) += 1;
334
0
                        }
335
1.02k
                    } else if (uri->hostData.ipFuture.first != NULL) {
336
                        /* IPvFuture */
337
157
                        const int charsToWrite = (int)(uri->hostData.ipFuture.afterLast
338
157
                                                       - uri->hostData.ipFuture.first);
339
157
                        if (dest != NULL) {
340
157
                            if (written + 1 <= maxChars) {
341
156
                                memcpy(dest + written, _UT("["), 1 * sizeof(URI_CHAR));
342
156
                                written += 1;
343
156
                            } else {
344
1
                                dest[0] = _UT('\0');
345
1
                                if (charsWritten != NULL) {
346
1
                                    *charsWritten = 0;
347
1
                                }
348
1
                                return URI_ERROR_TOSTRING_TOO_LONG;
349
1
                            }
350
351
156
                            if (written + charsToWrite <= maxChars) {
352
126
                                memcpy(dest + written, uri->hostData.ipFuture.first,
353
126
                                       charsToWrite * sizeof(URI_CHAR));
354
126
                                written += charsToWrite;
355
126
                            } else {
356
30
                                dest[0] = _UT('\0');
357
30
                                if (charsWritten != NULL) {
358
30
                                    *charsWritten = 0;
359
30
                                }
360
30
                                return URI_ERROR_TOSTRING_TOO_LONG;
361
30
                            }
362
363
126
                            if (written + 1 <= maxChars) {
364
125
                                memcpy(dest + written, _UT("]"), 1 * sizeof(URI_CHAR));
365
125
                                written += 1;
366
125
                            } else {
367
1
                                dest[0] = _UT('\0');
368
1
                                if (charsWritten != NULL) {
369
1
                                    *charsWritten = 0;
370
1
                                }
371
1
                                return URI_ERROR_TOSTRING_TOO_LONG;
372
1
                            }
373
126
                        } else {
374
0
                            (*charsRequired) += 1 + charsToWrite + 1;
375
0
                        }
376
869
                    } else if (uri->hostText.first != NULL) {
377
                        /* Regname */
378
869
                        const int charsToWrite =
379
869
                            (int)(uri->hostText.afterLast - uri->hostText.first);
380
869
                        if (dest != NULL) {
381
869
                            if (written + charsToWrite <= maxChars) {
382
844
                                memcpy(dest + written, uri->hostText.first,
383
844
                                       charsToWrite * sizeof(URI_CHAR));
384
844
                                written += charsToWrite;
385
844
                            } else {
386
25
                                dest[0] = _UT('\0');
387
25
                                if (charsWritten != NULL) {
388
25
                                    *charsWritten = 0;
389
25
                                }
390
25
                                return URI_ERROR_TOSTRING_TOO_LONG;
391
25
                            }
392
869
                        } else {
393
0
                            (*charsRequired) += charsToWrite;
394
0
                        }
395
869
                    }
396
397
                    /* Port */
398
1.31k
                    if (uri->portText.first != NULL) {
399
161
                        const int charsToWrite =
400
161
                            (int)(uri->portText.afterLast - uri->portText.first);
401
161
                        if (dest != NULL) {
402
                            /* Leading ':' */
403
161
                            if (written + 1 <= maxChars) {
404
160
                                memcpy(dest + written, _UT(":"), 1 * sizeof(URI_CHAR));
405
160
                                written += 1;
406
160
                            } else {
407
1
                                dest[0] = _UT('\0');
408
1
                                if (charsWritten != NULL) {
409
1
                                    *charsWritten = 0;
410
1
                                }
411
1
                                return URI_ERROR_TOSTRING_TOO_LONG;
412
1
                            }
413
414
                            /* Port number */
415
160
                            if (written + charsToWrite <= maxChars) {
416
130
                                memcpy(dest + written, uri->portText.first,
417
130
                                       charsToWrite * sizeof(URI_CHAR));
418
130
                                written += charsToWrite;
419
130
                            } else {
420
30
                                dest[0] = _UT('\0');
421
30
                                if (charsWritten != NULL) {
422
30
                                    *charsWritten = 0;
423
30
                                }
424
30
                                return URI_ERROR_TOSTRING_TOO_LONG;
425
30
                            }
426
160
                        } else {
427
0
                            (*charsRequired) += 1 + charsToWrite;
428
0
                        }
429
161
                    }
430
                    /* clang-format off */
431
    /* [09/19] endif; */
432
                    /* clang-format on */
433
1.31k
                }
434
                /* clang-format off */
435
    /* [10/19] append path to result; */
436
                /* clang-format on */
437
                /* Slash needed here? */
438
9.11k
                if (uri->absolutePath
439
8.76k
                    || ((uri->pathHead != NULL) && URI_FUNC(HasHost)(uri))) {
440
488
                    if (dest != NULL) {
441
488
                        if (written + 1 <= maxChars) {
442
486
                            memcpy(dest + written, _UT("/"), 1 * sizeof(URI_CHAR));
443
486
                            written += 1;
444
486
                        } else {
445
2
                            dest[0] = _UT('\0');
446
2
                            if (charsWritten != NULL) {
447
2
                                *charsWritten = 0;
448
2
                            }
449
2
                            return URI_ERROR_TOSTRING_TOO_LONG;
450
2
                        }
451
488
                    } else {
452
0
                        (*charsRequired) += 1;
453
0
                    }
454
488
                }
455
456
9.11k
                if (uri->pathHead != NULL) {
457
2.53k
                    URI_TYPE(PathSegment) * walker = uri->pathHead;
458
19.5k
                    do {
459
19.5k
                        const int charsToWrite =
460
19.5k
                            (int)(walker->text.afterLast - walker->text.first);
461
19.5k
                        if (dest != NULL) {
462
19.5k
                            if (written + charsToWrite <= maxChars) {
463
19.4k
                                memcpy(dest + written, walker->text.first,
464
19.4k
                                       charsToWrite * sizeof(URI_CHAR));
465
19.4k
                                written += charsToWrite;
466
19.4k
                            } else {
467
65
                                dest[0] = _UT('\0');
468
65
                                if (charsWritten != NULL) {
469
65
                                    *charsWritten = 0;
470
65
                                }
471
65
                                return URI_ERROR_TOSTRING_TOO_LONG;
472
65
                            }
473
19.5k
                        } else {
474
0
                            (*charsRequired) += charsToWrite;
475
0
                        }
476
477
                        /* Not last segment -> append slash */
478
19.4k
                        if (walker->next != NULL) {
479
17.0k
                            if (dest != NULL) {
480
17.0k
                                if (written + 1 <= maxChars) {
481
17.0k
                                    memcpy(dest + written, _UT("/"),
482
17.0k
                                           1 * sizeof(URI_CHAR));
483
17.0k
                                    written += 1;
484
17.0k
                                } else {
485
1
                                    dest[0] = _UT('\0');
486
1
                                    if (charsWritten != NULL) {
487
1
                                        *charsWritten = 0;
488
1
                                    }
489
1
                                    return URI_ERROR_TOSTRING_TOO_LONG;
490
1
                                }
491
17.0k
                            } else {
492
0
                                (*charsRequired) += 1;
493
0
                            }
494
17.0k
                        }
495
496
19.4k
                        walker = walker->next;
497
19.4k
                    } while (walker != NULL);
498
2.53k
                }
499
                /* clang-format off */
500
    /* [11/19] if defined(query) then */
501
                /* clang-format on */
502
9.04k
                if (uri->query.first != NULL) {
503
                    /* clang-format off */
504
    /* [12/19]     append "?" to result; */
505
                    /* clang-format on */
506
237
                    if (dest != NULL) {
507
237
                        if (written + 1 <= maxChars) {
508
236
                            memcpy(dest + written, _UT("?"), 1 * sizeof(URI_CHAR));
509
236
                            written += 1;
510
236
                        } else {
511
1
                            dest[0] = _UT('\0');
512
1
                            if (charsWritten != NULL) {
513
1
                                *charsWritten = 0;
514
1
                            }
515
1
                            return URI_ERROR_TOSTRING_TOO_LONG;
516
1
                        }
517
237
                    } else {
518
0
                        (*charsRequired) += 1;
519
0
                    }
520
                    /* clang-format off */
521
    /* [13/19]     append query to result; */
522
                    /* clang-format on */
523
236
                    const int charsToWrite =
524
236
                        (int)(uri->query.afterLast - uri->query.first);
525
236
                    if (dest != NULL) {
526
236
                        if (written + charsToWrite <= maxChars) {
527
204
                            memcpy(dest + written, uri->query.first,
528
204
                                   charsToWrite * sizeof(URI_CHAR));
529
204
                            written += charsToWrite;
530
204
                        } else {
531
32
                            dest[0] = _UT('\0');
532
32
                            if (charsWritten != NULL) {
533
32
                                *charsWritten = 0;
534
32
                            }
535
32
                            return URI_ERROR_TOSTRING_TOO_LONG;
536
32
                        }
537
236
                    } else {
538
0
                        (*charsRequired) += charsToWrite;
539
0
                    }
540
                    /* clang-format off */
541
    /* [14/19] endif; */
542
                    /* clang-format on */
543
236
                }
544
                /* clang-format off */
545
    /* [15/19] if defined(fragment) then */
546
                /* clang-format on */
547
9.01k
                if (uri->fragment.first != NULL) {
548
                    /* clang-format off */
549
    /* [16/19]     append "#" to result; */
550
                    /* clang-format on */
551
173
                    if (dest != NULL) {
552
173
                        if (written + 1 <= maxChars) {
553
172
                            memcpy(dest + written, _UT("#"), 1 * sizeof(URI_CHAR));
554
172
                            written += 1;
555
172
                        } else {
556
1
                            dest[0] = _UT('\0');
557
1
                            if (charsWritten != NULL) {
558
1
                                *charsWritten = 0;
559
1
                            }
560
1
                            return URI_ERROR_TOSTRING_TOO_LONG;
561
1
                        }
562
173
                    } else {
563
0
                        (*charsRequired) += 1;
564
0
                    }
565
                    /* clang-format off */
566
    /* [17/19]     append fragment to result; */
567
                    /* clang-format on */
568
172
                    const int charsToWrite =
569
172
                        (int)(uri->fragment.afterLast - uri->fragment.first);
570
172
                    if (dest != NULL) {
571
172
                        if (written + charsToWrite <= maxChars) {
572
140
                            memcpy(dest + written, uri->fragment.first,
573
140
                                   charsToWrite * sizeof(URI_CHAR));
574
140
                            written += charsToWrite;
575
140
                        } else {
576
32
                            dest[0] = _UT('\0');
577
32
                            if (charsWritten != NULL) {
578
32
                                *charsWritten = 0;
579
32
                            }
580
32
                            return URI_ERROR_TOSTRING_TOO_LONG;
581
32
                        }
582
172
                    } else {
583
0
                        (*charsRequired) += charsToWrite;
584
0
                    }
585
                    /* clang-format off */
586
    /* [18/19] endif; */
587
                    /* clang-format on */
588
172
                }
589
                /* clang-format off */
590
    /* [19/19] return result; */
591
                /* clang-format on */
592
8.97k
                if (dest != NULL) {
593
8.97k
                    dest[written++] = _UT('\0');
594
8.97k
                    if (charsWritten != NULL) {
595
8.97k
                        *charsWritten = written;
596
8.97k
                    }
597
8.97k
                }
598
8.97k
                return URI_SUCCESS;
599
9.01k
            }
600
9.01k
        }
601
9.01k
    }
602
9.01k
}
UriRecompose.c:uriToStringEngineW
Line
Count
Source
83
10.0k
                                               int * charsRequired) {
84
10.0k
    int written = 0;
85
10.0k
    if ((uri == NULL) || ((dest == NULL) && (charsRequired == NULL))) {
86
0
        if (charsWritten != NULL) {
87
0
            *charsWritten = 0;
88
0
        }
89
0
        return URI_ERROR_NULL;
90
0
    }
91
92
10.0k
    if (maxChars < 1) {
93
0
        if (charsWritten != NULL) {
94
0
            *charsWritten = 0;
95
0
        }
96
0
        return URI_ERROR_TOSTRING_TOO_LONG;
97
0
    }
98
10.0k
    maxChars--; /* So we don't have to subtract 1 for '\0' all the time */
99
100
    /* NOTE: The curly brackets here force deeper indent (and that's all) */
101
10.0k
    {
102
10.0k
        {
103
10.0k
            {
104
                /* clang-format off */
105
    /* [01/19] result = "" */
106
                /* clang-format on */
107
10.0k
                if (dest != NULL) {
108
10.0k
                    dest[0] = _UT('\0');
109
10.0k
                } else {
110
0
                    (*charsRequired) = 0;
111
0
                }
112
                /* clang-format off */
113
    /* [02/19] if defined(scheme) then */
114
                /* clang-format on */
115
10.0k
                if (uri->scheme.first != NULL) {
116
                    /* clang-format off */
117
    /* [03/19]     append scheme to result; */
118
                    /* clang-format on */
119
440
                    const int charsToWrite =
120
440
                        (int)(uri->scheme.afterLast - uri->scheme.first);
121
440
                    if (dest != NULL) {
122
440
                        if (written + charsToWrite <= maxChars) {
123
431
                            memcpy(dest + written, uri->scheme.first,
124
431
                                   charsToWrite * sizeof(URI_CHAR));
125
431
                            written += charsToWrite;
126
431
                        } else {
127
9
                            dest[0] = _UT('\0');
128
9
                            if (charsWritten != NULL) {
129
9
                                *charsWritten = 0;
130
9
                            }
131
9
                            return URI_ERROR_TOSTRING_TOO_LONG;
132
9
                        }
133
440
                    } else {
134
0
                        (*charsRequired) += charsToWrite;
135
0
                    }
136
                    /* clang-format off */
137
    /* [04/19]     append ":" to result; */
138
                    /* clang-format on */
139
431
                    if (dest != NULL) {
140
431
                        if (written + 1 <= maxChars) {
141
430
                            memcpy(dest + written, _UT(":"), 1 * sizeof(URI_CHAR));
142
430
                            written += 1;
143
430
                        } else {
144
1
                            dest[0] = _UT('\0');
145
1
                            if (charsWritten != NULL) {
146
1
                                *charsWritten = 0;
147
1
                            }
148
1
                            return URI_ERROR_TOSTRING_TOO_LONG;
149
1
                        }
150
431
                    } else {
151
0
                        (*charsRequired) += 1;
152
0
                    }
153
                    /* clang-format off */
154
    /* [05/19] endif; */
155
                    /* clang-format on */
156
431
                }
157
                /* clang-format off */
158
    /* [06/19] if defined(authority) then */
159
                /* clang-format on */
160
10.0k
                if (URI_FUNC(HasHost)(uri)) {
161
                    /* clang-format off */
162
    /* [07/19]     append "//" to result; */
163
                    /* clang-format on */
164
1.01k
                    if (dest != NULL) {
165
1.01k
                        if (written + 2 <= maxChars) {
166
1.01k
                            memcpy(dest + written, _UT("//"), 2 * sizeof(URI_CHAR));
167
1.01k
                            written += 2;
168
1.01k
                        } else {
169
2
                            dest[0] = _UT('\0');
170
2
                            if (charsWritten != NULL) {
171
2
                                *charsWritten = 0;
172
2
                            }
173
2
                            return URI_ERROR_TOSTRING_TOO_LONG;
174
2
                        }
175
1.01k
                    } else {
176
0
                        (*charsRequired) += 2;
177
0
                    }
178
                    /* clang-format off */
179
    /* [08/19]     append authority to result; */
180
                    /* clang-format on */
181
                    /* UserInfo */
182
1.01k
                    if (uri->userInfo.first != NULL) {
183
252
                        const int charsToWrite =
184
252
                            (int)(uri->userInfo.afterLast - uri->userInfo.first);
185
252
                        if (dest != NULL) {
186
252
                            if (written + charsToWrite <= maxChars) {
187
247
                                memcpy(dest + written, uri->userInfo.first,
188
247
                                       charsToWrite * sizeof(URI_CHAR));
189
247
                                written += charsToWrite;
190
247
                            } else {
191
5
                                dest[0] = _UT('\0');
192
5
                                if (charsWritten != NULL) {
193
5
                                    *charsWritten = 0;
194
5
                                }
195
5
                                return URI_ERROR_TOSTRING_TOO_LONG;
196
5
                            }
197
198
247
                            if (written + 1 <= maxChars) {
199
246
                                memcpy(dest + written, _UT("@"), 1 * sizeof(URI_CHAR));
200
246
                                written += 1;
201
246
                            } else {
202
1
                                dest[0] = _UT('\0');
203
1
                                if (charsWritten != NULL) {
204
1
                                    *charsWritten = 0;
205
1
                                }
206
1
                                return URI_ERROR_TOSTRING_TOO_LONG;
207
1
                            }
208
247
                        } else {
209
0
                            (*charsRequired) += charsToWrite + 1;
210
0
                        }
211
252
                    }
212
213
                    /* Host */
214
1.00k
                    if (uri->hostData.ip4 != NULL) {
215
                        /* IPv4 */
216
53
                        int i = 0;
217
255
                        for (; i < 4; i++) {
218
206
                            const unsigned char value = uri->hostData.ip4->data[i];
219
206
                            const int charsToWrite =
220
206
                                (value > 99) ? 3 : ((value > 9) ? 2 : 1);
221
206
                            if (dest != NULL) {
222
206
                                if (written + charsToWrite <= maxChars) {
223
203
                                    URI_CHAR text[4];
224
203
                                    if (value > 99) {
225
22
                                        text[0] = _UT('0') + (value / 100);
226
22
                                        text[1] = _UT('0') + ((value % 100) / 10);
227
22
                                        text[2] = _UT('0') + (value % 10);
228
181
                                    } else if (value > 9) {
229
36
                                        text[0] = _UT('0') + (value / 10);
230
36
                                        text[1] = _UT('0') + (value % 10);
231
145
                                    } else {
232
145
                                        text[0] = _UT('0') + value;
233
145
                                    }
234
203
                                    text[charsToWrite] = _UT('\0');
235
203
                                    memcpy(dest + written, text,
236
203
                                           charsToWrite * sizeof(URI_CHAR));
237
203
                                    written += charsToWrite;
238
203
                                } else {
239
3
                                    dest[0] = _UT('\0');
240
3
                                    if (charsWritten != NULL) {
241
3
                                        *charsWritten = 0;
242
3
                                    }
243
3
                                    return URI_ERROR_TOSTRING_TOO_LONG;
244
3
                                }
245
203
                                if (i < 3) {
246
154
                                    if (written + 1 <= maxChars) {
247
153
                                        memcpy(dest + written, _UT("."),
248
153
                                               1 * sizeof(URI_CHAR));
249
153
                                        written += 1;
250
153
                                    } else {
251
1
                                        dest[0] = _UT('\0');
252
1
                                        if (charsWritten != NULL) {
253
1
                                            *charsWritten = 0;
254
1
                                        }
255
1
                                        return URI_ERROR_TOSTRING_TOO_LONG;
256
1
                                    }
257
154
                                }
258
203
                            } else {
259
0
                                (*charsRequired) += charsToWrite + ((i == 3) ? 0 : 1);
260
0
                            }
261
206
                        }
262
953
                    } else if (uri->hostData.ip6 != NULL) {
263
                        /* IPv6 */
264
231
                        int i = 0;
265
231
                        if (dest != NULL) {
266
231
                            if (written + 1 <= maxChars) {
267
230
                                memcpy(dest + written, _UT("["), 1 * sizeof(URI_CHAR));
268
230
                                written += 1;
269
230
                            } else {
270
1
                                dest[0] = _UT('\0');
271
1
                                if (charsWritten != NULL) {
272
1
                                    *charsWritten = 0;
273
1
                                }
274
1
                                return URI_ERROR_TOSTRING_TOO_LONG;
275
1
                            }
276
231
                        } else {
277
0
                            (*charsRequired) += 1;
278
0
                        }
279
280
3.79k
                        for (; i < 16; i++) {
281
3.57k
                            const unsigned char value = uri->hostData.ip6->data[i];
282
3.57k
                            if (dest != NULL) {
283
3.57k
                                if (written + 2 <= maxChars) {
284
3.56k
                                    URI_CHAR text[3];
285
3.56k
                                    text[0] =
286
3.56k
                                        URI_FUNC(HexToLetterEx)(value / 16, URI_FALSE);
287
3.56k
                                    text[1] =
288
3.56k
                                        URI_FUNC(HexToLetterEx)(value % 16, URI_FALSE);
289
3.56k
                                    text[2] = _UT('\0');
290
3.56k
                                    memcpy(dest + written, text, 2 * sizeof(URI_CHAR));
291
3.56k
                                    written += 2;
292
3.56k
                                } else {
293
7
                                    dest[0] = _UT('\0');
294
7
                                    if (charsWritten != NULL) {
295
7
                                        *charsWritten = 0;
296
7
                                    }
297
7
                                    return URI_ERROR_TOSTRING_TOO_LONG;
298
7
                                }
299
3.57k
                            } else {
300
0
                                (*charsRequired) += 2;
301
0
                            }
302
3.56k
                            if (((i & 1) == 1) && (i < 15)) {
303
1.56k
                                if (dest != NULL) {
304
1.56k
                                    if (written + 1 <= maxChars) {
305
1.55k
                                        memcpy(dest + written, _UT(":"),
306
1.55k
                                               1 * sizeof(URI_CHAR));
307
1.55k
                                        written += 1;
308
1.55k
                                    } else {
309
3
                                        dest[0] = _UT('\0');
310
3
                                        if (charsWritten != NULL) {
311
3
                                            *charsWritten = 0;
312
3
                                        }
313
3
                                        return URI_ERROR_TOSTRING_TOO_LONG;
314
3
                                    }
315
1.56k
                                } else {
316
0
                                    (*charsRequired) += 1;
317
0
                                }
318
1.56k
                            }
319
3.56k
                        }
320
321
220
                        if (dest != NULL) {
322
220
                            if (written + 1 <= maxChars) {
323
219
                                memcpy(dest + written, _UT("]"), 1 * sizeof(URI_CHAR));
324
219
                                written += 1;
325
219
                            } else {
326
1
                                dest[0] = _UT('\0');
327
1
                                if (charsWritten != NULL) {
328
1
                                    *charsWritten = 0;
329
1
                                }
330
1
                                return URI_ERROR_TOSTRING_TOO_LONG;
331
1
                            }
332
220
                        } else {
333
0
                            (*charsRequired) += 1;
334
0
                        }
335
722
                    } else if (uri->hostData.ipFuture.first != NULL) {
336
                        /* IPvFuture */
337
167
                        const int charsToWrite = (int)(uri->hostData.ipFuture.afterLast
338
167
                                                       - uri->hostData.ipFuture.first);
339
167
                        if (dest != NULL) {
340
167
                            if (written + 1 <= maxChars) {
341
166
                                memcpy(dest + written, _UT("["), 1 * sizeof(URI_CHAR));
342
166
                                written += 1;
343
166
                            } else {
344
1
                                dest[0] = _UT('\0');
345
1
                                if (charsWritten != NULL) {
346
1
                                    *charsWritten = 0;
347
1
                                }
348
1
                                return URI_ERROR_TOSTRING_TOO_LONG;
349
1
                            }
350
351
166
                            if (written + charsToWrite <= maxChars) {
352
144
                                memcpy(dest + written, uri->hostData.ipFuture.first,
353
144
                                       charsToWrite * sizeof(URI_CHAR));
354
144
                                written += charsToWrite;
355
144
                            } else {
356
22
                                dest[0] = _UT('\0');
357
22
                                if (charsWritten != NULL) {
358
22
                                    *charsWritten = 0;
359
22
                                }
360
22
                                return URI_ERROR_TOSTRING_TOO_LONG;
361
22
                            }
362
363
144
                            if (written + 1 <= maxChars) {
364
143
                                memcpy(dest + written, _UT("]"), 1 * sizeof(URI_CHAR));
365
143
                                written += 1;
366
143
                            } else {
367
1
                                dest[0] = _UT('\0');
368
1
                                if (charsWritten != NULL) {
369
1
                                    *charsWritten = 0;
370
1
                                }
371
1
                                return URI_ERROR_TOSTRING_TOO_LONG;
372
1
                            }
373
144
                        } else {
374
0
                            (*charsRequired) += 1 + charsToWrite + 1;
375
0
                        }
376
555
                    } else if (uri->hostText.first != NULL) {
377
                        /* Regname */
378
555
                        const int charsToWrite =
379
555
                            (int)(uri->hostText.afterLast - uri->hostText.first);
380
555
                        if (dest != NULL) {
381
555
                            if (written + charsToWrite <= maxChars) {
382
532
                                memcpy(dest + written, uri->hostText.first,
383
532
                                       charsToWrite * sizeof(URI_CHAR));
384
532
                                written += charsToWrite;
385
532
                            } else {
386
23
                                dest[0] = _UT('\0');
387
23
                                if (charsWritten != NULL) {
388
23
                                    *charsWritten = 0;
389
23
                                }
390
23
                                return URI_ERROR_TOSTRING_TOO_LONG;
391
23
                            }
392
555
                        } else {
393
0
                            (*charsRequired) += charsToWrite;
394
0
                        }
395
555
                    }
396
397
                    /* Port */
398
943
                    if (uri->portText.first != NULL) {
399
72
                        const int charsToWrite =
400
72
                            (int)(uri->portText.afterLast - uri->portText.first);
401
72
                        if (dest != NULL) {
402
                            /* Leading ':' */
403
72
                            if (written + 1 <= maxChars) {
404
71
                                memcpy(dest + written, _UT(":"), 1 * sizeof(URI_CHAR));
405
71
                                written += 1;
406
71
                            } else {
407
1
                                dest[0] = _UT('\0');
408
1
                                if (charsWritten != NULL) {
409
1
                                    *charsWritten = 0;
410
1
                                }
411
1
                                return URI_ERROR_TOSTRING_TOO_LONG;
412
1
                            }
413
414
                            /* Port number */
415
71
                            if (written + charsToWrite <= maxChars) {
416
70
                                memcpy(dest + written, uri->portText.first,
417
70
                                       charsToWrite * sizeof(URI_CHAR));
418
70
                                written += charsToWrite;
419
70
                            } else {
420
1
                                dest[0] = _UT('\0');
421
1
                                if (charsWritten != NULL) {
422
1
                                    *charsWritten = 0;
423
1
                                }
424
1
                                return URI_ERROR_TOSTRING_TOO_LONG;
425
1
                            }
426
71
                        } else {
427
0
                            (*charsRequired) += 1 + charsToWrite;
428
0
                        }
429
72
                    }
430
                    /* clang-format off */
431
    /* [09/19] endif; */
432
                    /* clang-format on */
433
943
                }
434
                /* clang-format off */
435
    /* [10/19] append path to result; */
436
                /* clang-format on */
437
                /* Slash needed here? */
438
9.94k
                if (uri->absolutePath
439
9.67k
                    || ((uri->pathHead != NULL) && URI_FUNC(HasHost)(uri))) {
440
367
                    if (dest != NULL) {
441
367
                        if (written + 1 <= maxChars) {
442
366
                            memcpy(dest + written, _UT("/"), 1 * sizeof(URI_CHAR));
443
366
                            written += 1;
444
366
                        } else {
445
1
                            dest[0] = _UT('\0');
446
1
                            if (charsWritten != NULL) {
447
1
                                *charsWritten = 0;
448
1
                            }
449
1
                            return URI_ERROR_TOSTRING_TOO_LONG;
450
1
                        }
451
367
                    } else {
452
0
                        (*charsRequired) += 1;
453
0
                    }
454
367
                }
455
456
9.94k
                if (uri->pathHead != NULL) {
457
1.48k
                    URI_TYPE(PathSegment) * walker = uri->pathHead;
458
16.0k
                    do {
459
16.0k
                        const int charsToWrite =
460
16.0k
                            (int)(walker->text.afterLast - walker->text.first);
461
16.0k
                        if (dest != NULL) {
462
16.0k
                            if (written + charsToWrite <= maxChars) {
463
16.0k
                                memcpy(dest + written, walker->text.first,
464
16.0k
                                       charsToWrite * sizeof(URI_CHAR));
465
16.0k
                                written += charsToWrite;
466
16.0k
                            } else {
467
36
                                dest[0] = _UT('\0');
468
36
                                if (charsWritten != NULL) {
469
36
                                    *charsWritten = 0;
470
36
                                }
471
36
                                return URI_ERROR_TOSTRING_TOO_LONG;
472
36
                            }
473
16.0k
                        } else {
474
0
                            (*charsRequired) += charsToWrite;
475
0
                        }
476
477
                        /* Not last segment -> append slash */
478
16.0k
                        if (walker->next != NULL) {
479
14.5k
                            if (dest != NULL) {
480
14.5k
                                if (written + 1 <= maxChars) {
481
14.5k
                                    memcpy(dest + written, _UT("/"),
482
14.5k
                                           1 * sizeof(URI_CHAR));
483
14.5k
                                    written += 1;
484
14.5k
                                } else {
485
1
                                    dest[0] = _UT('\0');
486
1
                                    if (charsWritten != NULL) {
487
1
                                        *charsWritten = 0;
488
1
                                    }
489
1
                                    return URI_ERROR_TOSTRING_TOO_LONG;
490
1
                                }
491
14.5k
                            } else {
492
0
                                (*charsRequired) += 1;
493
0
                            }
494
14.5k
                        }
495
496
16.0k
                        walker = walker->next;
497
16.0k
                    } while (walker != NULL);
498
1.48k
                }
499
                /* clang-format off */
500
    /* [11/19] if defined(query) then */
501
                /* clang-format on */
502
9.90k
                if (uri->query.first != NULL) {
503
                    /* clang-format off */
504
    /* [12/19]     append "?" to result; */
505
                    /* clang-format on */
506
149
                    if (dest != NULL) {
507
149
                        if (written + 1 <= maxChars) {
508
148
                            memcpy(dest + written, _UT("?"), 1 * sizeof(URI_CHAR));
509
148
                            written += 1;
510
148
                        } else {
511
1
                            dest[0] = _UT('\0');
512
1
                            if (charsWritten != NULL) {
513
1
                                *charsWritten = 0;
514
1
                            }
515
1
                            return URI_ERROR_TOSTRING_TOO_LONG;
516
1
                        }
517
149
                    } else {
518
0
                        (*charsRequired) += 1;
519
0
                    }
520
                    /* clang-format off */
521
    /* [13/19]     append query to result; */
522
                    /* clang-format on */
523
148
                    const int charsToWrite =
524
148
                        (int)(uri->query.afterLast - uri->query.first);
525
148
                    if (dest != NULL) {
526
148
                        if (written + charsToWrite <= maxChars) {
527
126
                            memcpy(dest + written, uri->query.first,
528
126
                                   charsToWrite * sizeof(URI_CHAR));
529
126
                            written += charsToWrite;
530
126
                        } else {
531
22
                            dest[0] = _UT('\0');
532
22
                            if (charsWritten != NULL) {
533
22
                                *charsWritten = 0;
534
22
                            }
535
22
                            return URI_ERROR_TOSTRING_TOO_LONG;
536
22
                        }
537
148
                    } else {
538
0
                        (*charsRequired) += charsToWrite;
539
0
                    }
540
                    /* clang-format off */
541
    /* [14/19] endif; */
542
                    /* clang-format on */
543
148
                }
544
                /* clang-format off */
545
    /* [15/19] if defined(fragment) then */
546
                /* clang-format on */
547
9.88k
                if (uri->fragment.first != NULL) {
548
                    /* clang-format off */
549
    /* [16/19]     append "#" to result; */
550
                    /* clang-format on */
551
122
                    if (dest != NULL) {
552
122
                        if (written + 1 <= maxChars) {
553
118
                            memcpy(dest + written, _UT("#"), 1 * sizeof(URI_CHAR));
554
118
                            written += 1;
555
118
                        } else {
556
4
                            dest[0] = _UT('\0');
557
4
                            if (charsWritten != NULL) {
558
4
                                *charsWritten = 0;
559
4
                            }
560
4
                            return URI_ERROR_TOSTRING_TOO_LONG;
561
4
                        }
562
122
                    } else {
563
0
                        (*charsRequired) += 1;
564
0
                    }
565
                    /* clang-format off */
566
    /* [17/19]     append fragment to result; */
567
                    /* clang-format on */
568
118
                    const int charsToWrite =
569
118
                        (int)(uri->fragment.afterLast - uri->fragment.first);
570
118
                    if (dest != NULL) {
571
118
                        if (written + charsToWrite <= maxChars) {
572
98
                            memcpy(dest + written, uri->fragment.first,
573
98
                                   charsToWrite * sizeof(URI_CHAR));
574
98
                            written += charsToWrite;
575
98
                        } else {
576
20
                            dest[0] = _UT('\0');
577
20
                            if (charsWritten != NULL) {
578
20
                                *charsWritten = 0;
579
20
                            }
580
20
                            return URI_ERROR_TOSTRING_TOO_LONG;
581
20
                        }
582
118
                    } else {
583
0
                        (*charsRequired) += charsToWrite;
584
0
                    }
585
                    /* clang-format off */
586
    /* [18/19] endif; */
587
                    /* clang-format on */
588
118
                }
589
                /* clang-format off */
590
    /* [19/19] return result; */
591
                /* clang-format on */
592
9.86k
                if (dest != NULL) {
593
9.86k
                    dest[written++] = _UT('\0');
594
9.86k
                    if (charsWritten != NULL) {
595
9.86k
                        *charsWritten = written;
596
9.86k
                    }
597
9.86k
                }
598
9.86k
                return URI_SUCCESS;
599
9.88k
            }
600
9.88k
        }
601
9.88k
    }
602
9.88k
}
603
604
#endif