Coverage Report

Created: 2026-11-06 11:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sax/source/tools/converter.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
11
 *   Licensed to the Apache Software Foundation (ASF) under one or more
12
 *   contributor license agreements. See the NOTICE file distributed
13
 *   with this work for additional information regarding copyright
14
 *   ownership. The ASF licenses this file to you under the Apache
15
 *   License, Version 2.0 (the "License"); you may not use this file
16
 *   except in compliance with the License. You may obtain a copy of
17
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18
 */
19
20
#include <sax/tools/converter.hxx>
21
22
#include <com/sun/star/i18n/UnicodeType.hpp>
23
#include <com/sun/star/util/DateTime.hpp>
24
#include <com/sun/star/util/Date.hpp>
25
#include <com/sun/star/util/Duration.hpp>
26
#include <com/sun/star/util/Time.hpp>
27
#include <optional>
28
29
#include <comphelper/date.hxx>
30
#include <rtl/ustrbuf.hxx>
31
#include <rtl/math.hxx>
32
#include <rtl/character.hxx>
33
#include <sal/log.hxx>
34
#include <o3tl/string_view.hxx>
35
#include <o3tl/typed_flags_set.hxx>
36
#include <o3tl/unit_conversion.hxx>
37
#include <o3tl/numeric.hxx>
38
#include <osl/diagnose.h>
39
#include <tools/long.hxx>
40
#include <tools/time.hxx>
41
42
#include <algorithm>
43
#include <climits>
44
#include <map>
45
#include <string_view>
46
47
#include <frozen/bits/defines.h>
48
#include <frozen/bits/elsa_std.h>
49
#include <frozen/unordered_map.h>
50
51
using namespace com::sun::star;
52
using namespace com::sun::star::uno;
53
using namespace com::sun::star::util;
54
55
56
namespace sax {
57
58
static sal_Int64 toInt64_WithLength(const sal_Unicode * str, sal_Int16 radix, sal_Int32 nStrLength )
59
878k
{
60
878k
    return rtl_ustr_toInt64_WithLength(str, radix, nStrLength);
61
878k
}
62
static sal_Int64 toInt64_WithLength(const char * str, sal_Int16 radix, sal_Int32 nStrLength )
63
68.5k
{
64
68.5k
    return rtl_str_toInt64_WithLength(str, radix, nStrLength);
65
68.5k
}
66
67
namespace
68
{
69
constexpr std::string_view gpsMM = "mm";
70
constexpr std::string_view gpsCM = "cm";
71
constexpr std::string_view gpsPT = "pt";
72
constexpr std::string_view gpsINCH = "in";
73
constexpr std::string_view gpsPC = "pc";
74
constexpr std::string_view gpsPX = "px";
75
constexpr std::string_view gpsPERCENT = "%";
76
constexpr std::string_view gpsFONT_EM = "em";
77
constexpr std::string_view gpsFONT_IC = "ic";
78
79
const sal_Int8 XML_MAXDIGITSCOUNT_TIME = 14;
80
81
constexpr auto stConvertMeasureUnitStrMap = frozen::make_unordered_map<sal_Int16, std::string_view>({
82
    { MeasureUnit::MM, gpsMM },          { MeasureUnit::CM, gpsCM },
83
    { MeasureUnit::INCH, gpsINCH },      { MeasureUnit::POINT, gpsPT },
84
    { MeasureUnit::PICA, gpsPC },        { MeasureUnit::PERCENT, gpsPERCENT },
85
    { MeasureUnit::PIXEL, gpsPX },       { MeasureUnit::FONT_EM, gpsFONT_EM },
86
    { MeasureUnit::FONT_CJK_ADVANCE, gpsFONT_IC }
87
});
88
89
o3tl::Length Measure2O3tlUnit(sal_Int16 nUnit)
90
218k
{
91
218k
    switch (nUnit)
92
218k
    {
93
21.8k
        case MeasureUnit::TWIP:
94
21.8k
            return o3tl::Length::twip;
95
11
        case MeasureUnit::POINT:
96
11
            return o3tl::Length::pt;
97
0
        case MeasureUnit::MM_10TH:
98
0
            return o3tl::Length::mm10;
99
197k
        case MeasureUnit::MM_100TH:
100
197k
            return o3tl::Length::mm100;
101
0
        case MeasureUnit::MM:
102
0
            return o3tl::Length::mm;
103
1
        case MeasureUnit::CM:
104
1
            return o3tl::Length::cm;
105
0
        default:
106
0
            SAL_WARN("sax", "unit not supported for length");
107
0
            [[fallthrough]];
108
4
        case MeasureUnit::INCH:
109
4
            return o3tl::Length::in;
110
218k
    }
111
218k
}
112
113
std::string_view Measure2UnitString(sal_Int16 nUnit)
114
11
{
115
11
    switch (nUnit)
116
11
    {
117
6
        case MeasureUnit::TWIP:
118
6
            return gpsPC; // ??
119
0
        case MeasureUnit::POINT:
120
0
            return gpsPT;
121
0
        case MeasureUnit::MM_10TH:
122
0
        case MeasureUnit::MM_100TH:
123
0
            return {};
124
0
        case MeasureUnit::MM:
125
0
            return gpsMM;
126
1
        case MeasureUnit::CM:
127
1
            return gpsCM;
128
4
        case MeasureUnit::INCH:
129
4
        default:
130
4
            return gpsINCH;
131
11
    }
132
11
}
133
134
template <typename V> bool wordEndsWith(V string, std::string_view expected)
135
287k
{
136
287k
    V substr = string.substr(0, expected.size());
137
287k
    return std::equal(substr.begin(), substr.end(), expected.begin(), expected.end(),
138
287k
                      [](sal_uInt32 c1, sal_uInt32 c2) { return rtl::toAsciiLowerCase(c1) == c2; })
converter.cxx:sax::(anonymous namespace)::wordEndsWith<std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> > >(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >, std::__1::basic_string_view<char, std::__1::char_traits<char> >)::{lambda(unsigned int, unsigned int)#1}::operator()(unsigned int, unsigned int) const
Line
Count
Source
138
186k
                      [](sal_uInt32 c1, sal_uInt32 c2) { return rtl::toAsciiLowerCase(c1) == c2; })
converter.cxx:sax::(anonymous namespace)::wordEndsWith<std::__1::basic_string_view<char, std::__1::char_traits<char> > >(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::basic_string_view<char, std::__1::char_traits<char> >)::{lambda(unsigned int, unsigned int)#1}::operator()(unsigned int, unsigned int) const
Line
Count
Source
138
101k
                      [](sal_uInt32 c1, sal_uInt32 c2) { return rtl::toAsciiLowerCase(c1) == c2; })
139
236k
           && (string.size() == expected.size() || string[expected.size()] == ' ');
140
287k
}
converter.cxx:bool sax::(anonymous namespace)::wordEndsWith<std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> > >(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >, std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
135
186k
{
136
186k
    V substr = string.substr(0, expected.size());
137
186k
    return std::equal(substr.begin(), substr.end(), expected.begin(), expected.end(),
138
186k
                      [](sal_uInt32 c1, sal_uInt32 c2) { return rtl::toAsciiLowerCase(c1) == c2; })
139
153k
           && (string.size() == expected.size() || string[expected.size()] == ' ');
140
186k
}
converter.cxx:bool sax::(anonymous namespace)::wordEndsWith<std::__1::basic_string_view<char, std::__1::char_traits<char> > >(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
135
101k
{
136
101k
    V substr = string.substr(0, expected.size());
137
101k
    return std::equal(substr.begin(), substr.end(), expected.begin(), expected.end(),
138
101k
                      [](sal_uInt32 c1, sal_uInt32 c2) { return rtl::toAsciiLowerCase(c1) == c2; })
139
83.0k
           && (string.size() == expected.size() || string[expected.size()] == ' ');
140
101k
}
141
142
}
143
144
/** parse unit substring into measure unit*/
145
template <class V> static std::optional<sal_Int16> lcl_parseMeasureUnit(const V& rString)
146
257k
{
147
257k
    if (rString.empty())
148
0
    {
149
0
        return std::nullopt;
150
0
    }
151
152
257k
    switch (rtl::toAsciiLowerCase<sal_uInt32>(rString[0]))
153
257k
    {
154
18.9k
        case u'%':
155
18.9k
            return MeasureUnit::PERCENT;
156
157
182k
        case u'c':
158
182k
            if (wordEndsWith(rString.substr(1), "m"))
159
181k
                return MeasureUnit::CM;
160
328
            break;
161
162
328
        case u'e':
163
32
            if (wordEndsWith(rString.substr(1), "m"))
164
8
                return MeasureUnit::FONT_EM;
165
24
            break;
166
167
38.5k
        case u'i':
168
38.5k
            if (wordEndsWith(rString.substr(1), "c"))
169
0
                return MeasureUnit::FONT_CJK_ADVANCE;
170
38.5k
            if (wordEndsWith(rString.substr(1), "n"))
171
38.4k
                return MeasureUnit::INCH;
172
78
            break;
173
174
4.93k
        case u'm':
175
4.93k
            if (wordEndsWith(rString.substr(1), "m"))
176
4.81k
                return MeasureUnit::MM;
177
119
            break;
178
179
11.7k
        case u'p':
180
11.7k
            if (wordEndsWith(rString.substr(1), "c"))
181
0
                return MeasureUnit::PICA;
182
11.7k
            if (wordEndsWith(rString.substr(1), "t"))
183
11.4k
                return MeasureUnit::POINT;
184
222
            if (wordEndsWith(rString.substr(1), "x"))
185
0
                return MeasureUnit::PIXEL;
186
222
            break;
187
257k
    }
188
189
2.25k
    return std::nullopt;
190
257k
}
converter.cxx:std::__1::optional<short> sax::lcl_parseMeasureUnit<std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> > >(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> > const&)
Line
Count
Source
146
166k
{
147
166k
    if (rString.empty())
148
0
    {
149
0
        return std::nullopt;
150
0
    }
151
152
166k
    switch (rtl::toAsciiLowerCase<sal_uInt32>(rString[0]))
153
166k
    {
154
11.4k
        case u'%':
155
11.4k
            return MeasureUnit::PERCENT;
156
157
117k
        case u'c':
158
117k
            if (wordEndsWith(rString.substr(1), "m"))
159
117k
                return MeasureUnit::CM;
160
246
            break;
161
162
246
        case u'e':
163
28
            if (wordEndsWith(rString.substr(1), "m"))
164
8
                return MeasureUnit::FONT_EM;
165
20
            break;
166
167
20.5k
        case u'i':
168
20.5k
            if (wordEndsWith(rString.substr(1), "c"))
169
0
                return MeasureUnit::FONT_CJK_ADVANCE;
170
20.5k
            if (wordEndsWith(rString.substr(1), "n"))
171
20.4k
                return MeasureUnit::INCH;
172
63
            break;
173
174
4.15k
        case u'm':
175
4.15k
            if (wordEndsWith(rString.substr(1), "m"))
176
4.05k
                return MeasureUnit::MM;
177
94
            break;
178
179
11.5k
        case u'p':
180
11.5k
            if (wordEndsWith(rString.substr(1), "c"))
181
0
                return MeasureUnit::PICA;
182
11.5k
            if (wordEndsWith(rString.substr(1), "t"))
183
11.4k
                return MeasureUnit::POINT;
184
142
            if (wordEndsWith(rString.substr(1), "x"))
185
0
                return MeasureUnit::PIXEL;
186
142
            break;
187
166k
    }
188
189
1.54k
    return std::nullopt;
190
166k
}
converter.cxx:std::__1::optional<short> sax::lcl_parseMeasureUnit<std::__1::basic_string_view<char, std::__1::char_traits<char> > >(std::__1::basic_string_view<char, std::__1::char_traits<char> > const&)
Line
Count
Source
146
91.1k
{
147
91.1k
    if (rString.empty())
148
0
    {
149
0
        return std::nullopt;
150
0
    }
151
152
91.1k
    switch (rtl::toAsciiLowerCase<sal_uInt32>(rString[0]))
153
91.1k
    {
154
7.44k
        case u'%':
155
7.44k
            return MeasureUnit::PERCENT;
156
157
64.2k
        case u'c':
158
64.2k
            if (wordEndsWith(rString.substr(1), "m"))
159
64.1k
                return MeasureUnit::CM;
160
82
            break;
161
162
82
        case u'e':
163
4
            if (wordEndsWith(rString.substr(1), "m"))
164
0
                return MeasureUnit::FONT_EM;
165
4
            break;
166
167
18.0k
        case u'i':
168
18.0k
            if (wordEndsWith(rString.substr(1), "c"))
169
0
                return MeasureUnit::FONT_CJK_ADVANCE;
170
18.0k
            if (wordEndsWith(rString.substr(1), "n"))
171
18.0k
                return MeasureUnit::INCH;
172
15
            break;
173
174
779
        case u'm':
175
779
            if (wordEndsWith(rString.substr(1), "m"))
176
754
                return MeasureUnit::MM;
177
25
            break;
178
179
126
        case u'p':
180
126
            if (wordEndsWith(rString.substr(1), "c"))
181
0
                return MeasureUnit::PICA;
182
126
            if (wordEndsWith(rString.substr(1), "t"))
183
46
                return MeasureUnit::POINT;
184
80
            if (wordEndsWith(rString.substr(1), "x"))
185
0
                return MeasureUnit::PIXEL;
186
80
            break;
187
91.1k
    }
188
189
710
    return std::nullopt;
190
91.1k
}
191
192
/** parse measure string into double and measure unit*/
193
template <class V>
194
static bool lcl_parseMeasure(double& rValue, std::optional<sal_Int16>& rSourceUnit, bool& rNeg, const V& rString)
195
266k
{
196
266k
    rValue = 0.0;
197
266k
    rSourceUnit.reset();
198
266k
    rNeg = false;
199
200
266k
    bool bNeg = false;
201
266k
    double nVal = 0;
202
203
266k
    sal_Int32 nPos = 0;
204
266k
    sal_Int32 const nLen = rString.size();
205
206
    // skip white space
207
269k
    while( (nPos < nLen) && (rString[nPos] <= ' ') )
208
3.29k
        nPos++;
209
210
266k
    if( nPos < nLen && '-' == rString[nPos] )
211
17.9k
    {
212
17.9k
        bNeg = true;
213
17.9k
        nPos++;
214
17.9k
    }
215
216
    // get number
217
592k
    while( nPos < nLen &&
218
584k
           '0' <= rString[nPos] &&
219
384k
           '9' >= rString[nPos] )
220
326k
    {
221
        // TODO: check overflow!
222
326k
        nVal *= 10;
223
326k
        nVal += (rString[nPos] - '0');
224
326k
        nPos++;
225
326k
    }
226
266k
    if( nPos < nLen && '.' == rString[nPos] )
227
180k
    {
228
180k
        nPos++;
229
180k
        double nDiv = 1.;
230
231
593k
        while( nPos < nLen &&
232
593k
               '0' <= rString[nPos] &&
233
592k
               '9' >= rString[nPos] )
234
412k
        {
235
            // TODO: check overflow!
236
412k
            nDiv *= 10;
237
412k
            nVal += ( static_cast<double>(rString[nPos] - '0') / nDiv );
238
412k
            nPos++;
239
412k
        }
240
180k
    }
241
242
    // skip white space
243
267k
    while( (nPos < nLen) && (rString[nPos] <= ' ') )
244
1.02k
        nPos++;
245
246
266k
    if (nPos < nLen)
247
257k
    {
248
        // Parse unit from the tail
249
257k
        auto nUnit = lcl_parseMeasureUnit(rString.substr(nPos));
250
257k
        if (!nUnit.has_value())
251
2.25k
        {
252
2.25k
            return false;
253
2.25k
        }
254
255
255k
        rSourceUnit = nUnit.value();
256
255k
    }
257
258
263k
    rValue = nVal;
259
263k
    rNeg = bNeg;
260
261
263k
    return true;
262
266k
}
converter.cxx:bool sax::lcl_parseMeasure<std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> > >(double&, std::__1::optional<short>&, bool&, std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> > const&)
Line
Count
Source
195
174k
{
196
174k
    rValue = 0.0;
197
174k
    rSourceUnit.reset();
198
174k
    rNeg = false;
199
200
174k
    bool bNeg = false;
201
174k
    double nVal = 0;
202
203
174k
    sal_Int32 nPos = 0;
204
174k
    sal_Int32 const nLen = rString.size();
205
206
    // skip white space
207
177k
    while( (nPos < nLen) && (rString[nPos] <= ' ') )
208
2.73k
        nPos++;
209
210
174k
    if( nPos < nLen && '-' == rString[nPos] )
211
2.29k
    {
212
2.29k
        bNeg = true;
213
2.29k
        nPos++;
214
2.29k
    }
215
216
    // get number
217
392k
    while( nPos < nLen &&
218
383k
           '0' <= rString[nPos] &&
219
271k
           '9' >= rString[nPos] )
220
217k
    {
221
        // TODO: check overflow!
222
217k
        nVal *= 10;
223
217k
        nVal += (rString[nPos] - '0');
224
217k
        nPos++;
225
217k
    }
226
174k
    if( nPos < nLen && '.' == rString[nPos] )
227
100k
    {
228
100k
        nPos++;
229
100k
        double nDiv = 1.;
230
231
326k
        while( nPos < nLen &&
232
326k
               '0' <= rString[nPos] &&
233
326k
               '9' >= rString[nPos] )
234
225k
        {
235
            // TODO: check overflow!
236
225k
            nDiv *= 10;
237
225k
            nVal += ( static_cast<double>(rString[nPos] - '0') / nDiv );
238
225k
            nPos++;
239
225k
        }
240
100k
    }
241
242
    // skip white space
243
174k
    while( (nPos < nLen) && (rString[nPos] <= ' ') )
244
58
        nPos++;
245
246
174k
    if (nPos < nLen)
247
166k
    {
248
        // Parse unit from the tail
249
166k
        auto nUnit = lcl_parseMeasureUnit(rString.substr(nPos));
250
166k
        if (!nUnit.has_value())
251
1.54k
        {
252
1.54k
            return false;
253
1.54k
        }
254
255
165k
        rSourceUnit = nUnit.value();
256
165k
    }
257
258
173k
    rValue = nVal;
259
173k
    rNeg = bNeg;
260
261
173k
    return true;
262
174k
}
converter.cxx:bool sax::lcl_parseMeasure<std::__1::basic_string_view<char, std::__1::char_traits<char> > >(double&, std::__1::optional<short>&, bool&, std::__1::basic_string_view<char, std::__1::char_traits<char> > const&)
Line
Count
Source
195
91.1k
{
196
91.1k
    rValue = 0.0;
197
91.1k
    rSourceUnit.reset();
198
91.1k
    rNeg = false;
199
200
91.1k
    bool bNeg = false;
201
91.1k
    double nVal = 0;
202
203
91.1k
    sal_Int32 nPos = 0;
204
91.1k
    sal_Int32 const nLen = rString.size();
205
206
    // skip white space
207
91.7k
    while( (nPos < nLen) && (rString[nPos] <= ' ') )
208
557
        nPos++;
209
210
91.1k
    if( nPos < nLen && '-' == rString[nPos] )
211
15.6k
    {
212
15.6k
        bNeg = true;
213
15.6k
        nPos++;
214
15.6k
    }
215
216
    // get number
217
200k
    while( nPos < nLen &&
218
200k
           '0' <= rString[nPos] &&
219
113k
           '9' >= rString[nPos] )
220
109k
    {
221
        // TODO: check overflow!
222
109k
        nVal *= 10;
223
109k
        nVal += (rString[nPos] - '0');
224
109k
        nPos++;
225
109k
    }
226
91.1k
    if( nPos < nLen && '.' == rString[nPos] )
227
79.8k
    {
228
79.8k
        nPos++;
229
79.8k
        double nDiv = 1.;
230
231
266k
        while( nPos < nLen &&
232
266k
               '0' <= rString[nPos] &&
233
266k
               '9' >= rString[nPos] )
234
186k
        {
235
            // TODO: check overflow!
236
186k
            nDiv *= 10;
237
186k
            nVal += ( static_cast<double>(rString[nPos] - '0') / nDiv );
238
186k
            nPos++;
239
186k
        }
240
79.8k
    }
241
242
    // skip white space
243
92.1k
    while( (nPos < nLen) && (rString[nPos] <= ' ') )
244
969
        nPos++;
245
246
91.1k
    if (nPos < nLen)
247
91.1k
    {
248
        // Parse unit from the tail
249
91.1k
        auto nUnit = lcl_parseMeasureUnit(rString.substr(nPos));
250
91.1k
        if (!nUnit.has_value())
251
710
        {
252
710
            return false;
253
710
        }
254
255
90.4k
        rSourceUnit = nUnit.value();
256
90.4k
    }
257
258
90.4k
    rValue = nVal;
259
90.4k
    rNeg = bNeg;
260
261
90.4k
    return true;
262
91.1k
}
263
264
/** convert string to measure using optional min and max values*/
265
template <class V>
266
static bool lcl_convertMeasure(sal_Int32& rValue, const V& rString,
267
        sal_Int16 nTargetUnit /* = MeasureUnit::MM_100TH */,
268
        sal_Int32 nMin /* = SAL_MIN_INT32 */,
269
        sal_Int32 nMax /* = SAL_MAX_INT32 */)
270
266k
{
271
266k
    double nVal = 0.0;
272
266k
    std::optional<sal_Int16> nSourceUnit;
273
266k
    bool bNeg = false;
274
275
266k
    if (!lcl_parseMeasure(nVal, nSourceUnit, bNeg, rString))
276
2.25k
    {
277
2.25k
        return false;
278
2.25k
    }
279
280
263k
    if (nSourceUnit.has_value())
281
255k
    {
282
255k
        if( MeasureUnit::PERCENT == nTargetUnit )
283
49.0k
        {
284
49.0k
            if (MeasureUnit::PERCENT != nSourceUnit)
285
30.1k
                return false;
286
49.0k
        }
287
206k
        else if( MeasureUnit::PIXEL == nTargetUnit )
288
0
        {
289
0
            if (MeasureUnit::PIXEL != nSourceUnit)
290
0
                return false;
291
0
        }
292
206k
        else
293
206k
        {
294
206k
            OSL_ENSURE( MeasureUnit::TWIP == nTargetUnit || MeasureUnit::POINT == nTargetUnit ||
295
206k
                        MeasureUnit::MM_100TH == nTargetUnit || MeasureUnit::MM_10TH == nTargetUnit ||
296
206k
                        MeasureUnit::PIXEL == nTargetUnit, "unit is not supported");
297
298
206k
            o3tl::Length eFrom = o3tl::Length::invalid;
299
300
206k
            if( MeasureUnit::TWIP == nTargetUnit )
301
21.8k
            {
302
21.8k
                switch (nSourceUnit.value())
303
21.8k
                {
304
13.5k
                    case MeasureUnit::CM:
305
13.5k
                        eFrom = o3tl::Length::cm;
306
13.5k
                        break;
307
83
                    case MeasureUnit::INCH:
308
83
                        eFrom = o3tl::Length::in;
309
83
                        break;
310
0
                    case MeasureUnit::MM:
311
0
                        eFrom = o3tl::Length::mm;
312
0
                        break;
313
8.16k
                    case MeasureUnit::POINT:
314
8.16k
                        eFrom = o3tl::Length::pt;
315
8.16k
                        break;
316
0
                    case MeasureUnit::PICA:
317
0
                        eFrom = o3tl::Length::pc;
318
0
                        break;
319
21.8k
                }
320
21.8k
            }
321
184k
            else if( MeasureUnit::MM_100TH == nTargetUnit || MeasureUnit::MM_10TH == nTargetUnit )
322
184k
            {
323
184k
                switch (nSourceUnit.value())
324
184k
                {
325
146k
                    case MeasureUnit::CM:
326
146k
                        eFrom = o3tl::Length::cm;
327
146k
                        break;
328
31.0k
                    case MeasureUnit::INCH:
329
31.0k
                        eFrom = o3tl::Length::in;
330
31.0k
                        break;
331
3.96k
                    case MeasureUnit::MM:
332
3.96k
                        eFrom = o3tl::Length::mm;
333
3.96k
                        break;
334
3.28k
                    case MeasureUnit::POINT:
335
3.28k
                        eFrom = o3tl::Length::pt;
336
3.28k
                        break;
337
0
                    case MeasureUnit::PICA:
338
0
                        eFrom = o3tl::Length::pc;
339
0
                        break;
340
0
                    case MeasureUnit::PIXEL:
341
0
                        eFrom = o3tl::Length::px;
342
0
                        break;
343
184k
                }
344
184k
            }
345
0
            else if( MeasureUnit::POINT == nTargetUnit )
346
0
            {
347
0
                if (MeasureUnit::POINT == nSourceUnit)
348
0
                    eFrom = o3tl::Length::pt;
349
0
            }
350
351
206k
            if (eFrom == o3tl::Length::invalid)
352
120
                return false;
353
354
            // TODO: check overflow
355
206k
            nVal = o3tl::convert(nVal, eFrom, Measure2O3tlUnit(nTargetUnit));
356
206k
        }
357
255k
    }
358
359
233k
    nVal += .5;
360
233k
    if( bNeg )
361
17.0k
        nVal = -nVal;
362
363
233k
    if( nVal <= static_cast<double>(nMin) )
364
164
        rValue = nMin;
365
233k
    else if( nVal >= static_cast<double>(nMax) )
366
1.45k
        rValue = nMax;
367
231k
    else
368
231k
        rValue = static_cast<sal_Int32>(nVal);
369
370
233k
    return true;
371
263k
}
converter.cxx:bool sax::lcl_convertMeasure<std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> > >(int&, std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> > const&, short, int, int)
Line
Count
Source
270
174k
{
271
174k
    double nVal = 0.0;
272
174k
    std::optional<sal_Int16> nSourceUnit;
273
174k
    bool bNeg = false;
274
275
174k
    if (!lcl_parseMeasure(nVal, nSourceUnit, bNeg, rString))
276
1.54k
    {
277
1.54k
        return false;
278
1.54k
    }
279
280
173k
    if (nSourceUnit.has_value())
281
165k
    {
282
165k
        if( MeasureUnit::PERCENT == nTargetUnit )
283
41.6k
        {
284
41.6k
            if (MeasureUnit::PERCENT != nSourceUnit)
285
30.1k
                return false;
286
41.6k
        }
287
123k
        else if( MeasureUnit::PIXEL == nTargetUnit )
288
0
        {
289
0
            if (MeasureUnit::PIXEL != nSourceUnit)
290
0
                return false;
291
0
        }
292
123k
        else
293
123k
        {
294
123k
            OSL_ENSURE( MeasureUnit::TWIP == nTargetUnit || MeasureUnit::POINT == nTargetUnit ||
295
123k
                        MeasureUnit::MM_100TH == nTargetUnit || MeasureUnit::MM_10TH == nTargetUnit ||
296
123k
                        MeasureUnit::PIXEL == nTargetUnit, "unit is not supported");
297
298
123k
            o3tl::Length eFrom = o3tl::Length::invalid;
299
300
123k
            if( MeasureUnit::TWIP == nTargetUnit )
301
21.8k
            {
302
21.8k
                switch (nSourceUnit.value())
303
21.8k
                {
304
13.5k
                    case MeasureUnit::CM:
305
13.5k
                        eFrom = o3tl::Length::cm;
306
13.5k
                        break;
307
83
                    case MeasureUnit::INCH:
308
83
                        eFrom = o3tl::Length::in;
309
83
                        break;
310
0
                    case MeasureUnit::MM:
311
0
                        eFrom = o3tl::Length::mm;
312
0
                        break;
313
8.16k
                    case MeasureUnit::POINT:
314
8.16k
                        eFrom = o3tl::Length::pt;
315
8.16k
                        break;
316
0
                    case MeasureUnit::PICA:
317
0
                        eFrom = o3tl::Length::pc;
318
0
                        break;
319
21.8k
                }
320
21.8k
            }
321
101k
            else if( MeasureUnit::MM_100TH == nTargetUnit || MeasureUnit::MM_10TH == nTargetUnit )
322
101k
            {
323
101k
                switch (nSourceUnit.value())
324
101k
                {
325
82.1k
                    case MeasureUnit::CM:
326
82.1k
                        eFrom = o3tl::Length::cm;
327
82.1k
                        break;
328
13.0k
                    case MeasureUnit::INCH:
329
13.0k
                        eFrom = o3tl::Length::in;
330
13.0k
                        break;
331
3.21k
                    case MeasureUnit::MM:
332
3.21k
                        eFrom = o3tl::Length::mm;
333
3.21k
                        break;
334
3.28k
                    case MeasureUnit::POINT:
335
3.28k
                        eFrom = o3tl::Length::pt;
336
3.28k
                        break;
337
0
                    case MeasureUnit::PICA:
338
0
                        eFrom = o3tl::Length::pc;
339
0
                        break;
340
0
                    case MeasureUnit::PIXEL:
341
0
                        eFrom = o3tl::Length::px;
342
0
                        break;
343
101k
                }
344
101k
            }
345
0
            else if( MeasureUnit::POINT == nTargetUnit )
346
0
            {
347
0
                if (MeasureUnit::POINT == nSourceUnit)
348
0
                    eFrom = o3tl::Length::pt;
349
0
            }
350
351
123k
            if (eFrom == o3tl::Length::invalid)
352
15
                return false;
353
354
            // TODO: check overflow
355
123k
            nVal = o3tl::convert(nVal, eFrom, Measure2O3tlUnit(nTargetUnit));
356
123k
        }
357
165k
    }
358
359
143k
    nVal += .5;
360
143k
    if( bNeg )
361
1.50k
        nVal = -nVal;
362
363
143k
    if( nVal <= static_cast<double>(nMin) )
364
17
        rValue = nMin;
365
143k
    else if( nVal >= static_cast<double>(nMax) )
366
1.41k
        rValue = nMax;
367
141k
    else
368
141k
        rValue = static_cast<sal_Int32>(nVal);
369
370
143k
    return true;
371
173k
}
converter.cxx:bool sax::lcl_convertMeasure<std::__1::basic_string_view<char, std::__1::char_traits<char> > >(int&, std::__1::basic_string_view<char, std::__1::char_traits<char> > const&, short, int, int)
Line
Count
Source
270
91.1k
{
271
91.1k
    double nVal = 0.0;
272
91.1k
    std::optional<sal_Int16> nSourceUnit;
273
91.1k
    bool bNeg = false;
274
275
91.1k
    if (!lcl_parseMeasure(nVal, nSourceUnit, bNeg, rString))
276
710
    {
277
710
        return false;
278
710
    }
279
280
90.4k
    if (nSourceUnit.has_value())
281
90.4k
    {
282
90.4k
        if( MeasureUnit::PERCENT == nTargetUnit )
283
7.38k
        {
284
7.38k
            if (MeasureUnit::PERCENT != nSourceUnit)
285
47
                return false;
286
7.38k
        }
287
83.0k
        else if( MeasureUnit::PIXEL == nTargetUnit )
288
0
        {
289
0
            if (MeasureUnit::PIXEL != nSourceUnit)
290
0
                return false;
291
0
        }
292
83.0k
        else
293
83.0k
        {
294
83.0k
            OSL_ENSURE( MeasureUnit::TWIP == nTargetUnit || MeasureUnit::POINT == nTargetUnit ||
295
83.0k
                        MeasureUnit::MM_100TH == nTargetUnit || MeasureUnit::MM_10TH == nTargetUnit ||
296
83.0k
                        MeasureUnit::PIXEL == nTargetUnit, "unit is not supported");
297
298
83.0k
            o3tl::Length eFrom = o3tl::Length::invalid;
299
300
83.0k
            if( MeasureUnit::TWIP == nTargetUnit )
301
0
            {
302
0
                switch (nSourceUnit.value())
303
0
                {
304
0
                    case MeasureUnit::CM:
305
0
                        eFrom = o3tl::Length::cm;
306
0
                        break;
307
0
                    case MeasureUnit::INCH:
308
0
                        eFrom = o3tl::Length::in;
309
0
                        break;
310
0
                    case MeasureUnit::MM:
311
0
                        eFrom = o3tl::Length::mm;
312
0
                        break;
313
0
                    case MeasureUnit::POINT:
314
0
                        eFrom = o3tl::Length::pt;
315
0
                        break;
316
0
                    case MeasureUnit::PICA:
317
0
                        eFrom = o3tl::Length::pc;
318
0
                        break;
319
0
                }
320
0
            }
321
83.0k
            else if( MeasureUnit::MM_100TH == nTargetUnit || MeasureUnit::MM_10TH == nTargetUnit )
322
83.0k
            {
323
83.0k
                switch (nSourceUnit.value())
324
83.0k
                {
325
64.1k
                    case MeasureUnit::CM:
326
64.1k
                        eFrom = o3tl::Length::cm;
327
64.1k
                        break;
328
18.0k
                    case MeasureUnit::INCH:
329
18.0k
                        eFrom = o3tl::Length::in;
330
18.0k
                        break;
331
754
                    case MeasureUnit::MM:
332
754
                        eFrom = o3tl::Length::mm;
333
754
                        break;
334
0
                    case MeasureUnit::POINT:
335
0
                        eFrom = o3tl::Length::pt;
336
0
                        break;
337
0
                    case MeasureUnit::PICA:
338
0
                        eFrom = o3tl::Length::pc;
339
0
                        break;
340
0
                    case MeasureUnit::PIXEL:
341
0
                        eFrom = o3tl::Length::px;
342
0
                        break;
343
83.0k
                }
344
83.0k
            }
345
0
            else if( MeasureUnit::POINT == nTargetUnit )
346
0
            {
347
0
                if (MeasureUnit::POINT == nSourceUnit)
348
0
                    eFrom = o3tl::Length::pt;
349
0
            }
350
351
83.0k
            if (eFrom == o3tl::Length::invalid)
352
105
                return false;
353
354
            // TODO: check overflow
355
82.9k
            nVal = o3tl::convert(nVal, eFrom, Measure2O3tlUnit(nTargetUnit));
356
82.9k
        }
357
90.4k
    }
358
359
90.3k
    nVal += .5;
360
90.3k
    if( bNeg )
361
15.5k
        nVal = -nVal;
362
363
90.3k
    if( nVal <= static_cast<double>(nMin) )
364
147
        rValue = nMin;
365
90.1k
    else if( nVal >= static_cast<double>(nMax) )
366
43
        rValue = nMax;
367
90.1k
    else
368
90.1k
        rValue = static_cast<sal_Int32>(nVal);
369
370
90.3k
    return true;
371
90.4k
}
372
373
/** convert string to measure using optional min and max values*/
374
bool Converter::convertMeasure( sal_Int32& rValue,
375
                                std::u16string_view rString,
376
                                sal_Int16 nTargetUnit /* = MeasureUnit::MM_100TH */,
377
                                sal_Int32 nMin /* = SAL_MIN_INT32 */,
378
                                sal_Int32 nMax /* = SAL_MAX_INT32 */ )
379
174k
{
380
174k
    return lcl_convertMeasure(rValue, rString, nTargetUnit, nMin, nMax);
381
174k
}
382
383
/** convert string to measure using optional min and max values*/
384
bool Converter::convertMeasure( sal_Int32& rValue,
385
                                std::string_view rString,
386
                                sal_Int16 nTargetUnit /* = MeasureUnit::MM_100TH */,
387
                                sal_Int32 nMin /* = SAL_MIN_INT32 */,
388
                                sal_Int32 nMax /* = SAL_MAX_INT32 */ )
389
91.1k
{
390
91.1k
    return lcl_convertMeasure(rValue, rString, nTargetUnit, nMin, nMax);
391
91.1k
}
392
393
394
/** convert measure in given unit to string with given unit */
395
void Converter::convertMeasure( OUStringBuffer& rBuffer,
396
                                sal_Int32 nMeasure,
397
                                sal_Int16 nSourceUnit /* = MeasureUnit::MM_100TH */,
398
                                sal_Int16 nTargetUnit /* = MeasureUnit::INCH */  )
399
12.4k
{
400
12.4k
    if( nSourceUnit == MeasureUnit::PERCENT )
401
0
    {
402
0
        OSL_ENSURE( nTargetUnit == MeasureUnit::PERCENT,
403
0
                    "MeasureUnit::PERCENT only maps to MeasureUnit::PERCENT!" );
404
405
0
        rBuffer.append( nMeasure );
406
0
        rBuffer.append( '%' );
407
408
0
        return;
409
0
    }
410
12.4k
    sal_Int64 nValue(nMeasure); // extend to 64-bit first to avoid overflow
411
    // the sign is processed separately
412
12.4k
    if (nValue < 0)
413
536
    {
414
536
        nValue = -nValue;
415
536
        rBuffer.append( '-' );
416
536
    }
417
418
12.4k
    o3tl::Length eFrom = o3tl::Length::in, eTo = o3tl::Length::in;
419
12.4k
    int nFac = 100; // used to get specific number of decimals (2 by default)
420
12.4k
    std::string_view psUnit;
421
12.4k
    switch( nSourceUnit )
422
12.4k
    {
423
0
    case MeasureUnit::TWIP:
424
0
        eFrom = o3tl::Length::twip;
425
0
        switch( nTargetUnit )
426
0
        {
427
0
        case MeasureUnit::MM_100TH:
428
0
        case MeasureUnit::MM_10TH:
429
0
            OSL_ENSURE( MeasureUnit::INCH == nTargetUnit,"output unit not supported for twip values" );
430
0
            [[fallthrough]];
431
0
        case MeasureUnit::MM:
432
0
            eTo = o3tl::Length::mm;
433
0
            nFac = 100;
434
0
            psUnit = gpsMM;
435
0
            break;
436
437
0
        case MeasureUnit::CM:
438
0
            eTo = o3tl::Length::cm;
439
0
            nFac = 1000;
440
0
            psUnit = gpsCM;
441
0
            break;
442
443
0
        case MeasureUnit::POINT:
444
0
            eTo = o3tl::Length::pt;
445
0
            nFac = 100;
446
0
            psUnit = gpsPT;
447
0
            break;
448
449
0
        case MeasureUnit::INCH:
450
0
        default:
451
0
            OSL_ENSURE( MeasureUnit::INCH == nTargetUnit,
452
0
                        "output unit not supported for twip values" );
453
0
            nFac = 10000;
454
0
            psUnit = gpsINCH;
455
0
            break;
456
0
        }
457
0
        break;
458
459
0
    case MeasureUnit::POINT:
460
        // 1pt = 1pt (exactly)
461
0
        OSL_ENSURE( MeasureUnit::POINT == nTargetUnit,
462
0
                    "output unit not supported for pt values" );
463
0
        eFrom = eTo = o3tl::Length::pt;
464
0
        nFac = 1;
465
0
        psUnit = gpsPT;
466
0
        break;
467
0
    case MeasureUnit::MM_10TH:
468
12.4k
    case MeasureUnit::MM_100TH:
469
12.4k
        {
470
12.4k
            int nFac2 = (MeasureUnit::MM_100TH == nSourceUnit) ? 100 : 10;
471
12.4k
            eFrom = Measure2O3tlUnit(nSourceUnit);
472
12.4k
            switch( nTargetUnit )
473
12.4k
            {
474
0
            case MeasureUnit::MM_100TH:
475
0
            case MeasureUnit::MM_10TH:
476
0
                OSL_ENSURE( MeasureUnit::INCH == nTargetUnit,
477
0
                            "output unit not supported for 1/100mm values" );
478
0
                [[fallthrough]];
479
0
            case MeasureUnit::MM:
480
0
                eTo = o3tl::Length::mm;
481
0
                nFac = nFac2;
482
0
                psUnit = gpsMM;
483
0
                break;
484
485
12.4k
            case MeasureUnit::CM:
486
12.4k
                eTo = o3tl::Length::cm;
487
12.4k
                nFac = 10*nFac2;
488
12.4k
                psUnit = gpsCM;
489
12.4k
                break;
490
491
0
            case MeasureUnit::POINT:
492
0
                eTo = o3tl::Length::pt;
493
0
                nFac = nFac2;
494
0
                psUnit = gpsPT;
495
0
                break;
496
497
0
            case MeasureUnit::INCH:
498
0
            default:
499
0
                OSL_ENSURE( MeasureUnit::INCH == nTargetUnit,
500
0
                            "output unit not supported for 1/100mm values" );
501
0
                nFac = 100*nFac2;
502
0
                psUnit = gpsINCH;
503
0
                break;
504
12.4k
            }
505
12.4k
            break;
506
12.4k
        }
507
12.4k
    default:
508
0
        OSL_ENSURE(false, "sax::Converter::convertMeasure(): "
509
0
                "source unit not supported");
510
0
        break;
511
12.4k
    }
512
513
12.4k
    nValue = o3tl::convert(nValue * nFac, eFrom, eTo);
514
515
12.4k
    rBuffer.append( static_cast<sal_Int64>(nValue / nFac) );
516
12.4k
    if (nFac > 1 && (nValue % nFac) != 0)
517
10.2k
    {
518
10.2k
        rBuffer.append( '.' );
519
35.9k
        while (nFac > 1 && (nValue % nFac) != 0)
520
25.6k
        {
521
25.6k
            nFac /= 10;
522
25.6k
            rBuffer.append( static_cast<sal_Int32>((nValue / nFac) % 10) );
523
25.6k
        }
524
10.2k
    }
525
526
12.4k
    if (psUnit.length() > 0)
527
12.4k
        rBuffer.appendAscii(psUnit.data(), psUnit.length());
528
12.4k
}
529
530
/** convert string to measure with unit*/
531
bool Converter::convertMeasureUnit(double& rValue, std::optional<sal_Int16>& rValueUnit,
532
                                   std::u16string_view rString)
533
0
{
534
0
    bool bNeg = false;
535
0
    bool bResult = lcl_parseMeasure(rValue, rValueUnit, bNeg, rString);
536
537
0
    if (bNeg)
538
0
    {
539
0
        rValue = -rValue;
540
0
    }
541
542
0
    return bResult;
543
0
}
544
545
/** convert string to measure with unit*/
546
bool Converter::convertMeasureUnit(double& rValue, std::optional<sal_Int16>& rValueUnit,
547
                                   std::string_view rString)
548
0
{
549
0
    bool bNeg = false;
550
0
    bool bResult = lcl_parseMeasure(rValue, rValueUnit, bNeg, rString);
551
552
0
    if (bNeg)
553
0
    {
554
0
        rValue = -rValue;
555
0
    }
556
557
0
    return bResult;
558
0
}
559
560
/** convert measure with given unit to string with given unit*/
561
void Converter::convertMeasureUnit(OUStringBuffer& rBuffer, double dValue,
562
                                   std::optional<sal_Int16> nValueUnit)
563
0
{
564
0
    ::rtl::math::doubleToUStringBuffer(rBuffer, dValue, rtl_math_StringFormat_Automatic,
565
0
                                       rtl_math_DecimalPlaces_Max, '.', true);
566
567
0
    if (nValueUnit.has_value())
568
0
    {
569
0
        if (auto it = stConvertMeasureUnitStrMap.find(*nValueUnit);
570
0
            it != stConvertMeasureUnitStrMap.end())
571
0
        {
572
0
            rBuffer.appendAscii(it->second.data(), it->second.length());
573
0
        }
574
0
    }
575
0
}
576
577
/** convert string to boolean */
578
bool Converter::convertBool( bool& rBool, std::u16string_view rString )
579
59.1k
{
580
59.1k
    rBool = rString == u"true";
581
582
59.1k
    return rBool || (rString == u"false");
583
59.1k
}
584
585
/** convert string to boolean */
586
bool Converter::convertBool( bool& rBool, std::string_view rString )
587
2.32k
{
588
2.32k
    rBool = rString == "true";
589
590
2.32k
    return rBool || (rString == "false");
591
2.32k
}
592
593
/** convert boolean to string */
594
void Converter::convertBool( OUStringBuffer& rBuffer, bool bValue )
595
1.02k
{
596
1.02k
    rBuffer.append( bValue );
597
1.02k
}
598
599
/** convert string to percent */
600
bool Converter::convertPercent( sal_Int32& rPercent, std::u16string_view rString )
601
42.4k
{
602
42.4k
    return convertMeasure( rPercent, rString, MeasureUnit::PERCENT );
603
42.4k
}
604
605
/** convert string to percent */
606
bool Converter::convertPercent( sal_Int32& rPercent, std::string_view rString )
607
7.41k
{
608
7.41k
    return convertMeasure( rPercent, rString, MeasureUnit::PERCENT );
609
7.41k
}
610
611
/** convert percent to string */
612
void Converter::convertPercent( OUStringBuffer& rBuffer, sal_Int32 nValue )
613
3.19k
{
614
3.19k
    rBuffer.append( nValue );
615
3.19k
    rBuffer.append( '%' );
616
3.19k
}
617
618
/** convert string to pixel measure */
619
bool Converter::convertMeasurePx( sal_Int32& rPixel, std::u16string_view rString )
620
0
{
621
0
    return convertMeasure( rPixel, rString, MeasureUnit::PIXEL );
622
0
}
623
624
/** convert string to pixel measure */
625
bool Converter::convertMeasurePx( sal_Int32& rPixel, std::string_view rString )
626
0
{
627
0
    return convertMeasure( rPixel, rString, MeasureUnit::PIXEL );
628
0
}
629
630
/** convert pixel measure to string */
631
void Converter::convertMeasurePx( OUStringBuffer& rBuffer, sal_Int32 nValue )
632
0
{
633
0
    rBuffer.append( nValue );
634
0
    rBuffer.append( 'p' );
635
0
    rBuffer.append( 'x' );
636
0
}
637
638
/** convert string to rgb color */
639
template<typename V>
640
static bool lcl_convertColor( sal_Int32& rColor, V rValue )
641
65.0k
{
642
65.0k
    if( rValue.size() != 7 || rValue[0] != '#' )
643
25.3k
        return false;
644
645
39.7k
    rColor = o3tl::convertToHex<sal_Int32>(rValue[1], rValue[2]);
646
39.7k
    rColor <<= 8;
647
648
39.7k
    rColor |= o3tl::convertToHex<sal_Int32>(rValue[3], rValue[4]);
649
39.7k
    rColor <<= 8;
650
651
39.7k
    rColor |= o3tl::convertToHex<sal_Int32>(rValue[5], rValue[6]);
652
653
39.7k
    return true;
654
65.0k
}
converter.cxx:bool sax::lcl_convertColor<std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> > >(int&, std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >)
Line
Count
Source
641
57.8k
{
642
57.8k
    if( rValue.size() != 7 || rValue[0] != '#' )
643
25.2k
        return false;
644
645
32.6k
    rColor = o3tl::convertToHex<sal_Int32>(rValue[1], rValue[2]);
646
32.6k
    rColor <<= 8;
647
648
32.6k
    rColor |= o3tl::convertToHex<sal_Int32>(rValue[3], rValue[4]);
649
32.6k
    rColor <<= 8;
650
651
32.6k
    rColor |= o3tl::convertToHex<sal_Int32>(rValue[5], rValue[6]);
652
653
32.6k
    return true;
654
57.8k
}
converter.cxx:bool sax::lcl_convertColor<std::__1::basic_string_view<char, std::__1::char_traits<char> > >(int&, std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
641
7.15k
{
642
7.15k
    if( rValue.size() != 7 || rValue[0] != '#' )
643
52
        return false;
644
645
7.09k
    rColor = o3tl::convertToHex<sal_Int32>(rValue[1], rValue[2]);
646
7.09k
    rColor <<= 8;
647
648
7.09k
    rColor |= o3tl::convertToHex<sal_Int32>(rValue[3], rValue[4]);
649
7.09k
    rColor <<= 8;
650
651
7.09k
    rColor |= o3tl::convertToHex<sal_Int32>(rValue[5], rValue[6]);
652
653
7.09k
    return true;
654
7.15k
}
655
656
/** convert string to rgb color */
657
bool Converter::convertColor( sal_Int32& rColor, std::u16string_view rValue )
658
57.8k
{
659
57.8k
    return lcl_convertColor(rColor, rValue);
660
57.8k
}
661
662
/** convert string to rgb color */
663
bool Converter::convertColor( sal_Int32& rColor, std::string_view rValue )
664
7.15k
{
665
7.15k
    return lcl_convertColor(rColor, rValue);
666
7.15k
}
667
668
const char aHexTab[] = "0123456789abcdef";
669
670
/** convert color to string */
671
void Converter::convertColor( OUStringBuffer& rBuffer, sal_Int32 nColor )
672
2.97k
{
673
2.97k
    rBuffer.append( '#' );
674
675
2.97k
    sal_uInt8 nCol = static_cast<sal_uInt8>(nColor >> 16);
676
2.97k
    rBuffer.append( sal_Unicode( aHexTab[ nCol >> 4 ] ) );
677
2.97k
    rBuffer.append( sal_Unicode( aHexTab[ nCol & 0xf ] ) );
678
679
2.97k
    nCol = static_cast<sal_uInt8>(nColor >> 8);
680
2.97k
    rBuffer.append( sal_Unicode( aHexTab[ nCol >> 4 ] ) );
681
2.97k
    rBuffer.append( sal_Unicode( aHexTab[ nCol & 0xf ] ) );
682
683
2.97k
    nCol = static_cast<sal_uInt8>(nColor);
684
2.97k
    rBuffer.append( sal_Unicode( aHexTab[ nCol >> 4 ] ) );
685
2.97k
    rBuffer.append( sal_Unicode( aHexTab[ nCol & 0xf ] ) );
686
2.97k
}
687
688
/** convert string to number with optional min and max values */
689
bool Converter::convertNumber(  sal_Int32& rValue,
690
                                std::u16string_view aString,
691
                                sal_Int32 nMin, sal_Int32 nMax )
692
755k
{
693
755k
    rValue = 0;
694
755k
    sal_Int64 nNumber = 0;
695
755k
    bool bRet = convertNumber64(nNumber,aString,nMin,nMax);
696
755k
    if ( bRet )
697
750k
        rValue = static_cast<sal_Int32>(nNumber);
698
755k
    return bRet;
699
755k
}
700
701
/** convert string to number with optional min and max values */
702
bool Converter::convertNumber(  sal_Int32& rValue,
703
                                std::string_view aString,
704
                                sal_Int32 nMin, sal_Int32 nMax )
705
63.5k
{
706
63.5k
    rValue = 0;
707
63.5k
    sal_Int64 nNumber = 0;
708
63.5k
    bool bRet = convertNumber64(nNumber,aString,nMin,nMax);
709
63.5k
    if ( bRet )
710
52.8k
        rValue = static_cast<sal_Int32>(nNumber);
711
63.5k
    return bRet;
712
63.5k
}
713
714
/** convert string to 64-bit number with optional min and max values */
715
template<typename V>
716
static bool lcl_convertNumber64( sal_Int64& rValue,
717
                                 V aString,
718
                                 sal_Int64 nMin, sal_Int64 nMax )
719
819k
{
720
819k
    sal_Int32 nPos = 0;
721
819k
    sal_Int32 const nLen = aString.size();
722
723
    // skip white space
724
819k
    while( (nPos < nLen) && (aString[nPos] <= ' ') )
725
332
        nPos++;
726
727
819k
    sal_Int32 nNumberStartPos = nPos;
728
729
819k
    if( nPos < nLen && '-' == aString[nPos] )
730
41.7k
    {
731
41.7k
        nPos++;
732
41.7k
    }
733
734
    // get number
735
3.87M
    while( nPos < nLen &&
736
3.06M
           '0' <= aString[nPos] &&
737
3.05M
           '9' >= aString[nPos] )
738
3.05M
    {
739
3.05M
        nPos++;
740
3.05M
    }
741
742
819k
    rValue = toInt64_WithLength(aString.data() + nNumberStartPos, 10, nPos - nNumberStartPos);
743
744
819k
    if( rValue < nMin )
745
6.48k
        rValue = nMin;
746
813k
    else if( rValue > nMax )
747
3.48k
        rValue = nMax;
748
749
819k
    return ( nPos == nLen && rValue >= nMin && rValue <= nMax );
750
819k
}
converter.cxx:bool sax::lcl_convertNumber64<std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> > >(long&, std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >, long, long)
Line
Count
Source
719
755k
{
720
755k
    sal_Int32 nPos = 0;
721
755k
    sal_Int32 const nLen = aString.size();
722
723
    // skip white space
724
755k
    while( (nPos < nLen) && (aString[nPos] <= ' ') )
725
10
        nPos++;
726
727
755k
    sal_Int32 nNumberStartPos = nPos;
728
729
755k
    if( nPos < nLen && '-' == aString[nPos] )
730
41.0k
    {
731
41.0k
        nPos++;
732
41.0k
    }
733
734
    // get number
735
3.72M
    while( nPos < nLen &&
736
2.97M
           '0' <= aString[nPos] &&
737
2.96M
           '9' >= aString[nPos] )
738
2.96M
    {
739
2.96M
        nPos++;
740
2.96M
    }
741
742
755k
    rValue = toInt64_WithLength(aString.data() + nNumberStartPos, 10, nPos - nNumberStartPos);
743
744
755k
    if( rValue < nMin )
745
5.81k
        rValue = nMin;
746
750k
    else if( rValue > nMax )
747
3.31k
        rValue = nMax;
748
749
755k
    return ( nPos == nLen && rValue >= nMin && rValue <= nMax );
750
755k
}
converter.cxx:bool sax::lcl_convertNumber64<std::__1::basic_string_view<char, std::__1::char_traits<char> > >(long&, std::__1::basic_string_view<char, std::__1::char_traits<char> >, long, long)
Line
Count
Source
719
63.5k
{
720
63.5k
    sal_Int32 nPos = 0;
721
63.5k
    sal_Int32 const nLen = aString.size();
722
723
    // skip white space
724
63.8k
    while( (nPos < nLen) && (aString[nPos] <= ' ') )
725
322
        nPos++;
726
727
63.5k
    sal_Int32 nNumberStartPos = nPos;
728
729
63.5k
    if( nPos < nLen && '-' == aString[nPos] )
730
698
    {
731
698
        nPos++;
732
698
    }
733
734
    // get number
735
149k
    while( nPos < nLen &&
736
96.6k
           '0' <= aString[nPos] &&
737
86.5k
           '9' >= aString[nPos] )
738
85.9k
    {
739
85.9k
        nPos++;
740
85.9k
    }
741
742
63.5k
    rValue = toInt64_WithLength(aString.data() + nNumberStartPos, 10, nPos - nNumberStartPos);
743
744
63.5k
    if( rValue < nMin )
745
669
        rValue = nMin;
746
62.8k
    else if( rValue > nMax )
747
172
        rValue = nMax;
748
749
63.5k
    return ( nPos == nLen && rValue >= nMin && rValue <= nMax );
750
63.5k
}
751
752
/** convert string to 64-bit number with optional min and max values */
753
bool Converter::convertNumber64( sal_Int64& rValue,
754
                                 std::u16string_view aString,
755
                                 sal_Int64 nMin, sal_Int64 nMax )
756
755k
{
757
755k
    return lcl_convertNumber64(rValue, aString, nMin, nMax);
758
755k
}
759
760
/** convert string to 64-bit number with optional min and max values */
761
bool Converter::convertNumber64( sal_Int64& rValue,
762
                                 std::string_view aString,
763
                                 sal_Int64 nMin, sal_Int64 nMax )
764
63.5k
{
765
63.5k
    return lcl_convertNumber64(rValue, aString, nMin, nMax);
766
63.5k
}
767
768
769
/** convert double number to string (using ::rtl::math) */
770
void Converter::convertDouble(  OUStringBuffer& rBuffer,
771
                                double fNumber,
772
                                bool bWriteUnits,
773
                                sal_Int16 nSourceUnit,
774
                                sal_Int16 nTargetUnit)
775
1.28k
{
776
1.28k
    if(MeasureUnit::PERCENT == nSourceUnit)
777
0
    {
778
0
        OSL_ENSURE( nTargetUnit == MeasureUnit::PERCENT, "MeasureUnit::PERCENT only maps to MeasureUnit::PERCENT!" );
779
0
        ::rtl::math::doubleToUStringBuffer( rBuffer, fNumber, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', true);
780
0
        if(bWriteUnits)
781
0
            rBuffer.append('%');
782
0
    }
783
1.28k
    else
784
1.28k
    {
785
1.28k
        OUStringBuffer sUnit;
786
1.28k
        double fFactor = GetConversionFactor(sUnit, nSourceUnit, nTargetUnit);
787
1.28k
        if(fFactor != 1.0)
788
0
            fNumber *= fFactor;
789
1.28k
        ::rtl::math::doubleToUStringBuffer( rBuffer, fNumber, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', true);
790
1.28k
        if(bWriteUnits)
791
1.28k
            rBuffer.append(sUnit);
792
1.28k
    }
793
1.28k
}
794
795
/** convert double number to string (using ::rtl::math) */
796
void Converter::convertDouble( OUStringBuffer& rBuffer, double fNumber)
797
4.34k
{
798
4.34k
    ::rtl::math::doubleToUStringBuffer( rBuffer, fNumber, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', true);
799
4.34k
}
800
801
/** convert string to double number (using ::rtl::math) */
802
bool Converter::convertDouble(double& rValue,
803
    std::u16string_view rString, sal_Int16 nSourceUnit, sal_Int16 nTargetUnit)
804
47.3k
{
805
47.3k
    if (!convertDouble(rValue, rString))
806
23
        return false;
807
808
47.3k
    OUStringBuffer sUnit;
809
    // fdo#48969: switch source and target because factor is used to divide!
810
47.3k
    double const fFactor =
811
47.3k
        GetConversionFactor(sUnit, nTargetUnit, nSourceUnit);
812
47.3k
    if(fFactor != 1.0 && fFactor != 0.0)
813
11
        rValue /= fFactor;
814
47.3k
    return true;
815
47.3k
}
816
817
/** convert string to double number (using ::rtl::math) */
818
bool Converter::convertDouble(double& rValue,
819
    std::string_view rString, sal_Int16 nSourceUnit, sal_Int16 nTargetUnit)
820
0
{
821
0
    if (!convertDouble(rValue, rString))
822
0
        return false;
823
824
0
    OStringBuffer sUnit;
825
    // fdo#48969: switch source and target because factor is used to divide!
826
0
    double const fFactor =
827
0
        GetConversionFactor(sUnit, nTargetUnit, nSourceUnit);
828
0
    if(fFactor != 1.0 && fFactor != 0.0)
829
0
        rValue /= fFactor;
830
0
    return true;
831
0
}
832
833
/** convert string to double number (using ::rtl::math) */
834
bool Converter::convertDouble(double& rValue, std::u16string_view rString, std::u16string_view* pRest)
835
48.9k
{
836
48.9k
    rtl_math_ConversionStatus eStatus;
837
48.9k
    const sal_Unicode* pEnd;
838
48.9k
    rValue = rtl_math_uStringToDouble(rString.data(),
839
48.9k
                                     rString.data() + rString.size(),
840
48.9k
                                     /*cDecSeparator*/'.', /*cGroupSeparator*/',',
841
48.9k
                                     &eStatus, &pEnd);
842
48.9k
    if (pRest)
843
0
        *pRest = rString.substr(pEnd - rString.data());
844
48.9k
    return ( eStatus == rtl_math_ConversionStatus_Ok );
845
48.9k
}
846
847
/** convert string to double number (using ::rtl::math) */
848
bool Converter::convertDouble(double& rValue, std::string_view rString, std::string_view* pRest)
849
116
{
850
116
    rtl_math_ConversionStatus eStatus;
851
116
    const char* pEnd;
852
116
    rValue = rtl_math_stringToDouble(rString.data(),
853
116
                                     rString.data() + rString.size(),
854
116
                                     /*cDecSeparator*/'.', /*cGroupSeparator*/',',
855
116
                                     &eStatus, &pEnd);
856
116
    if (pRest)
857
0
        *pRest = rString.substr(pEnd - rString.data());
858
116
    return ( eStatus == rtl_math_ConversionStatus_Ok );
859
116
}
860
861
/** convert number, 10th of degrees with range [0..3600] to SVG angle */
862
void Converter::convert10thDegAngle(OUStringBuffer& rBuffer, sal_Int16 const nAngle,
863
                                    const bool isWrongOOo10thDegAngle)
864
282
{
865
282
    if (isWrongOOo10thDegAngle)
866
0
    {
867
0
        rBuffer.append(static_cast<sal_Int32>(nAngle));
868
0
    }
869
282
    else
870
282
    {
871
282
        double fAngle(double(nAngle) / 10.0);
872
282
        ::sax::Converter::convertDouble(rBuffer, fAngle);
873
282
        rBuffer.append("deg");
874
282
    }
875
282
}
876
877
/** convert SVG angle to number in 10th of degrees */
878
bool Converter::convert10thDegAngle(sal_Int16& rAngle, std::u16string_view rString,
879
                                    bool const isWrongOOo10thDegAngle)
880
0
{
881
    // ODF 1.1 leaves it undefined what the number means, but ODF 1.2 says it's
882
    // degrees, while OOo has historically used 10th of degrees :(
883
    // So import degrees when we see the "deg" suffix but continue with 10th of
884
    // degrees for now for the sake of existing OOo/LO documents, until the
885
    // new versions that can read "deg" suffix are widely deployed and we can
886
    // start to write the "deg" suffix.
887
0
    double fAngle(0.0);
888
0
    std::u16string_view aRest;
889
0
    bool bRet = ::sax::Converter::convertDouble(fAngle, rString, &aRest);
890
0
    if (bRet)
891
0
    {
892
0
        if (aRest == u"deg")
893
0
            fAngle *= 10.0;
894
0
        else if (aRest == u"grad")
895
0
            fAngle *= 9.0; // 360deg = 400grad
896
0
        else if (aRest == u"rad")
897
0
            fAngle = basegfx::rad2deg<10>(fAngle);
898
0
        else // no explicit unit
899
0
        { // isWrongOOo10thDegAngle = true: nothing to do here. Wrong, but backward compatible.
900
0
            if (!aRest.empty())
901
0
            {
902
                // Wrong unit. Don't change rAngle, rely on callers checking boolean return
903
0
                return false;
904
0
            }
905
0
            if (!isWrongOOo10thDegAngle)
906
0
                fAngle *= 10.0; // conform to ODF 1.2 and newer
907
0
        }
908
0
        fAngle = std::clamp<double>(basegfx::fround(fAngle), SHRT_MIN, SHRT_MAX);
909
0
        rAngle = static_cast<sal_Int16>(fAngle);
910
0
    }
911
0
    return bRet;
912
0
}
913
914
/** convert SVG angle to number, 10th of degrees with range [0..3600] */
915
bool Converter::convert10thDegAngle(sal_Int16& rAngle, std::string_view rString,
916
                                    bool const isWrongOOo10thDegAngle)
917
0
{
918
    // ODF 1.1 leaves it undefined what the number means, but ODF 1.2 says it's
919
    // degrees, while OOo has historically used 10th of degrees :(
920
    // So import degrees when we see the "deg" suffix but continue with 10th of
921
    // degrees for now for the sake of existing OOo/LO documents, until the
922
    // new versions that can read "deg" suffix are widely deployed and we can
923
    // start to write the "deg" suffix.
924
0
    double fAngle(0.0);
925
0
    std::string_view aRest;
926
0
    bool bRet = ::sax::Converter::convertDouble(fAngle, rString, &aRest);
927
0
    if (bRet)
928
0
    {
929
0
        if (aRest == "deg")
930
0
            fAngle *= 10.0;
931
0
        else if (aRest == "grad")
932
0
            fAngle *= 9.0; // 360deg = 400grad
933
0
        else if (aRest == "rad")
934
0
            fAngle = basegfx::rad2deg<10>(fAngle);
935
0
        else // no explicit unit
936
0
        { // isWrongOOo10thDegAngle = true: nothing to do here. Wrong, but backward compatible.
937
0
            if (!aRest.empty())
938
0
            {
939
                // Wrong unit. Don't change rAngle, rely on callers checking boolean return
940
0
                return false;
941
0
            }
942
0
            if (!isWrongOOo10thDegAngle)
943
0
                fAngle *= 10.0; // conform to ODF 1.2 and newer
944
0
        }
945
0
        fAngle = std::clamp<double>(basegfx::fround(fAngle), SHRT_MIN, SHRT_MAX);
946
0
        rAngle = static_cast<sal_Int16>(fAngle);
947
0
    }
948
0
    return bRet;
949
0
}
950
951
/** convert SVG angle to number, in degrees, range [0..360] */
952
bool Converter::convertAngle(double& rAngle, std::u16string_view rString)
953
0
{
954
    // ODF uses in several places angles in data type 'angle' (18.3.1, ODF 1.3). That is a double
955
    // followed by unit identifier deg, grad or rad or a unitless value in degrees.
956
    // This method converts ODF 'angle' to double degrees and normalizes it to range
957
    // [0..360]. Further type converting and range restriction are done by the caller.
958
0
    std::u16string_view aRest;
959
0
    bool bRet = ::sax::Converter::convertDouble(rAngle, rString, &aRest);
960
0
    if (bRet)
961
0
    {
962
        //degrees
963
0
        if (aRest == u"grad")
964
0
            rAngle *= 0.9; // 360deg = 400grad
965
0
        else if (aRest == u"rad")
966
0
            rAngle = basegfx::rad2deg(rAngle);
967
0
        else if (aRest != u"deg" && !aRest.empty())
968
0
        {
969
            // Wrong unit
970
0
            rAngle = 0;
971
0
            return false;
972
0
        }
973
        // degrees in range [0..360]
974
0
        rAngle = basegfx::snapToZeroRange(rAngle, 360.0);
975
0
    }
976
0
    return bRet;
977
0
}
978
979
/** convert SVG angle to number, in degrees, range [0..360] */
980
bool Converter::convertAngle(double& rAngle, std::string_view rString)
981
0
{
982
    // ODF uses in several places angles in data type 'angle' (18.3.1, ODF 1.3). That is a double
983
    // followed by unit identifier deg, grad or rad or a unitless value in degrees.
984
    // This method converts ODF 'angle' to double degrees and normalizes it to range
985
    // [0..360]. Further type converting and range restriction are done by the caller.
986
0
    std::string_view aRest;
987
0
    bool bRet = ::sax::Converter::convertDouble(rAngle, rString, &aRest);
988
0
    if (bRet)
989
0
    {
990
        // degrees
991
0
        if (aRest == "grad")
992
0
            rAngle *= 0.9; // 360deg = 400grad
993
0
        else if (aRest == "rad")
994
0
            rAngle = basegfx::rad2deg(rAngle);
995
0
        else if (aRest != "deg" && !aRest.empty())
996
0
        {
997
            // Wrong unit
998
0
            rAngle = 0;
999
0
            return false;
1000
0
        }
1001
        // degrees in range [0..360]
1002
0
        rAngle = basegfx::snapToZeroRange(rAngle, 360.0);
1003
0
    }
1004
0
    return bRet;
1005
0
}
1006
1007
/** convert double to ISO "duration" string; negative durations allowed */
1008
void Converter::convertDuration(OUStringBuffer& rBuffer,
1009
                                const double fTime)
1010
0
{
1011
0
    double fValue = fTime;
1012
1013
    // take care of negative durations as specified in:
1014
    // XML Schema, W3C Working Draft 07 April 2000, section 3.2.6.1
1015
0
    if (fValue < 0.0)
1016
0
    {
1017
0
        rBuffer.append('-');
1018
0
        fValue = - fValue;
1019
0
    }
1020
1021
0
    rBuffer.append( "PT" );
1022
0
    fValue *= 24;
1023
0
    double fHoursValue = ::rtl::math::approxFloor (fValue);
1024
0
    fValue -= fHoursValue;
1025
0
    fValue *= 60;
1026
0
    double fMinsValue = ::rtl::math::approxFloor (fValue);
1027
0
    fValue -= fMinsValue;
1028
0
    fValue *= 60;
1029
0
    double fSecsValue = ::rtl::math::approxFloor (fValue);
1030
0
    fValue -= fSecsValue;
1031
0
    double fNanoSecsValue;
1032
0
    if (fValue > 0.00000000001)
1033
0
        fNanoSecsValue = ::rtl::math::round( fValue, XML_MAXDIGITSCOUNT_TIME - 5);
1034
0
    else
1035
0
        fNanoSecsValue = 0.0;
1036
1037
0
    if (fNanoSecsValue == 1.0)
1038
0
    {
1039
0
        fNanoSecsValue = 0.0;
1040
0
        fSecsValue += 1.0;
1041
0
    }
1042
0
    if (fSecsValue >= 60.0)
1043
0
    {
1044
0
        fSecsValue -= 60.0;
1045
0
        fMinsValue += 1.0;
1046
0
    }
1047
0
    if (fMinsValue >= 60.0)
1048
0
    {
1049
0
        fMinsValue -= 60.0;
1050
0
        fHoursValue += 1.0;
1051
0
    }
1052
1053
0
    if (fHoursValue < 10)
1054
0
        rBuffer.append( '0');
1055
0
    rBuffer.append( sal_Int32( fHoursValue));
1056
0
    rBuffer.append( 'H');
1057
0
    if (fMinsValue < 10)
1058
0
        rBuffer.append( '0');
1059
0
    rBuffer.append( sal_Int32( fMinsValue));
1060
0
    rBuffer.append( 'M');
1061
0
    if (fSecsValue < 10)
1062
0
        rBuffer.append( '0');
1063
0
    rBuffer.append( sal_Int32( fSecsValue));
1064
0
    if (fNanoSecsValue > 0.0)
1065
0
    {
1066
0
        OUString aNS( ::rtl::math::doubleToUString( fValue,
1067
0
                    rtl_math_StringFormat_F, XML_MAXDIGITSCOUNT_TIME - 5, '.',
1068
0
                    true));
1069
0
        if ( aNS.getLength() > 2 )
1070
0
        {
1071
0
            rBuffer.append( '.');
1072
0
            rBuffer.append( aNS.subView(2) );     // strip "0."
1073
0
        }
1074
0
    }
1075
0
    rBuffer.append( 'S');
1076
0
}
1077
1078
/** helper function of Converter::convertDuration */
1079
template<typename V>
1080
static bool convertDurationHelper(double& rfTime, V pStr)
1081
0
{
1082
    // negative time duration?
1083
0
    bool bIsNegativeDuration = false;
1084
0
    if ( '-' == (*pStr) )
1085
0
    {
1086
0
        bIsNegativeDuration = true;
1087
0
        pStr++;
1088
0
    }
1089
1090
0
    if ( *pStr != 'P' && *pStr != 'p' )            // duration must start with "P"
1091
0
        return false;
1092
0
    pStr++;
1093
1094
0
    OUStringBuffer sDoubleStr;
1095
0
    bool bSuccess = true;
1096
0
    bool bDone = false;
1097
0
    bool bTimePart = false;
1098
0
    bool bIsFraction = false;
1099
0
    sal_Int32 nDays  = 0;
1100
0
    sal_Int32 nHours = 0;
1101
0
    sal_Int32 nMins  = 0;
1102
0
    sal_Int32 nSecs  = 0;
1103
0
    sal_Int32 nTemp = 0;
1104
1105
0
    while ( bSuccess && !bDone )
1106
0
    {
1107
0
        sal_Unicode c = *(pStr++);
1108
0
        if ( !c )                               // end
1109
0
            bDone = true;
1110
0
        else if ( '0' <= c && '9' >= c )
1111
0
        {
1112
0
            if ( nTemp >= SAL_MAX_INT32 / 10 )
1113
0
                bSuccess = false;
1114
0
            else
1115
0
            {
1116
0
                if ( !bIsFraction )
1117
0
                {
1118
0
                    nTemp *= 10;
1119
0
                    nTemp += (c - u'0');
1120
0
                }
1121
0
                else
1122
0
                {
1123
0
                    sDoubleStr.append(c);
1124
0
                }
1125
0
            }
1126
0
        }
1127
0
        else if ( bTimePart )
1128
0
        {
1129
0
            if ( c == 'H' || c == 'h' )
1130
0
            {
1131
0
                nHours = nTemp;
1132
0
                nTemp = 0;
1133
0
            }
1134
0
            else if ( c == 'M' || c == 'm')
1135
0
            {
1136
0
                nMins = nTemp;
1137
0
                nTemp = 0;
1138
0
            }
1139
0
            else if ( (c == ',') || (c == '.') )
1140
0
            {
1141
0
                nSecs = nTemp;
1142
0
                nTemp = 0;
1143
0
                bIsFraction = true;
1144
0
                sDoubleStr = "0.";
1145
0
            }
1146
0
            else if ( c == 'S' || c == 's' )
1147
0
            {
1148
0
                if ( !bIsFraction )
1149
0
                {
1150
0
                    nSecs = nTemp;
1151
0
                    nTemp = 0;
1152
0
                    sDoubleStr = "0.0";
1153
0
                }
1154
0
            }
1155
0
            else
1156
0
                bSuccess = false;               // invalid character
1157
0
        }
1158
0
        else
1159
0
        {
1160
0
            if ( c == 'T' || c == 't' )            // "T" starts time part
1161
0
                bTimePart = true;
1162
0
            else if ( c == 'D' || c == 'd')
1163
0
            {
1164
0
                nDays = nTemp;
1165
0
                nTemp = 0;
1166
0
            }
1167
0
            else if ( c == 'Y' || c == 'y' || c == 'M' || c == 'm' )
1168
0
            {
1169
                //! how many days is a year or month?
1170
1171
0
                OSL_FAIL( "years or months in duration: not implemented");
1172
0
                bSuccess = false;
1173
0
            }
1174
0
            else
1175
0
                bSuccess = false;               // invalid character
1176
0
        }
1177
0
    }
1178
1179
0
    if ( bSuccess )
1180
0
    {
1181
        // Calculate similar to ImpSvNumberInputScan::GetTimeRef: first, sum whole seconds, add
1182
        // second fraction, and finally, divide. Produces less rounding errors than calculating
1183
        // fractions of a day from seconds, minutes, hours separately, and then adding together.
1184
0
        double seconds = nDays * tools::Time::secondPerDay + nHours * tools::Time::secondPerHour
1185
0
                         + nMins * tools::Time::secondPerMinute + nSecs
1186
0
                         + o3tl::toDouble(sDoubleStr);
1187
0
        double fTempTime = seconds / tools::Time::secondPerDay;
1188
1189
        // negative duration?
1190
0
        if ( bIsNegativeDuration )
1191
0
        {
1192
0
            fTempTime = -fTempTime;
1193
0
        }
1194
1195
0
        rfTime = fTempTime;
1196
0
    }
1197
0
    return bSuccess;
1198
0
}
1199
1200
/** convert ISO "duration" string to double; negative durations allowed */
1201
bool Converter::convertDuration(double& rfTime,
1202
                                std::string_view rString)
1203
0
{
1204
0
    std::string_view aTrimmed = o3tl::trim(rString);
1205
0
    const char* pStr = aTrimmed.data();
1206
1207
0
    return convertDurationHelper(rfTime, pStr);
1208
0
}
1209
1210
/** convert util::Duration to ISO8601 "duration" string */
1211
void Converter::convertDuration(OUStringBuffer& rBuffer,
1212
        const ::util::Duration& rDuration)
1213
7.92k
{
1214
7.92k
    if (rDuration.Negative)
1215
0
    {
1216
0
        rBuffer.append('-');
1217
0
    }
1218
7.92k
    rBuffer.append('P');
1219
7.92k
    const bool bHaveDate(rDuration.Years  != 0 ||
1220
7.92k
                         rDuration.Months != 0 ||
1221
7.92k
                         rDuration.Days   != 0);
1222
7.92k
    if (rDuration.Years)
1223
0
    {
1224
0
        rBuffer.append(static_cast<sal_Int32>(rDuration.Years));
1225
0
        rBuffer.append('Y');
1226
0
    }
1227
7.92k
    if (rDuration.Months)
1228
0
    {
1229
0
        rBuffer.append(static_cast<sal_Int32>(rDuration.Months));
1230
0
        rBuffer.append('M');
1231
0
    }
1232
7.92k
    if (rDuration.Days)
1233
803
    {
1234
803
        rBuffer.append(static_cast<sal_Int32>(rDuration.Days));
1235
803
        rBuffer.append('D');
1236
803
    }
1237
7.92k
    if ( rDuration.Hours != 0
1238
6.08k
         || rDuration.Minutes != 0
1239
2.26k
         || rDuration.Seconds != 0
1240
1.86k
         || rDuration.NanoSeconds != 0 )
1241
6.06k
    {
1242
6.06k
        rBuffer.append('T'); // time separator
1243
6.06k
        if (rDuration.Hours)
1244
1.83k
        {
1245
1.83k
            rBuffer.append(static_cast<sal_Int32>(rDuration.Hours));
1246
1.83k
            rBuffer.append('H');
1247
1.83k
        }
1248
6.06k
        if (rDuration.Minutes)
1249
5.63k
        {
1250
5.63k
            rBuffer.append(static_cast<sal_Int32>(rDuration.Minutes));
1251
5.63k
            rBuffer.append('M');
1252
5.63k
        }
1253
6.06k
        if (rDuration.Seconds != 0 || rDuration.NanoSeconds != 0)
1254
2.85k
        {
1255
            // seconds must not be omitted (i.e. ".42S" is not valid)
1256
2.85k
            rBuffer.append(static_cast<sal_Int32>(rDuration.Seconds));
1257
2.85k
            if (rDuration.NanoSeconds)
1258
0
            {
1259
0
                OSL_ENSURE(rDuration.NanoSeconds < 1000000000,"NanoSeconds cannot be more than 999 999 999");
1260
0
                rBuffer.append('.');
1261
0
                std::ostringstream ostr;
1262
0
                ostr.fill('0');
1263
0
                ostr.width(9);
1264
0
                ostr << rDuration.NanoSeconds;
1265
0
                rBuffer.appendAscii(ostr.str().c_str());
1266
0
            }
1267
2.85k
            rBuffer.append('S');
1268
2.85k
        }
1269
6.06k
    }
1270
1.86k
    else if (!bHaveDate)
1271
1.84k
    {
1272
        // zero duration: XMLSchema-2 says there must be at least one component
1273
1.84k
        rBuffer.append('0');
1274
1.84k
        rBuffer.append('D');
1275
1.84k
    }
1276
7.92k
}
1277
1278
namespace {
1279
1280
enum Result { R_NOTHING, R_OVERFLOW, R_SUCCESS };
1281
1282
}
1283
1284
template <typename V>
1285
static Result
1286
readUnsignedNumber(V rString,
1287
    size_t & io_rnPos, sal_Int32 & o_rNumber)
1288
496k
{
1289
496k
    size_t nPos(io_rnPos);
1290
1291
798k
    while (nPos < rString.size())
1292
424k
    {
1293
424k
        const typename V::value_type c = rString[nPos];
1294
424k
        if (('0' > c) || (c > '9'))
1295
122k
            break;
1296
302k
        ++nPos;
1297
302k
    }
1298
1299
496k
    if (io_rnPos == nPos) // read something?
1300
368k
    {
1301
368k
        o_rNumber = -1;
1302
368k
        return R_NOTHING;
1303
368k
    }
1304
1305
127k
    const sal_Int64 nTemp = toInt64_WithLength(rString.data() + io_rnPos, 10, nPos - io_rnPos);
1306
1307
127k
    const bool bOverflow = (nTemp >= SAL_MAX_INT32);
1308
1309
127k
    io_rnPos = nPos;
1310
127k
    o_rNumber = nTemp;
1311
127k
    return bOverflow ? R_OVERFLOW : R_SUCCESS;
1312
496k
}
converter.cxx:sax::(anonymous namespace)::Result sax::readUnsignedNumber<std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> > >(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >, unsigned long&, int&)
Line
Count
Source
1288
489k
{
1289
489k
    size_t nPos(io_rnPos);
1290
1291
775k
    while (nPos < rString.size())
1292
402k
    {
1293
402k
        const typename V::value_type c = rString[nPos];
1294
402k
        if (('0' > c) || (c > '9'))
1295
116k
            break;
1296
286k
        ++nPos;
1297
286k
    }
1298
1299
489k
    if (io_rnPos == nPos) // read something?
1300
367k
    {
1301
367k
        o_rNumber = -1;
1302
367k
        return R_NOTHING;
1303
367k
    }
1304
1305
122k
    const sal_Int64 nTemp = toInt64_WithLength(rString.data() + io_rnPos, 10, nPos - io_rnPos);
1306
1307
122k
    const bool bOverflow = (nTemp >= SAL_MAX_INT32);
1308
1309
122k
    io_rnPos = nPos;
1310
122k
    o_rNumber = nTemp;
1311
122k
    return bOverflow ? R_OVERFLOW : R_SUCCESS;
1312
489k
}
converter.cxx:sax::(anonymous namespace)::Result sax::readUnsignedNumber<std::__1::basic_string_view<char, std::__1::char_traits<char> > >(std::__1::basic_string_view<char, std::__1::char_traits<char> >, unsigned long&, int&)
Line
Count
Source
1288
6.84k
{
1289
6.84k
    size_t nPos(io_rnPos);
1290
1291
22.5k
    while (nPos < rString.size())
1292
22.3k
    {
1293
22.3k
        const typename V::value_type c = rString[nPos];
1294
22.3k
        if (('0' > c) || (c > '9'))
1295
6.69k
            break;
1296
15.6k
        ++nPos;
1297
15.6k
    }
1298
1299
6.84k
    if (io_rnPos == nPos) // read something?
1300
1.83k
    {
1301
1.83k
        o_rNumber = -1;
1302
1.83k
        return R_NOTHING;
1303
1.83k
    }
1304
1305
5.01k
    const sal_Int64 nTemp = toInt64_WithLength(rString.data() + io_rnPos, 10, nPos - io_rnPos);
1306
1307
5.01k
    const bool bOverflow = (nTemp >= SAL_MAX_INT32);
1308
1309
5.01k
    io_rnPos = nPos;
1310
5.01k
    o_rNumber = nTemp;
1311
5.01k
    return bOverflow ? R_OVERFLOW : R_SUCCESS;
1312
6.84k
}
1313
1314
template<typename V>
1315
static Result
1316
readUnsignedNumberMaxDigits(int maxDigits,
1317
                            V rString, size_t & io_rnPos,
1318
                            sal_Int32 & o_rNumber)
1319
13.8k
{
1320
13.8k
    bool bOverflow(false);
1321
13.8k
    sal_Int64 nTemp(0);
1322
13.8k
    size_t nPos(io_rnPos);
1323
13.8k
    OSL_ENSURE(maxDigits >= 0, "negative amount of digits makes no sense");
1324
1325
120k
    while (nPos < rString.size())
1326
106k
    {
1327
106k
        const sal_Unicode c = rString[nPos];
1328
106k
        if (('0' <= c) && (c <= '9'))
1329
106k
        {
1330
106k
            if (maxDigits > 0)
1331
106k
            {
1332
106k
                nTemp *= 10;
1333
106k
                nTemp += (c - u'0');
1334
106k
                if (nTemp >= SAL_MAX_INT32)
1335
0
                {
1336
0
                    bOverflow = true;
1337
0
                }
1338
106k
                --maxDigits;
1339
106k
            }
1340
106k
        }
1341
2
        else
1342
2
        {
1343
2
            break;
1344
2
        }
1345
106k
        ++nPos;
1346
106k
    }
1347
1348
13.8k
    if (io_rnPos == nPos) // read something?
1349
0
    {
1350
0
        o_rNumber = -1;
1351
0
        return R_NOTHING;
1352
0
    }
1353
1354
13.8k
    io_rnPos = nPos;
1355
13.8k
    o_rNumber = nTemp;
1356
13.8k
    return bOverflow ? R_OVERFLOW : R_SUCCESS;
1357
13.8k
}
converter.cxx:sax::(anonymous namespace)::Result sax::readUnsignedNumberMaxDigits<std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> > >(int, std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >, unsigned long&, int&)
Line
Count
Source
1319
13.8k
{
1320
13.8k
    bool bOverflow(false);
1321
13.8k
    sal_Int64 nTemp(0);
1322
13.8k
    size_t nPos(io_rnPos);
1323
13.8k
    OSL_ENSURE(maxDigits >= 0, "negative amount of digits makes no sense");
1324
1325
120k
    while (nPos < rString.size())
1326
106k
    {
1327
106k
        const sal_Unicode c = rString[nPos];
1328
106k
        if (('0' <= c) && (c <= '9'))
1329
106k
        {
1330
106k
            if (maxDigits > 0)
1331
106k
            {
1332
106k
                nTemp *= 10;
1333
106k
                nTemp += (c - u'0');
1334
106k
                if (nTemp >= SAL_MAX_INT32)
1335
0
                {
1336
0
                    bOverflow = true;
1337
0
                }
1338
106k
                --maxDigits;
1339
106k
            }
1340
106k
        }
1341
2
        else
1342
2
        {
1343
2
            break;
1344
2
        }
1345
106k
        ++nPos;
1346
106k
    }
1347
1348
13.8k
    if (io_rnPos == nPos) // read something?
1349
0
    {
1350
0
        o_rNumber = -1;
1351
0
        return R_NOTHING;
1352
0
    }
1353
1354
13.8k
    io_rnPos = nPos;
1355
13.8k
    o_rNumber = nTemp;
1356
13.8k
    return bOverflow ? R_OVERFLOW : R_SUCCESS;
1357
13.8k
}
Unexecuted instantiation: converter.cxx:sax::(anonymous namespace)::Result sax::readUnsignedNumberMaxDigits<std::__1::basic_string_view<char, std::__1::char_traits<char> > >(int, std::__1::basic_string_view<char, std::__1::char_traits<char> >, unsigned long&, int&)
1358
1359
template<typename V>
1360
static bool
1361
readDurationT(V rString, size_t & io_rnPos)
1362
161k
{
1363
161k
    if ((io_rnPos < rString.size()) &&
1364
0
        (rString[io_rnPos] == 'T' || rString[io_rnPos] == 't'))
1365
0
    {
1366
0
        ++io_rnPos;
1367
0
        return true;
1368
0
    }
1369
161k
    return false;
1370
161k
}
converter.cxx:bool sax::readDurationT<std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> > >(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >, unsigned long&)
Line
Count
Source
1362
161k
{
1363
161k
    if ((io_rnPos < rString.size()) &&
1364
0
        (rString[io_rnPos] == 'T' || rString[io_rnPos] == 't'))
1365
0
    {
1366
0
        ++io_rnPos;
1367
0
        return true;
1368
0
    }
1369
161k
    return false;
1370
161k
}
Unexecuted instantiation: converter.cxx:bool sax::readDurationT<std::__1::basic_string_view<char, std::__1::char_traits<char> > >(std::__1::basic_string_view<char, std::__1::char_traits<char> >, unsigned long&)
1371
1372
template<typename V>
1373
static bool
1374
readDurationComponent(V rString,
1375
    size_t & io_rnPos, sal_Int32 & io_rnTemp, bool & io_rbTimePart,
1376
    sal_Int32 & o_rnTarget, const sal_Unicode cLower, const sal_Unicode cUpper)
1377
0
{
1378
0
    if (io_rnPos < rString.size())
1379
0
    {
1380
0
        if (cLower == rString[io_rnPos] || cUpper == rString[io_rnPos])
1381
0
        {
1382
0
            ++io_rnPos;
1383
0
            if (-1 != io_rnTemp)
1384
0
            {
1385
0
                o_rnTarget = io_rnTemp;
1386
0
                io_rnTemp = -1;
1387
0
                if (!io_rbTimePart)
1388
0
                {
1389
0
                    io_rbTimePart = readDurationT(rString, io_rnPos);
1390
0
                }
1391
0
                return (R_OVERFLOW !=
1392
0
                        readUnsignedNumber(rString, io_rnPos, io_rnTemp));
1393
0
            }
1394
0
            else
1395
0
            {
1396
0
                return false;
1397
0
            }
1398
0
        }
1399
0
    }
1400
0
    return true;
1401
0
}
Unexecuted instantiation: converter.cxx:bool sax::readDurationComponent<std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> > >(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >, unsigned long&, int&, bool&, int&, char16_t, char16_t)
Unexecuted instantiation: converter.cxx:bool sax::readDurationComponent<std::__1::basic_string_view<char, std::__1::char_traits<char> > >(std::__1::basic_string_view<char, std::__1::char_traits<char> >, unsigned long&, int&, bool&, int&, char16_t, char16_t)
1402
1403
template <typename V>
1404
static bool convertDurationHelper(util::Duration& rDuration, V string)
1405
161k
{
1406
161k
    size_t nPos(0);
1407
1408
161k
    bool bIsNegativeDuration(false);
1409
161k
    if (!string.empty() && ('-' == string[0]))
1410
0
    {
1411
0
        bIsNegativeDuration = true;
1412
0
        ++nPos;
1413
0
    }
1414
1415
161k
    if (nPos < string.size()
1416
0
        && string[nPos] != 'P' && string[nPos] != 'p') // duration must start with "P"
1417
0
    {
1418
0
        return false;
1419
0
    }
1420
1421
161k
    ++nPos;
1422
1423
    /// last read number; -1 == no valid number! always reset after using!
1424
161k
    sal_Int32 nTemp(-1);
1425
161k
    bool bTimePart(false); // have we read 'T'?
1426
161k
    bool bSuccess(false);
1427
161k
    sal_Int32 nYears(0);
1428
161k
    sal_Int32 nMonths(0);
1429
161k
    sal_Int32 nDays(0);
1430
161k
    sal_Int32 nHours(0);
1431
161k
    sal_Int32 nMinutes(0);
1432
161k
    sal_Int32 nSeconds(0);
1433
161k
    sal_Int32 nNanoSeconds(0);
1434
1435
161k
    bTimePart = readDurationT(string, nPos);
1436
161k
    bSuccess = (R_SUCCESS == readUnsignedNumber(string, nPos, nTemp));
1437
1438
161k
    if (!bTimePart && bSuccess)
1439
0
    {
1440
0
        bSuccess = readDurationComponent(string, nPos, nTemp, bTimePart,
1441
0
                     nYears, 'y', 'Y');
1442
0
    }
1443
1444
161k
    if (!bTimePart && bSuccess)
1445
0
    {
1446
0
        bSuccess = readDurationComponent(string, nPos, nTemp, bTimePart,
1447
0
                     nMonths, 'm', 'M');
1448
0
    }
1449
1450
161k
    if (!bTimePart && bSuccess)
1451
0
    {
1452
0
        bSuccess = readDurationComponent(string, nPos, nTemp, bTimePart,
1453
0
                     nDays, 'd', 'D');
1454
0
    }
1455
1456
161k
    if (bTimePart)
1457
0
    {
1458
0
        if (-1 == nTemp) // a 'T' must be followed by a component
1459
0
        {
1460
0
            bSuccess = false;
1461
0
        }
1462
1463
0
        if (bSuccess)
1464
0
        {
1465
0
            bSuccess = readDurationComponent(string, nPos, nTemp, bTimePart,
1466
0
                         nHours, 'h', 'H');
1467
0
        }
1468
1469
0
        if (bSuccess)
1470
0
        {
1471
0
            bSuccess = readDurationComponent(string, nPos, nTemp, bTimePart,
1472
0
                         nMinutes, 'm', 'M');
1473
0
        }
1474
1475
        // eeek! seconds are icky.
1476
0
        if ((nPos < string.size()) && bSuccess)
1477
0
        {
1478
0
            if (string[nPos] == '.' ||
1479
0
                string[nPos] == ',')
1480
0
            {
1481
0
                ++nPos;
1482
0
                if (-1 != nTemp)
1483
0
                {
1484
0
                    nSeconds = nTemp;
1485
0
                    nTemp = -1;
1486
0
                    const sal_Int32 nStart(nPos);
1487
0
                    bSuccess = readUnsignedNumberMaxDigits(9, string, nPos, nTemp) == R_SUCCESS;
1488
0
                    if ((nPos < string.size()) && bSuccess)
1489
0
                    {
1490
0
                        if (-1 != nTemp)
1491
0
                        {
1492
0
                            nNanoSeconds = nTemp;
1493
0
                            sal_Int32 nDigits = nPos - nStart;
1494
0
                            assert(nDigits >= 0);
1495
0
                            for (; nDigits < 9; ++nDigits)
1496
0
                            {
1497
0
                                nNanoSeconds *= 10;
1498
0
                            }
1499
0
                            nTemp=-1;
1500
0
                            if ('S' == string[nPos] || 's' == string[nPos])
1501
0
                            {
1502
0
                                ++nPos;
1503
0
                            }
1504
0
                            else
1505
0
                            {
1506
0
                                bSuccess = false;
1507
0
                            }
1508
0
                        }
1509
0
                        else
1510
0
                        {
1511
0
                            bSuccess = false;
1512
0
                        }
1513
0
                    }
1514
0
                }
1515
0
                else
1516
0
                {
1517
0
                    bSuccess = false;
1518
0
                }
1519
0
            }
1520
0
            else if ('S' == string[nPos] || 's' == string[nPos])
1521
0
            {
1522
0
                ++nPos;
1523
0
                if (-1 != nTemp)
1524
0
                {
1525
0
                    nSeconds = nTemp;
1526
0
                    nTemp = -1;
1527
0
                }
1528
0
                else
1529
0
                {
1530
0
                    bSuccess = false;
1531
0
                }
1532
0
            }
1533
0
        }
1534
0
    }
1535
1536
161k
    if (nPos != string.size()) // string not processed completely?
1537
161k
    {
1538
161k
        bSuccess = false;
1539
161k
    }
1540
1541
161k
    if (nTemp != -1) // unprocessed number?
1542
0
    {
1543
0
        bSuccess = false;
1544
0
    }
1545
1546
161k
    if (bSuccess)
1547
0
    {
1548
0
        rDuration.Negative      = bIsNegativeDuration;
1549
0
        rDuration.Years         = static_cast<sal_uInt16>(nYears);
1550
0
        rDuration.Months        = static_cast<sal_uInt16>(nMonths);
1551
0
        rDuration.Days          = static_cast<sal_uInt16>(nDays);
1552
0
        rDuration.Hours         = static_cast<sal_uInt16>(nHours);
1553
0
        rDuration.Minutes       = static_cast<sal_uInt16>(nMinutes);
1554
0
        rDuration.Seconds       = static_cast<sal_uInt16>(nSeconds);
1555
0
        rDuration.NanoSeconds   = nNanoSeconds;
1556
0
    }
1557
1558
161k
    return bSuccess;
1559
161k
}
converter.cxx:bool sax::convertDurationHelper<std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> > >(com::sun::star::util::Duration&, std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >)
Line
Count
Source
1405
161k
{
1406
161k
    size_t nPos(0);
1407
1408
161k
    bool bIsNegativeDuration(false);
1409
161k
    if (!string.empty() && ('-' == string[0]))
1410
0
    {
1411
0
        bIsNegativeDuration = true;
1412
0
        ++nPos;
1413
0
    }
1414
1415
161k
    if (nPos < string.size()
1416
0
        && string[nPos] != 'P' && string[nPos] != 'p') // duration must start with "P"
1417
0
    {
1418
0
        return false;
1419
0
    }
1420
1421
161k
    ++nPos;
1422
1423
    /// last read number; -1 == no valid number! always reset after using!
1424
161k
    sal_Int32 nTemp(-1);
1425
161k
    bool bTimePart(false); // have we read 'T'?
1426
161k
    bool bSuccess(false);
1427
161k
    sal_Int32 nYears(0);
1428
161k
    sal_Int32 nMonths(0);
1429
161k
    sal_Int32 nDays(0);
1430
161k
    sal_Int32 nHours(0);
1431
161k
    sal_Int32 nMinutes(0);
1432
161k
    sal_Int32 nSeconds(0);
1433
161k
    sal_Int32 nNanoSeconds(0);
1434
1435
161k
    bTimePart = readDurationT(string, nPos);
1436
161k
    bSuccess = (R_SUCCESS == readUnsignedNumber(string, nPos, nTemp));
1437
1438
161k
    if (!bTimePart && bSuccess)
1439
0
    {
1440
0
        bSuccess = readDurationComponent(string, nPos, nTemp, bTimePart,
1441
0
                     nYears, 'y', 'Y');
1442
0
    }
1443
1444
161k
    if (!bTimePart && bSuccess)
1445
0
    {
1446
0
        bSuccess = readDurationComponent(string, nPos, nTemp, bTimePart,
1447
0
                     nMonths, 'm', 'M');
1448
0
    }
1449
1450
161k
    if (!bTimePart && bSuccess)
1451
0
    {
1452
0
        bSuccess = readDurationComponent(string, nPos, nTemp, bTimePart,
1453
0
                     nDays, 'd', 'D');
1454
0
    }
1455
1456
161k
    if (bTimePart)
1457
0
    {
1458
0
        if (-1 == nTemp) // a 'T' must be followed by a component
1459
0
        {
1460
0
            bSuccess = false;
1461
0
        }
1462
1463
0
        if (bSuccess)
1464
0
        {
1465
0
            bSuccess = readDurationComponent(string, nPos, nTemp, bTimePart,
1466
0
                         nHours, 'h', 'H');
1467
0
        }
1468
1469
0
        if (bSuccess)
1470
0
        {
1471
0
            bSuccess = readDurationComponent(string, nPos, nTemp, bTimePart,
1472
0
                         nMinutes, 'm', 'M');
1473
0
        }
1474
1475
        // eeek! seconds are icky.
1476
0
        if ((nPos < string.size()) && bSuccess)
1477
0
        {
1478
0
            if (string[nPos] == '.' ||
1479
0
                string[nPos] == ',')
1480
0
            {
1481
0
                ++nPos;
1482
0
                if (-1 != nTemp)
1483
0
                {
1484
0
                    nSeconds = nTemp;
1485
0
                    nTemp = -1;
1486
0
                    const sal_Int32 nStart(nPos);
1487
0
                    bSuccess = readUnsignedNumberMaxDigits(9, string, nPos, nTemp) == R_SUCCESS;
1488
0
                    if ((nPos < string.size()) && bSuccess)
1489
0
                    {
1490
0
                        if (-1 != nTemp)
1491
0
                        {
1492
0
                            nNanoSeconds = nTemp;
1493
0
                            sal_Int32 nDigits = nPos - nStart;
1494
0
                            assert(nDigits >= 0);
1495
0
                            for (; nDigits < 9; ++nDigits)
1496
0
                            {
1497
0
                                nNanoSeconds *= 10;
1498
0
                            }
1499
0
                            nTemp=-1;
1500
0
                            if ('S' == string[nPos] || 's' == string[nPos])
1501
0
                            {
1502
0
                                ++nPos;
1503
0
                            }
1504
0
                            else
1505
0
                            {
1506
0
                                bSuccess = false;
1507
0
                            }
1508
0
                        }
1509
0
                        else
1510
0
                        {
1511
0
                            bSuccess = false;
1512
0
                        }
1513
0
                    }
1514
0
                }
1515
0
                else
1516
0
                {
1517
0
                    bSuccess = false;
1518
0
                }
1519
0
            }
1520
0
            else if ('S' == string[nPos] || 's' == string[nPos])
1521
0
            {
1522
0
                ++nPos;
1523
0
                if (-1 != nTemp)
1524
0
                {
1525
0
                    nSeconds = nTemp;
1526
0
                    nTemp = -1;
1527
0
                }
1528
0
                else
1529
0
                {
1530
0
                    bSuccess = false;
1531
0
                }
1532
0
            }
1533
0
        }
1534
0
    }
1535
1536
161k
    if (nPos != string.size()) // string not processed completely?
1537
161k
    {
1538
161k
        bSuccess = false;
1539
161k
    }
1540
1541
161k
    if (nTemp != -1) // unprocessed number?
1542
0
    {
1543
0
        bSuccess = false;
1544
0
    }
1545
1546
161k
    if (bSuccess)
1547
0
    {
1548
0
        rDuration.Negative      = bIsNegativeDuration;
1549
0
        rDuration.Years         = static_cast<sal_uInt16>(nYears);
1550
0
        rDuration.Months        = static_cast<sal_uInt16>(nMonths);
1551
0
        rDuration.Days          = static_cast<sal_uInt16>(nDays);
1552
0
        rDuration.Hours         = static_cast<sal_uInt16>(nHours);
1553
0
        rDuration.Minutes       = static_cast<sal_uInt16>(nMinutes);
1554
0
        rDuration.Seconds       = static_cast<sal_uInt16>(nSeconds);
1555
0
        rDuration.NanoSeconds   = nNanoSeconds;
1556
0
    }
1557
1558
161k
    return bSuccess;
1559
161k
}
Unexecuted instantiation: converter.cxx:bool sax::convertDurationHelper<std::__1::basic_string_view<char, std::__1::char_traits<char> > >(com::sun::star::util::Duration&, std::__1::basic_string_view<char, std::__1::char_traits<char> >)
1560
1561
/** convert ISO8601 "duration" string to util::Duration */
1562
bool Converter::convertDuration(util::Duration& rDuration,
1563
                                std::u16string_view rString)
1564
161k
{
1565
161k
    return convertDurationHelper(rDuration, o3tl::trim(rString));
1566
161k
}
1567
1568
/** convert ISO8601 "duration" string to util::Duration */
1569
bool Converter::convertDuration(util::Duration& rDuration,
1570
                                std::string_view rString)
1571
0
{
1572
0
    return convertDurationHelper(rDuration, o3tl::trim(rString));
1573
0
}
1574
1575
template<typename TStringBuffer>
1576
static void
1577
lcl_AppendTimezone(TStringBuffer & i_rBuffer, int const nOffset)
1578
0
{
1579
0
    if (0 == nOffset)
1580
0
    {
1581
0
        i_rBuffer.append('Z');
1582
0
    }
1583
0
    else
1584
0
    {
1585
0
        if (0 < nOffset)
1586
0
        {
1587
0
            i_rBuffer.append('+');
1588
0
        }
1589
0
        else
1590
0
        {
1591
0
            i_rBuffer.append('-');
1592
0
        }
1593
0
        const sal_Int32 nHours  (abs(nOffset) / 60);
1594
0
        const sal_Int32 nMinutes(abs(nOffset) % 60);
1595
0
        SAL_WARN_IF(nHours > 14 || (nHours == 14 && nMinutes > 0),
1596
0
                "sax", "convertDateTime: timezone overflow");
1597
0
        if (nHours < 10)
1598
0
        {
1599
0
            i_rBuffer.append('0');
1600
0
        }
1601
0
        i_rBuffer.append(nHours);
1602
0
        i_rBuffer.append(':');
1603
0
        if (nMinutes < 10)
1604
0
        {
1605
0
            i_rBuffer.append('0');
1606
0
        }
1607
0
        i_rBuffer.append(nMinutes);
1608
0
    }
1609
0
}
Unexecuted instantiation: converter.cxx:void sax::lcl_AppendTimezone<rtl::OUStringBuffer>(rtl::OUStringBuffer&, int)
Unexecuted instantiation: converter.cxx:void sax::lcl_AppendTimezone<rtl::OStringBuffer>(rtl::OStringBuffer&, int)
1610
1611
/** convert util::Date to ISO "date" string */
1612
void Converter::convertDate(
1613
        OUStringBuffer& i_rBuffer,
1614
        const util::Date& i_rDate,
1615
        sal_Int16 const*const pTimeZoneOffset)
1616
0
{
1617
0
    const util::DateTime dt(0, 0, 0, 0,
1618
0
        i_rDate.Day, i_rDate.Month, i_rDate.Year, false);
1619
0
    convertDateTime(i_rBuffer, dt, pTimeZoneOffset);
1620
0
}
1621
1622
template<typename TStringBuffer, typename TString>
1623
static void convertTime(
1624
        TStringBuffer& i_rBuffer,
1625
        const css::util::DateTime& i_rDateTime)
1626
34.2k
{
1627
34.2k
    if (i_rDateTime.Hours   < 10) {
1628
13.2k
        i_rBuffer.append('0');
1629
13.2k
    }
1630
34.2k
    i_rBuffer.append( TString::number(static_cast<sal_Int32>(i_rDateTime.Hours)) + ":");
1631
34.2k
    if (i_rDateTime.Minutes < 10) {
1632
11.8k
        i_rBuffer.append('0');
1633
11.8k
    }
1634
34.2k
    i_rBuffer.append( TString::number(static_cast<sal_Int32>(i_rDateTime.Minutes) ) + ":");
1635
34.2k
    if (i_rDateTime.Seconds < 10) {
1636
17.1k
        i_rBuffer.append('0');
1637
17.1k
    }
1638
34.2k
    i_rBuffer.append( static_cast<sal_Int32>(i_rDateTime.Seconds) );
1639
34.2k
    if (i_rDateTime.NanoSeconds > 0) {
1640
10.3k
        OSL_ENSURE(i_rDateTime.NanoSeconds < 1000000000,"NanoSeconds cannot be more than 999 999 999");
1641
10.3k
        i_rBuffer.append('.');
1642
        // pad to 9 characters length
1643
10.3k
        auto sNanoStr = TString::number(i_rDateTime.NanoSeconds);
1644
19.0k
        for (int i=0; i < 9 - sNanoStr.length; i++)
1645
8.65k
            i_rBuffer.append('0');
1646
10.3k
        i_rBuffer.append(sNanoStr);
1647
10.3k
    }
1648
34.2k
}
converter.cxx:void sax::convertTime<rtl::OUStringBuffer, rtl::OUString>(rtl::OUStringBuffer&, com::sun::star::util::DateTime const&)
Line
Count
Source
1626
34.2k
{
1627
34.2k
    if (i_rDateTime.Hours   < 10) {
1628
13.2k
        i_rBuffer.append('0');
1629
13.2k
    }
1630
34.2k
    i_rBuffer.append( TString::number(static_cast<sal_Int32>(i_rDateTime.Hours)) + ":");
1631
34.2k
    if (i_rDateTime.Minutes < 10) {
1632
11.8k
        i_rBuffer.append('0');
1633
11.8k
    }
1634
34.2k
    i_rBuffer.append( TString::number(static_cast<sal_Int32>(i_rDateTime.Minutes) ) + ":");
1635
34.2k
    if (i_rDateTime.Seconds < 10) {
1636
17.1k
        i_rBuffer.append('0');
1637
17.1k
    }
1638
34.2k
    i_rBuffer.append( static_cast<sal_Int32>(i_rDateTime.Seconds) );
1639
34.2k
    if (i_rDateTime.NanoSeconds > 0) {
1640
10.3k
        OSL_ENSURE(i_rDateTime.NanoSeconds < 1000000000,"NanoSeconds cannot be more than 999 999 999");
1641
10.3k
        i_rBuffer.append('.');
1642
        // pad to 9 characters length
1643
10.3k
        auto sNanoStr = TString::number(i_rDateTime.NanoSeconds);
1644
19.0k
        for (int i=0; i < 9 - sNanoStr.length; i++)
1645
8.65k
            i_rBuffer.append('0');
1646
10.3k
        i_rBuffer.append(sNanoStr);
1647
10.3k
    }
1648
34.2k
}
Unexecuted instantiation: converter.cxx:void sax::convertTime<rtl::OStringBuffer, rtl::OString>(rtl::OStringBuffer&, com::sun::star::util::DateTime const&)
1649
1650
template<typename TStringBuffer>
1651
static void convertTimeZone(
1652
        TStringBuffer& i_rBuffer,
1653
        const css::util::DateTime& i_rDateTime,
1654
        sal_Int16 const* pTimeZoneOffset)
1655
34.2k
{
1656
34.2k
    if (pTimeZoneOffset)
1657
0
    {
1658
0
        lcl_AppendTimezone(i_rBuffer, *pTimeZoneOffset);
1659
0
    }
1660
34.2k
    else if (i_rDateTime.IsUTC)
1661
0
    {
1662
0
        lcl_AppendTimezone(i_rBuffer, 0);
1663
0
    }
1664
34.2k
}
converter.cxx:void sax::convertTimeZone<rtl::OUStringBuffer>(rtl::OUStringBuffer&, com::sun::star::util::DateTime const&, short const*)
Line
Count
Source
1655
34.2k
{
1656
34.2k
    if (pTimeZoneOffset)
1657
0
    {
1658
0
        lcl_AppendTimezone(i_rBuffer, *pTimeZoneOffset);
1659
0
    }
1660
34.2k
    else if (i_rDateTime.IsUTC)
1661
0
    {
1662
0
        lcl_AppendTimezone(i_rBuffer, 0);
1663
0
    }
1664
34.2k
}
Unexecuted instantiation: converter.cxx:void sax::convertTimeZone<rtl::OStringBuffer>(rtl::OStringBuffer&, com::sun::star::util::DateTime const&, short const*)
1665
1666
/** convert util::DateTime to ISO "time" or "dateTime" string */
1667
void Converter::convertTimeOrDateTime(
1668
        OUStringBuffer& i_rBuffer,
1669
        const css::util::DateTime& i_rDateTime)
1670
0
{
1671
0
    if (i_rDateTime.Year == 0 ||
1672
0
        i_rDateTime.Month < 1 || i_rDateTime.Month > 12 ||
1673
0
        i_rDateTime.Day < 1 || i_rDateTime.Day > 31)
1674
0
    {
1675
0
        convertTime<OUStringBuffer, OUString>(i_rBuffer, i_rDateTime);
1676
0
        convertTimeZone(i_rBuffer, i_rDateTime, nullptr);
1677
0
    }
1678
0
    else
1679
0
    {
1680
0
        convertDateTime(i_rBuffer, i_rDateTime, nullptr, true);
1681
0
    }
1682
0
}
1683
1684
/** convert util::DateTime to ISO "date" or "dateTime" string */
1685
template<typename TStringBuffer, typename TString, typename TStringChar>
1686
static void lcl_convertDateTime(
1687
        TStringBuffer& i_rBuffer,
1688
        const css::util::DateTime& i_rDateTime,
1689
        sal_Int16 const*const pTimeZoneOffset,
1690
        bool i_bAddTimeIf0AM )
1691
34.2k
{
1692
34.2k
    const char dash('-');
1693
34.2k
    const char zero('0');
1694
1695
34.2k
    sal_Int32 const nYear(abs(i_rDateTime.Year));
1696
34.2k
    if (i_rDateTime.Year < 0) {
1697
92
        i_rBuffer.append(dash); // negative
1698
92
    }
1699
34.2k
    if (nYear < 1000) {
1700
547
        i_rBuffer.append(zero);
1701
547
    }
1702
34.2k
    if (nYear < 100) {
1703
528
        i_rBuffer.append(zero);
1704
528
    }
1705
34.2k
    if (nYear < 10) {
1706
55
        i_rBuffer.append(zero);
1707
55
    }
1708
34.2k
    i_rBuffer.append( TString::number(nYear) + TStringChar(dash) );
1709
34.2k
    if( i_rDateTime.Month < 10 ) {
1710
25.3k
        i_rBuffer.append(zero);
1711
25.3k
    }
1712
34.2k
    i_rBuffer.append( TString::number(i_rDateTime.Month) + TStringChar(dash) );
1713
34.2k
    if( i_rDateTime.Day   < 10 ) {
1714
11.2k
        i_rBuffer.append(zero);
1715
11.2k
    }
1716
34.2k
    i_rBuffer.append( static_cast<sal_Int32>(i_rDateTime.Day)   );
1717
1718
34.2k
    if( i_rDateTime.Seconds != 0 ||
1719
14.6k
        i_rDateTime.Minutes != 0 ||
1720
5.18k
        i_rDateTime.Hours   != 0 ||
1721
4.18k
        i_bAddTimeIf0AM )
1722
34.2k
    {
1723
34.2k
        i_rBuffer.append('T');
1724
34.2k
        convertTime<TStringBuffer, TString>(i_rBuffer, i_rDateTime);
1725
34.2k
    }
1726
1727
34.2k
    convertTimeZone(i_rBuffer, i_rDateTime, pTimeZoneOffset);
1728
34.2k
}
converter.cxx:void sax::lcl_convertDateTime<rtl::OUStringBuffer, rtl::OUString, rtl::OUStringChar_ const>(rtl::OUStringBuffer&, com::sun::star::util::DateTime const&, short const*, bool)
Line
Count
Source
1691
34.2k
{
1692
34.2k
    const char dash('-');
1693
34.2k
    const char zero('0');
1694
1695
34.2k
    sal_Int32 const nYear(abs(i_rDateTime.Year));
1696
34.2k
    if (i_rDateTime.Year < 0) {
1697
92
        i_rBuffer.append(dash); // negative
1698
92
    }
1699
34.2k
    if (nYear < 1000) {
1700
547
        i_rBuffer.append(zero);
1701
547
    }
1702
34.2k
    if (nYear < 100) {
1703
528
        i_rBuffer.append(zero);
1704
528
    }
1705
34.2k
    if (nYear < 10) {
1706
55
        i_rBuffer.append(zero);
1707
55
    }
1708
34.2k
    i_rBuffer.append( TString::number(nYear) + TStringChar(dash) );
1709
34.2k
    if( i_rDateTime.Month < 10 ) {
1710
25.3k
        i_rBuffer.append(zero);
1711
25.3k
    }
1712
34.2k
    i_rBuffer.append( TString::number(i_rDateTime.Month) + TStringChar(dash) );
1713
34.2k
    if( i_rDateTime.Day   < 10 ) {
1714
11.2k
        i_rBuffer.append(zero);
1715
11.2k
    }
1716
34.2k
    i_rBuffer.append( static_cast<sal_Int32>(i_rDateTime.Day)   );
1717
1718
34.2k
    if( i_rDateTime.Seconds != 0 ||
1719
14.6k
        i_rDateTime.Minutes != 0 ||
1720
5.18k
        i_rDateTime.Hours   != 0 ||
1721
4.18k
        i_bAddTimeIf0AM )
1722
34.2k
    {
1723
34.2k
        i_rBuffer.append('T');
1724
34.2k
        convertTime<TStringBuffer, TString>(i_rBuffer, i_rDateTime);
1725
34.2k
    }
1726
1727
34.2k
    convertTimeZone(i_rBuffer, i_rDateTime, pTimeZoneOffset);
1728
34.2k
}
Unexecuted instantiation: converter.cxx:void sax::lcl_convertDateTime<rtl::OStringBuffer, rtl::OString, rtl::OStringChar>(rtl::OStringBuffer&, com::sun::star::util::DateTime const&, short const*, bool)
1729
1730
/** convert util::DateTime to ISO "date" or "dateTime" string */
1731
void Converter::convertDateTime(
1732
        OUStringBuffer& i_rBuffer,
1733
        const css::util::DateTime& i_rDateTime,
1734
        sal_Int16 const*const pTimeZoneOffset,
1735
        bool i_bAddTimeIf0AM )
1736
34.2k
{
1737
34.2k
    lcl_convertDateTime<OUStringBuffer, OUString, OUStringChar>(i_rBuffer, i_rDateTime, pTimeZoneOffset, i_bAddTimeIf0AM);
1738
34.2k
}
1739
1740
/** convert util::DateTime to ISO "date" or "dateTime" string */
1741
void Converter::convertDateTime(
1742
        OStringBuffer& i_rBuffer,
1743
        const css::util::DateTime& i_rDateTime,
1744
        sal_Int16 const*const pTimeZoneOffset,
1745
        bool i_bAddTimeIf0AM )
1746
0
{
1747
0
    lcl_convertDateTime<OStringBuffer, OString, OStringChar>(i_rBuffer, i_rDateTime, pTimeZoneOffset, i_bAddTimeIf0AM);
1748
0
}
1749
1750
/** convert ISO "date" or "dateTime" string to util::DateTime */
1751
bool Converter::parseDateTime(   util::DateTime& rDateTime,
1752
                                 std::u16string_view rString )
1753
226k
{
1754
226k
    bool isDateTime;
1755
226k
    return parseDateOrDateTime(nullptr, rDateTime, isDateTime, nullptr,
1756
226k
            rString);
1757
226k
}
1758
1759
/** convert ISO "date" or "dateTime" string to util::DateTime */
1760
bool Converter::parseDateTime(   util::DateTime& rDateTime,
1761
                                 std::string_view rString )
1762
2.24k
{
1763
2.24k
    bool isDateTime;
1764
2.24k
    return parseDateOrDateTime(nullptr, rDateTime, isDateTime, nullptr,
1765
2.24k
            rString);
1766
2.24k
}
1767
1768
static void lcl_ConvertToUTC(
1769
        sal_Int16 & o_rYear, sal_uInt16 & o_rMonth, sal_uInt16 & o_rDay,
1770
        sal_uInt16 & o_rHours, sal_uInt16 & o_rMinutes,
1771
        int const nSourceOffset)
1772
0
{
1773
0
    sal_Int16 nOffsetHours(abs(nSourceOffset) / 60);
1774
0
    sal_Int16 const nOffsetMinutes(abs(nSourceOffset) % 60);
1775
0
    o_rMinutes += nOffsetMinutes;
1776
0
    if (nSourceOffset < 0)
1777
0
    {
1778
0
        o_rMinutes += nOffsetMinutes;
1779
0
        if (60 <= o_rMinutes)
1780
0
        {
1781
0
            o_rMinutes -= 60;
1782
0
            ++nOffsetHours;
1783
0
        }
1784
0
        o_rHours += nOffsetHours;
1785
0
        if (o_rHours < 24)
1786
0
        {
1787
0
            return;
1788
0
        }
1789
0
        sal_Int16 nDayAdd(0);
1790
0
        while (24 <= o_rHours)
1791
0
        {
1792
0
            o_rHours -= 24;
1793
0
            ++nDayAdd;
1794
0
        }
1795
0
        if (o_rDay == 0)
1796
0
        {
1797
0
            return; // handle time without date - don't adjust what isn't there
1798
0
        }
1799
0
        o_rDay += nDayAdd;
1800
0
        sal_Int16 const nDaysInMonth(comphelper::date::getDaysInMonth(o_rMonth, o_rYear));
1801
0
        if (o_rDay <= nDaysInMonth)
1802
0
        {
1803
0
            return;
1804
0
        }
1805
0
        o_rDay -= nDaysInMonth;
1806
0
        ++o_rMonth;
1807
0
        if (o_rMonth <= 12)
1808
0
        {
1809
0
            return;
1810
0
        }
1811
0
        o_rMonth = 1;
1812
0
        ++o_rYear; // works for negative year too
1813
0
    }
1814
0
    else if (0 < nSourceOffset)
1815
0
    {
1816
        // argh everything is unsigned
1817
0
        if (o_rMinutes < nOffsetMinutes)
1818
0
        {
1819
0
            o_rMinutes += 60;
1820
0
            ++nOffsetHours;
1821
0
        }
1822
0
        o_rMinutes -= nOffsetMinutes;
1823
0
        sal_Int16 nDaySubtract(0);
1824
0
        while (o_rHours < nOffsetHours)
1825
0
        {
1826
0
            o_rHours += 24;
1827
0
            ++nDaySubtract;
1828
0
        }
1829
0
        o_rHours -= nOffsetHours;
1830
0
        if (o_rDay == 0)
1831
0
        {
1832
0
            return; // handle time without date - don't adjust what isn't there
1833
0
        }
1834
0
        if (nDaySubtract < o_rDay)
1835
0
        {
1836
0
            o_rDay -= nDaySubtract;
1837
0
            return;
1838
0
        }
1839
0
        sal_Int16 const nPrevMonth((o_rMonth == 1) ? 12 : o_rMonth - 1);
1840
0
        sal_Int16 const nDaysInMonth(comphelper::date::getDaysInMonth(nPrevMonth, o_rYear));
1841
0
        o_rDay += nDaysInMonth;
1842
0
        --o_rMonth;
1843
0
        if (0 == o_rMonth)
1844
0
        {
1845
0
            o_rMonth = 12;
1846
0
            --o_rYear; // works for negative year too
1847
0
        }
1848
0
        o_rDay -= nDaySubtract;
1849
0
    }
1850
0
}
1851
1852
template <typename V>
1853
static bool
1854
readDateTimeComponent(V rString,
1855
    size_t & io_rnPos, sal_Int32 & o_rnTarget,
1856
    const sal_Int32 nMinLength, const bool bExactLength)
1857
334k
{
1858
334k
    const size_t nOldPos(io_rnPos);
1859
334k
    sal_Int32 nTemp(0);
1860
334k
    if (R_SUCCESS != readUnsignedNumber<V>(rString, io_rnPos, nTemp))
1861
207k
    {
1862
207k
        return false;
1863
207k
    }
1864
127k
    const sal_Int32 nTokenLength(io_rnPos - nOldPos);
1865
127k
    if ((nTokenLength < nMinLength) ||
1866
127k
        (bExactLength && (nTokenLength > nMinLength)))
1867
132
    {
1868
132
        return false; // bad length
1869
132
    }
1870
127k
    o_rnTarget = nTemp;
1871
127k
    return true;
1872
127k
}
converter.cxx:bool sax::readDateTimeComponent<std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> > >(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >, unsigned long&, int&, int, bool)
Line
Count
Source
1857
327k
{
1858
327k
    const size_t nOldPos(io_rnPos);
1859
327k
    sal_Int32 nTemp(0);
1860
327k
    if (R_SUCCESS != readUnsignedNumber<V>(rString, io_rnPos, nTemp))
1861
205k
    {
1862
205k
        return false;
1863
205k
    }
1864
122k
    const sal_Int32 nTokenLength(io_rnPos - nOldPos);
1865
122k
    if ((nTokenLength < nMinLength) ||
1866
122k
        (bExactLength && (nTokenLength > nMinLength)))
1867
6
    {
1868
6
        return false; // bad length
1869
6
    }
1870
122k
    o_rnTarget = nTemp;
1871
122k
    return true;
1872
122k
}
converter.cxx:bool sax::readDateTimeComponent<std::__1::basic_string_view<char, std::__1::char_traits<char> > >(std::__1::basic_string_view<char, std::__1::char_traits<char> >, unsigned long&, int&, int, bool)
Line
Count
Source
1857
6.84k
{
1858
6.84k
    const size_t nOldPos(io_rnPos);
1859
6.84k
    sal_Int32 nTemp(0);
1860
6.84k
    if (R_SUCCESS != readUnsignedNumber<V>(rString, io_rnPos, nTemp))
1861
1.83k
    {
1862
1.83k
        return false;
1863
1.83k
    }
1864
5.00k
    const sal_Int32 nTokenLength(io_rnPos - nOldPos);
1865
5.00k
    if ((nTokenLength < nMinLength) ||
1866
4.88k
        (bExactLength && (nTokenLength > nMinLength)))
1867
126
    {
1868
126
        return false; // bad length
1869
126
    }
1870
4.88k
    o_rnTarget = nTemp;
1871
4.88k
    return true;
1872
5.00k
}
1873
1874
/** convert ISO "date" or "dateTime" string to util::DateTime or util::Date */
1875
template<typename V>
1876
static bool lcl_parseDate(
1877
                bool & isNegative,
1878
                sal_Int32 & nYear, sal_Int32 & nMonth, sal_Int32 & nDay,
1879
                bool & bHaveTime,
1880
                size_t & nPos,
1881
                V string,
1882
                bool const bIgnoreInvalidOrMissingDate)
1883
228k
{
1884
228k
    bool bSuccess = true;
1885
1886
228k
    if (string.size() > nPos)
1887
22.8k
    {
1888
22.8k
        if ('-' == string[nPos])
1889
371
        {
1890
371
            isNegative = true;
1891
371
            ++nPos;
1892
371
        }
1893
22.8k
    }
1894
1895
228k
    {
1896
        // While W3C XMLSchema specifies years with a minimum of 4 digits, be
1897
        // lenient in what we accept for years < 1000. One digit is acceptable
1898
        // if the remainders match.
1899
228k
        bSuccess = readDateTimeComponent<V>(string, nPos, nYear, 1, false);
1900
228k
        if (!bIgnoreInvalidOrMissingDate)
1901
228k
        {
1902
228k
            bSuccess &= (0 < nYear);
1903
228k
        }
1904
228k
        bSuccess &= (nYear <= (isNegative ? 32768 : 32767)); // Must fit into css::util::Date
1905
228k
        bSuccess &= (nPos < string.size()); // not last token
1906
228k
    }
1907
228k
    if (bSuccess && ('-' != string[nPos])) // separator
1908
11
    {
1909
11
        bSuccess = false;
1910
11
    }
1911
228k
    if (bSuccess)
1912
22.7k
    {
1913
22.7k
        ++nPos;
1914
1915
22.7k
        bSuccess = readDateTimeComponent<V>(string, nPos, nMonth, 2, true);
1916
22.7k
        if (!bIgnoreInvalidOrMissingDate)
1917
22.7k
        {
1918
22.7k
            bSuccess &= (0 < nMonth);
1919
22.7k
        }
1920
22.7k
        bSuccess &= (nMonth <= 12);
1921
22.7k
        bSuccess &= (nPos < string.size()); // not last token
1922
22.7k
    }
1923
228k
    if (bSuccess && ('-' != string[nPos])) // separator
1924
100
    {
1925
100
        bSuccess = false;
1926
100
    }
1927
228k
    if (bSuccess)
1928
22.4k
    {
1929
22.4k
        ++nPos;
1930
1931
22.4k
        bSuccess = readDateTimeComponent(string, nPos, nDay, 2, true);
1932
22.4k
        if (!bIgnoreInvalidOrMissingDate)
1933
22.4k
        {
1934
22.4k
            bSuccess &= (0 < nDay);
1935
22.4k
        }
1936
22.4k
        if (nMonth > 0) // not possible to check if month was missing
1937
22.4k
        {
1938
22.4k
            sal_Int32 nMaxDay
1939
22.4k
                = comphelper::date::getDaysInMonth(nMonth, isNegative ? -nYear : nYear);
1940
22.4k
            bSuccess &= (nDay <= nMaxDay);
1941
22.4k
        }
1942
22.4k
        else assert(bIgnoreInvalidOrMissingDate);
1943
22.4k
    }
1944
1945
228k
    if (bSuccess && (nPos < string.size()))
1946
20.4k
    {
1947
20.4k
        if ('T' == string[nPos] || 't' == string[nPos]) // time separator
1948
20.4k
        {
1949
20.4k
            bHaveTime = true;
1950
20.4k
            ++nPos;
1951
20.4k
        }
1952
20.4k
    }
1953
1954
228k
    return bSuccess;
1955
228k
}
converter.cxx:bool sax::lcl_parseDate<std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> > >(bool&, int&, int&, int&, bool&, unsigned long&, std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >, bool)
Line
Count
Source
1883
226k
{
1884
226k
    bool bSuccess = true;
1885
1886
226k
    if (string.size() > nPos)
1887
20.6k
    {
1888
20.6k
        if ('-' == string[nPos])
1889
371
        {
1890
371
            isNegative = true;
1891
371
            ++nPos;
1892
371
        }
1893
20.6k
    }
1894
1895
226k
    {
1896
        // While W3C XMLSchema specifies years with a minimum of 4 digits, be
1897
        // lenient in what we accept for years < 1000. One digit is acceptable
1898
        // if the remainders match.
1899
226k
        bSuccess = readDateTimeComponent<V>(string, nPos, nYear, 1, false);
1900
226k
        if (!bIgnoreInvalidOrMissingDate)
1901
226k
        {
1902
226k
            bSuccess &= (0 < nYear);
1903
226k
        }
1904
226k
        bSuccess &= (nYear <= (isNegative ? 32768 : 32767)); // Must fit into css::util::Date
1905
226k
        bSuccess &= (nPos < string.size()); // not last token
1906
226k
    }
1907
226k
    if (bSuccess && ('-' != string[nPos])) // separator
1908
1
    {
1909
1
        bSuccess = false;
1910
1
    }
1911
226k
    if (bSuccess)
1912
20.5k
    {
1913
20.5k
        ++nPos;
1914
1915
20.5k
        bSuccess = readDateTimeComponent<V>(string, nPos, nMonth, 2, true);
1916
20.5k
        if (!bIgnoreInvalidOrMissingDate)
1917
20.5k
        {
1918
20.5k
            bSuccess &= (0 < nMonth);
1919
20.5k
        }
1920
20.5k
        bSuccess &= (nMonth <= 12);
1921
20.5k
        bSuccess &= (nPos < string.size()); // not last token
1922
20.5k
    }
1923
226k
    if (bSuccess && ('-' != string[nPos])) // separator
1924
1
    {
1925
1
        bSuccess = false;
1926
1
    }
1927
226k
    if (bSuccess)
1928
20.5k
    {
1929
20.5k
        ++nPos;
1930
1931
20.5k
        bSuccess = readDateTimeComponent(string, nPos, nDay, 2, true);
1932
20.5k
        if (!bIgnoreInvalidOrMissingDate)
1933
20.5k
        {
1934
20.5k
            bSuccess &= (0 < nDay);
1935
20.5k
        }
1936
20.5k
        if (nMonth > 0) // not possible to check if month was missing
1937
20.5k
        {
1938
20.5k
            sal_Int32 nMaxDay
1939
20.5k
                = comphelper::date::getDaysInMonth(nMonth, isNegative ? -nYear : nYear);
1940
20.5k
            bSuccess &= (nDay <= nMaxDay);
1941
20.5k
        }
1942
20.5k
        else assert(bIgnoreInvalidOrMissingDate);
1943
20.5k
    }
1944
1945
226k
    if (bSuccess && (nPos < string.size()))
1946
20.3k
    {
1947
20.3k
        if ('T' == string[nPos] || 't' == string[nPos]) // time separator
1948
20.3k
        {
1949
20.3k
            bHaveTime = true;
1950
20.3k
            ++nPos;
1951
20.3k
        }
1952
20.3k
    }
1953
1954
226k
    return bSuccess;
1955
226k
}
converter.cxx:bool sax::lcl_parseDate<std::__1::basic_string_view<char, std::__1::char_traits<char> > >(bool&, int&, int&, int&, bool&, unsigned long&, std::__1::basic_string_view<char, std::__1::char_traits<char> >, bool)
Line
Count
Source
1883
2.24k
{
1884
2.24k
    bool bSuccess = true;
1885
1886
2.24k
    if (string.size() > nPos)
1887
2.24k
    {
1888
2.24k
        if ('-' == string[nPos])
1889
0
        {
1890
0
            isNegative = true;
1891
0
            ++nPos;
1892
0
        }
1893
2.24k
    }
1894
1895
2.24k
    {
1896
        // While W3C XMLSchema specifies years with a minimum of 4 digits, be
1897
        // lenient in what we accept for years < 1000. One digit is acceptable
1898
        // if the remainders match.
1899
2.24k
        bSuccess = readDateTimeComponent<V>(string, nPos, nYear, 1, false);
1900
2.24k
        if (!bIgnoreInvalidOrMissingDate)
1901
2.24k
        {
1902
2.24k
            bSuccess &= (0 < nYear);
1903
2.24k
        }
1904
2.24k
        bSuccess &= (nYear <= (isNegative ? 32768 : 32767)); // Must fit into css::util::Date
1905
2.24k
        bSuccess &= (nPos < string.size()); // not last token
1906
2.24k
    }
1907
2.24k
    if (bSuccess && ('-' != string[nPos])) // separator
1908
10
    {
1909
10
        bSuccess = false;
1910
10
    }
1911
2.24k
    if (bSuccess)
1912
2.20k
    {
1913
2.20k
        ++nPos;
1914
1915
2.20k
        bSuccess = readDateTimeComponent<V>(string, nPos, nMonth, 2, true);
1916
2.20k
        if (!bIgnoreInvalidOrMissingDate)
1917
2.20k
        {
1918
2.20k
            bSuccess &= (0 < nMonth);
1919
2.20k
        }
1920
2.20k
        bSuccess &= (nMonth <= 12);
1921
2.20k
        bSuccess &= (nPos < string.size()); // not last token
1922
2.20k
    }
1923
2.24k
    if (bSuccess && ('-' != string[nPos])) // separator
1924
99
    {
1925
99
        bSuccess = false;
1926
99
    }
1927
2.24k
    if (bSuccess)
1928
1.95k
    {
1929
1.95k
        ++nPos;
1930
1931
1.95k
        bSuccess = readDateTimeComponent(string, nPos, nDay, 2, true);
1932
1.95k
        if (!bIgnoreInvalidOrMissingDate)
1933
1.94k
        {
1934
1.94k
            bSuccess &= (0 < nDay);
1935
1.94k
        }
1936
1.95k
        if (nMonth > 0) // not possible to check if month was missing
1937
1.94k
        {
1938
1.94k
            sal_Int32 nMaxDay
1939
1.94k
                = comphelper::date::getDaysInMonth(nMonth, isNegative ? -nYear : nYear);
1940
1.94k
            bSuccess &= (nDay <= nMaxDay);
1941
1.94k
        }
1942
1.95k
        else assert(bIgnoreInvalidOrMissingDate);
1943
1.95k
    }
1944
1945
2.24k
    if (bSuccess && (nPos < string.size()))
1946
151
    {
1947
151
        if ('T' == string[nPos] || 't' == string[nPos]) // time separator
1948
151
        {
1949
151
            bHaveTime = true;
1950
151
            ++nPos;
1951
151
        }
1952
151
    }
1953
1954
2.24k
    return bSuccess;
1955
2.24k
}
1956
1957
/** convert ISO "date" or "dateTime" string to util::DateTime or util::Date */
1958
template <typename V>
1959
static bool lcl_parseDateTime(
1960
                util::Date *const pDate, util::DateTime & rDateTime,
1961
                bool & rbDateTime,
1962
                std::optional<sal_Int16> *const pTimeZoneOffset,
1963
                V string,
1964
                bool const bIgnoreInvalidOrMissingDate)
1965
228k
{
1966
228k
    bool bSuccess = true;
1967
1968
228k
    string = o3tl::trim(string);
1969
1970
228k
    bool isNegative(false);
1971
228k
    sal_Int32 nYear(0);
1972
228k
    sal_Int32 nMonth(0);
1973
228k
    sal_Int32 nDay(0);
1974
228k
    size_t nPos(0);
1975
228k
    bool bHaveTime(false);
1976
1977
228k
    if (    !bIgnoreInvalidOrMissingDate
1978
1
        ||  string.find(':') == V::npos  // no time?
1979
1
        ||  (string.find('-') != V::npos
1980
1
             && string.find('-') < string.find(':')))
1981
228k
    {
1982
228k
        bSuccess &= lcl_parseDate<V>(isNegative, nYear, nMonth, nDay,
1983
228k
                bHaveTime, nPos, string, bIgnoreInvalidOrMissingDate);
1984
228k
    }
1985
0
    else
1986
0
    {
1987
0
        bHaveTime = true;
1988
0
    }
1989
1990
228k
    sal_Int32 nHours(0);
1991
228k
    sal_Int32 nMinutes(0);
1992
228k
    sal_Int32 nSeconds(0);
1993
228k
    sal_Int32 nNanoSeconds(0);
1994
228k
    if (bSuccess && bHaveTime)
1995
20.4k
    {
1996
20.4k
        {
1997
20.4k
            bSuccess = readDateTimeComponent(string, nPos, nHours, 2, true);
1998
20.4k
            bSuccess &= (0 <= nHours) && (nHours <= 24);
1999
20.4k
            bSuccess &= (nPos < string.size()); // not last token
2000
20.4k
        }
2001
20.4k
        if (bSuccess && (':' != string[nPos])) // separator
2002
1
        {
2003
1
            bSuccess = false;
2004
1
        }
2005
20.4k
        if (bSuccess)
2006
20.3k
        {
2007
20.3k
            ++nPos;
2008
2009
20.3k
            bSuccess = readDateTimeComponent(string, nPos, nMinutes, 2, true);
2010
20.3k
            bSuccess &= (0 <= nMinutes) && (nMinutes < 60);
2011
20.3k
            bSuccess &= (nPos < string.size()); // not last token
2012
20.3k
        }
2013
20.4k
        if (bSuccess && (':' != string[nPos])) // separator
2014
0
        {
2015
0
            bSuccess = false;
2016
0
        }
2017
20.4k
        if (bSuccess)
2018
20.3k
        {
2019
20.3k
            ++nPos;
2020
2021
20.3k
            bSuccess = readDateTimeComponent(string, nPos, nSeconds, 2, true);
2022
20.3k
            bSuccess &= (0 <= nSeconds) && (nSeconds < 60);
2023
20.3k
        }
2024
20.4k
        if (bSuccess && (nPos < string.size()) &&
2025
13.8k
            ('.' == string[nPos] || ',' == string[nPos])) // fraction separator
2026
13.8k
        {
2027
13.8k
            ++nPos;
2028
13.8k
            const sal_Int32 nStart(nPos);
2029
13.8k
            sal_Int32 nTemp(0);
2030
13.8k
            if (R_NOTHING == readUnsignedNumberMaxDigits<V>(9, string, nPos, nTemp))
2031
0
            {
2032
0
                bSuccess = false;
2033
0
            }
2034
13.8k
            if (bSuccess)
2035
13.8k
            {
2036
13.8k
                sal_Int32 nDigits = std::min<sal_Int32>(nPos - nStart, 9);
2037
13.8k
                assert(nDigits > 0);
2038
31.7k
                for (; nDigits < 9; ++nDigits)
2039
17.8k
                {
2040
17.8k
                    nTemp *= 10;
2041
17.8k
                }
2042
13.8k
                nNanoSeconds = nTemp;
2043
13.8k
            }
2044
13.8k
        }
2045
2046
20.4k
        if (bSuccess && (nHours == 24))
2047
24
        {
2048
24
            if (!((0 == nMinutes) && (0 == nSeconds) && (0 == nNanoSeconds)))
2049
18
            {
2050
18
                bSuccess = false; // only 24:00:00 is valid
2051
18
            }
2052
24
        }
2053
20.4k
    }
2054
2055
228k
    bool bHaveTimezone(false);
2056
228k
    bool bHaveTimezonePlus(false);
2057
228k
    bool bHaveTimezoneMinus(false);
2058
228k
    if (bSuccess && (nPos < string.size()))
2059
3
    {
2060
3
        const sal_Unicode c(string[nPos]);
2061
3
        if ('+' == c)
2062
0
        {
2063
0
            bHaveTimezone = true;
2064
0
            bHaveTimezonePlus = true;
2065
0
            ++nPos;
2066
0
        }
2067
3
        else if ('-' == c)
2068
0
        {
2069
0
            bHaveTimezone = true;
2070
0
            bHaveTimezoneMinus = true;
2071
0
            ++nPos;
2072
0
        }
2073
3
        else if ('Z' == c || 'z' == c)
2074
0
        {
2075
0
            bHaveTimezone = true;
2076
0
            ++nPos;
2077
0
        }
2078
3
        else
2079
3
        {
2080
3
            bSuccess = false;
2081
3
        }
2082
3
    }
2083
228k
    sal_Int32 nTimezoneHours(0);
2084
228k
    sal_Int32 nTimezoneMinutes(0);
2085
228k
    if (bSuccess && (bHaveTimezonePlus || bHaveTimezoneMinus))
2086
0
    {
2087
0
        bSuccess = readDateTimeComponent<V>(
2088
0
                        string, nPos, nTimezoneHours, 2, true);
2089
0
        bSuccess &= (0 <= nTimezoneHours) && (nTimezoneHours <= 14);
2090
0
        bSuccess &= (nPos < string.size()); // not last token
2091
0
        if (bSuccess && (':' != string[nPos])) // separator
2092
0
        {
2093
0
            bSuccess = false;
2094
0
        }
2095
0
        if (bSuccess)
2096
0
        {
2097
0
            ++nPos;
2098
2099
0
            bSuccess = readDateTimeComponent<V>(
2100
0
                        string, nPos, nTimezoneMinutes, 2, true);
2101
0
            bSuccess &= (0 <= nTimezoneMinutes) && (nTimezoneMinutes < 60);
2102
0
        }
2103
0
        if (bSuccess && (nTimezoneHours == 14))
2104
0
        {
2105
0
            if (0 != nTimezoneMinutes)
2106
0
            {
2107
0
                bSuccess = false; // only +-14:00 is valid
2108
0
            }
2109
0
        }
2110
0
    }
2111
2112
228k
    bSuccess &= (nPos == string.size()); // trailing junk?
2113
2114
228k
    if (bSuccess)
2115
20.2k
    {
2116
20.2k
        sal_Int16 const nTimezoneOffset = (bHaveTimezoneMinus ? -1 : +1)
2117
20.2k
                        * ((nTimezoneHours * 60) + nTimezoneMinutes);
2118
20.2k
        if (!pDate || bHaveTime) // time is optional
2119
20.2k
        {
2120
20.2k
            rDateTime.Year =
2121
20.2k
                (isNegative ? -1 : +1) * static_cast<sal_Int16>(nYear);
2122
20.2k
            rDateTime.Month = static_cast<sal_uInt16>(nMonth);
2123
20.2k
            rDateTime.Day = static_cast<sal_uInt16>(nDay);
2124
20.2k
            rDateTime.Hours = static_cast<sal_uInt16>(nHours);
2125
20.2k
            rDateTime.Minutes = static_cast<sal_uInt16>(nMinutes);
2126
20.2k
            rDateTime.Seconds = static_cast<sal_uInt16>(nSeconds);
2127
20.2k
            rDateTime.NanoSeconds = static_cast<sal_uInt32>(nNanoSeconds);
2128
20.2k
            if (bHaveTimezone)
2129
0
            {
2130
0
                if (pTimeZoneOffset)
2131
0
                {
2132
0
                    *pTimeZoneOffset = nTimezoneOffset;
2133
0
                    rDateTime.IsUTC = (0 == nTimezoneOffset);
2134
0
                }
2135
0
                else
2136
0
                {
2137
0
                    lcl_ConvertToUTC(rDateTime.Year, rDateTime.Month,
2138
0
                            rDateTime.Day, rDateTime.Hours, rDateTime.Minutes,
2139
0
                            nTimezoneOffset);
2140
0
                    rDateTime.IsUTC = true;
2141
0
                }
2142
0
            }
2143
20.2k
            else
2144
20.2k
            {
2145
20.2k
                if (pTimeZoneOffset)
2146
0
                {
2147
0
                    pTimeZoneOffset->reset();
2148
0
                }
2149
20.2k
                rDateTime.IsUTC = false;
2150
20.2k
            }
2151
20.2k
            rbDateTime = bHaveTime;
2152
20.2k
        }
2153
0
        else
2154
0
        {
2155
0
            pDate->Year =
2156
0
                (isNegative ? -1 : +1) * static_cast<sal_Int16>(nYear);
2157
0
            pDate->Month = static_cast<sal_uInt16>(nMonth);
2158
0
            pDate->Day = static_cast<sal_uInt16>(nDay);
2159
0
            if (bHaveTimezone)
2160
0
            {
2161
0
                if (pTimeZoneOffset)
2162
0
                {
2163
0
                    *pTimeZoneOffset = nTimezoneOffset;
2164
0
                }
2165
0
                else
2166
0
                {
2167
                    // a Date cannot be adjusted
2168
0
                    SAL_INFO("sax", "dropping timezone");
2169
0
                }
2170
0
            }
2171
0
            else
2172
0
            {
2173
0
                if (pTimeZoneOffset)
2174
0
                {
2175
0
                    pTimeZoneOffset->reset();
2176
0
                }
2177
0
            }
2178
0
            rbDateTime = false;
2179
0
        }
2180
20.2k
    }
2181
228k
    return bSuccess;
2182
228k
}
converter.cxx:bool sax::lcl_parseDateTime<std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> > >(com::sun::star::util::Date*, com::sun::star::util::DateTime&, bool&, std::__1::optional<short>*, std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >, bool)
Line
Count
Source
1965
226k
{
1966
226k
    bool bSuccess = true;
1967
1968
226k
    string = o3tl::trim(string);
1969
1970
226k
    bool isNegative(false);
1971
226k
    sal_Int32 nYear(0);
1972
226k
    sal_Int32 nMonth(0);
1973
226k
    sal_Int32 nDay(0);
1974
226k
    size_t nPos(0);
1975
226k
    bool bHaveTime(false);
1976
1977
226k
    if (    !bIgnoreInvalidOrMissingDate
1978
0
        ||  string.find(':') == V::npos  // no time?
1979
0
        ||  (string.find('-') != V::npos
1980
0
             && string.find('-') < string.find(':')))
1981
226k
    {
1982
226k
        bSuccess &= lcl_parseDate<V>(isNegative, nYear, nMonth, nDay,
1983
226k
                bHaveTime, nPos, string, bIgnoreInvalidOrMissingDate);
1984
226k
    }
1985
0
    else
1986
0
    {
1987
0
        bHaveTime = true;
1988
0
    }
1989
1990
226k
    sal_Int32 nHours(0);
1991
226k
    sal_Int32 nMinutes(0);
1992
226k
    sal_Int32 nSeconds(0);
1993
226k
    sal_Int32 nNanoSeconds(0);
1994
226k
    if (bSuccess && bHaveTime)
1995
20.3k
    {
1996
20.3k
        {
1997
20.3k
            bSuccess = readDateTimeComponent(string, nPos, nHours, 2, true);
1998
20.3k
            bSuccess &= (0 <= nHours) && (nHours <= 24);
1999
20.3k
            bSuccess &= (nPos < string.size()); // not last token
2000
20.3k
        }
2001
20.3k
        if (bSuccess && (':' != string[nPos])) // separator
2002
1
        {
2003
1
            bSuccess = false;
2004
1
        }
2005
20.3k
        if (bSuccess)
2006
20.1k
        {
2007
20.1k
            ++nPos;
2008
2009
20.1k
            bSuccess = readDateTimeComponent(string, nPos, nMinutes, 2, true);
2010
20.1k
            bSuccess &= (0 <= nMinutes) && (nMinutes < 60);
2011
20.1k
            bSuccess &= (nPos < string.size()); // not last token
2012
20.1k
        }
2013
20.3k
        if (bSuccess && (':' != string[nPos])) // separator
2014
0
        {
2015
0
            bSuccess = false;
2016
0
        }
2017
20.3k
        if (bSuccess)
2018
20.1k
        {
2019
20.1k
            ++nPos;
2020
2021
20.1k
            bSuccess = readDateTimeComponent(string, nPos, nSeconds, 2, true);
2022
20.1k
            bSuccess &= (0 <= nSeconds) && (nSeconds < 60);
2023
20.1k
        }
2024
20.3k
        if (bSuccess && (nPos < string.size()) &&
2025
13.8k
            ('.' == string[nPos] || ',' == string[nPos])) // fraction separator
2026
13.8k
        {
2027
13.8k
            ++nPos;
2028
13.8k
            const sal_Int32 nStart(nPos);
2029
13.8k
            sal_Int32 nTemp(0);
2030
13.8k
            if (R_NOTHING == readUnsignedNumberMaxDigits<V>(9, string, nPos, nTemp))
2031
0
            {
2032
0
                bSuccess = false;
2033
0
            }
2034
13.8k
            if (bSuccess)
2035
13.8k
            {
2036
13.8k
                sal_Int32 nDigits = std::min<sal_Int32>(nPos - nStart, 9);
2037
13.8k
                assert(nDigits > 0);
2038
31.7k
                for (; nDigits < 9; ++nDigits)
2039
17.8k
                {
2040
17.8k
                    nTemp *= 10;
2041
17.8k
                }
2042
13.8k
                nNanoSeconds = nTemp;
2043
13.8k
            }
2044
13.8k
        }
2045
2046
20.3k
        if (bSuccess && (nHours == 24))
2047
24
        {
2048
24
            if (!((0 == nMinutes) && (0 == nSeconds) && (0 == nNanoSeconds)))
2049
18
            {
2050
18
                bSuccess = false; // only 24:00:00 is valid
2051
18
            }
2052
24
        }
2053
20.3k
    }
2054
2055
226k
    bool bHaveTimezone(false);
2056
226k
    bool bHaveTimezonePlus(false);
2057
226k
    bool bHaveTimezoneMinus(false);
2058
226k
    if (bSuccess && (nPos < string.size()))
2059
3
    {
2060
3
        const sal_Unicode c(string[nPos]);
2061
3
        if ('+' == c)
2062
0
        {
2063
0
            bHaveTimezone = true;
2064
0
            bHaveTimezonePlus = true;
2065
0
            ++nPos;
2066
0
        }
2067
3
        else if ('-' == c)
2068
0
        {
2069
0
            bHaveTimezone = true;
2070
0
            bHaveTimezoneMinus = true;
2071
0
            ++nPos;
2072
0
        }
2073
3
        else if ('Z' == c || 'z' == c)
2074
0
        {
2075
0
            bHaveTimezone = true;
2076
0
            ++nPos;
2077
0
        }
2078
3
        else
2079
3
        {
2080
3
            bSuccess = false;
2081
3
        }
2082
3
    }
2083
226k
    sal_Int32 nTimezoneHours(0);
2084
226k
    sal_Int32 nTimezoneMinutes(0);
2085
226k
    if (bSuccess && (bHaveTimezonePlus || bHaveTimezoneMinus))
2086
0
    {
2087
0
        bSuccess = readDateTimeComponent<V>(
2088
0
                        string, nPos, nTimezoneHours, 2, true);
2089
0
        bSuccess &= (0 <= nTimezoneHours) && (nTimezoneHours <= 14);
2090
0
        bSuccess &= (nPos < string.size()); // not last token
2091
0
        if (bSuccess && (':' != string[nPos])) // separator
2092
0
        {
2093
0
            bSuccess = false;
2094
0
        }
2095
0
        if (bSuccess)
2096
0
        {
2097
0
            ++nPos;
2098
2099
0
            bSuccess = readDateTimeComponent<V>(
2100
0
                        string, nPos, nTimezoneMinutes, 2, true);
2101
0
            bSuccess &= (0 <= nTimezoneMinutes) && (nTimezoneMinutes < 60);
2102
0
        }
2103
0
        if (bSuccess && (nTimezoneHours == 14))
2104
0
        {
2105
0
            if (0 != nTimezoneMinutes)
2106
0
            {
2107
0
                bSuccess = false; // only +-14:00 is valid
2108
0
            }
2109
0
        }
2110
0
    }
2111
2112
226k
    bSuccess &= (nPos == string.size()); // trailing junk?
2113
2114
226k
    if (bSuccess)
2115
20.1k
    {
2116
20.1k
        sal_Int16 const nTimezoneOffset = (bHaveTimezoneMinus ? -1 : +1)
2117
20.1k
                        * ((nTimezoneHours * 60) + nTimezoneMinutes);
2118
20.1k
        if (!pDate || bHaveTime) // time is optional
2119
20.1k
        {
2120
20.1k
            rDateTime.Year =
2121
20.1k
                (isNegative ? -1 : +1) * static_cast<sal_Int16>(nYear);
2122
20.1k
            rDateTime.Month = static_cast<sal_uInt16>(nMonth);
2123
20.1k
            rDateTime.Day = static_cast<sal_uInt16>(nDay);
2124
20.1k
            rDateTime.Hours = static_cast<sal_uInt16>(nHours);
2125
20.1k
            rDateTime.Minutes = static_cast<sal_uInt16>(nMinutes);
2126
20.1k
            rDateTime.Seconds = static_cast<sal_uInt16>(nSeconds);
2127
20.1k
            rDateTime.NanoSeconds = static_cast<sal_uInt32>(nNanoSeconds);
2128
20.1k
            if (bHaveTimezone)
2129
0
            {
2130
0
                if (pTimeZoneOffset)
2131
0
                {
2132
0
                    *pTimeZoneOffset = nTimezoneOffset;
2133
0
                    rDateTime.IsUTC = (0 == nTimezoneOffset);
2134
0
                }
2135
0
                else
2136
0
                {
2137
0
                    lcl_ConvertToUTC(rDateTime.Year, rDateTime.Month,
2138
0
                            rDateTime.Day, rDateTime.Hours, rDateTime.Minutes,
2139
0
                            nTimezoneOffset);
2140
0
                    rDateTime.IsUTC = true;
2141
0
                }
2142
0
            }
2143
20.1k
            else
2144
20.1k
            {
2145
20.1k
                if (pTimeZoneOffset)
2146
0
                {
2147
0
                    pTimeZoneOffset->reset();
2148
0
                }
2149
20.1k
                rDateTime.IsUTC = false;
2150
20.1k
            }
2151
20.1k
            rbDateTime = bHaveTime;
2152
20.1k
        }
2153
0
        else
2154
0
        {
2155
0
            pDate->Year =
2156
0
                (isNegative ? -1 : +1) * static_cast<sal_Int16>(nYear);
2157
0
            pDate->Month = static_cast<sal_uInt16>(nMonth);
2158
0
            pDate->Day = static_cast<sal_uInt16>(nDay);
2159
0
            if (bHaveTimezone)
2160
0
            {
2161
0
                if (pTimeZoneOffset)
2162
0
                {
2163
0
                    *pTimeZoneOffset = nTimezoneOffset;
2164
0
                }
2165
0
                else
2166
0
                {
2167
                    // a Date cannot be adjusted
2168
0
                    SAL_INFO("sax", "dropping timezone");
2169
0
                }
2170
0
            }
2171
0
            else
2172
0
            {
2173
0
                if (pTimeZoneOffset)
2174
0
                {
2175
0
                    pTimeZoneOffset->reset();
2176
0
                }
2177
0
            }
2178
0
            rbDateTime = false;
2179
0
        }
2180
20.1k
    }
2181
226k
    return bSuccess;
2182
226k
}
converter.cxx:bool sax::lcl_parseDateTime<std::__1::basic_string_view<char, std::__1::char_traits<char> > >(com::sun::star::util::Date*, com::sun::star::util::DateTime&, bool&, std::__1::optional<short>*, std::__1::basic_string_view<char, std::__1::char_traits<char> >, bool)
Line
Count
Source
1965
2.24k
{
1966
2.24k
    bool bSuccess = true;
1967
1968
2.24k
    string = o3tl::trim(string);
1969
1970
2.24k
    bool isNegative(false);
1971
2.24k
    sal_Int32 nYear(0);
1972
2.24k
    sal_Int32 nMonth(0);
1973
2.24k
    sal_Int32 nDay(0);
1974
2.24k
    size_t nPos(0);
1975
2.24k
    bool bHaveTime(false);
1976
1977
2.24k
    if (    !bIgnoreInvalidOrMissingDate
1978
1
        ||  string.find(':') == V::npos  // no time?
1979
1
        ||  (string.find('-') != V::npos
1980
1
             && string.find('-') < string.find(':')))
1981
2.24k
    {
1982
2.24k
        bSuccess &= lcl_parseDate<V>(isNegative, nYear, nMonth, nDay,
1983
2.24k
                bHaveTime, nPos, string, bIgnoreInvalidOrMissingDate);
1984
2.24k
    }
1985
0
    else
1986
0
    {
1987
0
        bHaveTime = true;
1988
0
    }
1989
1990
2.24k
    sal_Int32 nHours(0);
1991
2.24k
    sal_Int32 nMinutes(0);
1992
2.24k
    sal_Int32 nSeconds(0);
1993
2.24k
    sal_Int32 nNanoSeconds(0);
1994
2.24k
    if (bSuccess && bHaveTime)
1995
151
    {
1996
151
        {
1997
151
            bSuccess = readDateTimeComponent(string, nPos, nHours, 2, true);
1998
151
            bSuccess &= (0 <= nHours) && (nHours <= 24);
1999
151
            bSuccess &= (nPos < string.size()); // not last token
2000
151
        }
2001
151
        if (bSuccess && (':' != string[nPos])) // separator
2002
0
        {
2003
0
            bSuccess = false;
2004
0
        }
2005
151
        if (bSuccess)
2006
150
        {
2007
150
            ++nPos;
2008
2009
150
            bSuccess = readDateTimeComponent(string, nPos, nMinutes, 2, true);
2010
150
            bSuccess &= (0 <= nMinutes) && (nMinutes < 60);
2011
150
            bSuccess &= (nPos < string.size()); // not last token
2012
150
        }
2013
151
        if (bSuccess && (':' != string[nPos])) // separator
2014
0
        {
2015
0
            bSuccess = false;
2016
0
        }
2017
151
        if (bSuccess)
2018
147
        {
2019
147
            ++nPos;
2020
2021
147
            bSuccess = readDateTimeComponent(string, nPos, nSeconds, 2, true);
2022
147
            bSuccess &= (0 <= nSeconds) && (nSeconds < 60);
2023
147
        }
2024
151
        if (bSuccess && (nPos < string.size()) &&
2025
0
            ('.' == string[nPos] || ',' == string[nPos])) // fraction separator
2026
0
        {
2027
0
            ++nPos;
2028
0
            const sal_Int32 nStart(nPos);
2029
0
            sal_Int32 nTemp(0);
2030
0
            if (R_NOTHING == readUnsignedNumberMaxDigits<V>(9, string, nPos, nTemp))
2031
0
            {
2032
0
                bSuccess = false;
2033
0
            }
2034
0
            if (bSuccess)
2035
0
            {
2036
0
                sal_Int32 nDigits = std::min<sal_Int32>(nPos - nStart, 9);
2037
0
                assert(nDigits > 0);
2038
0
                for (; nDigits < 9; ++nDigits)
2039
0
                {
2040
0
                    nTemp *= 10;
2041
0
                }
2042
0
                nNanoSeconds = nTemp;
2043
0
            }
2044
0
        }
2045
2046
151
        if (bSuccess && (nHours == 24))
2047
0
        {
2048
0
            if (!((0 == nMinutes) && (0 == nSeconds) && (0 == nNanoSeconds)))
2049
0
            {
2050
0
                bSuccess = false; // only 24:00:00 is valid
2051
0
            }
2052
0
        }
2053
151
    }
2054
2055
2.24k
    bool bHaveTimezone(false);
2056
2.24k
    bool bHaveTimezonePlus(false);
2057
2.24k
    bool bHaveTimezoneMinus(false);
2058
2.24k
    if (bSuccess && (nPos < string.size()))
2059
0
    {
2060
0
        const sal_Unicode c(string[nPos]);
2061
0
        if ('+' == c)
2062
0
        {
2063
0
            bHaveTimezone = true;
2064
0
            bHaveTimezonePlus = true;
2065
0
            ++nPos;
2066
0
        }
2067
0
        else if ('-' == c)
2068
0
        {
2069
0
            bHaveTimezone = true;
2070
0
            bHaveTimezoneMinus = true;
2071
0
            ++nPos;
2072
0
        }
2073
0
        else if ('Z' == c || 'z' == c)
2074
0
        {
2075
0
            bHaveTimezone = true;
2076
0
            ++nPos;
2077
0
        }
2078
0
        else
2079
0
        {
2080
0
            bSuccess = false;
2081
0
        }
2082
0
    }
2083
2.24k
    sal_Int32 nTimezoneHours(0);
2084
2.24k
    sal_Int32 nTimezoneMinutes(0);
2085
2.24k
    if (bSuccess && (bHaveTimezonePlus || bHaveTimezoneMinus))
2086
0
    {
2087
0
        bSuccess = readDateTimeComponent<V>(
2088
0
                        string, nPos, nTimezoneHours, 2, true);
2089
0
        bSuccess &= (0 <= nTimezoneHours) && (nTimezoneHours <= 14);
2090
0
        bSuccess &= (nPos < string.size()); // not last token
2091
0
        if (bSuccess && (':' != string[nPos])) // separator
2092
0
        {
2093
0
            bSuccess = false;
2094
0
        }
2095
0
        if (bSuccess)
2096
0
        {
2097
0
            ++nPos;
2098
2099
0
            bSuccess = readDateTimeComponent<V>(
2100
0
                        string, nPos, nTimezoneMinutes, 2, true);
2101
0
            bSuccess &= (0 <= nTimezoneMinutes) && (nTimezoneMinutes < 60);
2102
0
        }
2103
0
        if (bSuccess && (nTimezoneHours == 14))
2104
0
        {
2105
0
            if (0 != nTimezoneMinutes)
2106
0
            {
2107
0
                bSuccess = false; // only +-14:00 is valid
2108
0
            }
2109
0
        }
2110
0
    }
2111
2112
2.24k
    bSuccess &= (nPos == string.size()); // trailing junk?
2113
2114
2.24k
    if (bSuccess)
2115
148
    {
2116
148
        sal_Int16 const nTimezoneOffset = (bHaveTimezoneMinus ? -1 : +1)
2117
148
                        * ((nTimezoneHours * 60) + nTimezoneMinutes);
2118
148
        if (!pDate || bHaveTime) // time is optional
2119
148
        {
2120
148
            rDateTime.Year =
2121
148
                (isNegative ? -1 : +1) * static_cast<sal_Int16>(nYear);
2122
148
            rDateTime.Month = static_cast<sal_uInt16>(nMonth);
2123
148
            rDateTime.Day = static_cast<sal_uInt16>(nDay);
2124
148
            rDateTime.Hours = static_cast<sal_uInt16>(nHours);
2125
148
            rDateTime.Minutes = static_cast<sal_uInt16>(nMinutes);
2126
148
            rDateTime.Seconds = static_cast<sal_uInt16>(nSeconds);
2127
148
            rDateTime.NanoSeconds = static_cast<sal_uInt32>(nNanoSeconds);
2128
148
            if (bHaveTimezone)
2129
0
            {
2130
0
                if (pTimeZoneOffset)
2131
0
                {
2132
0
                    *pTimeZoneOffset = nTimezoneOffset;
2133
0
                    rDateTime.IsUTC = (0 == nTimezoneOffset);
2134
0
                }
2135
0
                else
2136
0
                {
2137
0
                    lcl_ConvertToUTC(rDateTime.Year, rDateTime.Month,
2138
0
                            rDateTime.Day, rDateTime.Hours, rDateTime.Minutes,
2139
0
                            nTimezoneOffset);
2140
0
                    rDateTime.IsUTC = true;
2141
0
                }
2142
0
            }
2143
148
            else
2144
148
            {
2145
148
                if (pTimeZoneOffset)
2146
0
                {
2147
0
                    pTimeZoneOffset->reset();
2148
0
                }
2149
148
                rDateTime.IsUTC = false;
2150
148
            }
2151
148
            rbDateTime = bHaveTime;
2152
148
        }
2153
0
        else
2154
0
        {
2155
0
            pDate->Year =
2156
0
                (isNegative ? -1 : +1) * static_cast<sal_Int16>(nYear);
2157
0
            pDate->Month = static_cast<sal_uInt16>(nMonth);
2158
0
            pDate->Day = static_cast<sal_uInt16>(nDay);
2159
0
            if (bHaveTimezone)
2160
0
            {
2161
0
                if (pTimeZoneOffset)
2162
0
                {
2163
0
                    *pTimeZoneOffset = nTimezoneOffset;
2164
0
                }
2165
0
                else
2166
0
                {
2167
                    // a Date cannot be adjusted
2168
0
                    SAL_INFO("sax", "dropping timezone");
2169
0
                }
2170
0
            }
2171
0
            else
2172
0
            {
2173
0
                if (pTimeZoneOffset)
2174
0
                {
2175
0
                    pTimeZoneOffset->reset();
2176
0
                }
2177
0
            }
2178
0
            rbDateTime = false;
2179
0
        }
2180
148
    }
2181
2.24k
    return bSuccess;
2182
2.24k
}
2183
2184
/** convert ISO "time" or "dateTime" string to util::DateTime */
2185
bool Converter::parseTimeOrDateTime(
2186
                util::DateTime & rDateTime,
2187
                std::u16string_view rString)
2188
0
{
2189
0
    bool dummy;
2190
0
    return lcl_parseDateTime(
2191
0
                nullptr, rDateTime, dummy, nullptr, rString, true);
2192
0
}
2193
2194
/** convert ISO "time" or "dateTime" string to util::DateTime */
2195
bool Converter::parseTimeOrDateTime(
2196
                util::DateTime & rDateTime,
2197
                std::string_view rString)
2198
1
{
2199
1
    bool dummy;
2200
1
    return lcl_parseDateTime(
2201
1
                nullptr, rDateTime, dummy, nullptr, rString, true);
2202
1
}
2203
2204
/** convert ISO "date" or "dateTime" string to util::DateTime or util::Date */
2205
bool Converter::parseDateOrDateTime(
2206
                util::Date *const pDate, util::DateTime & rDateTime,
2207
                bool & rbDateTime,
2208
                std::optional<sal_Int16> *const pTimeZoneOffset,
2209
                std::u16string_view rString )
2210
226k
{
2211
226k
    return lcl_parseDateTime(
2212
226k
                pDate, rDateTime, rbDateTime, pTimeZoneOffset, rString, false);
2213
226k
}
2214
2215
/** convert ISO "date" or "dateTime" string to util::DateTime or util::Date */
2216
bool Converter::parseDateOrDateTime(
2217
                util::Date *const pDate, util::DateTime & rDateTime,
2218
                bool & rbDateTime,
2219
                std::optional<sal_Int16> *const pTimeZoneOffset,
2220
                std::string_view rString )
2221
2.24k
{
2222
2.24k
    return lcl_parseDateTime(
2223
2.24k
                pDate, rDateTime, rbDateTime, pTimeZoneOffset, rString, false);
2224
2.24k
}
2225
2226
/** gets the position of the first comma after npos in the string
2227
    rStr. Commas inside '"' pairs are not matched */
2228
sal_Int32 Converter::indexOfComma( std::u16string_view rStr,
2229
                                            sal_Int32 nPos )
2230
24.6k
{
2231
24.6k
    sal_Unicode cQuote = 0;
2232
24.6k
    sal_Int32 nLen = rStr.size();
2233
330k
    for( ; nPos < nLen; nPos++ )
2234
305k
    {
2235
305k
        sal_Unicode c = rStr[nPos];
2236
305k
        switch( c )
2237
305k
        {
2238
25.4k
        case u'\'':
2239
25.4k
            if( 0 == cQuote )
2240
12.7k
                cQuote = c;
2241
12.6k
            else if( '\'' == cQuote )
2242
12.6k
                cQuote = 0;
2243
25.4k
            break;
2244
2245
3
        case u'"':
2246
3
            if( 0 == cQuote )
2247
2
                cQuote = c;
2248
1
            else if( '\"' == cQuote )
2249
0
                cQuote = 0;
2250
3
            break;
2251
2252
19
        case u',':
2253
19
            if( 0 == cQuote )
2254
3
                return nPos;
2255
16
            break;
2256
305k
        }
2257
305k
    }
2258
2259
24.6k
    return -1;
2260
24.6k
}
2261
2262
double Converter::GetConversionFactor(OUStringBuffer& rUnit, sal_Int16 nSourceUnit, sal_Int16 nTargetUnit)
2263
48.6k
{
2264
48.6k
    double fRetval(1.0);
2265
48.6k
    rUnit.setLength(0);
2266
2267
2268
48.6k
    if(nSourceUnit != nTargetUnit)
2269
11
    {
2270
11
        const o3tl::Length eFrom = Measure2O3tlUnit(nSourceUnit);
2271
11
        const o3tl::Length eTo = Measure2O3tlUnit(nTargetUnit);
2272
11
        fRetval = o3tl::convert(1.0, eFrom, eTo);
2273
2274
11
        if (const auto sUnit = Measure2UnitString(nTargetUnit); sUnit.size() > 0)
2275
11
            rUnit.appendAscii(sUnit.data(), sUnit.size());
2276
11
    }
2277
2278
48.6k
    return fRetval;
2279
48.6k
}
2280
2281
double Converter::GetConversionFactor(OStringBuffer& rUnit, sal_Int16 nSourceUnit, sal_Int16 nTargetUnit)
2282
0
{
2283
0
    double fRetval(1.0);
2284
0
    rUnit.setLength(0);
2285
2286
2287
0
    if(nSourceUnit != nTargetUnit)
2288
0
    {
2289
0
        const o3tl::Length eFrom = Measure2O3tlUnit(nSourceUnit);
2290
0
        const o3tl::Length eTo = Measure2O3tlUnit(nTargetUnit);
2291
0
        fRetval = o3tl::convert(1.0, eFrom, eTo);
2292
2293
0
        if (const auto sUnit = Measure2UnitString(nTargetUnit); sUnit.size() > 0)
2294
0
            rUnit.append(sUnit.data(), sUnit.size());
2295
0
    }
2296
2297
0
    return fRetval;
2298
0
}
2299
2300
template<typename V>
2301
static sal_Int16 lcl_GetUnitFromString(V rString, sal_Int16 nDefaultUnit)
2302
47.3k
{
2303
47.3k
    sal_Int32 nPos = 0;
2304
47.3k
    sal_Int32 nLen = rString.size();
2305
47.3k
    sal_Int16 nRetUnit = nDefaultUnit;
2306
2307
    // skip white space
2308
47.3k
    while( nPos < nLen && ' ' == rString[nPos] )
2309
4
        nPos++;
2310
2311
    // skip negative
2312
47.3k
    if( nPos < nLen && '-' == rString[nPos] )
2313
129
        nPos++;
2314
2315
    // skip number
2316
167k
    while( nPos < nLen && '0' <= rString[nPos] && '9' >= rString[nPos] )
2317
119k
        nPos++;
2318
2319
47.3k
    if( nPos < nLen && '.' == rString[nPos] )
2320
4.83k
    {
2321
4.83k
        nPos++;
2322
10.7k
        while( nPos < nLen && '0' <= rString[nPos] && '9' >= rString[nPos] )
2323
5.89k
            nPos++;
2324
4.83k
    }
2325
2326
    // skip white space
2327
47.4k
    while( nPos < nLen && ' ' == rString[nPos] )
2328
116
        nPos++;
2329
2330
47.3k
    if( nPos < nLen )
2331
47.1k
    {
2332
47.1k
        switch(rString[nPos])
2333
47.1k
        {
2334
0
            case '%' :
2335
0
            {
2336
0
                nRetUnit = MeasureUnit::PERCENT;
2337
0
                break;
2338
0
            }
2339
6
            case 'c':
2340
7
            case 'C':
2341
7
            {
2342
7
                if(nPos+1 < nLen && (rString[nPos+1] == 'm'
2343
6
                    || rString[nPos+1] == 'M'))
2344
1
                    nRetUnit = MeasureUnit::CM;
2345
7
                break;
2346
6
            }
2347
4
            case 'e':
2348
26
            case 'E':
2349
26
            {
2350
                // CSS1_EMS or CSS1_EMX later
2351
26
                break;
2352
4
            }
2353
13
            case 'i':
2354
13
            case 'I':
2355
13
            {
2356
13
                if(nPos+1 < nLen && (rString[nPos+1] == 'n'
2357
9
                    || rString[nPos+1] == 'N'))
2358
4
                    nRetUnit = MeasureUnit::INCH;
2359
13
                break;
2360
13
            }
2361
5
            case 'm':
2362
7
            case 'M':
2363
7
            {
2364
7
                if(nPos+1 < nLen && (rString[nPos+1] == 'm'
2365
7
                    || rString[nPos+1] == 'M'))
2366
0
                    nRetUnit = MeasureUnit::MM;
2367
7
                break;
2368
5
            }
2369
46.1k
            case 'p':
2370
46.1k
            case 'P':
2371
46.1k
            {
2372
46.1k
                if(nPos+1 < nLen && (rString[nPos+1] == 't'
2373
94
                    || rString[nPos+1] == 'T'))
2374
46.0k
                    nRetUnit = MeasureUnit::POINT;
2375
46.1k
                if(nPos+1 < nLen && (rString[nPos+1] == 'c'
2376
46.1k
                    || rString[nPos+1] == 'C'))
2377
6
                    nRetUnit = MeasureUnit::TWIP;
2378
46.1k
                break;
2379
46.1k
            }
2380
47.1k
        }
2381
47.1k
    }
2382
2383
47.3k
    return nRetUnit;
2384
47.3k
}
converter.cxx:short sax::lcl_GetUnitFromString<std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> > >(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >, short)
Line
Count
Source
2302
47.3k
{
2303
47.3k
    sal_Int32 nPos = 0;
2304
47.3k
    sal_Int32 nLen = rString.size();
2305
47.3k
    sal_Int16 nRetUnit = nDefaultUnit;
2306
2307
    // skip white space
2308
47.3k
    while( nPos < nLen && ' ' == rString[nPos] )
2309
4
        nPos++;
2310
2311
    // skip negative
2312
47.3k
    if( nPos < nLen && '-' == rString[nPos] )
2313
129
        nPos++;
2314
2315
    // skip number
2316
167k
    while( nPos < nLen && '0' <= rString[nPos] && '9' >= rString[nPos] )
2317
119k
        nPos++;
2318
2319
47.3k
    if( nPos < nLen && '.' == rString[nPos] )
2320
4.83k
    {
2321
4.83k
        nPos++;
2322
10.7k
        while( nPos < nLen && '0' <= rString[nPos] && '9' >= rString[nPos] )
2323
5.89k
            nPos++;
2324
4.83k
    }
2325
2326
    // skip white space
2327
47.4k
    while( nPos < nLen && ' ' == rString[nPos] )
2328
116
        nPos++;
2329
2330
47.3k
    if( nPos < nLen )
2331
47.1k
    {
2332
47.1k
        switch(rString[nPos])
2333
47.1k
        {
2334
0
            case '%' :
2335
0
            {
2336
0
                nRetUnit = MeasureUnit::PERCENT;
2337
0
                break;
2338
0
            }
2339
6
            case 'c':
2340
7
            case 'C':
2341
7
            {
2342
7
                if(nPos+1 < nLen && (rString[nPos+1] == 'm'
2343
6
                    || rString[nPos+1] == 'M'))
2344
1
                    nRetUnit = MeasureUnit::CM;
2345
7
                break;
2346
6
            }
2347
4
            case 'e':
2348
26
            case 'E':
2349
26
            {
2350
                // CSS1_EMS or CSS1_EMX later
2351
26
                break;
2352
4
            }
2353
13
            case 'i':
2354
13
            case 'I':
2355
13
            {
2356
13
                if(nPos+1 < nLen && (rString[nPos+1] == 'n'
2357
9
                    || rString[nPos+1] == 'N'))
2358
4
                    nRetUnit = MeasureUnit::INCH;
2359
13
                break;
2360
13
            }
2361
5
            case 'm':
2362
7
            case 'M':
2363
7
            {
2364
7
                if(nPos+1 < nLen && (rString[nPos+1] == 'm'
2365
7
                    || rString[nPos+1] == 'M'))
2366
0
                    nRetUnit = MeasureUnit::MM;
2367
7
                break;
2368
5
            }
2369
46.1k
            case 'p':
2370
46.1k
            case 'P':
2371
46.1k
            {
2372
46.1k
                if(nPos+1 < nLen && (rString[nPos+1] == 't'
2373
94
                    || rString[nPos+1] == 'T'))
2374
46.0k
                    nRetUnit = MeasureUnit::POINT;
2375
46.1k
                if(nPos+1 < nLen && (rString[nPos+1] == 'c'
2376
46.1k
                    || rString[nPos+1] == 'C'))
2377
6
                    nRetUnit = MeasureUnit::TWIP;
2378
46.1k
                break;
2379
46.1k
            }
2380
47.1k
        }
2381
47.1k
    }
2382
2383
47.3k
    return nRetUnit;
2384
47.3k
}
Unexecuted instantiation: converter.cxx:short sax::lcl_GetUnitFromString<std::__1::basic_string_view<char, std::__1::char_traits<char> > >(std::__1::basic_string_view<char, std::__1::char_traits<char> >, short)
2385
2386
sal_Int16 Converter::GetUnitFromString(std::u16string_view rString, sal_Int16 nDefaultUnit)
2387
47.3k
{
2388
47.3k
    return lcl_GetUnitFromString(rString, nDefaultUnit);
2389
47.3k
}
2390
sal_Int16 Converter::GetUnitFromString(std::string_view rString, sal_Int16 nDefaultUnit)
2391
0
{
2392
0
    return lcl_GetUnitFromString(rString, nDefaultUnit);
2393
0
}
2394
2395
bool Converter::convertAny(OUStringBuffer&    rsValue,
2396
                           OUStringBuffer&    rsType ,
2397
                           const css::uno::Any& rValue)
2398
0
{
2399
0
    bool bConverted = false;
2400
2401
0
    rsValue.setLength(0);
2402
0
    rsType.setLength (0);
2403
2404
0
    switch (rValue.getValueTypeClass())
2405
0
    {
2406
0
        case css::uno::TypeClass_BYTE :
2407
0
        case css::uno::TypeClass_SHORT :
2408
0
        case css::uno::TypeClass_UNSIGNED_SHORT :
2409
0
        case css::uno::TypeClass_LONG :
2410
0
        case css::uno::TypeClass_UNSIGNED_LONG :
2411
0
            {
2412
0
                sal_Int32 nTempValue = 0;
2413
0
                if (rValue >>= nTempValue)
2414
0
                {
2415
0
                    rsType.append("integer");
2416
0
                    bConverted = true;
2417
0
                    rsValue.append(nTempValue);
2418
0
                }
2419
0
            }
2420
0
            break;
2421
2422
0
        case css::uno::TypeClass_BOOLEAN :
2423
0
            {
2424
0
                bool bTempValue = false;
2425
0
                if (rValue >>= bTempValue)
2426
0
                {
2427
0
                    rsType.append("boolean");
2428
0
                    bConverted = true;
2429
0
                    ::sax::Converter::convertBool(rsValue, bTempValue);
2430
0
                }
2431
0
            }
2432
0
            break;
2433
2434
0
        case css::uno::TypeClass_FLOAT :
2435
0
        case css::uno::TypeClass_DOUBLE :
2436
0
            {
2437
0
                double fTempValue = 0.0;
2438
0
                if (rValue >>= fTempValue)
2439
0
                {
2440
0
                    rsType.append("float");
2441
0
                    bConverted = true;
2442
0
                    ::sax::Converter::convertDouble(rsValue, fTempValue);
2443
0
                }
2444
0
            }
2445
0
            break;
2446
2447
0
        case css::uno::TypeClass_STRING :
2448
0
            {
2449
0
                OUString sTempValue;
2450
0
                if (rValue >>= sTempValue)
2451
0
                {
2452
0
                    rsType.append("string");
2453
0
                    bConverted = true;
2454
0
                    rsValue.append(sTempValue);
2455
0
                }
2456
0
            }
2457
0
            break;
2458
2459
0
        case css::uno::TypeClass_STRUCT :
2460
0
            {
2461
0
                css::util::Date     aDate    ;
2462
0
                css::util::Time     aTime    ;
2463
0
                css::util::DateTime aDateTime;
2464
2465
0
                if (rValue >>= aDate)
2466
0
                {
2467
0
                    rsType.append("date");
2468
0
                    bConverted = true;
2469
0
                    css::util::DateTime aTempValue;
2470
0
                    aTempValue.Day              = aDate.Day;
2471
0
                    aTempValue.Month            = aDate.Month;
2472
0
                    aTempValue.Year             = aDate.Year;
2473
0
                    aTempValue.NanoSeconds = 0;
2474
0
                    aTempValue.Seconds          = 0;
2475
0
                    aTempValue.Minutes          = 0;
2476
0
                    aTempValue.Hours            = 0;
2477
0
                    ::sax::Converter::convertDateTime(rsValue, aTempValue, nullptr);
2478
0
                }
2479
0
                else
2480
0
                if (rValue >>= aTime)
2481
0
                {
2482
0
                    rsType.append("time");
2483
0
                    bConverted = true;
2484
0
                    css::util::Duration aTempValue;
2485
0
                    aTempValue.Days             = 0;
2486
0
                    aTempValue.Months           = 0;
2487
0
                    aTempValue.Years            = 0;
2488
0
                    aTempValue.NanoSeconds     = aTime.NanoSeconds;
2489
0
                    aTempValue.Seconds          = aTime.Seconds;
2490
0
                    aTempValue.Minutes          = aTime.Minutes;
2491
0
                    aTempValue.Hours            = aTime.Hours;
2492
0
                    ::sax::Converter::convertDuration(rsValue, aTempValue);
2493
0
                }
2494
0
                else
2495
0
                if (rValue >>= aDateTime)
2496
0
                {
2497
0
                    rsType.append("date");
2498
0
                    bConverted = true;
2499
0
                    ::sax::Converter::convertDateTime(rsValue, aDateTime, nullptr);
2500
0
                }
2501
0
            }
2502
0
            break;
2503
0
        default:
2504
0
            break;
2505
0
    }
2506
2507
0
    return bConverted;
2508
0
}
2509
2510
void Converter::convertBytesToHexBinary(OUStringBuffer& rBuffer, const void* pBytes,
2511
                                        sal_Int32 nBytes)
2512
0
{
2513
0
    rBuffer.setLength(0);
2514
0
    rBuffer.ensureCapacity(nBytes * 2);
2515
0
    auto pChars = static_cast<const unsigned char*>(pBytes);
2516
0
    for (sal_Int32 i = 0; i < nBytes; ++i)
2517
0
    {
2518
0
        sal_Int32 c = *pChars++;
2519
0
        if (c < 16)
2520
0
            rBuffer.append('0');
2521
0
        rBuffer.append(c, 16);
2522
0
    }
2523
0
}
2524
2525
}
2526
2527
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */