• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Tehreer / SheenBidi / 19308576644

12 Nov 2025 06:56PM UTC coverage: 95.907% (+16.4%) from 79.545%
19308576644

push

github

mta452
[lib] Fix memory management issues

13 of 13 new or added lines in 3 files covered. (100.0%)

29 existing lines in 10 files now uncovered.

3866 of 4031 relevant lines covered (95.91%)

462026.31 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.05
/Source/SBScriptLocator.c
1
/*
2
 * Copyright (C) 2018-2025 Muhammad Tayyab Akram
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16

17
#include <stddef.h>
18

19
#include "GeneralCategoryLookup.h"
20
#include "Object.h"
21
#include "PairingLookup.h"
22
#include "SBBase.h"
23
#include "SBCodepoint.h"
24
#include "SBCodepointSequence.h"
25
#include "ScriptLookup.h"
26
#include "ScriptStack.h"
27
#include "SBScriptLocator.h"
28

29
static SBBoolean IsSimilarScript(SBScript lhs, SBScript rhs)
5,608✔
30
{
31
    return SBScriptIsCommonOrInherited(lhs)
32
        || SBScriptIsCommonOrInherited(rhs)
5,205✔
33
        || lhs == rhs;
10,813✔
34
}
35

36
SBScriptLocatorRef SBScriptLocatorCreate(void)
173✔
37
{
38
    const SBUInteger size = sizeof(SBScriptLocator);
173✔
39
    void *pointer = NULL;
173✔
40
    SBScriptLocatorRef locator;
41

42
    locator = ObjectCreate(&size, 1, &pointer, NULL);
173✔
43

44
    if (locator) {
173✔
45
        locator->_codepointSequence.stringEncoding = SBStringEncodingUTF8;
173✔
46
        locator->_codepointSequence.stringBuffer = NULL;
173✔
47
        locator->_codepointSequence.stringLength = 0;
173✔
48

49
        SBScriptLocatorReset(locator);
173✔
50
    }
51

52
    return locator;
173✔
53
}
54

55
void SBScriptLocatorLoadCodepoints(SBScriptLocatorRef locator, const SBCodepointSequence *codepointSequence)
331✔
56
{
57
    locator->_codepointSequence = *codepointSequence;
331✔
58
    SBScriptLocatorReset(locator);
331✔
59
}
331✔
60

61
const SBScriptAgent *SBScriptLocatorGetAgent(SBScriptLocatorRef locator)
9✔
62
{
63
    return &locator->agent;
9✔
64
}
65

66
static void ResolveScriptRun(SBScriptLocatorRef locator, SBUInteger offset)
381✔
67
{
68
    const SBCodepointSequence *sequence = &locator->_codepointSequence;
381✔
69
    ScriptStackRef stack = &locator->_scriptStack;
381✔
70
    SBScript result = SBScriptZYYY;
381✔
71
    SBUInteger current = offset;
381✔
72
    SBUInteger next = offset;
381✔
73
    SBCodepoint codepoint;
74

75
    /* Iterate over the code points of specified string buffer. */
76
    while ((codepoint = SBCodepointSequenceGetCodepointAt(sequence, &next)) != SBCodepointInvalid) {
5,938✔
77
        SBBoolean isStacked = SBFalse;
5,608✔
78
        SBScript script;
79

80
        script = LookupScript(codepoint);
5,608✔
81

82
        /* Handle paired punctuations in case of a common script. */
83
        if (script == SBScriptZYYY) {
5,608✔
84
            SBGeneralCategory generalCategory = LookupGeneralCategory(codepoint);
694✔
85

86
            /* Check if current code point is an open punctuation. */
87
            if (generalCategory == SBGeneralCategoryPS) {
694✔
88
                SBCodepoint mirror = LookupMirror(codepoint);
8✔
89
                if (mirror) {
8✔
90
                    /* A closing pair exists for this punctuation, so push it onto the stack. */
91
                    ScriptStackPush(stack, result, mirror);
8✔
92
                }
93
            }
94
            /* Check if current code point is a close punctuation. */
95
            else if (generalCategory == SBGeneralCategoryPE) {
686✔
96
                SBBoolean isMirrored = (LookupMirror(codepoint) != 0);
15✔
97
                if (isMirrored) {
15✔
98
                    /* Find the matching entry in the stack, while popping the unmatched ones. */
99
                    while (!ScriptStackIsEmpty(stack)) {
15✔
100
                        SBCodepoint mirror = ScriptStackGetMirror(stack);
15✔
101
                        if (mirror != codepoint) {
15✔
UNCOV
102
                            ScriptStackPop(stack);
×
103
                        } else {
104
                            break;
15✔
105
                        }
106
                    }
107

108
                    if (!ScriptStackIsEmpty(stack)) {
15✔
109
                        isStacked = SBTrue;
15✔
110
                        /* Paired punctuation match the script of enclosing text. */
111
                        script = ScriptStackGetScript(stack);
15✔
112
                    }
113
                }
114
            }
115
        }
116

117
        if (IsSimilarScript(result, script)) {
5,608✔
118
            if (SBScriptIsCommonOrInherited(result) && !SBScriptIsCommonOrInherited(script)) {
5,557✔
119
                /* Set the concrete script of this code point as the result. */
120
                result = script;
367✔
121
                /* Seal the pending punctuations with the result. */
122
                ScriptStackSealPairs(stack, result);
367✔
123
            }
124

125
            if (isStacked) {
5,557✔
126
                /* Pop the paired punctuation from the stack. */
127
                ScriptStackPop(stack);
8✔
128
            }
129
        } else {
130
            /* The current code point has a different script, so finish the run. */
131
            break;
51✔
132
        }
133

134
        current = next;
5,557✔
135
    }
136

137
    ScriptStackLeavePairs(stack);
381✔
138

139
    /* Set the run info in agent. */
140
    locator->agent.offset = offset;
381✔
141
    locator->agent.length = current - offset;
381✔
142
    locator->agent.script = result;
381✔
143
}
381✔
144

145
SBBoolean SBScriptLocatorMoveNext(SBScriptLocatorRef locator)
712✔
146
{
147
    SBUInteger offset = locator->agent.offset + locator->agent.length;
712✔
148

149
    if (offset < locator->_codepointSequence.stringLength) {
712✔
150
        ResolveScriptRun(locator, offset);
381✔
151
        return SBTrue;
381✔
152
    }
153

154
    SBScriptLocatorReset(locator);
331✔
155
    return SBFalse;
331✔
156
}
157

158
void SBScriptLocatorReset(SBScriptLocatorRef locator)
835✔
159
{
160
    ScriptStackReset(&locator->_scriptStack);
835✔
161
    locator->agent.offset = 0;
835✔
162
    locator->agent.length = 0;
835✔
163
    locator->agent.script = SBScriptNil;
835✔
164
}
835✔
165

UNCOV
166
SBScriptLocatorRef SBScriptLocatorRetain(SBScriptLocatorRef locator)
×
167
{
168
    return ObjectRetain((ObjectRef)locator);
×
169
}
170

171
void SBScriptLocatorRelease(SBScriptLocatorRef locator)
173✔
172
{
173
    ObjectRelease((ObjectRef)locator);
173✔
174
}
173✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc