Coverage Report

Created: 2026-04-09 07:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/xps/xpsmem.c
Line
Count
Source
1
/* Copyright (C) 2001-2025 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, for further information.
14
*/
15
16
17
/* XPS interpreter - string manipulation functions */
18
19
#include "ghostxps.h"
20
21
void *
22
xps_realloc_imp(xps_context_t *ctx, void *ptr, size_t size, const char *func)
23
0
{
24
0
    if (!ptr)
25
0
        return gs_alloc_bytes(ctx->memory, size, func);
26
0
    return gs_resize_object(ctx->memory, ptr, size, func);
27
0
}
28
29
static inline int
30
xps_tolower(int c)
31
51.0k
{
32
51.0k
    if (c >= 'A' && c <= 'Z')
33
11.8k
        return c + 32;
34
39.2k
    return c;
35
51.0k
}
36
37
int
38
xps_strcasecmp(const char *a, const char *b)
39
3.03k
{
40
22.7k
        while (xps_tolower(*a) == xps_tolower(*b))
41
20.0k
        {
42
20.0k
                if (*a++ == 0)
43
302
                        return 0;
44
19.7k
                b++;
45
19.7k
        }
46
2.72k
        return xps_tolower(*a) - xps_tolower(*b);
47
3.03k
}
48
49
char *
50
xps_strdup_imp(xps_context_t *ctx, const char *str, const char *cname)
51
492
{
52
492
    char *cpy = NULL;
53
492
    if (str)
54
492
        cpy = (char*) gs_alloc_bytes(ctx->memory, (size_t)strlen(str) + 1, cname);
55
492
    if (cpy)
56
492
        strcpy(cpy, str);
57
492
    return cpy;
58
492
}
59
60
0
#define SEP(x)  ((x)=='/' || (x) == 0)
61
62
static char *
63
xps_clean_path(char *name)
64
301
{
65
301
    char *p, *q, *dotdot;
66
301
    int rooted;
67
68
301
    rooted = name[0] == '/';
69
70
    /*
71
     * invariants:
72
     *      p points at beginning of path element we're considering.
73
     *      q points just past the last path element we wrote (no slash).
74
     *      dotdot points just past the point where .. cannot backtrack
75
     *              any further (no slash).
76
     */
77
301
    p = q = dotdot = name + rooted;
78
1.88k
    while (*p)
79
1.58k
    {
80
1.58k
        if(p[0] == '/') /* null element */
81
643
            p++;
82
944
        else if (p[0] == '.' && SEP(p[1]))
83
0
            p += 1; /* don't count the separator in case it is nul */
84
944
        else if (p[0] == '.' && p[1] == '.' && SEP(p[2]))
85
0
        {
86
0
            p += 2;
87
0
            if (q > dotdot) /* can backtrack */
88
0
            {
89
0
                while(--q > dotdot && *q != '/')
90
0
                    ;
91
0
            }
92
0
            else if (!rooted) /* /.. is / but ./../ is .. */
93
0
            {
94
0
                if (q != name)
95
0
                    *q++ = '/';
96
0
                *q++ = '.';
97
0
                *q++ = '.';
98
0
                dotdot = q;
99
0
            }
100
0
        }
101
944
        else /* real path element */
102
944
        {
103
944
            if (q != name+rooted)
104
643
                *q++ = '/';
105
10.3k
            while ((*q = *p) != '/' && *q != 0)
106
9.42k
                p++, q++;
107
944
        }
108
1.58k
    }
109
110
    /* Guard against the 'blah:' case, where name == terminator. */
111
301
    if (q == name && *q != 0) /* empty string is really "." */
112
0
        *q++ = '.';
113
301
    *q = '\0';
114
115
301
    return name;
116
301
}
117
118
void
119
xps_absolute_path(char *output, char *base_uri, char *path, int output_size)
120
301
{
121
301
    if (path[0] == '/')
122
301
    {
123
301
        gs_strlcpy(output, path, output_size);
124
301
    }
125
0
    else
126
0
    {
127
0
        gs_strlcpy(output, base_uri, output_size);
128
0
        gs_strlcat(output, "/", output_size);
129
0
        gs_strlcat(output, path, output_size);
130
0
    }
131
301
    xps_clean_path(output);
132
301
}