Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/intl/icu/source/common/bytesinkutil.cpp
Line
Count
Source (jump to first uncovered line)
1
// © 2017 and later: Unicode, Inc. and others.
2
// License & terms of use: http://www.unicode.org/copyright.html
3
4
// bytesinkutil.cpp
5
// created: 2017sep14 Markus W. Scherer
6
7
#include "unicode/utypes.h"
8
#include "unicode/bytestream.h"
9
#include "unicode/edits.h"
10
#include "unicode/stringoptions.h"
11
#include "unicode/utf8.h"
12
#include "unicode/utf16.h"
13
#include "bytesinkutil.h"
14
#include "cmemory.h"
15
#include "uassert.h"
16
17
U_NAMESPACE_BEGIN
18
19
UBool
20
ByteSinkUtil::appendChange(int32_t length, const char16_t *s16, int32_t s16Length,
21
0
                           ByteSink &sink, Edits *edits, UErrorCode &errorCode) {
22
0
    if (U_FAILURE(errorCode)) { return FALSE; }
23
0
    char scratch[200];
24
0
    int32_t s8Length = 0;
25
0
    for (int32_t i = 0; i < s16Length;) {
26
0
        int32_t capacity;
27
0
        int32_t desiredCapacity = s16Length - i;
28
0
        if (desiredCapacity < (INT32_MAX / 3)) {
29
0
            desiredCapacity *= 3;  // max 3 UTF-8 bytes per UTF-16 code unit
30
0
        } else if (desiredCapacity < (INT32_MAX / 2)) {
31
0
            desiredCapacity *= 2;
32
0
        } else {
33
0
            desiredCapacity = INT32_MAX;
34
0
        }
35
0
        char *buffer = sink.GetAppendBuffer(U8_MAX_LENGTH, desiredCapacity,
36
0
                                            scratch, UPRV_LENGTHOF(scratch), &capacity);
37
0
        capacity -= U8_MAX_LENGTH - 1;
38
0
        int32_t j = 0;
39
0
        for (; i < s16Length && j < capacity;) {
40
0
            UChar32 c;
41
0
            U16_NEXT_UNSAFE(s16, i, c);
42
0
            U8_APPEND_UNSAFE(buffer, j, c);
43
0
        }
44
0
        if (j > (INT32_MAX - s8Length)) {
45
0
            errorCode = U_INDEX_OUTOFBOUNDS_ERROR;
46
0
            return FALSE;
47
0
        }
48
0
        sink.Append(buffer, j);
49
0
        s8Length += j;
50
0
    }
51
0
    if (edits != nullptr) {
52
0
        edits->addReplace(length, s8Length);
53
0
    }
54
0
    return TRUE;
55
0
}
56
57
UBool
58
ByteSinkUtil::appendChange(const uint8_t *s, const uint8_t *limit,
59
                           const char16_t *s16, int32_t s16Length,
60
0
                           ByteSink &sink, Edits *edits, UErrorCode &errorCode) {
61
0
    if (U_FAILURE(errorCode)) { return FALSE; }
62
0
    if ((limit - s) > INT32_MAX) {
63
0
        errorCode = U_INDEX_OUTOFBOUNDS_ERROR;
64
0
        return FALSE;
65
0
    }
66
0
    return appendChange((int32_t)(limit - s), s16, s16Length, sink, edits, errorCode);
67
0
}
68
69
void
70
0
ByteSinkUtil::appendCodePoint(int32_t length, UChar32 c, ByteSink &sink, Edits *edits) {
71
0
    char s8[U8_MAX_LENGTH];
72
0
    int32_t s8Length = 0;
73
0
    U8_APPEND_UNSAFE(s8, s8Length, c);
74
0
    if (edits != nullptr) {
75
0
        edits->addReplace(length, s8Length);
76
0
    }
77
0
    sink.Append(s8, s8Length);
78
0
}
79
80
namespace {
81
82
// See unicode/utf8.h U8_APPEND_UNSAFE().
83
0
inline uint8_t getTwoByteLead(UChar32 c) { return (uint8_t)((c >> 6) | 0xc0); }
84
0
inline uint8_t getTwoByteTrail(UChar32 c) { return (uint8_t)((c & 0x3f) | 0x80); }
85
86
}  // namespace
87
88
void
89
0
ByteSinkUtil::appendTwoBytes(UChar32 c, ByteSink &sink) {
90
0
    U_ASSERT(0x80 <= c && c <= 0x7ff);  // 2-byte UTF-8
91
0
    char s8[2] = { (char)getTwoByteLead(c), (char)getTwoByteTrail(c) };
92
0
    sink.Append(s8, 2);
93
0
}
94
95
void
96
ByteSinkUtil::appendNonEmptyUnchanged(const uint8_t *s, int32_t length,
97
0
                                      ByteSink &sink, uint32_t options, Edits *edits) {
98
0
    U_ASSERT(length > 0);
99
0
    if (edits != nullptr) {
100
0
        edits->addUnchanged(length);
101
0
    }
102
0
    if ((options & U_OMIT_UNCHANGED_TEXT) == 0) {
103
0
        sink.Append(reinterpret_cast<const char *>(s), length);
104
0
    }
105
0
}
106
107
UBool
108
ByteSinkUtil::appendUnchanged(const uint8_t *s, const uint8_t *limit,
109
                              ByteSink &sink, uint32_t options, Edits *edits,
110
0
                              UErrorCode &errorCode) {
111
0
    if (U_FAILURE(errorCode)) { return FALSE; }
112
0
    if ((limit - s) > INT32_MAX) {
113
0
        errorCode = U_INDEX_OUTOFBOUNDS_ERROR;
114
0
        return FALSE;
115
0
    }
116
0
    int32_t length = (int32_t)(limit - s);
117
0
    if (length > 0) {
118
0
        appendNonEmptyUnchanged(s, length, sink, options, edits);
119
0
    }
120
0
    return TRUE;
121
0
}
122
123
U_NAMESPACE_END