Coverage Report

Created: 2026-04-01 07:17

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
19.3k
{
32
19.3k
    if (c >= 'A' && c <= 'Z')
33
4.52k
        return c + 32;
34
14.8k
    return c;
35
19.3k
}
36
37
int
38
xps_strcasecmp(const char *a, const char *b)
39
1.10k
{
40
8.68k
        while (xps_tolower(*a) == xps_tolower(*b))
41
7.68k
        {
42
7.68k
                if (*a++ == 0)
43
108
                        return 0;
44
7.58k
                b++;
45
7.58k
        }
46
1.00k
        return xps_tolower(*a) - xps_tolower(*b);
47
1.10k
}
48
49
char *
50
xps_strdup_imp(xps_context_t *ctx, const char *str, const char *cname)
51
165
{
52
165
    char *cpy = NULL;
53
165
    if (str)
54
165
        cpy = (char*) gs_alloc_bytes(ctx->memory, (size_t)strlen(str) + 1, cname);
55
165
    if (cpy)
56
165
        strcpy(cpy, str);
57
165
    return cpy;
58
165
}
59
60
0
#define SEP(x)  ((x)=='/' || (x) == 0)
61
62
static char *
63
xps_clean_path(char *name)
64
107
{
65
107
    char *p, *q, *dotdot;
66
107
    int rooted;
67
68
107
    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
107
    p = q = dotdot = name + rooted;
78
694
    while (*p)
79
587
    {
80
587
        if(p[0] == '/') /* null element */
81
240
            p++;
82
347
        else if (p[0] == '.' && SEP(p[1]))
83
0
            p += 1; /* don't count the separator in case it is nul */
84
347
        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
347
        else /* real path element */
102
347
        {
103
347
            if (q != name+rooted)
104
240
                *q++ = '/';
105
3.93k
            while ((*q = *p) != '/' && *q != 0)
106
3.58k
                p++, q++;
107
347
        }
108
587
    }
109
110
    /* Guard against the 'blah:' case, where name == terminator. */
111
107
    if (q == name && *q != 0) /* empty string is really "." */
112
0
        *q++ = '.';
113
107
    *q = '\0';
114
115
107
    return name;
116
107
}
117
118
void
119
xps_absolute_path(char *output, char *base_uri, char *path, int output_size)
120
107
{
121
107
    if (path[0] == '/')
122
107
    {
123
107
        gs_strlcpy(output, path, output_size);
124
107
    }
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
107
    xps_clean_path(output);
132
107
}