Coverage Report

Created: 2025-12-08 09:28

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
1.22M
{
60
1.22M
    return rtl_ustr_toInt64_WithLength(str, radix, nStrLength);
61
1.22M
}
62
static sal_Int64 toInt64_WithLength(const char * str, sal_Int16 radix, sal_Int32 nStrLength )
63
119k
{
64
119k
    return rtl_str_toInt64_WithLength(str, radix, nStrLength);
65
119k
}
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
309k
{
91
309k
    switch (nUnit)
92
309k
    {
93
11.3k
        case MeasureUnit::TWIP:
94
11.3k
            return o3tl::Length::twip;
95
43
        case MeasureUnit::POINT:
96
43
            return o3tl::Length::pt;
97
0
        case MeasureUnit::MM_10TH:
98
0
            return o3tl::Length::mm10;
99
297k
        case MeasureUnit::MM_100TH:
100
297k
            return o3tl::Length::mm100;
101
5
        case MeasureUnit::MM:
102
5
            return o3tl::Length::mm;
103
7
        case MeasureUnit::CM:
104
7
            return o3tl::Length::cm;
105
0
        default:
106
0
            SAL_WARN("sax", "unit not supported for length");
107
0
            [[fallthrough]];
108
28
        case MeasureUnit::INCH:
109
28
            return o3tl::Length::in;
110
309k
    }
111
309k
}
112
113
std::string_view Measure2UnitString(sal_Int16 nUnit)
114
43
{
115
43
    switch (nUnit)
116
43
    {
117
3
        case MeasureUnit::TWIP:
118
3
            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
5
        case MeasureUnit::MM:
125
5
            return gpsMM;
126
7
        case MeasureUnit::CM:
127
7
            return gpsCM;
128
28
        case MeasureUnit::INCH:
129
28
        default:
130
28
            return gpsINCH;
131
43
    }
132
43
}
133
134
template <typename V> bool wordEndsWith(V string, std::string_view expected)
135
434k
{
136
434k
    V substr = string.substr(0, expected.size());
137
434k
    return std::equal(substr.begin(), substr.end(), expected.begin(), expected.end(),
138
434k
                      [](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
258k
                      [](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
175k
                      [](sal_uInt32 c1, sal_uInt32 c2) { return rtl::toAsciiLowerCase(c1) == c2; })
139
348k
           && (string.size() == expected.size() || string[expected.size()] == ' ');
140
434k
}
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
258k
{
136
258k
    V substr = string.substr(0, expected.size());
137
258k
    return std::equal(substr.begin(), substr.end(), expected.begin(), expected.end(),
138
258k
                      [](sal_uInt32 c1, sal_uInt32 c2) { return rtl::toAsciiLowerCase(c1) == c2; })
139
202k
           && (string.size() == expected.size() || string[expected.size()] == ' ');
140
258k
}
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
175k
{
136
175k
    V substr = string.substr(0, expected.size());
137
175k
    return std::equal(substr.begin(), substr.end(), expected.begin(), expected.end(),
138
175k
                      [](sal_uInt32 c1, sal_uInt32 c2) { return rtl::toAsciiLowerCase(c1) == c2; })
139
145k
           && (string.size() == expected.size() || string[expected.size()] == ' ');
140
175k
}
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
382k
{
147
382k
    if (rString.empty())
148
0
    {
149
0
        return std::nullopt;
150
0
    }
151
152
382k
    switch (rtl::toAsciiLowerCase<sal_uInt32>(rString[0]))
153
382k
    {
154
28.1k
        case u'%':
155
28.1k
            return MeasureUnit::PERCENT;
156
157
252k
        case u'c':
158
252k
            if (wordEndsWith(rString.substr(1), "m"))
159
251k
                return MeasureUnit::CM;
160
928
            break;
161
162
928
        case u'e':
163
97
            if (wordEndsWith(rString.substr(1), "m"))
164
9
                return MeasureUnit::FONT_EM;
165
88
            break;
166
167
67.5k
        case u'i':
168
67.5k
            if (wordEndsWith(rString.substr(1), "c"))
169
2
                return MeasureUnit::FONT_CJK_ADVANCE;
170
67.5k
            if (wordEndsWith(rString.substr(1), "n"))
171
67.0k
                return MeasureUnit::INCH;
172
440
            break;
173
174
12.8k
        case u'm':
175
12.8k
            if (wordEndsWith(rString.substr(1), "m"))
176
12.5k
                return MeasureUnit::MM;
177
282
            break;
178
179
17.0k
        case u'p':
180
17.0k
            if (wordEndsWith(rString.substr(1), "c"))
181
0
                return MeasureUnit::PICA;
182
17.0k
            if (wordEndsWith(rString.substr(1), "t"))
183
16.6k
                return MeasureUnit::POINT;
184
382
            if (wordEndsWith(rString.substr(1), "x"))
185
1
                return MeasureUnit::PIXEL;
186
381
            break;
187
382k
    }
188
189
7.04k
    return std::nullopt;
190
382k
}
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
218k
{
147
218k
    if (rString.empty())
148
0
    {
149
0
        return std::nullopt;
150
0
    }
151
152
218k
    switch (rtl::toAsciiLowerCase<sal_uInt32>(rString[0]))
153
218k
    {
154
11.3k
        case u'%':
155
11.3k
            return MeasureUnit::PERCENT;
156
157
137k
        case u'c':
158
137k
            if (wordEndsWith(rString.substr(1), "m"))
159
136k
                return MeasureUnit::CM;
160
732
            break;
161
162
732
        case u'e':
163
77
            if (wordEndsWith(rString.substr(1), "m"))
164
9
                return MeasureUnit::FONT_EM;
165
68
            break;
166
167
37.8k
        case u'i':
168
37.8k
            if (wordEndsWith(rString.substr(1), "c"))
169
1
                return MeasureUnit::FONT_CJK_ADVANCE;
170
37.8k
            if (wordEndsWith(rString.substr(1), "n"))
171
37.6k
                return MeasureUnit::INCH;
172
167
            break;
173
174
11.7k
        case u'm':
175
11.7k
            if (wordEndsWith(rString.substr(1), "m"))
176
11.5k
                return MeasureUnit::MM;
177
214
            break;
178
179
16.8k
        case u'p':
180
16.8k
            if (wordEndsWith(rString.substr(1), "c"))
181
0
                return MeasureUnit::PICA;
182
16.8k
            if (wordEndsWith(rString.substr(1), "t"))
183
16.5k
                return MeasureUnit::POINT;
184
265
            if (wordEndsWith(rString.substr(1), "x"))
185
1
                return MeasureUnit::PIXEL;
186
264
            break;
187
218k
    }
188
189
4.95k
    return std::nullopt;
190
218k
}
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
164k
{
147
164k
    if (rString.empty())
148
0
    {
149
0
        return std::nullopt;
150
0
    }
151
152
164k
    switch (rtl::toAsciiLowerCase<sal_uInt32>(rString[0]))
153
164k
    {
154
16.8k
        case u'%':
155
16.8k
            return MeasureUnit::PERCENT;
156
157
115k
        case u'c':
158
115k
            if (wordEndsWith(rString.substr(1), "m"))
159
114k
                return MeasureUnit::CM;
160
196
            break;
161
162
196
        case u'e':
163
20
            if (wordEndsWith(rString.substr(1), "m"))
164
0
                return MeasureUnit::FONT_EM;
165
20
            break;
166
167
29.6k
        case u'i':
168
29.6k
            if (wordEndsWith(rString.substr(1), "c"))
169
1
                return MeasureUnit::FONT_CJK_ADVANCE;
170
29.6k
            if (wordEndsWith(rString.substr(1), "n"))
171
29.4k
                return MeasureUnit::INCH;
172
273
            break;
173
174
1.10k
        case u'm':
175
1.10k
            if (wordEndsWith(rString.substr(1), "m"))
176
1.03k
                return MeasureUnit::MM;
177
68
            break;
178
179
190
        case u'p':
180
190
            if (wordEndsWith(rString.substr(1), "c"))
181
0
                return MeasureUnit::PICA;
182
190
            if (wordEndsWith(rString.substr(1), "t"))
183
73
                return MeasureUnit::POINT;
184
117
            if (wordEndsWith(rString.substr(1), "x"))
185
0
                return MeasureUnit::PIXEL;
186
117
            break;
187
164k
    }
188
189
2.09k
    return std::nullopt;
190
164k
}
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
407k
{
196
407k
    rValue = 0.0;
197
407k
    rSourceUnit.reset();
198
407k
    rNeg = false;
199
200
407k
    bool bNeg = false;
201
407k
    double nVal = 0;
202
203
407k
    sal_Int32 nPos = 0;
204
407k
    sal_Int32 const nLen = rString.size();
205
206
    // skip white space
207
411k
    while( (nPos < nLen) && (rString[nPos] <= ' ') )
208
4.42k
        nPos++;
209
210
407k
    if( nPos < nLen && '-' == rString[nPos] )
211
27.0k
    {
212
27.0k
        bNeg = true;
213
27.0k
        nPos++;
214
27.0k
    }
215
216
    // get number
217
954k
    while( nPos < nLen &&
218
930k
           '0' <= rString[nPos] &&
219
637k
           '9' >= rString[nPos] )
220
547k
    {
221
        // TODO: check overflow!
222
547k
        nVal *= 10;
223
547k
        nVal += (rString[nPos] - '0');
224
547k
        nPos++;
225
547k
    }
226
407k
    if( nPos < nLen && '.' == rString[nPos] )
227
264k
    {
228
264k
        nPos++;
229
264k
        double nDiv = 1.;
230
231
893k
        while( nPos < nLen &&
232
893k
               '0' <= rString[nPos] &&
233
892k
               '9' >= rString[nPos] )
234
629k
        {
235
            // TODO: check overflow!
236
629k
            nDiv *= 10;
237
629k
            nVal += ( static_cast<double>(rString[nPos] - '0') / nDiv );
238
629k
            nPos++;
239
629k
        }
240
264k
    }
241
242
    // skip white space
243
410k
    while( (nPos < nLen) && (rString[nPos] <= ' ') )
244
3.11k
        nPos++;
245
246
407k
    if (nPos < nLen)
247
382k
    {
248
        // Parse unit from the tail
249
382k
        auto nUnit = lcl_parseMeasureUnit(rString.substr(nPos));
250
382k
        if (!nUnit.has_value())
251
7.04k
        {
252
7.04k
            return false;
253
7.04k
        }
254
255
375k
        rSourceUnit = nUnit.value();
256
375k
    }
257
258
400k
    rValue = nVal;
259
400k
    rNeg = bNeg;
260
261
400k
    return true;
262
407k
}
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
242k
{
196
242k
    rValue = 0.0;
197
242k
    rSourceUnit.reset();
198
242k
    rNeg = false;
199
200
242k
    bool bNeg = false;
201
242k
    double nVal = 0;
202
203
242k
    sal_Int32 nPos = 0;
204
242k
    sal_Int32 const nLen = rString.size();
205
206
    // skip white space
207
246k
    while( (nPos < nLen) && (rString[nPos] <= ' ') )
208
3.71k
        nPos++;
209
210
242k
    if( nPos < nLen && '-' == rString[nPos] )
211
9.79k
    {
212
9.79k
        bNeg = true;
213
9.79k
        nPos++;
214
9.79k
    }
215
216
    // get number
217
580k
    while( nPos < nLen &&
218
556k
           '0' <= rString[nPos] &&
219
414k
           '9' >= rString[nPos] )
220
337k
    {
221
        // TODO: check overflow!
222
337k
        nVal *= 10;
223
337k
        nVal += (rString[nPos] - '0');
224
337k
        nPos++;
225
337k
    }
226
242k
    if( nPos < nLen && '.' == rString[nPos] )
227
130k
    {
228
130k
        nPos++;
229
130k
        double nDiv = 1.;
230
231
462k
        while( nPos < nLen &&
232
462k
               '0' <= rString[nPos] &&
233
461k
               '9' >= rString[nPos] )
234
332k
        {
235
            // TODO: check overflow!
236
332k
            nDiv *= 10;
237
332k
            nVal += ( static_cast<double>(rString[nPos] - '0') / nDiv );
238
332k
            nPos++;
239
332k
        }
240
130k
    }
241
242
    // skip white space
243
243k
    while( (nPos < nLen) && (rString[nPos] <= ' ') )
244
390
        nPos++;
245
246
242k
    if (nPos < nLen)
247
218k
    {
248
        // Parse unit from the tail
249
218k
        auto nUnit = lcl_parseMeasureUnit(rString.substr(nPos));
250
218k
        if (!nUnit.has_value())
251
4.95k
        {
252
4.95k
            return false;
253
4.95k
        }
254
255
213k
        rSourceUnit = nUnit.value();
256
213k
    }
257
258
237k
    rValue = nVal;
259
237k
    rNeg = bNeg;
260
261
237k
    return true;
262
242k
}
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
164k
{
196
164k
    rValue = 0.0;
197
164k
    rSourceUnit.reset();
198
164k
    rNeg = false;
199
200
164k
    bool bNeg = false;
201
164k
    double nVal = 0;
202
203
164k
    sal_Int32 nPos = 0;
204
164k
    sal_Int32 const nLen = rString.size();
205
206
    // skip white space
207
165k
    while( (nPos < nLen) && (rString[nPos] <= ' ') )
208
716
        nPos++;
209
210
164k
    if( nPos < nLen && '-' == rString[nPos] )
211
17.2k
    {
212
17.2k
        bNeg = true;
213
17.2k
        nPos++;
214
17.2k
    }
215
216
    // get number
217
374k
    while( nPos < nLen &&
218
374k
           '0' <= rString[nPos] &&
219
223k
           '9' >= rString[nPos] )
220
210k
    {
221
        // TODO: check overflow!
222
210k
        nVal *= 10;
223
210k
        nVal += (rString[nPos] - '0');
224
210k
        nPos++;
225
210k
    }
226
164k
    if( nPos < nLen && '.' == rString[nPos] )
227
134k
    {
228
134k
        nPos++;
229
134k
        double nDiv = 1.;
230
231
431k
        while( nPos < nLen &&
232
431k
               '0' <= rString[nPos] &&
233
430k
               '9' >= rString[nPos] )
234
297k
        {
235
            // TODO: check overflow!
236
297k
            nDiv *= 10;
237
297k
            nVal += ( static_cast<double>(rString[nPos] - '0') / nDiv );
238
297k
            nPos++;
239
297k
        }
240
134k
    }
241
242
    // skip white space
243
167k
    while( (nPos < nLen) && (rString[nPos] <= ' ') )
244
2.72k
        nPos++;
245
246
164k
    if (nPos < nLen)
247
164k
    {
248
        // Parse unit from the tail
249
164k
        auto nUnit = lcl_parseMeasureUnit(rString.substr(nPos));
250
164k
        if (!nUnit.has_value())
251
2.09k
        {
252
2.09k
            return false;
253
2.09k
        }
254
255
162k
        rSourceUnit = nUnit.value();
256
162k
    }
257
258
162k
    rValue = nVal;
259
162k
    rNeg = bNeg;
260
261
162k
    return true;
262
164k
}
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
407k
{
271
407k
    double nVal = 0.0;
272
407k
    std::optional<sal_Int16> nSourceUnit;
273
407k
    bool bNeg = false;
274
275
407k
    if (!lcl_parseMeasure(nVal, nSourceUnit, bNeg, rString))
276
7.04k
    {
277
7.04k
        return false;
278
7.04k
    }
279
280
400k
    if (nSourceUnit.has_value())
281
375k
    {
282
375k
        if( MeasureUnit::PERCENT == nTargetUnit )
283
66.8k
        {
284
66.8k
            if (MeasureUnit::PERCENT != nSourceUnit)
285
38.7k
                return false;
286
66.8k
        }
287
308k
        else if( MeasureUnit::PIXEL == nTargetUnit )
288
0
        {
289
0
            if (MeasureUnit::PIXEL != nSourceUnit)
290
0
                return false;
291
0
        }
292
308k
        else
293
308k
        {
294
308k
            OSL_ENSURE( MeasureUnit::TWIP == nTargetUnit || MeasureUnit::POINT == nTargetUnit ||
295
308k
                        MeasureUnit::MM_100TH == nTargetUnit || MeasureUnit::MM_10TH == nTargetUnit ||
296
308k
                        MeasureUnit::PIXEL == nTargetUnit, "unit is not supported");
297
298
308k
            o3tl::Length eFrom = o3tl::Length::invalid;
299
300
308k
            if( MeasureUnit::TWIP == nTargetUnit )
301
11.3k
            {
302
11.3k
                switch (nSourceUnit.value())
303
11.3k
                {
304
7.32k
                    case MeasureUnit::CM:
305
7.32k
                        eFrom = o3tl::Length::cm;
306
7.32k
                        break;
307
81
                    case MeasureUnit::INCH:
308
81
                        eFrom = o3tl::Length::in;
309
81
                        break;
310
5
                    case MeasureUnit::MM:
311
5
                        eFrom = o3tl::Length::mm;
312
5
                        break;
313
3.92k
                    case MeasureUnit::POINT:
314
3.92k
                        eFrom = o3tl::Length::pt;
315
3.92k
                        break;
316
0
                    case MeasureUnit::PICA:
317
0
                        eFrom = o3tl::Length::pc;
318
0
                        break;
319
11.3k
                }
320
11.3k
            }
321
297k
            else if( MeasureUnit::MM_100TH == nTargetUnit || MeasureUnit::MM_10TH == nTargetUnit )
322
297k
            {
323
297k
                switch (nSourceUnit.value())
324
297k
                {
325
219k
                    case MeasureUnit::CM:
326
219k
                        eFrom = o3tl::Length::cm;
327
219k
                        break;
328
56.5k
                    case MeasureUnit::INCH:
329
56.5k
                        eFrom = o3tl::Length::in;
330
56.5k
                        break;
331
9.19k
                    case MeasureUnit::MM:
332
9.19k
                        eFrom = o3tl::Length::mm;
333
9.19k
                        break;
334
12.6k
                    case MeasureUnit::POINT:
335
12.6k
                        eFrom = o3tl::Length::pt;
336
12.6k
                        break;
337
0
                    case MeasureUnit::PICA:
338
0
                        eFrom = o3tl::Length::pc;
339
0
                        break;
340
1
                    case MeasureUnit::PIXEL:
341
1
                        eFrom = o3tl::Length::px;
342
1
                        break;
343
297k
                }
344
297k
            }
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
308k
            if (eFrom == o3tl::Length::invalid)
352
127
                return false;
353
354
            // TODO: check overflow
355
308k
            nVal = o3tl::convert(nVal, eFrom, Measure2O3tlUnit(nTargetUnit));
356
308k
        }
357
375k
    }
358
359
361k
    nVal += .5;
360
361k
    if( bNeg )
361
23.7k
        nVal = -nVal;
362
363
361k
    if( nVal <= static_cast<double>(nMin) )
364
400
        rValue = nMin;
365
360k
    else if( nVal >= static_cast<double>(nMax) )
366
6.23k
        rValue = nMax;
367
354k
    else
368
354k
        rValue = static_cast<sal_Int32>(nVal);
369
370
361k
    return true;
371
400k
}
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
242k
{
271
242k
    double nVal = 0.0;
272
242k
    std::optional<sal_Int16> nSourceUnit;
273
242k
    bool bNeg = false;
274
275
242k
    if (!lcl_parseMeasure(nVal, nSourceUnit, bNeg, rString))
276
4.95k
    {
277
4.95k
        return false;
278
4.95k
    }
279
280
237k
    if (nSourceUnit.has_value())
281
213k
    {
282
213k
        if( MeasureUnit::PERCENT == nTargetUnit )
283
50.0k
        {
284
50.0k
            if (MeasureUnit::PERCENT != nSourceUnit)
285
38.6k
                return false;
286
50.0k
        }
287
163k
        else if( MeasureUnit::PIXEL == nTargetUnit )
288
0
        {
289
0
            if (MeasureUnit::PIXEL != nSourceUnit)
290
0
                return false;
291
0
        }
292
163k
        else
293
163k
        {
294
163k
            OSL_ENSURE( MeasureUnit::TWIP == nTargetUnit || MeasureUnit::POINT == nTargetUnit ||
295
163k
                        MeasureUnit::MM_100TH == nTargetUnit || MeasureUnit::MM_10TH == nTargetUnit ||
296
163k
                        MeasureUnit::PIXEL == nTargetUnit, "unit is not supported");
297
298
163k
            o3tl::Length eFrom = o3tl::Length::invalid;
299
300
163k
            if( MeasureUnit::TWIP == nTargetUnit )
301
11.3k
            {
302
11.3k
                switch (nSourceUnit.value())
303
11.3k
                {
304
7.32k
                    case MeasureUnit::CM:
305
7.32k
                        eFrom = o3tl::Length::cm;
306
7.32k
                        break;
307
81
                    case MeasureUnit::INCH:
308
81
                        eFrom = o3tl::Length::in;
309
81
                        break;
310
5
                    case MeasureUnit::MM:
311
5
                        eFrom = o3tl::Length::mm;
312
5
                        break;
313
3.92k
                    case MeasureUnit::POINT:
314
3.92k
                        eFrom = o3tl::Length::pt;
315
3.92k
                        break;
316
0
                    case MeasureUnit::PICA:
317
0
                        eFrom = o3tl::Length::pc;
318
0
                        break;
319
11.3k
                }
320
11.3k
            }
321
152k
            else if( MeasureUnit::MM_100TH == nTargetUnit || MeasureUnit::MM_10TH == nTargetUnit )
322
152k
            {
323
152k
                switch (nSourceUnit.value())
324
152k
                {
325
104k
                    case MeasureUnit::CM:
326
104k
                        eFrom = o3tl::Length::cm;
327
104k
                        break;
328
27.1k
                    case MeasureUnit::INCH:
329
27.1k
                        eFrom = o3tl::Length::in;
330
27.1k
                        break;
331
8.15k
                    case MeasureUnit::MM:
332
8.15k
                        eFrom = o3tl::Length::mm;
333
8.15k
                        break;
334
12.6k
                    case MeasureUnit::POINT:
335
12.6k
                        eFrom = o3tl::Length::pt;
336
12.6k
                        break;
337
0
                    case MeasureUnit::PICA:
338
0
                        eFrom = o3tl::Length::pc;
339
0
                        break;
340
1
                    case MeasureUnit::PIXEL:
341
1
                        eFrom = o3tl::Length::px;
342
1
                        break;
343
152k
                }
344
152k
            }
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
163k
            if (eFrom == o3tl::Length::invalid)
352
23
                return false;
353
354
            // TODO: check overflow
355
163k
            nVal = o3tl::convert(nVal, eFrom, Measure2O3tlUnit(nTargetUnit));
356
163k
        }
357
213k
    }
358
359
199k
    nVal += .5;
360
199k
    if( bNeg )
361
6.59k
        nVal = -nVal;
362
363
199k
    if( nVal <= static_cast<double>(nMin) )
364
33
        rValue = nMin;
365
199k
    else if( nVal >= static_cast<double>(nMax) )
366
5.95k
        rValue = nMax;
367
193k
    else
368
193k
        rValue = static_cast<sal_Int32>(nVal);
369
370
199k
    return true;
371
237k
}
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
164k
{
271
164k
    double nVal = 0.0;
272
164k
    std::optional<sal_Int16> nSourceUnit;
273
164k
    bool bNeg = false;
274
275
164k
    if (!lcl_parseMeasure(nVal, nSourceUnit, bNeg, rString))
276
2.09k
    {
277
2.09k
        return false;
278
2.09k
    }
279
280
162k
    if (nSourceUnit.has_value())
281
162k
    {
282
162k
        if( MeasureUnit::PERCENT == nTargetUnit )
283
16.8k
        {
284
16.8k
            if (MeasureUnit::PERCENT != nSourceUnit)
285
74
                return false;
286
16.8k
        }
287
145k
        else if( MeasureUnit::PIXEL == nTargetUnit )
288
0
        {
289
0
            if (MeasureUnit::PIXEL != nSourceUnit)
290
0
                return false;
291
0
        }
292
145k
        else
293
145k
        {
294
145k
            OSL_ENSURE( MeasureUnit::TWIP == nTargetUnit || MeasureUnit::POINT == nTargetUnit ||
295
145k
                        MeasureUnit::MM_100TH == nTargetUnit || MeasureUnit::MM_10TH == nTargetUnit ||
296
145k
                        MeasureUnit::PIXEL == nTargetUnit, "unit is not supported");
297
298
145k
            o3tl::Length eFrom = o3tl::Length::invalid;
299
300
145k
            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
145k
            else if( MeasureUnit::MM_100TH == nTargetUnit || MeasureUnit::MM_10TH == nTargetUnit )
322
145k
            {
323
145k
                switch (nSourceUnit.value())
324
145k
                {
325
114k
                    case MeasureUnit::CM:
326
114k
                        eFrom = o3tl::Length::cm;
327
114k
                        break;
328
29.3k
                    case MeasureUnit::INCH:
329
29.3k
                        eFrom = o3tl::Length::in;
330
29.3k
                        break;
331
1.03k
                    case MeasureUnit::MM:
332
1.03k
                        eFrom = o3tl::Length::mm;
333
1.03k
                        break;
334
1
                    case MeasureUnit::POINT:
335
1
                        eFrom = o3tl::Length::pt;
336
1
                        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
145k
                }
344
145k
            }
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
145k
            if (eFrom == o3tl::Length::invalid)
352
104
                return false;
353
354
            // TODO: check overflow
355
145k
            nVal = o3tl::convert(nVal, eFrom, Measure2O3tlUnit(nTargetUnit));
356
145k
        }
357
162k
    }
358
359
162k
    nVal += .5;
360
162k
    if( bNeg )
361
17.1k
        nVal = -nVal;
362
363
162k
    if( nVal <= static_cast<double>(nMin) )
364
367
        rValue = nMin;
365
161k
    else if( nVal >= static_cast<double>(nMax) )
366
281
        rValue = nMax;
367
161k
    else
368
161k
        rValue = static_cast<sal_Int32>(nVal);
369
370
162k
    return true;
371
162k
}
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
242k
{
380
242k
    return lcl_convertMeasure(rValue, rString, nTargetUnit, nMin, nMax);
381
242k
}
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
164k
{
390
164k
    return lcl_convertMeasure(rValue, rString, nTargetUnit, nMin, nMax);
391
164k
}
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
69
{
400
69
    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
69
    sal_Int64 nValue(nMeasure); // extend to 64-bit first to avoid overflow
411
    // the sign is processed separately
412
69
    if (nValue < 0)
413
0
    {
414
0
        nValue = -nValue;
415
0
        rBuffer.append( '-' );
416
0
    }
417
418
69
    o3tl::Length eFrom = o3tl::Length::in, eTo = o3tl::Length::in;
419
69
    int nFac = 100; // used to get specific number of decimals (2 by default)
420
69
    std::string_view psUnit;
421
69
    switch( nSourceUnit )
422
69
    {
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
69
    case MeasureUnit::MM_100TH:
469
69
        {
470
69
            int nFac2 = (MeasureUnit::MM_100TH == nSourceUnit) ? 100 : 10;
471
69
            eFrom = Measure2O3tlUnit(nSourceUnit);
472
69
            switch( nTargetUnit )
473
69
            {
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
69
            case MeasureUnit::CM:
486
69
                eTo = o3tl::Length::cm;
487
69
                nFac = 10*nFac2;
488
69
                psUnit = gpsCM;
489
69
                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
69
            }
505
69
            break;
506
69
        }
507
69
    default:
508
0
        OSL_ENSURE(false, "sax::Converter::convertMeasure(): "
509
0
                "source unit not supported");
510
0
        break;
511
69
    }
512
513
69
    nValue = o3tl::convert(nValue * nFac, eFrom, eTo);
514
515
69
    rBuffer.append( static_cast<sal_Int64>(nValue / nFac) );
516
69
    if (nFac > 1 && (nValue % nFac) != 0)
517
53
    {
518
53
        rBuffer.append( '.' );
519
125
        while (nFac > 1 && (nValue % nFac) != 0)
520
72
        {
521
72
            nFac /= 10;
522
72
            rBuffer.append( static_cast<sal_Int32>((nValue / nFac) % 10) );
523
72
        }
524
53
    }
525
526
69
    if (psUnit.length() > 0)
527
69
        rBuffer.appendAscii(psUnit.data(), psUnit.length());
528
69
}
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
80.7k
{
580
80.7k
    rBool = rString == u"true";
581
582
80.7k
    return rBool || (rString == u"false");
583
80.7k
}
584
585
/** convert string to boolean */
586
bool Converter::convertBool( bool& rBool, std::string_view rString )
587
18.3k
{
588
18.3k
    rBool = rString == "true";
589
590
18.3k
    return rBool || (rString == "false");
591
18.3k
}
592
593
/** convert boolean to string */
594
void Converter::convertBool( OUStringBuffer& rBuffer, bool bValue )
595
12
{
596
12
    rBuffer.append( bValue );
597
12
}
598
599
/** convert string to percent */
600
bool Converter::convertPercent( sal_Int32& rPercent, std::u16string_view rString )
601
66.6k
{
602
66.6k
    return convertMeasure( rPercent, rString, MeasureUnit::PERCENT );
603
66.6k
}
604
605
/** convert string to percent */
606
bool Converter::convertPercent( sal_Int32& rPercent, std::string_view rString )
607
16.8k
{
608
16.8k
    return convertMeasure( rPercent, rString, MeasureUnit::PERCENT );
609
16.8k
}
610
611
/** convert percent to string */
612
void Converter::convertPercent( OUStringBuffer& rBuffer, sal_Int32 nValue )
613
55
{
614
55
    rBuffer.append( nValue );
615
55
    rBuffer.append( '%' );
616
55
}
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
97.1k
{
642
97.1k
    if( rValue.size() != 7 || rValue[0] != '#' )
643
46.1k
        return false;
644
645
50.9k
    rColor = o3tl::convertToHex<sal_Int32>(rValue[1], rValue[2]);
646
50.9k
    rColor <<= 8;
647
648
50.9k
    rColor |= o3tl::convertToHex<sal_Int32>(rValue[3], rValue[4]);
649
50.9k
    rColor <<= 8;
650
651
50.9k
    rColor |= o3tl::convertToHex<sal_Int32>(rValue[5], rValue[6]);
652
653
50.9k
    return true;
654
97.1k
}
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
89.2k
{
642
89.2k
    if( rValue.size() != 7 || rValue[0] != '#' )
643
46.0k
        return false;
644
645
43.1k
    rColor = o3tl::convertToHex<sal_Int32>(rValue[1], rValue[2]);
646
43.1k
    rColor <<= 8;
647
648
43.1k
    rColor |= o3tl::convertToHex<sal_Int32>(rValue[3], rValue[4]);
649
43.1k
    rColor <<= 8;
650
651
43.1k
    rColor |= o3tl::convertToHex<sal_Int32>(rValue[5], rValue[6]);
652
653
43.1k
    return true;
654
89.2k
}
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.86k
{
642
7.86k
    if( rValue.size() != 7 || rValue[0] != '#' )
643
79
        return false;
644
645
7.78k
    rColor = o3tl::convertToHex<sal_Int32>(rValue[1], rValue[2]);
646
7.78k
    rColor <<= 8;
647
648
7.78k
    rColor |= o3tl::convertToHex<sal_Int32>(rValue[3], rValue[4]);
649
7.78k
    rColor <<= 8;
650
651
7.78k
    rColor |= o3tl::convertToHex<sal_Int32>(rValue[5], rValue[6]);
652
653
7.78k
    return true;
654
7.86k
}
655
656
/** convert string to rgb color */
657
bool Converter::convertColor( sal_Int32& rColor, std::u16string_view rValue )
658
89.2k
{
659
89.2k
    return lcl_convertColor(rColor, rValue);
660
89.2k
}
661
662
/** convert string to rgb color */
663
bool Converter::convertColor( sal_Int32& rColor, std::string_view rValue )
664
7.86k
{
665
7.86k
    return lcl_convertColor(rColor, rValue);
666
7.86k
}
667
668
const char aHexTab[] = "0123456789abcdef";
669
670
/** convert color to string */
671
void Converter::convertColor( OUStringBuffer& rBuffer, sal_Int32 nColor )
672
41
{
673
41
    rBuffer.append( '#' );
674
675
41
    sal_uInt8 nCol = static_cast<sal_uInt8>(nColor >> 16);
676
41
    rBuffer.append( sal_Unicode( aHexTab[ nCol >> 4 ] ) );
677
41
    rBuffer.append( sal_Unicode( aHexTab[ nCol & 0xf ] ) );
678
679
41
    nCol = static_cast<sal_uInt8>(nColor >> 8);
680
41
    rBuffer.append( sal_Unicode( aHexTab[ nCol >> 4 ] ) );
681
41
    rBuffer.append( sal_Unicode( aHexTab[ nCol & 0xf ] ) );
682
683
41
    nCol = static_cast<sal_uInt8>(nColor);
684
41
    rBuffer.append( sal_Unicode( aHexTab[ nCol >> 4 ] ) );
685
41
    rBuffer.append( sal_Unicode( aHexTab[ nCol & 0xf ] ) );
686
41
}
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
988k
{
693
988k
    rValue = 0;
694
988k
    sal_Int64 nNumber = 0;
695
988k
    bool bRet = convertNumber64(nNumber,aString,nMin,nMax);
696
988k
    if ( bRet )
697
977k
        rValue = static_cast<sal_Int32>(nNumber);
698
988k
    return bRet;
699
988k
}
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
99.5k
{
706
99.5k
    rValue = 0;
707
99.5k
    sal_Int64 nNumber = 0;
708
99.5k
    bool bRet = convertNumber64(nNumber,aString,nMin,nMax);
709
99.5k
    if ( bRet )
710
85.6k
        rValue = static_cast<sal_Int32>(nNumber);
711
99.5k
    return bRet;
712
99.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
1.08M
{
720
1.08M
    sal_Int32 nPos = 0;
721
1.08M
    sal_Int32 const nLen = aString.size();
722
723
    // skip white space
724
1.08M
    while( (nPos < nLen) && (aString[nPos] <= ' ') )
725
996
        nPos++;
726
727
1.08M
    sal_Int32 nNumberStartPos = nPos;
728
729
1.08M
    if( nPos < nLen && '-' == aString[nPos] )
730
58.6k
    {
731
58.6k
        nPos++;
732
58.6k
    }
733
734
    // get number
735
5.06M
    while( nPos < nLen &&
736
4.00M
           '0' <= aString[nPos] &&
737
3.98M
           '9' >= aString[nPos] )
738
3.97M
    {
739
3.97M
        nPos++;
740
3.97M
    }
741
742
1.08M
    rValue = toInt64_WithLength(aString.data() + nNumberStartPos, 10, nPos - nNumberStartPos);
743
744
1.08M
    if( rValue < nMin )
745
16.0k
        rValue = nMin;
746
1.07M
    else if( rValue > nMax )
747
6.22k
        rValue = nMax;
748
749
1.08M
    return ( nPos == nLen && rValue >= nMin && rValue <= nMax );
750
1.08M
}
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
988k
{
720
988k
    sal_Int32 nPos = 0;
721
988k
    sal_Int32 const nLen = aString.size();
722
723
    // skip white space
724
989k
    while( (nPos < nLen) && (aString[nPos] <= ' ') )
725
266
        nPos++;
726
727
988k
    sal_Int32 nNumberStartPos = nPos;
728
729
988k
    if( nPos < nLen && '-' == aString[nPos] )
730
57.4k
    {
731
57.4k
        nPos++;
732
57.4k
    }
733
734
    // get number
735
4.83M
    while( nPos < nLen &&
736
3.86M
           '0' <= aString[nPos] &&
737
3.85M
           '9' >= aString[nPos] )
738
3.85M
    {
739
3.85M
        nPos++;
740
3.85M
    }
741
742
988k
    rValue = toInt64_WithLength(aString.data() + nNumberStartPos, 10, nPos - nNumberStartPos);
743
744
988k
    if( rValue < nMin )
745
14.9k
        rValue = nMin;
746
973k
    else if( rValue > nMax )
747
6.04k
        rValue = nMax;
748
749
988k
    return ( nPos == nLen && rValue >= nMin && rValue <= nMax );
750
988k
}
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
99.5k
{
720
99.5k
    sal_Int32 nPos = 0;
721
99.5k
    sal_Int32 const nLen = aString.size();
722
723
    // skip white space
724
100k
    while( (nPos < nLen) && (aString[nPos] <= ' ') )
725
730
        nPos++;
726
727
99.5k
    sal_Int32 nNumberStartPos = nPos;
728
729
99.5k
    if( nPos < nLen && '-' == aString[nPos] )
730
1.15k
    {
731
1.15k
        nPos++;
732
1.15k
    }
733
734
    // get number
735
227k
    while( nPos < nLen &&
736
142k
           '0' <= aString[nPos] &&
737
129k
           '9' >= aString[nPos] )
738
128k
    {
739
128k
        nPos++;
740
128k
    }
741
742
99.5k
    rValue = toInt64_WithLength(aString.data() + nNumberStartPos, 10, nPos - nNumberStartPos);
743
744
99.5k
    if( rValue < nMin )
745
1.10k
        rValue = nMin;
746
98.4k
    else if( rValue > nMax )
747
183
        rValue = nMax;
748
749
99.5k
    return ( nPos == nLen && rValue >= nMin && rValue <= nMax );
750
99.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
988k
{
757
988k
    return lcl_convertNumber64(rValue, aString, nMin, nMax);
758
988k
}
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
99.5k
{
765
99.5k
    return lcl_convertNumber64(rValue, aString, nMin, nMax);
766
99.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
20
{
776
20
    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
20
    else
784
20
    {
785
20
        OUStringBuffer sUnit;
786
20
        double fFactor = GetConversionFactor(sUnit, nSourceUnit, nTargetUnit);
787
20
        if(fFactor != 1.0)
788
0
            fNumber *= fFactor;
789
20
        ::rtl::math::doubleToUStringBuffer( rBuffer, fNumber, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', true);
790
20
        if(bWriteUnits)
791
20
            rBuffer.append(sUnit);
792
20
    }
793
20
}
794
795
/** convert double number to string (using ::rtl::math) */
796
void Converter::convertDouble( OUStringBuffer& rBuffer, double fNumber)
797
10
{
798
10
    ::rtl::math::doubleToUStringBuffer( rBuffer, fNumber, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', true);
799
10
}
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
98.6k
{
805
98.6k
    if (!convertDouble(rValue, rString))
806
6
        return false;
807
808
98.6k
    OUStringBuffer sUnit;
809
    // fdo#48969: switch source and target because factor is used to divide!
810
98.6k
    double const fFactor =
811
98.6k
        GetConversionFactor(sUnit, nTargetUnit, nSourceUnit);
812
98.6k
    if(fFactor != 1.0 && fFactor != 0.0)
813
43
        rValue /= fFactor;
814
98.6k
    return true;
815
98.6k
}
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
172k
{
836
172k
    rtl_math_ConversionStatus eStatus;
837
172k
    const sal_Unicode* pEnd;
838
172k
    rValue = rtl_math_uStringToDouble(rString.data(),
839
172k
                                     rString.data() + rString.size(),
840
172k
                                     /*cDecSeparator*/'.', /*cGroupSeparator*/',',
841
172k
                                     &eStatus, &pEnd);
842
172k
    if (pRest)
843
1.99k
        *pRest = rString.substr(pEnd - rString.data());
844
172k
    return ( eStatus == rtl_math_ConversionStatus_Ok );
845
172k
}
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
457
{
850
457
    rtl_math_ConversionStatus eStatus;
851
457
    const char* pEnd;
852
457
    rValue = rtl_math_stringToDouble(rString.data(),
853
457
                                     rString.data() + rString.size(),
854
457
                                     /*cDecSeparator*/'.', /*cGroupSeparator*/',',
855
457
                                     &eStatus, &pEnd);
856
457
    if (pRest)
857
298
        *pRest = rString.substr(pEnd - rString.data());
858
457
    return ( eStatus == rtl_math_ConversionStatus_Ok );
859
457
}
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
6
{
865
6
    if (isWrongOOo10thDegAngle)
866
0
    {
867
0
        rBuffer.append(static_cast<sal_Int32>(nAngle));
868
0
    }
869
6
    else
870
6
    {
871
6
        double fAngle(double(nAngle) / 10.0);
872
6
        ::sax::Converter::convertDouble(rBuffer, fAngle);
873
6
        rBuffer.append("deg");
874
6
    }
875
6
}
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
298
{
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
298
    double fAngle(0.0);
925
298
    std::string_view aRest;
926
298
    bool bRet = ::sax::Converter::convertDouble(fAngle, rString, &aRest);
927
298
    if (bRet)
928
298
    {
929
298
        if (aRest == "deg")
930
0
            fAngle *= 10.0;
931
298
        else if (aRest == "grad")
932
0
            fAngle *= 9.0; // 360deg = 400grad
933
298
        else if (aRest == "rad")
934
0
            fAngle = basegfx::rad2deg<10>(fAngle);
935
298
        else // no explicit unit
936
298
        { // isWrongOOo10thDegAngle = true: nothing to do here. Wrong, but backward compatible.
937
298
            if (!aRest.empty())
938
5
            {
939
                // Wrong unit. Don't change rAngle, rely on callers checking boolean return
940
5
                return false;
941
5
            }
942
293
            if (!isWrongOOo10thDegAngle)
943
24
                fAngle *= 10.0; // conform to ODF 1.2 and newer
944
293
        }
945
293
        fAngle = std::clamp<double>(basegfx::fround(fAngle), SHRT_MIN, SHRT_MAX);
946
293
        rAngle = static_cast<sal_Int16>(fAngle);
947
293
    }
948
293
    return bRet;
949
298
}
950
951
/** convert SVG angle to number, in degrees, range [0..360] */
952
bool Converter::convertAngle(double& rAngle, std::u16string_view rString)
953
1.99k
{
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
1.99k
    std::u16string_view aRest;
959
1.99k
    bool bRet = ::sax::Converter::convertDouble(rAngle, rString, &aRest);
960
1.99k
    if (bRet)
961
1.99k
    {
962
        //degrees
963
1.99k
        if (aRest == u"grad")
964
0
            rAngle *= 0.9; // 360deg = 400grad
965
1.99k
        else if (aRest == u"rad")
966
0
            rAngle = basegfx::rad2deg(rAngle);
967
1.99k
        else if (aRest != u"deg" && !aRest.empty())
968
11
        {
969
            // Wrong unit
970
11
            rAngle = 0;
971
11
            return false;
972
11
        }
973
        // degrees in range [0..360]
974
1.98k
        rAngle = basegfx::snapToZeroRange(rAngle, 360.0);
975
1.98k
    }
976
1.98k
    return bRet;
977
1.99k
}
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
8.25k
{
1214
8.25k
    if (rDuration.Negative)
1215
0
    {
1216
0
        rBuffer.append('-');
1217
0
    }
1218
8.25k
    rBuffer.append('P');
1219
8.25k
    const bool bHaveDate(rDuration.Years  != 0 ||
1220
8.25k
                         rDuration.Months != 0 ||
1221
8.25k
                         rDuration.Days   != 0);
1222
8.25k
    if (rDuration.Years)
1223
0
    {
1224
0
        rBuffer.append(static_cast<sal_Int32>(rDuration.Years));
1225
0
        rBuffer.append('Y');
1226
0
    }
1227
8.25k
    if (rDuration.Months)
1228
0
    {
1229
0
        rBuffer.append(static_cast<sal_Int32>(rDuration.Months));
1230
0
        rBuffer.append('M');
1231
0
    }
1232
8.25k
    if (rDuration.Days)
1233
848
    {
1234
848
        rBuffer.append(static_cast<sal_Int32>(rDuration.Days));
1235
848
        rBuffer.append('D');
1236
848
    }
1237
8.25k
    if ( rDuration.Hours != 0
1238
6.32k
         || rDuration.Minutes != 0
1239
2.43k
         || rDuration.Seconds != 0
1240
1.97k
         || rDuration.NanoSeconds != 0 )
1241
6.27k
    {
1242
6.27k
        rBuffer.append('T'); // time separator
1243
6.27k
        if (rDuration.Hours)
1244
1.93k
        {
1245
1.93k
            rBuffer.append(static_cast<sal_Int32>(rDuration.Hours));
1246
1.93k
            rBuffer.append('H');
1247
1.93k
        }
1248
6.27k
        if (rDuration.Minutes)
1249
5.79k
        {
1250
5.79k
            rBuffer.append(static_cast<sal_Int32>(rDuration.Minutes));
1251
5.79k
            rBuffer.append('M');
1252
5.79k
        }
1253
6.27k
        if (rDuration.Seconds != 0 || rDuration.NanoSeconds != 0)
1254
3.00k
        {
1255
            // seconds must not be omitted (i.e. ".42S" is not valid)
1256
3.00k
            rBuffer.append(static_cast<sal_Int32>(rDuration.Seconds));
1257
3.00k
            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
3.00k
            rBuffer.append('S');
1268
3.00k
        }
1269
6.27k
    }
1270
1.97k
    else if (!bHaveDate)
1271
1.95k
    {
1272
        // zero duration: XMLSchema-2 says there must be at least one component
1273
1.95k
        rBuffer.append('0');
1274
1.95k
        rBuffer.append('D');
1275
1.95k
    }
1276
8.25k
}
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
764k
{
1289
764k
    size_t nPos(io_rnPos);
1290
1291
1.40M
    while (nPos < rString.size())
1292
888k
    {
1293
888k
        const typename V::value_type c = rString[nPos];
1294
888k
        if (('0' > c) || (c > '9'))
1295
243k
            break;
1296
645k
        ++nPos;
1297
645k
    }
1298
1299
764k
    if (io_rnPos == nPos) // read something?
1300
509k
    {
1301
509k
        o_rNumber = -1;
1302
509k
        return R_NOTHING;
1303
509k
    }
1304
1305
254k
    const sal_Int64 nTemp = toInt64_WithLength(rString.data() + io_rnPos, 10, nPos - io_rnPos);
1306
1307
254k
    const bool bOverflow = (nTemp >= SAL_MAX_INT32);
1308
1309
254k
    io_rnPos = nPos;
1310
254k
    o_rNumber = nTemp;
1311
254k
    return bOverflow ? R_OVERFLOW : R_SUCCESS;
1312
764k
}
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
739k
{
1289
739k
    size_t nPos(io_rnPos);
1290
1291
1.28M
    while (nPos < rString.size())
1292
771k
    {
1293
771k
        const typename V::value_type c = rString[nPos];
1294
771k
        if (('0' > c) || (c > '9'))
1295
222k
            break;
1296
549k
        ++nPos;
1297
549k
    }
1298
1299
739k
    if (io_rnPos == nPos) // read something?
1300
505k
    {
1301
505k
        o_rNumber = -1;
1302
505k
        return R_NOTHING;
1303
505k
    }
1304
1305
234k
    const sal_Int64 nTemp = toInt64_WithLength(rString.data() + io_rnPos, 10, nPos - io_rnPos);
1306
1307
234k
    const bool bOverflow = (nTemp >= SAL_MAX_INT32);
1308
1309
234k
    io_rnPos = nPos;
1310
234k
    o_rNumber = nTemp;
1311
234k
    return bOverflow ? R_OVERFLOW : R_SUCCESS;
1312
739k
}
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
24.3k
{
1289
24.3k
    size_t nPos(io_rnPos);
1290
1291
120k
    while (nPos < rString.size())
1292
117k
    {
1293
117k
        const typename V::value_type c = rString[nPos];
1294
117k
        if (('0' > c) || (c > '9'))
1295
21.2k
            break;
1296
95.9k
        ++nPos;
1297
95.9k
    }
1298
1299
24.3k
    if (io_rnPos == nPos) // read something?
1300
4.01k
    {
1301
4.01k
        o_rNumber = -1;
1302
4.01k
        return R_NOTHING;
1303
4.01k
    }
1304
1305
20.3k
    const sal_Int64 nTemp = toInt64_WithLength(rString.data() + io_rnPos, 10, nPos - io_rnPos);
1306
1307
20.3k
    const bool bOverflow = (nTemp >= SAL_MAX_INT32);
1308
1309
20.3k
    io_rnPos = nPos;
1310
20.3k
    o_rNumber = nTemp;
1311
20.3k
    return bOverflow ? R_OVERFLOW : R_SUCCESS;
1312
24.3k
}
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
26.9k
{
1320
26.9k
    bool bOverflow(false);
1321
26.9k
    sal_Int64 nTemp(0);
1322
26.9k
    size_t nPos(io_rnPos);
1323
26.9k
    OSL_ENSURE(maxDigits >= 0, "negative amount of digits makes no sense");
1324
1325
258k
    while (nPos < rString.size())
1326
231k
    {
1327
231k
        const sal_Unicode c = rString[nPos];
1328
231k
        if (('0' <= c) && (c <= '9'))
1329
231k
        {
1330
231k
            if (maxDigits > 0)
1331
231k
            {
1332
231k
                nTemp *= 10;
1333
231k
                nTemp += (c - u'0');
1334
231k
                if (nTemp >= SAL_MAX_INT32)
1335
0
                {
1336
0
                    bOverflow = true;
1337
0
                }
1338
231k
                --maxDigits;
1339
231k
            }
1340
231k
        }
1341
8
        else
1342
8
        {
1343
8
            break;
1344
8
        }
1345
231k
        ++nPos;
1346
231k
    }
1347
1348
26.9k
    if (io_rnPos == nPos) // read something?
1349
0
    {
1350
0
        o_rNumber = -1;
1351
0
        return R_NOTHING;
1352
0
    }
1353
1354
26.9k
    io_rnPos = nPos;
1355
26.9k
    o_rNumber = nTemp;
1356
26.9k
    return bOverflow ? R_OVERFLOW : R_SUCCESS;
1357
26.9k
}
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
26.8k
{
1320
26.8k
    bool bOverflow(false);
1321
26.8k
    sal_Int64 nTemp(0);
1322
26.8k
    size_t nPos(io_rnPos);
1323
26.8k
    OSL_ENSURE(maxDigits >= 0, "negative amount of digits makes no sense");
1324
1325
258k
    while (nPos < rString.size())
1326
231k
    {
1327
231k
        const sal_Unicode c = rString[nPos];
1328
231k
        if (('0' <= c) && (c <= '9'))
1329
231k
        {
1330
231k
            if (maxDigits > 0)
1331
231k
            {
1332
231k
                nTemp *= 10;
1333
231k
                nTemp += (c - u'0');
1334
231k
                if (nTemp >= SAL_MAX_INT32)
1335
0
                {
1336
0
                    bOverflow = true;
1337
0
                }
1338
231k
                --maxDigits;
1339
231k
            }
1340
231k
        }
1341
8
        else
1342
8
        {
1343
8
            break;
1344
8
        }
1345
231k
        ++nPos;
1346
231k
    }
1347
1348
26.8k
    if (io_rnPos == nPos) // read something?
1349
0
    {
1350
0
        o_rNumber = -1;
1351
0
        return R_NOTHING;
1352
0
    }
1353
1354
26.8k
    io_rnPos = nPos;
1355
26.8k
    o_rNumber = nTemp;
1356
26.8k
    return bOverflow ? R_OVERFLOW : R_SUCCESS;
1357
26.8k
}
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&)
Line
Count
Source
1319
50
{
1320
50
    bool bOverflow(false);
1321
50
    sal_Int64 nTemp(0);
1322
50
    size_t nPos(io_rnPos);
1323
50
    OSL_ENSURE(maxDigits >= 0, "negative amount of digits makes no sense");
1324
1325
472
    while (nPos < rString.size())
1326
422
    {
1327
422
        const sal_Unicode c = rString[nPos];
1328
422
        if (('0' <= c) && (c <= '9'))
1329
422
        {
1330
422
            if (maxDigits > 0)
1331
422
            {
1332
422
                nTemp *= 10;
1333
422
                nTemp += (c - u'0');
1334
422
                if (nTemp >= SAL_MAX_INT32)
1335
0
                {
1336
0
                    bOverflow = true;
1337
0
                }
1338
422
                --maxDigits;
1339
422
            }
1340
422
        }
1341
0
        else
1342
0
        {
1343
0
            break;
1344
0
        }
1345
422
        ++nPos;
1346
422
    }
1347
1348
50
    if (io_rnPos == nPos) // read something?
1349
0
    {
1350
0
        o_rNumber = -1;
1351
0
        return R_NOTHING;
1352
0
    }
1353
1354
50
    io_rnPos = nPos;
1355
50
    o_rNumber = nTemp;
1356
50
    return bOverflow ? R_OVERFLOW : R_SUCCESS;
1357
50
}
1358
1359
template<typename V>
1360
static bool
1361
readDurationT(V rString, size_t & io_rnPos)
1362
220k
{
1363
220k
    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
220k
    return false;
1370
220k
}
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
220k
{
1363
220k
    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
220k
    return false;
1370
220k
}
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
220k
{
1406
220k
    size_t nPos(0);
1407
1408
220k
    bool bIsNegativeDuration(false);
1409
220k
    if (!string.empty() && ('-' == string[0]))
1410
0
    {
1411
0
        bIsNegativeDuration = true;
1412
0
        ++nPos;
1413
0
    }
1414
1415
220k
    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
220k
    ++nPos;
1422
1423
    /// last read number; -1 == no valid number! always reset after using!
1424
220k
    sal_Int32 nTemp(-1);
1425
220k
    bool bTimePart(false); // have we read 'T'?
1426
220k
    bool bSuccess(false);
1427
220k
    sal_Int32 nYears(0);
1428
220k
    sal_Int32 nMonths(0);
1429
220k
    sal_Int32 nDays(0);
1430
220k
    sal_Int32 nHours(0);
1431
220k
    sal_Int32 nMinutes(0);
1432
220k
    sal_Int32 nSeconds(0);
1433
220k
    sal_Int32 nNanoSeconds(0);
1434
1435
220k
    bTimePart = readDurationT(string, nPos);
1436
220k
    bSuccess = (R_SUCCESS == readUnsignedNumber(string, nPos, nTemp));
1437
1438
220k
    if (!bTimePart && bSuccess)
1439
0
    {
1440
0
        bSuccess = readDurationComponent(string, nPos, nTemp, bTimePart,
1441
0
                     nYears, 'y', 'Y');
1442
0
    }
1443
1444
220k
    if (!bTimePart && bSuccess)
1445
0
    {
1446
0
        bSuccess = readDurationComponent(string, nPos, nTemp, bTimePart,
1447
0
                     nMonths, 'm', 'M');
1448
0
    }
1449
1450
220k
    if (!bTimePart && bSuccess)
1451
0
    {
1452
0
        bSuccess = readDurationComponent(string, nPos, nTemp, bTimePart,
1453
0
                     nDays, 'd', 'D');
1454
0
    }
1455
1456
220k
    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
220k
    if (nPos != string.size()) // string not processed completely?
1537
220k
    {
1538
220k
        bSuccess = false;
1539
220k
    }
1540
1541
220k
    if (nTemp != -1) // unprocessed number?
1542
0
    {
1543
0
        bSuccess = false;
1544
0
    }
1545
1546
220k
    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
220k
    return bSuccess;
1559
220k
}
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
220k
{
1406
220k
    size_t nPos(0);
1407
1408
220k
    bool bIsNegativeDuration(false);
1409
220k
    if (!string.empty() && ('-' == string[0]))
1410
0
    {
1411
0
        bIsNegativeDuration = true;
1412
0
        ++nPos;
1413
0
    }
1414
1415
220k
    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
220k
    ++nPos;
1422
1423
    /// last read number; -1 == no valid number! always reset after using!
1424
220k
    sal_Int32 nTemp(-1);
1425
220k
    bool bTimePart(false); // have we read 'T'?
1426
220k
    bool bSuccess(false);
1427
220k
    sal_Int32 nYears(0);
1428
220k
    sal_Int32 nMonths(0);
1429
220k
    sal_Int32 nDays(0);
1430
220k
    sal_Int32 nHours(0);
1431
220k
    sal_Int32 nMinutes(0);
1432
220k
    sal_Int32 nSeconds(0);
1433
220k
    sal_Int32 nNanoSeconds(0);
1434
1435
220k
    bTimePart = readDurationT(string, nPos);
1436
220k
    bSuccess = (R_SUCCESS == readUnsignedNumber(string, nPos, nTemp));
1437
1438
220k
    if (!bTimePart && bSuccess)
1439
0
    {
1440
0
        bSuccess = readDurationComponent(string, nPos, nTemp, bTimePart,
1441
0
                     nYears, 'y', 'Y');
1442
0
    }
1443
1444
220k
    if (!bTimePart && bSuccess)
1445
0
    {
1446
0
        bSuccess = readDurationComponent(string, nPos, nTemp, bTimePart,
1447
0
                     nMonths, 'm', 'M');
1448
0
    }
1449
1450
220k
    if (!bTimePart && bSuccess)
1451
0
    {
1452
0
        bSuccess = readDurationComponent(string, nPos, nTemp, bTimePart,
1453
0
                     nDays, 'd', 'D');
1454
0
    }
1455
1456
220k
    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
220k
    if (nPos != string.size()) // string not processed completely?
1537
220k
    {
1538
220k
        bSuccess = false;
1539
220k
    }
1540
1541
220k
    if (nTemp != -1) // unprocessed number?
1542
0
    {
1543
0
        bSuccess = false;
1544
0
    }
1545
1546
220k
    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
220k
    return bSuccess;
1559
220k
}
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
220k
{
1565
220k
    return convertDurationHelper(rDuration, o3tl::trim(rString));
1566
220k
}
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
38.4k
{
1627
38.4k
    if (i_rDateTime.Hours   < 10) {
1628
15.6k
        i_rBuffer.append('0');
1629
15.6k
    }
1630
38.4k
    i_rBuffer.append( TString::number(static_cast<sal_Int32>(i_rDateTime.Hours)) + ":");
1631
38.4k
    if (i_rDateTime.Minutes < 10) {
1632
15.2k
        i_rBuffer.append('0');
1633
15.2k
    }
1634
38.4k
    i_rBuffer.append( TString::number(static_cast<sal_Int32>(i_rDateTime.Minutes) ) + ":");
1635
38.4k
    if (i_rDateTime.Seconds < 10) {
1636
19.3k
        i_rBuffer.append('0');
1637
19.3k
    }
1638
38.4k
    i_rBuffer.append( static_cast<sal_Int32>(i_rDateTime.Seconds) );
1639
38.4k
    if (i_rDateTime.NanoSeconds > 0) {
1640
13.9k
        OSL_ENSURE(i_rDateTime.NanoSeconds < 1000000000,"NanoSeconds cannot be more than 999 999 999");
1641
13.9k
        i_rBuffer.append('.');
1642
        // pad to 9 characters length
1643
13.9k
        auto sNanoStr = TString::number(i_rDateTime.NanoSeconds);
1644
29.3k
        for (int i=0; i < 9 - sNanoStr.length; i++)
1645
15.4k
            i_rBuffer.append('0');
1646
13.9k
        i_rBuffer.append(sNanoStr);
1647
13.9k
    }
1648
38.4k
}
converter.cxx:void sax::convertTime<rtl::OUStringBuffer, rtl::OUString>(rtl::OUStringBuffer&, com::sun::star::util::DateTime const&)
Line
Count
Source
1626
38.4k
{
1627
38.4k
    if (i_rDateTime.Hours   < 10) {
1628
15.6k
        i_rBuffer.append('0');
1629
15.6k
    }
1630
38.4k
    i_rBuffer.append( TString::number(static_cast<sal_Int32>(i_rDateTime.Hours)) + ":");
1631
38.4k
    if (i_rDateTime.Minutes < 10) {
1632
15.2k
        i_rBuffer.append('0');
1633
15.2k
    }
1634
38.4k
    i_rBuffer.append( TString::number(static_cast<sal_Int32>(i_rDateTime.Minutes) ) + ":");
1635
38.4k
    if (i_rDateTime.Seconds < 10) {
1636
19.3k
        i_rBuffer.append('0');
1637
19.3k
    }
1638
38.4k
    i_rBuffer.append( static_cast<sal_Int32>(i_rDateTime.Seconds) );
1639
38.4k
    if (i_rDateTime.NanoSeconds > 0) {
1640
13.9k
        OSL_ENSURE(i_rDateTime.NanoSeconds < 1000000000,"NanoSeconds cannot be more than 999 999 999");
1641
13.9k
        i_rBuffer.append('.');
1642
        // pad to 9 characters length
1643
13.9k
        auto sNanoStr = TString::number(i_rDateTime.NanoSeconds);
1644
29.3k
        for (int i=0; i < 9 - sNanoStr.length; i++)
1645
15.4k
            i_rBuffer.append('0');
1646
13.9k
        i_rBuffer.append(sNanoStr);
1647
13.9k
    }
1648
38.4k
}
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
38.4k
{
1656
38.4k
    if (pTimeZoneOffset)
1657
0
    {
1658
0
        lcl_AppendTimezone(i_rBuffer, *pTimeZoneOffset);
1659
0
    }
1660
38.4k
    else if (i_rDateTime.IsUTC)
1661
0
    {
1662
0
        lcl_AppendTimezone(i_rBuffer, 0);
1663
0
    }
1664
38.4k
}
converter.cxx:void sax::convertTimeZone<rtl::OUStringBuffer>(rtl::OUStringBuffer&, com::sun::star::util::DateTime const&, short const*)
Line
Count
Source
1655
38.4k
{
1656
38.4k
    if (pTimeZoneOffset)
1657
0
    {
1658
0
        lcl_AppendTimezone(i_rBuffer, *pTimeZoneOffset);
1659
0
    }
1660
38.4k
    else if (i_rDateTime.IsUTC)
1661
0
    {
1662
0
        lcl_AppendTimezone(i_rBuffer, 0);
1663
0
    }
1664
38.4k
}
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
38.4k
{
1692
38.4k
    const char dash('-');
1693
38.4k
    const char zero('0');
1694
1695
38.4k
    sal_Int32 const nYear(abs(i_rDateTime.Year));
1696
38.4k
    if (i_rDateTime.Year < 0) {
1697
119
        i_rBuffer.append(dash); // negative
1698
119
    }
1699
38.4k
    if (nYear < 1000) {
1700
1.28k
        i_rBuffer.append(zero);
1701
1.28k
    }
1702
38.4k
    if (nYear < 100) {
1703
1.22k
        i_rBuffer.append(zero);
1704
1.22k
    }
1705
38.4k
    if (nYear < 10) {
1706
210
        i_rBuffer.append(zero);
1707
210
    }
1708
38.4k
    i_rBuffer.append( TString::number(nYear) + TStringChar(dash) );
1709
38.4k
    if( i_rDateTime.Month < 10 ) {
1710
28.4k
        i_rBuffer.append(zero);
1711
28.4k
    }
1712
38.4k
    i_rBuffer.append( TString::number(i_rDateTime.Month) + TStringChar(dash) );
1713
38.4k
    if( i_rDateTime.Day   < 10 ) {
1714
12.3k
        i_rBuffer.append(zero);
1715
12.3k
    }
1716
38.4k
    i_rBuffer.append( static_cast<sal_Int32>(i_rDateTime.Day)   );
1717
1718
38.4k
    if( i_rDateTime.Seconds != 0 ||
1719
16.6k
        i_rDateTime.Minutes != 0 ||
1720
7.63k
        i_rDateTime.Hours   != 0 ||
1721
6.49k
        i_bAddTimeIf0AM )
1722
38.4k
    {
1723
38.4k
        i_rBuffer.append('T');
1724
38.4k
        convertTime<TStringBuffer, TString>(i_rBuffer, i_rDateTime);
1725
38.4k
    }
1726
1727
38.4k
    convertTimeZone(i_rBuffer, i_rDateTime, pTimeZoneOffset);
1728
38.4k
}
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
38.4k
{
1692
38.4k
    const char dash('-');
1693
38.4k
    const char zero('0');
1694
1695
38.4k
    sal_Int32 const nYear(abs(i_rDateTime.Year));
1696
38.4k
    if (i_rDateTime.Year < 0) {
1697
119
        i_rBuffer.append(dash); // negative
1698
119
    }
1699
38.4k
    if (nYear < 1000) {
1700
1.28k
        i_rBuffer.append(zero);
1701
1.28k
    }
1702
38.4k
    if (nYear < 100) {
1703
1.22k
        i_rBuffer.append(zero);
1704
1.22k
    }
1705
38.4k
    if (nYear < 10) {
1706
210
        i_rBuffer.append(zero);
1707
210
    }
1708
38.4k
    i_rBuffer.append( TString::number(nYear) + TStringChar(dash) );
1709
38.4k
    if( i_rDateTime.Month < 10 ) {
1710
28.4k
        i_rBuffer.append(zero);
1711
28.4k
    }
1712
38.4k
    i_rBuffer.append( TString::number(i_rDateTime.Month) + TStringChar(dash) );
1713
38.4k
    if( i_rDateTime.Day   < 10 ) {
1714
12.3k
        i_rBuffer.append(zero);
1715
12.3k
    }
1716
38.4k
    i_rBuffer.append( static_cast<sal_Int32>(i_rDateTime.Day)   );
1717
1718
38.4k
    if( i_rDateTime.Seconds != 0 ||
1719
16.6k
        i_rDateTime.Minutes != 0 ||
1720
7.63k
        i_rDateTime.Hours   != 0 ||
1721
6.49k
        i_bAddTimeIf0AM )
1722
38.4k
    {
1723
38.4k
        i_rBuffer.append('T');
1724
38.4k
        convertTime<TStringBuffer, TString>(i_rBuffer, i_rDateTime);
1725
38.4k
    }
1726
1727
38.4k
    convertTimeZone(i_rBuffer, i_rDateTime, pTimeZoneOffset);
1728
38.4k
}
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
38.4k
{
1737
38.4k
    lcl_convertDateTime<OUStringBuffer, OUString, OUStringChar>(i_rBuffer, i_rDateTime, pTimeZoneOffset, i_bAddTimeIf0AM);
1738
38.4k
}
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
324k
{
1754
324k
    bool isDateTime;
1755
324k
    return parseDateOrDateTime(nullptr, rDateTime, isDateTime, nullptr,
1756
324k
            rString);
1757
324k
}
1758
1759
/** convert ISO "date" or "dateTime" string to util::DateTime */
1760
bool Converter::parseDateTime(   util::DateTime& rDateTime,
1761
                                 std::string_view rString )
1762
7.91k
{
1763
7.91k
    bool isDateTime;
1764
7.91k
    return parseDateOrDateTime(nullptr, rDateTime, isDateTime, nullptr,
1765
7.91k
            rString);
1766
7.91k
}
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
543k
{
1858
543k
    const size_t nOldPos(io_rnPos);
1859
543k
    sal_Int32 nTemp(0);
1860
543k
    if (R_SUCCESS != readUnsignedNumber<V>(rString, io_rnPos, nTemp))
1861
291k
    {
1862
291k
        return false;
1863
291k
    }
1864
252k
    const sal_Int32 nTokenLength(io_rnPos - nOldPos);
1865
252k
    if ((nTokenLength < nMinLength) ||
1866
251k
        (bExactLength && (nTokenLength > nMinLength)))
1867
602
    {
1868
602
        return false; // bad length
1869
602
    }
1870
251k
    o_rnTarget = nTemp;
1871
251k
    return true;
1872
252k
}
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
519k
{
1858
519k
    const size_t nOldPos(io_rnPos);
1859
519k
    sal_Int32 nTemp(0);
1860
519k
    if (R_SUCCESS != readUnsignedNumber<V>(rString, io_rnPos, nTemp))
1861
284k
    {
1862
284k
        return false;
1863
284k
    }
1864
234k
    const sal_Int32 nTokenLength(io_rnPos - nOldPos);
1865
234k
    if ((nTokenLength < nMinLength) ||
1866
234k
        (bExactLength && (nTokenLength > nMinLength)))
1867
7
    {
1868
7
        return false; // bad length
1869
7
    }
1870
234k
    o_rnTarget = nTemp;
1871
234k
    return true;
1872
234k
}
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
24.3k
{
1858
24.3k
    const size_t nOldPos(io_rnPos);
1859
24.3k
    sal_Int32 nTemp(0);
1860
24.3k
    if (R_SUCCESS != readUnsignedNumber<V>(rString, io_rnPos, nTemp))
1861
6.28k
    {
1862
6.28k
        return false;
1863
6.28k
    }
1864
18.0k
    const sal_Int32 nTokenLength(io_rnPos - nOldPos);
1865
18.0k
    if ((nTokenLength < nMinLength) ||
1866
17.6k
        (bExactLength && (nTokenLength > nMinLength)))
1867
595
    {
1868
595
        return false; // bad length
1869
595
    }
1870
17.4k
    o_rnTarget = nTemp;
1871
17.4k
    return true;
1872
18.0k
}
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
332k
{
1884
332k
    bool bSuccess = true;
1885
1886
332k
    if (string.size() > nPos)
1887
47.3k
    {
1888
47.3k
        if ('-' == string[nPos])
1889
1.69k
        {
1890
1.69k
            isNegative = true;
1891
1.69k
            ++nPos;
1892
1.69k
        }
1893
47.3k
    }
1894
1895
332k
    {
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
332k
        bSuccess = readDateTimeComponent<V>(string, nPos, nYear, 1, false);
1900
332k
        if (!bIgnoreInvalidOrMissingDate)
1901
332k
        {
1902
332k
            bSuccess &= (0 < nYear);
1903
332k
        }
1904
332k
        bSuccess &= (nYear <= (isNegative ? 32768 : 32767)); // Must fit into css::util::Date
1905
332k
        bSuccess &= (nPos < string.size()); // not last token
1906
332k
    }
1907
332k
    if (bSuccess && ('-' != string[nPos])) // separator
1908
98
    {
1909
98
        bSuccess = false;
1910
98
    }
1911
332k
    if (bSuccess)
1912
47.1k
    {
1913
47.1k
        ++nPos;
1914
1915
47.1k
        bSuccess = readDateTimeComponent<V>(string, nPos, nMonth, 2, true);
1916
47.1k
        if (!bIgnoreInvalidOrMissingDate)
1917
47.0k
        {
1918
47.0k
            bSuccess &= (0 < nMonth);
1919
47.0k
        }
1920
47.1k
        bSuccess &= (nMonth <= 12);
1921
47.1k
        bSuccess &= (nPos < string.size()); // not last token
1922
47.1k
    }
1923
332k
    if (bSuccess && ('-' != string[nPos])) // separator
1924
200
    {
1925
200
        bSuccess = false;
1926
200
    }
1927
332k
    if (bSuccess)
1928
46.4k
    {
1929
46.4k
        ++nPos;
1930
1931
46.4k
        bSuccess = readDateTimeComponent(string, nPos, nDay, 2, true);
1932
46.4k
        if (!bIgnoreInvalidOrMissingDate)
1933
46.2k
        {
1934
46.2k
            bSuccess &= (0 < nDay);
1935
46.2k
        }
1936
46.4k
        if (nMonth > 0) // not possible to check if month was missing
1937
46.2k
        {
1938
46.2k
            sal_Int32 nMaxDay
1939
46.2k
                = comphelper::date::getDaysInMonth(nMonth, isNegative ? -nYear : nYear);
1940
46.2k
            bSuccess &= (nDay <= nMaxDay);
1941
46.2k
        }
1942
46.4k
        else assert(bIgnoreInvalidOrMissingDate);
1943
46.4k
    }
1944
1945
332k
    if (bSuccess && (nPos < string.size()))
1946
39.2k
    {
1947
39.2k
        if ('T' == string[nPos] || 't' == string[nPos]) // time separator
1948
39.2k
        {
1949
39.2k
            bHaveTime = true;
1950
39.2k
            ++nPos;
1951
39.2k
        }
1952
39.2k
    }
1953
1954
332k
    return bSuccess;
1955
332k
}
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
324k
{
1884
324k
    bool bSuccess = true;
1885
1886
324k
    if (string.size() > nPos)
1887
39.2k
    {
1888
39.2k
        if ('-' == string[nPos])
1889
1.68k
        {
1890
1.68k
            isNegative = true;
1891
1.68k
            ++nPos;
1892
1.68k
        }
1893
39.2k
    }
1894
1895
324k
    {
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
324k
        bSuccess = readDateTimeComponent<V>(string, nPos, nYear, 1, false);
1900
324k
        if (!bIgnoreInvalidOrMissingDate)
1901
324k
        {
1902
324k
            bSuccess &= (0 < nYear);
1903
324k
        }
1904
324k
        bSuccess &= (nYear <= (isNegative ? 32768 : 32767)); // Must fit into css::util::Date
1905
324k
        bSuccess &= (nPos < string.size()); // not last token
1906
324k
    }
1907
324k
    if (bSuccess && ('-' != string[nPos])) // separator
1908
3
    {
1909
3
        bSuccess = false;
1910
3
    }
1911
324k
    if (bSuccess)
1912
39.2k
    {
1913
39.2k
        ++nPos;
1914
1915
39.2k
        bSuccess = readDateTimeComponent<V>(string, nPos, nMonth, 2, true);
1916
39.2k
        if (!bIgnoreInvalidOrMissingDate)
1917
39.2k
        {
1918
39.2k
            bSuccess &= (0 < nMonth);
1919
39.2k
        }
1920
39.2k
        bSuccess &= (nMonth <= 12);
1921
39.2k
        bSuccess &= (nPos < string.size()); // not last token
1922
39.2k
    }
1923
324k
    if (bSuccess && ('-' != string[nPos])) // separator
1924
0
    {
1925
0
        bSuccess = false;
1926
0
    }
1927
324k
    if (bSuccess)
1928
39.1k
    {
1929
39.1k
        ++nPos;
1930
1931
39.1k
        bSuccess = readDateTimeComponent(string, nPos, nDay, 2, true);
1932
39.1k
        if (!bIgnoreInvalidOrMissingDate)
1933
39.1k
        {
1934
39.1k
            bSuccess &= (0 < nDay);
1935
39.1k
        }
1936
39.1k
        if (nMonth > 0) // not possible to check if month was missing
1937
39.1k
        {
1938
39.1k
            sal_Int32 nMaxDay
1939
39.1k
                = comphelper::date::getDaysInMonth(nMonth, isNegative ? -nYear : nYear);
1940
39.1k
            bSuccess &= (nDay <= nMaxDay);
1941
39.1k
        }
1942
39.1k
        else assert(bIgnoreInvalidOrMissingDate);
1943
39.1k
    }
1944
1945
324k
    if (bSuccess && (nPos < string.size()))
1946
38.8k
    {
1947
38.8k
        if ('T' == string[nPos] || 't' == string[nPos]) // time separator
1948
38.8k
        {
1949
38.8k
            bHaveTime = true;
1950
38.8k
            ++nPos;
1951
38.8k
        }
1952
38.8k
    }
1953
1954
324k
    return bSuccess;
1955
324k
}
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
8.09k
{
1884
8.09k
    bool bSuccess = true;
1885
1886
8.09k
    if (string.size() > nPos)
1887
8.08k
    {
1888
8.08k
        if ('-' == string[nPos])
1889
7
        {
1890
7
            isNegative = true;
1891
7
            ++nPos;
1892
7
        }
1893
8.08k
    }
1894
1895
8.09k
    {
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
8.09k
        bSuccess = readDateTimeComponent<V>(string, nPos, nYear, 1, false);
1900
8.09k
        if (!bIgnoreInvalidOrMissingDate)
1901
7.91k
        {
1902
7.91k
            bSuccess &= (0 < nYear);
1903
7.91k
        }
1904
8.09k
        bSuccess &= (nYear <= (isNegative ? 32768 : 32767)); // Must fit into css::util::Date
1905
8.09k
        bSuccess &= (nPos < string.size()); // not last token
1906
8.09k
    }
1907
8.09k
    if (bSuccess && ('-' != string[nPos])) // separator
1908
95
    {
1909
95
        bSuccess = false;
1910
95
    }
1911
8.09k
    if (bSuccess)
1912
7.96k
    {
1913
7.96k
        ++nPos;
1914
1915
7.96k
        bSuccess = readDateTimeComponent<V>(string, nPos, nMonth, 2, true);
1916
7.96k
        if (!bIgnoreInvalidOrMissingDate)
1917
7.78k
        {
1918
7.78k
            bSuccess &= (0 < nMonth);
1919
7.78k
        }
1920
7.96k
        bSuccess &= (nMonth <= 12);
1921
7.96k
        bSuccess &= (nPos < string.size()); // not last token
1922
7.96k
    }
1923
8.09k
    if (bSuccess && ('-' != string[nPos])) // separator
1924
200
    {
1925
200
        bSuccess = false;
1926
200
    }
1927
8.09k
    if (bSuccess)
1928
7.26k
    {
1929
7.26k
        ++nPos;
1930
1931
7.26k
        bSuccess = readDateTimeComponent(string, nPos, nDay, 2, true);
1932
7.26k
        if (!bIgnoreInvalidOrMissingDate)
1933
7.09k
        {
1934
7.09k
            bSuccess &= (0 < nDay);
1935
7.09k
        }
1936
7.26k
        if (nMonth > 0) // not possible to check if month was missing
1937
7.10k
        {
1938
7.10k
            sal_Int32 nMaxDay
1939
7.10k
                = comphelper::date::getDaysInMonth(nMonth, isNegative ? -nYear : nYear);
1940
7.10k
            bSuccess &= (nDay <= nMaxDay);
1941
7.10k
        }
1942
7.26k
        else assert(bIgnoreInvalidOrMissingDate);
1943
7.26k
    }
1944
1945
8.09k
    if (bSuccess && (nPos < string.size()))
1946
309
    {
1947
309
        if ('T' == string[nPos] || 't' == string[nPos]) // time separator
1948
307
        {
1949
307
            bHaveTime = true;
1950
307
            ++nPos;
1951
307
        }
1952
309
    }
1953
1954
8.09k
    return bSuccess;
1955
8.09k
}
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
332k
{
1966
332k
    bool bSuccess = true;
1967
1968
332k
    string = o3tl::trim(string);
1969
1970
332k
    bool isNegative(false);
1971
332k
    sal_Int32 nYear(0);
1972
332k
    sal_Int32 nMonth(0);
1973
332k
    sal_Int32 nDay(0);
1974
332k
    size_t nPos(0);
1975
332k
    bool bHaveTime(false);
1976
1977
332k
    if (    !bIgnoreInvalidOrMissingDate
1978
223
        ||  string.find(':') == V::npos  // no time?
1979
222
        ||  (string.find('-') != V::npos
1980
176
             && string.find('-') < string.find(':')))
1981
332k
    {
1982
332k
        bSuccess &= lcl_parseDate<V>(isNegative, nYear, nMonth, nDay,
1983
332k
                bHaveTime, nPos, string, bIgnoreInvalidOrMissingDate);
1984
332k
    }
1985
47
    else
1986
47
    {
1987
47
        bHaveTime = true;
1988
47
    }
1989
1990
332k
    sal_Int32 nHours(0);
1991
332k
    sal_Int32 nMinutes(0);
1992
332k
    sal_Int32 nSeconds(0);
1993
332k
    sal_Int32 nNanoSeconds(0);
1994
332k
    if (bSuccess && bHaveTime)
1995
39.2k
    {
1996
39.2k
        {
1997
39.2k
            bSuccess = readDateTimeComponent(string, nPos, nHours, 2, true);
1998
39.2k
            bSuccess &= (0 <= nHours) && (nHours <= 24);
1999
39.2k
            bSuccess &= (nPos < string.size()); // not last token
2000
39.2k
        }
2001
39.2k
        if (bSuccess && (':' != string[nPos])) // separator
2002
3
        {
2003
3
            bSuccess = false;
2004
3
        }
2005
39.2k
        if (bSuccess)
2006
39.1k
        {
2007
39.1k
            ++nPos;
2008
2009
39.1k
            bSuccess = readDateTimeComponent(string, nPos, nMinutes, 2, true);
2010
39.1k
            bSuccess &= (0 <= nMinutes) && (nMinutes < 60);
2011
39.1k
            bSuccess &= (nPos < string.size()); // not last token
2012
39.1k
        }
2013
39.2k
        if (bSuccess && (':' != string[nPos])) // separator
2014
1
        {
2015
1
            bSuccess = false;
2016
1
        }
2017
39.2k
        if (bSuccess)
2018
39.1k
        {
2019
39.1k
            ++nPos;
2020
2021
39.1k
            bSuccess = readDateTimeComponent(string, nPos, nSeconds, 2, true);
2022
39.1k
            bSuccess &= (0 <= nSeconds) && (nSeconds < 60);
2023
39.1k
        }
2024
39.2k
        if (bSuccess && (nPos < string.size()) &&
2025
26.9k
            ('.' == string[nPos] || ',' == string[nPos])) // fraction separator
2026
26.9k
        {
2027
26.9k
            ++nPos;
2028
26.9k
            const sal_Int32 nStart(nPos);
2029
26.9k
            sal_Int32 nTemp(0);
2030
26.9k
            if (R_NOTHING == readUnsignedNumberMaxDigits<V>(9, string, nPos, nTemp))
2031
0
            {
2032
0
                bSuccess = false;
2033
0
            }
2034
26.9k
            if (bSuccess)
2035
26.9k
            {
2036
26.9k
                sal_Int32 nDigits = std::min<sal_Int32>(nPos - nStart, 9);
2037
26.9k
                assert(nDigits > 0);
2038
37.5k
                for (; nDigits < 9; ++nDigits)
2039
10.6k
                {
2040
10.6k
                    nTemp *= 10;
2041
10.6k
                }
2042
26.9k
                nNanoSeconds = nTemp;
2043
26.9k
            }
2044
26.9k
        }
2045
2046
39.2k
        if (bSuccess && (nHours == 24))
2047
69
        {
2048
69
            if (!((0 == nMinutes) && (0 == nSeconds) && (0 == nNanoSeconds)))
2049
69
            {
2050
69
                bSuccess = false; // only 24:00:00 is valid
2051
69
            }
2052
69
        }
2053
39.2k
    }
2054
2055
332k
    bool bHaveTimezone(false);
2056
332k
    bool bHaveTimezonePlus(false);
2057
332k
    bool bHaveTimezoneMinus(false);
2058
332k
    if (bSuccess && (nPos < string.size()))
2059
11
    {
2060
11
        const sal_Unicode c(string[nPos]);
2061
11
        if ('+' == c)
2062
0
        {
2063
0
            bHaveTimezone = true;
2064
0
            bHaveTimezonePlus = true;
2065
0
            ++nPos;
2066
0
        }
2067
11
        else if ('-' == c)
2068
1
        {
2069
1
            bHaveTimezone = true;
2070
1
            bHaveTimezoneMinus = true;
2071
1
            ++nPos;
2072
1
        }
2073
10
        else if ('Z' == c || 'z' == c)
2074
1
        {
2075
1
            bHaveTimezone = true;
2076
1
            ++nPos;
2077
1
        }
2078
9
        else
2079
9
        {
2080
9
            bSuccess = false;
2081
9
        }
2082
11
    }
2083
332k
    sal_Int32 nTimezoneHours(0);
2084
332k
    sal_Int32 nTimezoneMinutes(0);
2085
332k
    if (bSuccess && (bHaveTimezonePlus || bHaveTimezoneMinus))
2086
1
    {
2087
1
        bSuccess = readDateTimeComponent<V>(
2088
1
                        string, nPos, nTimezoneHours, 2, true);
2089
1
        bSuccess &= (0 <= nTimezoneHours) && (nTimezoneHours <= 14);
2090
1
        bSuccess &= (nPos < string.size()); // not last token
2091
1
        if (bSuccess && (':' != string[nPos])) // separator
2092
0
        {
2093
0
            bSuccess = false;
2094
0
        }
2095
1
        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
1
        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
1
    }
2111
2112
332k
    bSuccess &= (nPos == string.size()); // trailing junk?
2113
2114
332k
    if (bSuccess)
2115
39.6k
    {
2116
39.6k
        sal_Int16 const nTimezoneOffset = (bHaveTimezoneMinus ? -1 : +1)
2117
39.6k
                        * ((nTimezoneHours * 60) + nTimezoneMinutes);
2118
39.6k
        if (!pDate || bHaveTime) // time is optional
2119
39.6k
        {
2120
39.6k
            rDateTime.Year =
2121
39.6k
                (isNegative ? -1 : +1) * static_cast<sal_Int16>(nYear);
2122
39.6k
            rDateTime.Month = static_cast<sal_uInt16>(nMonth);
2123
39.6k
            rDateTime.Day = static_cast<sal_uInt16>(nDay);
2124
39.6k
            rDateTime.Hours = static_cast<sal_uInt16>(nHours);
2125
39.6k
            rDateTime.Minutes = static_cast<sal_uInt16>(nMinutes);
2126
39.6k
            rDateTime.Seconds = static_cast<sal_uInt16>(nSeconds);
2127
39.6k
            rDateTime.NanoSeconds = static_cast<sal_uInt32>(nNanoSeconds);
2128
39.6k
            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
39.6k
            else
2144
39.6k
            {
2145
39.6k
                if (pTimeZoneOffset)
2146
0
                {
2147
0
                    pTimeZoneOffset->reset();
2148
0
                }
2149
39.6k
                rDateTime.IsUTC = false;
2150
39.6k
            }
2151
39.6k
            rbDateTime = bHaveTime;
2152
39.6k
        }
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
39.6k
    }
2181
332k
    return bSuccess;
2182
332k
}
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
324k
{
1966
324k
    bool bSuccess = true;
1967
1968
324k
    string = o3tl::trim(string);
1969
1970
324k
    bool isNegative(false);
1971
324k
    sal_Int32 nYear(0);
1972
324k
    sal_Int32 nMonth(0);
1973
324k
    sal_Int32 nDay(0);
1974
324k
    size_t nPos(0);
1975
324k
    bool bHaveTime(false);
1976
1977
324k
    if (    !bIgnoreInvalidOrMissingDate
1978
0
        ||  string.find(':') == V::npos  // no time?
1979
0
        ||  (string.find('-') != V::npos
1980
0
             && string.find('-') < string.find(':')))
1981
324k
    {
1982
324k
        bSuccess &= lcl_parseDate<V>(isNegative, nYear, nMonth, nDay,
1983
324k
                bHaveTime, nPos, string, bIgnoreInvalidOrMissingDate);
1984
324k
    }
1985
0
    else
1986
0
    {
1987
0
        bHaveTime = true;
1988
0
    }
1989
1990
324k
    sal_Int32 nHours(0);
1991
324k
    sal_Int32 nMinutes(0);
1992
324k
    sal_Int32 nSeconds(0);
1993
324k
    sal_Int32 nNanoSeconds(0);
1994
324k
    if (bSuccess && bHaveTime)
1995
38.8k
    {
1996
38.8k
        {
1997
38.8k
            bSuccess = readDateTimeComponent(string, nPos, nHours, 2, true);
1998
38.8k
            bSuccess &= (0 <= nHours) && (nHours <= 24);
1999
38.8k
            bSuccess &= (nPos < string.size()); // not last token
2000
38.8k
        }
2001
38.8k
        if (bSuccess && (':' != string[nPos])) // separator
2002
2
        {
2003
2
            bSuccess = false;
2004
2
        }
2005
38.8k
        if (bSuccess)
2006
38.8k
        {
2007
38.8k
            ++nPos;
2008
2009
38.8k
            bSuccess = readDateTimeComponent(string, nPos, nMinutes, 2, true);
2010
38.8k
            bSuccess &= (0 <= nMinutes) && (nMinutes < 60);
2011
38.8k
            bSuccess &= (nPos < string.size()); // not last token
2012
38.8k
        }
2013
38.8k
        if (bSuccess && (':' != string[nPos])) // separator
2014
0
        {
2015
0
            bSuccess = false;
2016
0
        }
2017
38.8k
        if (bSuccess)
2018
38.8k
        {
2019
38.8k
            ++nPos;
2020
2021
38.8k
            bSuccess = readDateTimeComponent(string, nPos, nSeconds, 2, true);
2022
38.8k
            bSuccess &= (0 <= nSeconds) && (nSeconds < 60);
2023
38.8k
        }
2024
38.8k
        if (bSuccess && (nPos < string.size()) &&
2025
26.8k
            ('.' == string[nPos] || ',' == string[nPos])) // fraction separator
2026
26.8k
        {
2027
26.8k
            ++nPos;
2028
26.8k
            const sal_Int32 nStart(nPos);
2029
26.8k
            sal_Int32 nTemp(0);
2030
26.8k
            if (R_NOTHING == readUnsignedNumberMaxDigits<V>(9, string, nPos, nTemp))
2031
0
            {
2032
0
                bSuccess = false;
2033
0
            }
2034
26.8k
            if (bSuccess)
2035
26.8k
            {
2036
26.8k
                sal_Int32 nDigits = std::min<sal_Int32>(nPos - nStart, 9);
2037
26.8k
                assert(nDigits > 0);
2038
37.4k
                for (; nDigits < 9; ++nDigits)
2039
10.5k
                {
2040
10.5k
                    nTemp *= 10;
2041
10.5k
                }
2042
26.8k
                nNanoSeconds = nTemp;
2043
26.8k
            }
2044
26.8k
        }
2045
2046
38.8k
        if (bSuccess && (nHours == 24))
2047
69
        {
2048
69
            if (!((0 == nMinutes) && (0 == nSeconds) && (0 == nNanoSeconds)))
2049
69
            {
2050
69
                bSuccess = false; // only 24:00:00 is valid
2051
69
            }
2052
69
        }
2053
38.8k
    }
2054
2055
324k
    bool bHaveTimezone(false);
2056
324k
    bool bHaveTimezonePlus(false);
2057
324k
    bool bHaveTimezoneMinus(false);
2058
324k
    if (bSuccess && (nPos < string.size()))
2059
9
    {
2060
9
        const sal_Unicode c(string[nPos]);
2061
9
        if ('+' == c)
2062
0
        {
2063
0
            bHaveTimezone = true;
2064
0
            bHaveTimezonePlus = true;
2065
0
            ++nPos;
2066
0
        }
2067
9
        else if ('-' == c)
2068
0
        {
2069
0
            bHaveTimezone = true;
2070
0
            bHaveTimezoneMinus = true;
2071
0
            ++nPos;
2072
0
        }
2073
9
        else if ('Z' == c || 'z' == c)
2074
1
        {
2075
1
            bHaveTimezone = true;
2076
1
            ++nPos;
2077
1
        }
2078
8
        else
2079
8
        {
2080
8
            bSuccess = false;
2081
8
        }
2082
9
    }
2083
324k
    sal_Int32 nTimezoneHours(0);
2084
324k
    sal_Int32 nTimezoneMinutes(0);
2085
324k
    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
324k
    bSuccess &= (nPos == string.size()); // trailing junk?
2113
2114
324k
    if (bSuccess)
2115
38.7k
    {
2116
38.7k
        sal_Int16 const nTimezoneOffset = (bHaveTimezoneMinus ? -1 : +1)
2117
38.7k
                        * ((nTimezoneHours * 60) + nTimezoneMinutes);
2118
38.7k
        if (!pDate || bHaveTime) // time is optional
2119
38.7k
        {
2120
38.7k
            rDateTime.Year =
2121
38.7k
                (isNegative ? -1 : +1) * static_cast<sal_Int16>(nYear);
2122
38.7k
            rDateTime.Month = static_cast<sal_uInt16>(nMonth);
2123
38.7k
            rDateTime.Day = static_cast<sal_uInt16>(nDay);
2124
38.7k
            rDateTime.Hours = static_cast<sal_uInt16>(nHours);
2125
38.7k
            rDateTime.Minutes = static_cast<sal_uInt16>(nMinutes);
2126
38.7k
            rDateTime.Seconds = static_cast<sal_uInt16>(nSeconds);
2127
38.7k
            rDateTime.NanoSeconds = static_cast<sal_uInt32>(nNanoSeconds);
2128
38.7k
            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
38.7k
            else
2144
38.7k
            {
2145
38.7k
                if (pTimeZoneOffset)
2146
0
                {
2147
0
                    pTimeZoneOffset->reset();
2148
0
                }
2149
38.7k
                rDateTime.IsUTC = false;
2150
38.7k
            }
2151
38.7k
            rbDateTime = bHaveTime;
2152
38.7k
        }
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
38.7k
    }
2181
324k
    return bSuccess;
2182
324k
}
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
8.14k
{
1966
8.14k
    bool bSuccess = true;
1967
1968
8.14k
    string = o3tl::trim(string);
1969
1970
8.14k
    bool isNegative(false);
1971
8.14k
    sal_Int32 nYear(0);
1972
8.14k
    sal_Int32 nMonth(0);
1973
8.14k
    sal_Int32 nDay(0);
1974
8.14k
    size_t nPos(0);
1975
8.14k
    bool bHaveTime(false);
1976
1977
8.14k
    if (    !bIgnoreInvalidOrMissingDate
1978
223
        ||  string.find(':') == V::npos  // no time?
1979
222
        ||  (string.find('-') != V::npos
1980
176
             && string.find('-') < string.find(':')))
1981
8.09k
    {
1982
8.09k
        bSuccess &= lcl_parseDate<V>(isNegative, nYear, nMonth, nDay,
1983
8.09k
                bHaveTime, nPos, string, bIgnoreInvalidOrMissingDate);
1984
8.09k
    }
1985
47
    else
1986
47
    {
1987
47
        bHaveTime = true;
1988
47
    }
1989
1990
8.14k
    sal_Int32 nHours(0);
1991
8.14k
    sal_Int32 nMinutes(0);
1992
8.14k
    sal_Int32 nSeconds(0);
1993
8.14k
    sal_Int32 nNanoSeconds(0);
1994
8.14k
    if (bSuccess && bHaveTime)
1995
354
    {
1996
354
        {
1997
354
            bSuccess = readDateTimeComponent(string, nPos, nHours, 2, true);
1998
354
            bSuccess &= (0 <= nHours) && (nHours <= 24);
1999
354
            bSuccess &= (nPos < string.size()); // not last token
2000
354
        }
2001
354
        if (bSuccess && (':' != string[nPos])) // separator
2002
1
        {
2003
1
            bSuccess = false;
2004
1
        }
2005
354
        if (bSuccess)
2006
342
        {
2007
342
            ++nPos;
2008
2009
342
            bSuccess = readDateTimeComponent(string, nPos, nMinutes, 2, true);
2010
342
            bSuccess &= (0 <= nMinutes) && (nMinutes < 60);
2011
342
            bSuccess &= (nPos < string.size()); // not last token
2012
342
        }
2013
354
        if (bSuccess && (':' != string[nPos])) // separator
2014
1
        {
2015
1
            bSuccess = false;
2016
1
        }
2017
354
        if (bSuccess)
2018
337
        {
2019
337
            ++nPos;
2020
2021
337
            bSuccess = readDateTimeComponent(string, nPos, nSeconds, 2, true);
2022
337
            bSuccess &= (0 <= nSeconds) && (nSeconds < 60);
2023
337
        }
2024
354
        if (bSuccess && (nPos < string.size()) &&
2025
50
            ('.' == string[nPos] || ',' == string[nPos])) // fraction separator
2026
50
        {
2027
50
            ++nPos;
2028
50
            const sal_Int32 nStart(nPos);
2029
50
            sal_Int32 nTemp(0);
2030
50
            if (R_NOTHING == readUnsignedNumberMaxDigits<V>(9, string, nPos, nTemp))
2031
0
            {
2032
0
                bSuccess = false;
2033
0
            }
2034
50
            if (bSuccess)
2035
50
            {
2036
50
                sal_Int32 nDigits = std::min<sal_Int32>(nPos - nStart, 9);
2037
50
                assert(nDigits > 0);
2038
78
                for (; nDigits < 9; ++nDigits)
2039
28
                {
2040
28
                    nTemp *= 10;
2041
28
                }
2042
50
                nNanoSeconds = nTemp;
2043
50
            }
2044
50
        }
2045
2046
354
        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
354
    }
2054
2055
8.14k
    bool bHaveTimezone(false);
2056
8.14k
    bool bHaveTimezonePlus(false);
2057
8.14k
    bool bHaveTimezoneMinus(false);
2058
8.14k
    if (bSuccess && (nPos < string.size()))
2059
2
    {
2060
2
        const sal_Unicode c(string[nPos]);
2061
2
        if ('+' == c)
2062
0
        {
2063
0
            bHaveTimezone = true;
2064
0
            bHaveTimezonePlus = true;
2065
0
            ++nPos;
2066
0
        }
2067
2
        else if ('-' == c)
2068
1
        {
2069
1
            bHaveTimezone = true;
2070
1
            bHaveTimezoneMinus = true;
2071
1
            ++nPos;
2072
1
        }
2073
1
        else if ('Z' == c || 'z' == c)
2074
0
        {
2075
0
            bHaveTimezone = true;
2076
0
            ++nPos;
2077
0
        }
2078
1
        else
2079
1
        {
2080
1
            bSuccess = false;
2081
1
        }
2082
2
    }
2083
8.14k
    sal_Int32 nTimezoneHours(0);
2084
8.14k
    sal_Int32 nTimezoneMinutes(0);
2085
8.14k
    if (bSuccess && (bHaveTimezonePlus || bHaveTimezoneMinus))
2086
1
    {
2087
1
        bSuccess = readDateTimeComponent<V>(
2088
1
                        string, nPos, nTimezoneHours, 2, true);
2089
1
        bSuccess &= (0 <= nTimezoneHours) && (nTimezoneHours <= 14);
2090
1
        bSuccess &= (nPos < string.size()); // not last token
2091
1
        if (bSuccess && (':' != string[nPos])) // separator
2092
0
        {
2093
0
            bSuccess = false;
2094
0
        }
2095
1
        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
1
        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
1
    }
2111
2112
8.14k
    bSuccess &= (nPos == string.size()); // trailing junk?
2113
2114
8.14k
    if (bSuccess)
2115
937
    {
2116
937
        sal_Int16 const nTimezoneOffset = (bHaveTimezoneMinus ? -1 : +1)
2117
937
                        * ((nTimezoneHours * 60) + nTimezoneMinutes);
2118
937
        if (!pDate || bHaveTime) // time is optional
2119
937
        {
2120
937
            rDateTime.Year =
2121
937
                (isNegative ? -1 : +1) * static_cast<sal_Int16>(nYear);
2122
937
            rDateTime.Month = static_cast<sal_uInt16>(nMonth);
2123
937
            rDateTime.Day = static_cast<sal_uInt16>(nDay);
2124
937
            rDateTime.Hours = static_cast<sal_uInt16>(nHours);
2125
937
            rDateTime.Minutes = static_cast<sal_uInt16>(nMinutes);
2126
937
            rDateTime.Seconds = static_cast<sal_uInt16>(nSeconds);
2127
937
            rDateTime.NanoSeconds = static_cast<sal_uInt32>(nNanoSeconds);
2128
937
            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
937
            else
2144
937
            {
2145
937
                if (pTimeZoneOffset)
2146
0
                {
2147
0
                    pTimeZoneOffset->reset();
2148
0
                }
2149
937
                rDateTime.IsUTC = false;
2150
937
            }
2151
937
            rbDateTime = bHaveTime;
2152
937
        }
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
937
    }
2181
8.14k
    return bSuccess;
2182
8.14k
}
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
223
{
2199
223
    bool dummy;
2200
223
    return lcl_parseDateTime(
2201
223
                nullptr, rDateTime, dummy, nullptr, rString, true);
2202
223
}
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
324k
{
2211
324k
    return lcl_parseDateTime(
2212
324k
                pDate, rDateTime, rbDateTime, pTimeZoneOffset, rString, false);
2213
324k
}
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
7.91k
{
2222
7.91k
    return lcl_parseDateTime(
2223
7.91k
                pDate, rDateTime, rbDateTime, pTimeZoneOffset, rString, false);
2224
7.91k
}
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
82.4k
{
2231
82.4k
    sal_Unicode cQuote = 0;
2232
82.4k
    sal_Int32 nLen = rStr.size();
2233
1.02M
    for( ; nPos < nLen; nPos++ )
2234
965k
    {
2235
965k
        sal_Unicode c = rStr[nPos];
2236
965k
        switch( c )
2237
965k
        {
2238
59.1k
        case u'\'':
2239
59.1k
            if( 0 == cQuote )
2240
29.6k
                cQuote = c;
2241
29.4k
            else if( '\'' == cQuote )
2242
29.4k
                cQuote = 0;
2243
59.1k
            break;
2244
2245
16
        case u'"':
2246
16
            if( 0 == cQuote )
2247
14
                cQuote = c;
2248
2
            else if( '\"' == cQuote )
2249
0
                cQuote = 0;
2250
16
            break;
2251
2252
44.4k
        case u',':
2253
44.4k
            if( 0 == cQuote )
2254
26.6k
                return nPos;
2255
17.8k
            break;
2256
965k
        }
2257
965k
    }
2258
2259
55.8k
    return -1;
2260
82.4k
}
2261
2262
double Converter::GetConversionFactor(OUStringBuffer& rUnit, sal_Int16 nSourceUnit, sal_Int16 nTargetUnit)
2263
98.6k
{
2264
98.6k
    double fRetval(1.0);
2265
98.6k
    rUnit.setLength(0);
2266
2267
2268
98.6k
    if(nSourceUnit != nTargetUnit)
2269
43
    {
2270
43
        const o3tl::Length eFrom = Measure2O3tlUnit(nSourceUnit);
2271
43
        const o3tl::Length eTo = Measure2O3tlUnit(nTargetUnit);
2272
43
        fRetval = o3tl::convert(1.0, eFrom, eTo);
2273
2274
43
        if (const auto sUnit = Measure2UnitString(nTargetUnit); sUnit.size() > 0)
2275
43
            rUnit.appendAscii(sUnit.data(), sUnit.size());
2276
43
    }
2277
2278
98.6k
    return fRetval;
2279
98.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
98.6k
{
2303
98.6k
    sal_Int32 nPos = 0;
2304
98.6k
    sal_Int32 nLen = rString.size();
2305
98.6k
    sal_Int16 nRetUnit = nDefaultUnit;
2306
2307
    // skip white space
2308
98.6k
    while( nPos < nLen && ' ' == rString[nPos] )
2309
2
        nPos++;
2310
2311
    // skip negative
2312
98.6k
    if( nPos < nLen && '-' == rString[nPos] )
2313
639
        nPos++;
2314
2315
    // skip number
2316
420k
    while( nPos < nLen && '0' <= rString[nPos] && '9' >= rString[nPos] )
2317
321k
        nPos++;
2318
2319
98.6k
    if( nPos < nLen && '.' == rString[nPos] )
2320
6.34k
    {
2321
6.34k
        nPos++;
2322
16.0k
        while( nPos < nLen && '0' <= rString[nPos] && '9' >= rString[nPos] )
2323
9.70k
            nPos++;
2324
6.34k
    }
2325
2326
    // skip white space
2327
99.0k
    while( nPos < nLen && ' ' == rString[nPos] )
2328
366
        nPos++;
2329
2330
98.6k
    if( nPos < nLen )
2331
98.1k
    {
2332
98.1k
        switch(rString[nPos])
2333
98.1k
        {
2334
0
            case '%' :
2335
0
            {
2336
0
                nRetUnit = MeasureUnit::PERCENT;
2337
0
                break;
2338
0
            }
2339
20
            case 'c':
2340
20
            case 'C':
2341
20
            {
2342
20
                if(nPos+1 < nLen && (rString[nPos+1] == 'm'
2343
13
                    || rString[nPos+1] == 'M'))
2344
7
                    nRetUnit = MeasureUnit::CM;
2345
20
                break;
2346
20
            }
2347
11
            case 'e':
2348
17
            case 'E':
2349
17
            {
2350
                // CSS1_EMS or CSS1_EMX later
2351
17
                break;
2352
11
            }
2353
58
            case 'i':
2354
62
            case 'I':
2355
62
            {
2356
62
                if(nPos+1 < nLen && (rString[nPos+1] == 'n'
2357
34
                    || rString[nPos+1] == 'N'))
2358
28
                    nRetUnit = MeasureUnit::INCH;
2359
62
                break;
2360
58
            }
2361
11
            case 'm':
2362
31
            case 'M':
2363
31
            {
2364
31
                if(nPos+1 < nLen && (rString[nPos+1] == 'm'
2365
24
                    || rString[nPos+1] == 'M'))
2366
5
                    nRetUnit = MeasureUnit::MM;
2367
31
                break;
2368
11
            }
2369
95.1k
            case 'p':
2370
95.1k
            case 'P':
2371
95.1k
            {
2372
95.1k
                if(nPos+1 < nLen && (rString[nPos+1] == 't'
2373
327
                    || rString[nPos+1] == 'T'))
2374
94.8k
                    nRetUnit = MeasureUnit::POINT;
2375
95.1k
                if(nPos+1 < nLen && (rString[nPos+1] == 'c'
2376
95.1k
                    || rString[nPos+1] == 'C'))
2377
3
                    nRetUnit = MeasureUnit::TWIP;
2378
95.1k
                break;
2379
95.1k
            }
2380
98.1k
        }
2381
98.1k
    }
2382
2383
98.6k
    return nRetUnit;
2384
98.6k
}
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
98.6k
{
2303
98.6k
    sal_Int32 nPos = 0;
2304
98.6k
    sal_Int32 nLen = rString.size();
2305
98.6k
    sal_Int16 nRetUnit = nDefaultUnit;
2306
2307
    // skip white space
2308
98.6k
    while( nPos < nLen && ' ' == rString[nPos] )
2309
2
        nPos++;
2310
2311
    // skip negative
2312
98.6k
    if( nPos < nLen && '-' == rString[nPos] )
2313
639
        nPos++;
2314
2315
    // skip number
2316
420k
    while( nPos < nLen && '0' <= rString[nPos] && '9' >= rString[nPos] )
2317
321k
        nPos++;
2318
2319
98.6k
    if( nPos < nLen && '.' == rString[nPos] )
2320
6.34k
    {
2321
6.34k
        nPos++;
2322
16.0k
        while( nPos < nLen && '0' <= rString[nPos] && '9' >= rString[nPos] )
2323
9.70k
            nPos++;
2324
6.34k
    }
2325
2326
    // skip white space
2327
99.0k
    while( nPos < nLen && ' ' == rString[nPos] )
2328
366
        nPos++;
2329
2330
98.6k
    if( nPos < nLen )
2331
98.1k
    {
2332
98.1k
        switch(rString[nPos])
2333
98.1k
        {
2334
0
            case '%' :
2335
0
            {
2336
0
                nRetUnit = MeasureUnit::PERCENT;
2337
0
                break;
2338
0
            }
2339
20
            case 'c':
2340
20
            case 'C':
2341
20
            {
2342
20
                if(nPos+1 < nLen && (rString[nPos+1] == 'm'
2343
13
                    || rString[nPos+1] == 'M'))
2344
7
                    nRetUnit = MeasureUnit::CM;
2345
20
                break;
2346
20
            }
2347
11
            case 'e':
2348
17
            case 'E':
2349
17
            {
2350
                // CSS1_EMS or CSS1_EMX later
2351
17
                break;
2352
11
            }
2353
58
            case 'i':
2354
62
            case 'I':
2355
62
            {
2356
62
                if(nPos+1 < nLen && (rString[nPos+1] == 'n'
2357
34
                    || rString[nPos+1] == 'N'))
2358
28
                    nRetUnit = MeasureUnit::INCH;
2359
62
                break;
2360
58
            }
2361
11
            case 'm':
2362
31
            case 'M':
2363
31
            {
2364
31
                if(nPos+1 < nLen && (rString[nPos+1] == 'm'
2365
24
                    || rString[nPos+1] == 'M'))
2366
5
                    nRetUnit = MeasureUnit::MM;
2367
31
                break;
2368
11
            }
2369
95.1k
            case 'p':
2370
95.1k
            case 'P':
2371
95.1k
            {
2372
95.1k
                if(nPos+1 < nLen && (rString[nPos+1] == 't'
2373
327
                    || rString[nPos+1] == 'T'))
2374
94.8k
                    nRetUnit = MeasureUnit::POINT;
2375
95.1k
                if(nPos+1 < nLen && (rString[nPos+1] == 'c'
2376
95.1k
                    || rString[nPos+1] == 'C'))
2377
3
                    nRetUnit = MeasureUnit::TWIP;
2378
95.1k
                break;
2379
95.1k
            }
2380
98.1k
        }
2381
98.1k
    }
2382
2383
98.6k
    return nRetUnit;
2384
98.6k
}
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
98.6k
{
2388
98.6k
    return lcl_GetUnitFromString(rString, nDefaultUnit);
2389
98.6k
}
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: */