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>
29#include <rtl/ustrbuf.hxx>
30#include <rtl/math.hxx>
31#include <rtl/character.hxx>
36#include <osl/diagnose.h>
50const std::string_view
gpsMM =
"mm";
51const std::string_view
gpsCM =
"cm";
52const std::string_view
gpsPT =
"pt";
54const std::string_view
gpsPC =
"pc";
60 return rtl_ustr_toInt64_WithLength(str, radix, nStrLength);
64 return rtl_str_toInt64_WithLength(str, radix, nStrLength);
73 case MeasureUnit::TWIP:
75 case MeasureUnit::POINT:
77 case MeasureUnit::MM_10TH:
79 case MeasureUnit::MM_100TH:
86 SAL_WARN(
"sax",
"unit not supported for length");
88 case MeasureUnit::INCH:
93std::string_view Measure2UnitString(sal_Int16 nUnit)
97 case MeasureUnit::TWIP:
99 case MeasureUnit::POINT:
101 case MeasureUnit::MM_10TH:
102 case MeasureUnit::MM_100TH:
104 case MeasureUnit::MM:
106 case MeasureUnit::CM:
108 case MeasureUnit::INCH:
114template <
typename V>
bool wordEndsWith(V
string, std::string_view expected)
116 V substr =
string.substr(0, expected.size());
117 return std::equal(substr.begin(), substr.end(), expected.begin(), expected.end(),
118 [](sal_uInt32 c1, sal_uInt32 c2) { return rtl::toAsciiLowerCase(c1) == c2; })
119 && (
string.size() == expected.size() ||
string[expected.size()] ==
' ');
128 sal_Int16 nTargetUnit ,
136 sal_Int32
const nLen = rString.size();
139 while( (
nPos < nLen) && (rString[
nPos] <=
' ') )
142 if(
nPos < nLen &&
'-' == rString[
nPos] )
149 while(
nPos < nLen &&
150 '0' <= rString[
nPos] &&
151 '9' >= rString[
nPos] )
155 nVal += (rString[
nPos] -
'0');
158 if(
nPos < nLen &&
'.' == rString[
nPos] )
163 while(
nPos < nLen &&
164 '0' <= rString[
nPos] &&
165 '9' >= rString[
nPos] )
169 nVal += (
static_cast<double>(rString[
nPos] -
'0') / nDiv );
175 while( (
nPos < nLen) && (rString[
nPos] <=
' ') )
181 if( MeasureUnit::PERCENT == nTargetUnit )
183 if(
'%' != rString[
nPos] )
186 else if( MeasureUnit::PIXEL == nTargetUnit )
188 if(
nPos + 1 >= nLen ||
189 (
'p' != rString[
nPos] &&
190 'P' != rString[
nPos])||
191 (
'x' != rString[
nPos+1] &&
192 'X' != rString[
nPos+1]) )
197 OSL_ENSURE( MeasureUnit::TWIP == nTargetUnit || MeasureUnit::POINT == nTargetUnit ||
198 MeasureUnit::MM_100TH == nTargetUnit || MeasureUnit::MM_10TH == nTargetUnit ||
199 MeasureUnit::PIXEL == nTargetUnit,
"unit is not supported");
203 if( MeasureUnit::TWIP == nTargetUnit )
205 switch (rtl::toAsciiLowerCase<sal_uInt32>(rString[
nPos]))
208 if (wordEndsWith(rString.substr(
nPos + 1),
"m"))
212 if (wordEndsWith(rString.substr(
nPos + 1),
"n"))
216 if (wordEndsWith(rString.substr(
nPos + 1),
"m"))
220 if (wordEndsWith(rString.substr(
nPos + 1),
"t"))
222 else if (wordEndsWith(rString.substr(
nPos + 1),
"c"))
227 else if( MeasureUnit::MM_100TH == nTargetUnit || MeasureUnit::MM_10TH == nTargetUnit )
229 switch (rtl::toAsciiLowerCase<sal_uInt32>(rString[
nPos]))
232 if (wordEndsWith(rString.substr(
nPos + 1),
"m"))
236 if (wordEndsWith(rString.substr(
nPos + 1),
"n"))
240 if (wordEndsWith(rString.substr(
nPos + 1),
"m"))
244 if (wordEndsWith(rString.substr(
nPos + 1),
"t"))
246 else if (wordEndsWith(rString.substr(
nPos + 1),
"c"))
248 else if (wordEndsWith(rString.substr(
nPos + 1),
"x"))
253 else if( MeasureUnit::POINT == nTargetUnit )
255 if (wordEndsWith(rString.substr(
nPos),
"pt"))
263 nVal =
o3tl::convert(nVal, eFrom, Measure2O3tlUnit(nTargetUnit));
271 if( nVal <=
static_cast<double>(nMin) )
273 else if( nVal >=
static_cast<double>(nMax) )
276 rValue =
static_cast<sal_Int32
>(nVal);
283 std::u16string_view rString,
284 sal_Int16 nTargetUnit ,
293 std::string_view rString,
294 sal_Int16 nTargetUnit ,
305 sal_Int16 nSourceUnit ,
306 sal_Int16 nTargetUnit )
308 if( nSourceUnit == MeasureUnit::PERCENT )
310 OSL_ENSURE( nTargetUnit == MeasureUnit::PERCENT,
311 "MeasureUnit::PERCENT only maps to MeasureUnit::PERCENT!" );
313 rBuffer.append( nMeasure );
314 rBuffer.append(
'%' );
318 sal_Int64
nValue(nMeasure);
323 rBuffer.append(
'-' );
328 std::string_view psUnit;
329 switch( nSourceUnit )
331 case MeasureUnit::TWIP:
333 switch( nTargetUnit )
335 case MeasureUnit::MM_100TH:
336 case MeasureUnit::MM_10TH:
337 OSL_ENSURE( MeasureUnit::INCH == nTargetUnit,
"output unit not supported for twip values" );
339 case MeasureUnit::MM:
345 case MeasureUnit::CM:
351 case MeasureUnit::POINT:
357 case MeasureUnit::INCH:
359 OSL_ENSURE( MeasureUnit::INCH == nTargetUnit,
360 "output unit not supported for twip values" );
367 case MeasureUnit::POINT:
369 OSL_ENSURE( MeasureUnit::POINT == nTargetUnit,
370 "output unit not supported for pt values" );
375 case MeasureUnit::MM_10TH:
376 case MeasureUnit::MM_100TH:
378 int nFac2 = (MeasureUnit::MM_100TH == nSourceUnit) ? 100 : 10;
379 eFrom = Measure2O3tlUnit(nSourceUnit);
380 switch( nTargetUnit )
382 case MeasureUnit::MM_100TH:
383 case MeasureUnit::MM_10TH:
384 OSL_ENSURE( MeasureUnit::INCH == nTargetUnit,
385 "output unit not supported for 1/100mm values" );
387 case MeasureUnit::MM:
393 case MeasureUnit::CM:
399 case MeasureUnit::POINT:
405 case MeasureUnit::INCH:
407 OSL_ENSURE( MeasureUnit::INCH == nTargetUnit,
408 "output unit not supported for 1/100mm values" );
416 OSL_ENSURE(
false,
"sax::Converter::convertMeasure(): "
417 "source unit not supported");
423 rBuffer.append(
static_cast<sal_Int64
>(
nValue / nFac) );
424 if (nFac > 1 && (
nValue % nFac) != 0)
426 rBuffer.append(
'.' );
427 while (nFac > 1 && (
nValue % nFac) != 0)
430 rBuffer.append(
static_cast<sal_Int32
>((
nValue / nFac) % 10) );
434 if (psUnit.length() > 0)
435 rBuffer.appendAscii(psUnit.data(), psUnit.length());
441 rBool = rString ==
u"true";
443 return rBool || (rString ==
u"false");
449 rBool = rString ==
"true";
451 return rBool || (rString ==
"false");
457 rBuffer.append( bValue );
476 rBuffer.append(
'%' );
495 rBuffer.append(
'p' );
496 rBuffer.append(
'x' );
501 if( nChar >=
'0' && nChar <=
'9' )
503 else if( nChar >=
'a' && nChar <=
'f' )
504 return nChar -
'a' + 10;
505 else if( nChar >=
'A' && nChar <=
'F' )
506 return nChar -
'A' + 10;
515 if( rValue.size() != 7 || rValue[0] !=
'#' )
546 rBuffer.append(
'#' );
552 nCol =
static_cast<sal_uInt8>(nColor >> 8);
563 std::u16string_view aString,
564 sal_Int32 nMin, sal_Int32 nMax )
567 sal_Int64 nNumber = 0;
570 rValue =
static_cast<sal_Int32
>(nNumber);
576 std::string_view aString,
577 sal_Int32 nMin, sal_Int32 nMax )
580 sal_Int64 nNumber = 0;
583 rValue =
static_cast<sal_Int32
>(nNumber);
591 sal_Int64 nMin, sal_Int64 nMax )
594 sal_Int32
const nLen = aString.size();
597 while( (
nPos < nLen) && (aString[
nPos] <=
' ') )
600 sal_Int32 nNumberStartPos =
nPos;
602 if(
nPos < nLen &&
'-' == aString[
nPos] )
608 while(
nPos < nLen &&
609 '0' <= aString[
nPos] &&
610 '9' >= aString[
nPos] )
619 else if( rValue > nMax )
622 return (
nPos == nLen && rValue >= nMin && rValue <= nMax );
627 std::u16string_view aString,
628 sal_Int64 nMin, sal_Int64 nMax )
635 std::string_view aString,
636 sal_Int64 nMin, sal_Int64 nMax )
646 sal_Int16 nSourceUnit,
647 sal_Int16 nTargetUnit)
649 if(MeasureUnit::PERCENT == nSourceUnit)
651 OSL_ENSURE( nTargetUnit == MeasureUnit::PERCENT,
"MeasureUnit::PERCENT only maps to MeasureUnit::PERCENT!" );
652 ::rtl::math::doubleToUStringBuffer( rBuffer, fNumber, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max,
'.',
true);
658 OUStringBuffer sUnit;
662 ::rtl::math::doubleToUStringBuffer( rBuffer, fNumber, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max,
'.',
true);
664 rBuffer.append(sUnit);
671 ::rtl::math::doubleToUStringBuffer( rBuffer, fNumber, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max,
'.',
true);
676 std::u16string_view rString, sal_Int16 nSourceUnit, sal_Int16 nTargetUnit)
681 OUStringBuffer sUnit;
683 double const fFactor =
685 if(fFactor != 1.0 && fFactor != 0.0)
692 std::string_view rString, sal_Int16 nSourceUnit, sal_Int16 nTargetUnit)
699 double const fFactor =
701 if(fFactor != 1.0 && fFactor != 0.0)
709 rtl_math_ConversionStatus eStatus;
710 rValue = rtl_math_uStringToDouble(rString.data(),
711 rString.data() + rString.size(),
714 return ( eStatus == rtl_math_ConversionStatus_Ok );
720 rtl_math_ConversionStatus eStatus;
721 rValue = rtl_math_stringToDouble(rString.data(),
722 rString.data() + rString.size(),
725 return ( eStatus == rtl_math_ConversionStatus_Ok );
735 rBuffer.append(
static_cast<sal_Int32
>(nAngle));
739 double fAngle(
double(nAngle) / 10.0);
741 rBuffer.append(
"deg");
747 bool const isWrongOOo10thDegAngle)
758 if (std::u16string_view::npos != rString.find(
u"deg"))
762 else if (std::u16string_view::npos != rString.find(
u"grad"))
764 nValue = (fValue * 9.0 / 10.0) * 10.0;
766 else if (std::u16string_view::npos != rString.find(
u"rad"))
768 nValue = basegfx::rad2deg<10>(fValue);
772 if (isWrongOOo10thDegAngle)
790 rAngle = sal::static_int_cast<sal_Int16>(
nValue);
797 bool const isWrongOOo10thDegAngle)
808 if (std::string_view::npos != rString.find(
"deg"))
812 else if (std::string_view::npos != rString.find(
"grad"))
814 nValue = (fValue * 9.0 / 10.0) * 10.0;
816 else if (std::string_view::npos != rString.find(
"rad"))
818 nValue = basegfx::rad2deg<10>(fValue);
822 if (isWrongOOo10thDegAngle)
840 rAngle = sal::static_int_cast<sal_Int16>(
nValue);
849 double fValue = fTime;
859 rBuffer.append(
"PT" );
861 double fHoursValue = ::rtl::math::approxFloor (fValue);
862 fValue -= fHoursValue;
864 double fMinsValue = ::rtl::math::approxFloor (fValue);
865 fValue -= fMinsValue;
867 double fSecsValue = ::rtl::math::approxFloor (fValue);
868 fValue -= fSecsValue;
869 double fNanoSecsValue;
870 if (fValue > 0.00000000001)
873 fNanoSecsValue = 0.0;
875 if (fNanoSecsValue == 1.0)
877 fNanoSecsValue = 0.0;
880 if (fSecsValue >= 60.0)
885 if (fMinsValue >= 60.0)
891 if (fHoursValue < 10)
892 rBuffer.append(
'0');
893 rBuffer.append( sal_Int32( fHoursValue));
894 rBuffer.append(
'H');
896 rBuffer.append(
'0');
897 rBuffer.append( sal_Int32( fMinsValue));
898 rBuffer.append(
'M');
900 rBuffer.append(
'0');
901 rBuffer.append( sal_Int32( fSecsValue));
902 if (fNanoSecsValue > 0.0)
904 OUString aNS( ::rtl::math::doubleToUString( fValue,
907 if ( aNS.getLength() > 2 )
909 rBuffer.append(
'.');
910 rBuffer.append( aNS.subView(2) );
913 rBuffer.append(
'S');
921 bool bIsNegativeDuration =
false;
922 if (
'-' == (*pStr) )
924 bIsNegativeDuration =
true;
928 if ( *pStr !=
'P' && *pStr !=
'p' )
932 OUStringBuffer sDoubleStr;
933 bool bSuccess =
true;
935 bool bTimePart =
false;
936 bool bIsFraction =
false;
938 sal_Int32 nHours = 0;
943 while ( bSuccess && !bDone )
948 else if (
'0' <= c &&
'9' >= c )
961 sDoubleStr.append(c);
965 else if ( bTimePart )
967 if ( c ==
'H' || c ==
'h' )
972 else if ( c ==
'M' || c ==
'm')
977 else if ( (c ==
',') || (c ==
'.') )
984 else if ( c ==
'S' || c ==
's' )
998 if ( c ==
'T' || c ==
't' )
1000 else if ( c ==
'D' || c ==
'd')
1005 else if ( c ==
'Y' || c ==
'y' || c ==
'M' || c ==
'm' )
1009 OSL_FAIL(
"years or months in duration: not implemented");
1020 nHours += nDays * 24;
1021 double fHour = nHours;
1022 double fMin = nMins;
1023 double fSec = nSecs;
1025 double fTempTime = fHour / 24;
1026 fTempTime += fMin / (24 * 60);
1027 fTempTime += fSec / (24 * 60 * 60);
1028 fTempTime += fFraction / (24 * 60 * 60);
1031 if ( bIsNegativeDuration )
1033 fTempTime = -fTempTime;
1043 std::string_view rString)
1045 std::string_view aTrimmed =
o3tl::trim(rString);
1046 const char* pStr = aTrimmed.data();
1053 const ::util::Duration& rDuration)
1055 if (rDuration.Negative)
1057 rBuffer.append(
'-');
1059 rBuffer.append(
'P');
1060 const bool bHaveDate(rDuration.Years != 0 ||
1061 rDuration.Months != 0 ||
1062 rDuration.Days != 0);
1063 if (rDuration.Years)
1065 rBuffer.append(
static_cast<sal_Int32
>(rDuration.Years));
1066 rBuffer.append(
'Y');
1068 if (rDuration.Months)
1070 rBuffer.append(
static_cast<sal_Int32
>(rDuration.Months));
1071 rBuffer.append(
'M');
1075 rBuffer.append(
static_cast<sal_Int32
>(rDuration.Days));
1076 rBuffer.append(
'D');
1078 if ( rDuration.Hours != 0
1079 || rDuration.Minutes != 0
1080 || rDuration.Seconds != 0
1081 || rDuration.NanoSeconds != 0 )
1083 rBuffer.append(
'T');
1084 if (rDuration.Hours)
1086 rBuffer.append(
static_cast<sal_Int32
>(rDuration.Hours));
1087 rBuffer.append(
'H');
1089 if (rDuration.Minutes)
1091 rBuffer.append(
static_cast<sal_Int32
>(rDuration.Minutes));
1092 rBuffer.append(
'M');
1094 if (rDuration.Seconds != 0 || rDuration.NanoSeconds != 0)
1097 rBuffer.append(
static_cast<sal_Int32
>(rDuration.Seconds));
1098 if (rDuration.NanoSeconds)
1100 OSL_ENSURE(rDuration.NanoSeconds < 1000000000,
"NanoSeconds cannot be more than 999 999 999");
1101 rBuffer.append(
'.');
1102 std::ostringstream ostr;
1105 ostr << rDuration.NanoSeconds;
1106 rBuffer.appendAscii(ostr.str().c_str());
1108 rBuffer.append(
'S');
1111 else if (!bHaveDate)
1114 rBuffer.append(
'0');
1115 rBuffer.append(
'D');
1121enum Result { R_NOTHING, R_OVERFLOW, R_SUCCESS };
1125template <
typename V>
1128 size_t & io_rnPos, sal_Int32 & o_rNumber)
1130 size_t nPos(io_rnPos);
1132 while (
nPos < rString.size())
1134 const typename V::value_type c = rString[
nPos];
1135 if ((
'0' > c) || (c >
'9'))
1140 if (io_rnPos ==
nPos)
1152 return bOverflow ? R_OVERFLOW : R_SUCCESS;
1158 V rString,
size_t & io_rnPos,
1159 sal_Int32 & o_rNumber)
1161 bool bOverflow(
false);
1163 size_t nPos(io_rnPos);
1164 OSL_ENSURE(maxDigits >= 0,
"negative amount of digits makes no sense");
1166 while (
nPos < rString.size())
1169 if ((
'0' <= c) && (c <=
'9'))
1174 nTemp += (c -
u'0');
1189 if (io_rnPos ==
nPos)
1197 return bOverflow ? R_OVERFLOW : R_SUCCESS;
1204 if ((io_rnPos < rString.size()) &&
1205 (rString[io_rnPos] ==
'T' || rString[io_rnPos] ==
't'))
1216 size_t & io_rnPos, sal_Int32 & io_rnTemp,
bool & io_rbTimePart,
1219 if (io_rnPos < rString.size())
1221 if (cLower == rString[io_rnPos] || cUpper == rString[io_rnPos])
1224 if (-1 != io_rnTemp)
1226 o_rnTarget = io_rnTemp;
1232 return (R_OVERFLOW !=
1244template <
typename V>
1249 bool bIsNegativeDuration(
false);
1250 if (!
string.empty() && (
'-' ==
string[0]))
1252 bIsNegativeDuration =
true;
1257 &&
string[
nPos] !=
'P' &&
string[
nPos] !=
'p')
1265 sal_Int32 nTemp(-1);
1266 bool bTimePart(
false);
1267 bool bSuccess(
false);
1268 sal_Int32 nYears(0);
1269 sal_Int32 nMonths(0);
1271 sal_Int32 nHours(0);
1272 sal_Int32 nMinutes(0);
1273 sal_Int32 nSeconds(0);
1274 sal_Int32 nNanoSeconds(0);
1279 if (!bTimePart && bSuccess)
1285 if (!bTimePart && bSuccess)
1291 if (!bTimePart && bSuccess)
1313 nMinutes,
'm',
'M');
1317 if ((
nPos <
string.
size()) && bSuccess)
1319 if (
string[
nPos] ==
'.' ||
1320 string[
nPos] ==
',')
1327 const sal_Int32 nStart(
nPos);
1329 if ((
nPos <
string.
size()) && bSuccess)
1333 nNanoSeconds = nTemp;
1334 sal_Int32 nDigits =
nPos - nStart;
1335 assert(nDigits >= 0);
1336 for (; nDigits < 9; ++nDigits)
1341 if (
'S' ==
string[
nPos] ||
's' ==
string[
nPos])
1361 else if (
'S' ==
string[
nPos] ||
's' ==
string[
nPos])
1389 rDuration.Negative = bIsNegativeDuration;
1390 rDuration.Years =
static_cast<sal_Int16
>(nYears);
1391 rDuration.Months =
static_cast<sal_Int16
>(nMonths);
1392 rDuration.Days =
static_cast<sal_Int16
>(nDays);
1393 rDuration.Hours =
static_cast<sal_Int16
>(nHours);
1394 rDuration.Minutes =
static_cast<sal_Int16
>(nMinutes);
1395 rDuration.Seconds =
static_cast<sal_Int16
>(nSeconds);
1396 rDuration.NanoSeconds = nNanoSeconds;
1404 std::u16string_view rString)
1411 std::string_view rString)
1421 i_rBuffer.append(
'Z');
1427 i_rBuffer.append(
'+');
1431 i_rBuffer.append(
'-');
1433 const sal_Int32 nHours (
abs(nOffset) / 60);
1434 const sal_Int32 nMinutes(
abs(nOffset) % 60);
1435 SAL_WARN_IF(nHours > 14 || (nHours == 14 && nMinutes > 0),
1436 "sax",
"convertDateTime: timezone overflow");
1439 i_rBuffer.append(
'0');
1441 i_rBuffer.append(nHours);
1442 i_rBuffer.append(
':');
1445 i_rBuffer.append(
'0');
1447 i_rBuffer.append(nMinutes);
1453 OUStringBuffer& i_rBuffer,
1454 const util::Date& i_rDate,
1455 sal_Int16
const*
const pTimeZoneOffset)
1457 const util::DateTime dt(0, 0, 0, 0,
1458 i_rDate.Day, i_rDate.Month, i_rDate.Year,
false);
1463 OUStringBuffer& i_rBuffer,
1464 const css::util::DateTime& i_rDateTime)
1466 if (i_rDateTime.Hours < 10) {
1467 i_rBuffer.append(
'0');
1469 i_rBuffer.append( OUString::number(
static_cast<sal_Int32
>(i_rDateTime.Hours)) +
":");
1470 if (i_rDateTime.Minutes < 10) {
1471 i_rBuffer.append(
'0');
1473 i_rBuffer.append( OUString::number(
static_cast<sal_Int32
>(i_rDateTime.Minutes) ) +
":");
1474 if (i_rDateTime.Seconds < 10) {
1475 i_rBuffer.append(
'0');
1477 i_rBuffer.append(
static_cast<sal_Int32
>(i_rDateTime.Seconds) );
1478 if (i_rDateTime.NanoSeconds > 0) {
1479 OSL_ENSURE(i_rDateTime.NanoSeconds < 1000000000,
"NanoSeconds cannot be more than 999 999 999");
1480 i_rBuffer.append(
'.');
1481 std::ostringstream ostr;
1484 ostr << i_rDateTime.NanoSeconds;
1485 i_rBuffer.appendAscii(ostr.str().c_str());
1490 OUStringBuffer& i_rBuffer,
1491 const css::util::DateTime& i_rDateTime,
1492 sal_Int16
const* pTimeZoneOffset)
1494 if (pTimeZoneOffset)
1498 else if (i_rDateTime.IsUTC)
1506 OUStringBuffer& i_rBuffer,
1507 const css::util::DateTime& i_rDateTime)
1509 if (i_rDateTime.Year == 0 ||
1510 i_rDateTime.Month < 1 || i_rDateTime.Month > 12 ||
1511 i_rDateTime.Day < 1 || i_rDateTime.Day > 31)
1524 OUStringBuffer& i_rBuffer,
1525 const css::util::DateTime& i_rDateTime,
1526 sal_Int16
const*
const pTimeZoneOffset,
1527 bool i_bAddTimeIf0AM )
1532 sal_Int32
const nYear(
abs(i_rDateTime.Year));
1533 if (i_rDateTime.Year < 0) {
1534 i_rBuffer.append(dash);
1537 i_rBuffer.append(zero);
1540 i_rBuffer.append(zero);
1543 i_rBuffer.append(zero);
1545 i_rBuffer.append( OUString::number(nYear) + OUStringChar(dash) );
1546 if( i_rDateTime.Month < 10 ) {
1547 i_rBuffer.append(zero);
1549 i_rBuffer.append( OUString::number(i_rDateTime.Month) + OUStringChar(dash) );
1550 if( i_rDateTime.Day < 10 ) {
1551 i_rBuffer.append(zero);
1553 i_rBuffer.append(
static_cast<sal_Int32
>(i_rDateTime.Day) );
1555 if( i_rDateTime.Seconds != 0 ||
1556 i_rDateTime.Minutes != 0 ||
1557 i_rDateTime.Hours != 0 ||
1560 i_rBuffer.append(
'T');
1569 std::u16string_view rString )
1578 std::string_view rString )
1587 return ((nYear % 4) == 0)
1588 && (((nYear % 100) != 0) || ((nYear % 400) == 0));
1594 static const sal_uInt16 s_MaxDaysPerMonth[12] =
1595 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
1596 assert(0 < nMonth && nMonth <= 12);
1601 return s_MaxDaysPerMonth[nMonth - 1];
1605 sal_Int16 & o_rYear, sal_uInt16 & o_rMonth, sal_uInt16 & o_rDay,
1606 sal_uInt16 & o_rHours, sal_uInt16 & o_rMinutes,
1607 int const nSourceOffset)
1609 sal_Int16 nOffsetHours(
abs(nSourceOffset) / 60);
1610 sal_Int16
const nOffsetMinutes(
abs(nSourceOffset) % 60);
1611 o_rMinutes += nOffsetMinutes;
1612 if (nSourceOffset < 0)
1614 o_rMinutes += nOffsetMinutes;
1615 if (60 <= o_rMinutes)
1620 o_rHours += nOffsetHours;
1625 sal_Int16 nDayAdd(0);
1626 while (24 <= o_rHours)
1637 if (o_rDay <= nDaysInMonth)
1641 o_rDay -= nDaysInMonth;
1650 else if (0 < nSourceOffset)
1653 if (o_rMinutes < nOffsetMinutes)
1658 o_rMinutes -= nOffsetMinutes;
1659 sal_Int16 nDaySubtract(0);
1660 while (o_rHours < nOffsetHours)
1665 o_rHours -= nOffsetHours;
1670 if (nDaySubtract < o_rDay)
1672 o_rDay -= nDaySubtract;
1675 sal_Int16
const nPrevMonth((o_rMonth == 1) ? 12 : o_rMonth - 1);
1677 o_rDay += nDaysInMonth;
1684 o_rDay -= nDaySubtract;
1688template <
typename V>
1691 size_t & io_rnPos, sal_Int32 & o_rnTarget,
1692 const sal_Int32 nMinLength,
const bool bExactLength)
1694 const size_t nOldPos(io_rnPos);
1696 if (R_SUCCESS != readUnsignedNumber<V>(rString, io_rnPos, nTemp))
1700 const sal_Int32 nTokenLength(io_rnPos - nOldPos);
1701 if ((nTokenLength < nMinLength) ||
1702 (bExactLength && (nTokenLength > nMinLength)))
1714 sal_Int32 & nYear, sal_Int32 & nMonth, sal_Int32 & nDay,
1718 bool const bIgnoreInvalidOrMissingDate)
1720 bool bSuccess =
true;
1724 if (
'-' ==
string[
nPos])
1735 bSuccess = readDateTimeComponent<V>(
string,
nPos, nYear, 1,
false);
1736 if (!bIgnoreInvalidOrMissingDate)
1738 bSuccess &= (0 < nYear);
1740 bSuccess &= (
nPos <
string.size());
1742 if (bSuccess && (
'-' !=
string[
nPos]))
1750 bSuccess = readDateTimeComponent<V>(
string,
nPos, nMonth, 2,
true);
1751 if (!bIgnoreInvalidOrMissingDate)
1753 bSuccess &= (0 < nMonth);
1755 bSuccess &= (nMonth <= 12);
1756 bSuccess &= (
nPos <
string.size());
1758 if (bSuccess && (
'-' !=
string[
nPos]))
1767 if (!bIgnoreInvalidOrMissingDate)
1769 bSuccess &= (0 < nDay);
1775 else assert(bIgnoreInvalidOrMissingDate);
1778 if (bSuccess && (
nPos <
string.
size()))
1780 if (
'T' ==
string[
nPos] ||
't' ==
string[
nPos])
1791template <
typename V>
1793 util::Date *
const pDate, util::DateTime & rDateTime,
1795 std::optional<sal_Int16> *
const pTimeZoneOffset,
1797 bool const bIgnoreInvalidOrMissingDate)
1799 bool bSuccess =
true;
1803 bool isNegative(
false);
1805 sal_Int32 nMonth(0);
1808 bool bHaveTime(
false);
1810 if ( !bIgnoreInvalidOrMissingDate
1811 ||
string.
find(
':') == V::npos
1812 || (
string.
find(
'-') != V::npos
1813 &&
string.
find(
'-') <
string.
find(
':')))
1815 bSuccess &= lcl_parseDate<V>(isNegative, nYear, nMonth, nDay,
1816 bHaveTime,
nPos,
string, bIgnoreInvalidOrMissingDate);
1823 sal_Int32 nHours(0);
1824 sal_Int32 nMinutes(0);
1825 sal_Int32 nSeconds(0);
1826 sal_Int32 nNanoSeconds(0);
1827 if (bSuccess && bHaveTime)
1831 bSuccess &= (0 <= nHours) && (nHours <= 24);
1832 bSuccess &= (
nPos <
string.size());
1834 if (bSuccess && (
':' !=
string[
nPos]))
1843 bSuccess &= (0 <= nMinutes) && (nMinutes < 60);
1844 bSuccess &= (
nPos <
string.size());
1846 if (bSuccess && (
':' !=
string[
nPos]))
1855 bSuccess &= (0 <= nSeconds) && (nSeconds < 60);
1857 if (bSuccess && (
nPos <
string.
size()) &&
1858 (
'.' ==
string[
nPos] ||
',' ==
string[
nPos]))
1861 const sal_Int32 nStart(
nPos);
1863 if (R_NOTHING == readUnsignedNumberMaxDigits<V>(9,
string,
nPos, nTemp))
1869 sal_Int32 nDigits = std::min<sal_Int32>(
nPos - nStart, 9);
1870 assert(nDigits > 0);
1871 for (; nDigits < 9; ++nDigits)
1875 nNanoSeconds = nTemp;
1879 if (bSuccess && (nHours == 24))
1881 if (!((0 == nMinutes) && (0 == nSeconds) && (0 == nNanoSeconds)))
1888 bool bHaveTimezone(
false);
1889 bool bHaveTimezonePlus(
false);
1890 bool bHaveTimezoneMinus(
false);
1891 if (bSuccess && (
nPos <
string.
size()))
1896 bHaveTimezone =
true;
1897 bHaveTimezonePlus =
true;
1902 bHaveTimezone =
true;
1903 bHaveTimezoneMinus =
true;
1906 else if (
'Z' == c ||
'z' == c)
1908 bHaveTimezone =
true;
1916 sal_Int32 nTimezoneHours(0);
1917 sal_Int32 nTimezoneMinutes(0);
1918 if (bSuccess && (bHaveTimezonePlus || bHaveTimezoneMinus))
1920 bSuccess = readDateTimeComponent<V>(
1921 string,
nPos, nTimezoneHours, 2,
true);
1922 bSuccess &= (0 <= nTimezoneHours) && (nTimezoneHours <= 14);
1923 bSuccess &= (
nPos <
string.size());
1924 if (bSuccess && (
':' !=
string[
nPos]))
1932 bSuccess = readDateTimeComponent<V>(
1933 string,
nPos, nTimezoneMinutes, 2,
true);
1934 bSuccess &= (0 <= nTimezoneMinutes) && (nTimezoneMinutes < 60);
1936 if (bSuccess && (nTimezoneHours == 14))
1938 if (0 != nTimezoneMinutes)
1945 bSuccess &= (
nPos ==
string.size());
1949 sal_Int16
const nTimezoneOffset = (bHaveTimezoneMinus ? -1 : +1)
1950 * ((nTimezoneHours * 60) + nTimezoneMinutes);
1951 if (!pDate || bHaveTime)
1954 (isNegative ? -1 : +1) *
static_cast<sal_Int16
>(nYear);
1955 rDateTime.Month =
static_cast<sal_uInt16
>(nMonth);
1956 rDateTime.Day =
static_cast<sal_uInt16
>(nDay);
1957 rDateTime.Hours =
static_cast<sal_uInt16
>(nHours);
1958 rDateTime.Minutes =
static_cast<sal_uInt16
>(nMinutes);
1959 rDateTime.Seconds =
static_cast<sal_uInt16
>(nSeconds);
1960 rDateTime.NanoSeconds =
static_cast<sal_uInt32
>(nNanoSeconds);
1963 if (pTimeZoneOffset)
1965 *pTimeZoneOffset = nTimezoneOffset;
1966 rDateTime.IsUTC = (0 == nTimezoneOffset);
1971 rDateTime.Day, rDateTime.Hours, rDateTime.Minutes,
1973 rDateTime.IsUTC =
true;
1978 if (pTimeZoneOffset)
1980 pTimeZoneOffset->reset();
1982 rDateTime.IsUTC =
false;
1984 rbDateTime = bHaveTime;
1989 (isNegative ? -1 : +1) *
static_cast<sal_Int16
>(nYear);
1990 pDate->Month =
static_cast<sal_uInt16
>(nMonth);
1991 pDate->Day =
static_cast<sal_uInt16
>(nDay);
1994 if (pTimeZoneOffset)
1996 *pTimeZoneOffset = nTimezoneOffset;
2001 SAL_INFO(
"sax",
"dropping timezone");
2006 if (pTimeZoneOffset)
2008 pTimeZoneOffset->reset();
2019 util::DateTime & rDateTime,
2020 std::u16string_view rString)
2024 nullptr, rDateTime, dummy,
nullptr, rString,
true);
2029 util::DateTime & rDateTime,
2030 std::string_view rString)
2034 nullptr, rDateTime, dummy,
nullptr, rString,
true);
2039 util::Date *
const pDate, util::DateTime & rDateTime,
2041 std::optional<sal_Int16> *
const pTimeZoneOffset,
2042 std::u16string_view rString )
2045 pDate, rDateTime, rbDateTime, pTimeZoneOffset, rString,
false);
2050 util::Date *
const pDate, util::DateTime & rDateTime,
2052 std::optional<sal_Int16> *
const pTimeZoneOffset,
2053 std::string_view rString )
2056 pDate, rDateTime, rbDateTime, pTimeZoneOffset, rString,
false);
2065 sal_Int32 nLen = rStr.size();
2074 else if(
'\'' == cQuote )
2081 else if(
'\"' == cQuote )
2097 double fRetval(1.0);
2101 if(nSourceUnit != nTargetUnit)
2103 const o3tl::Length eFrom = Measure2O3tlUnit(nSourceUnit);
2104 const o3tl::Length eTo = Measure2O3tlUnit(nTargetUnit);
2107 if (
const auto sUnit = Measure2UnitString(nTargetUnit); sUnit.size() > 0)
2108 rUnit.appendAscii(sUnit.data(), sUnit.size());
2116 double fRetval(1.0);
2120 if(nSourceUnit != nTargetUnit)
2122 const o3tl::Length eFrom = Measure2O3tlUnit(nSourceUnit);
2123 const o3tl::Length eTo = Measure2O3tlUnit(nTargetUnit);
2126 if (
const auto sUnit = Measure2UnitString(nTargetUnit); sUnit.size() > 0)
2127 rUnit.append(sUnit.data(), sUnit.size());
2137 sal_Int32 nLen = rString.size();
2138 sal_Int16 nRetUnit = nDefaultUnit;
2141 while(
nPos < nLen &&
' ' == rString[
nPos] )
2145 if(
nPos < nLen &&
'-' == rString[
nPos] )
2149 while(
nPos < nLen &&
'0' <= rString[
nPos] &&
'9' >= rString[
nPos] )
2152 if(
nPos < nLen &&
'.' == rString[
nPos] )
2155 while(
nPos < nLen &&
'0' <= rString[
nPos] &&
'9' >= rString[
nPos] )
2160 while(
nPos < nLen &&
' ' == rString[
nPos] )
2165 switch(rString[
nPos])
2169 nRetUnit = MeasureUnit::PERCENT;
2175 if(
nPos+1 < nLen && (rString[
nPos+1] ==
'm'
2176 || rString[
nPos+1] ==
'M'))
2177 nRetUnit = MeasureUnit::CM;
2189 if(
nPos+1 < nLen && (rString[
nPos+1] ==
'n'
2190 || rString[
nPos+1] ==
'N'))
2191 nRetUnit = MeasureUnit::INCH;
2197 if(
nPos+1 < nLen && (rString[
nPos+1] ==
'm'
2198 || rString[
nPos+1] ==
'M'))
2199 nRetUnit = MeasureUnit::MM;
2205 if(
nPos+1 < nLen && (rString[
nPos+1] ==
't'
2206 || rString[
nPos+1] ==
'T'))
2207 nRetUnit = MeasureUnit::POINT;
2208 if(
nPos+1 < nLen && (rString[
nPos+1] ==
'c'
2209 || rString[
nPos+1] ==
'C'))
2210 nRetUnit = MeasureUnit::TWIP;
2229 OUStringBuffer& rsType ,
2230 const css::uno::Any& rValue)
2232 bool bConverted =
false;
2234 rsValue.setLength(0);
2235 rsType.setLength (0);
2237 switch (rValue.getValueTypeClass())
2239 case css::uno::TypeClass_BYTE :
2240 case css::uno::TypeClass_SHORT :
2241 case css::uno::TypeClass_UNSIGNED_SHORT :
2242 case css::uno::TypeClass_LONG :
2243 case css::uno::TypeClass_UNSIGNED_LONG :
2245 sal_Int32 nTempValue = 0;
2246 if (rValue >>= nTempValue)
2248 rsType.append(
"integer");
2250 rsValue.append(nTempValue);
2255 case css::uno::TypeClass_BOOLEAN :
2257 bool bTempValue =
false;
2258 if (rValue >>= bTempValue)
2260 rsType.append(
"boolean");
2267 case css::uno::TypeClass_FLOAT :
2268 case css::uno::TypeClass_DOUBLE :
2270 double fTempValue = 0.0;
2271 if (rValue >>= fTempValue)
2273 rsType.append(
"float");
2280 case css::uno::TypeClass_STRING :
2282 OUString sTempValue;
2283 if (rValue >>= sTempValue)
2285 rsType.append(
"string");
2287 rsValue.append(sTempValue);
2292 case css::uno::TypeClass_STRUCT :
2294 css::util::Date aDate ;
2295 css::util::Time aTime ;
2296 css::util::DateTime aDateTime;
2298 if (rValue >>= aDate)
2300 rsType.append(
"date");
2302 css::util::DateTime aTempValue;
2303 aTempValue.Day = aDate.Day;
2304 aTempValue.Month = aDate.Month;
2305 aTempValue.Year = aDate.Year;
2306 aTempValue.NanoSeconds = 0;
2307 aTempValue.Seconds = 0;
2308 aTempValue.Minutes = 0;
2309 aTempValue.Hours = 0;
2313 if (rValue >>= aTime)
2315 rsType.append(
"time");
2317 css::util::Duration aTempValue;
2318 aTempValue.Days = 0;
2319 aTempValue.Months = 0;
2320 aTempValue.Years = 0;
2321 aTempValue.NanoSeconds = aTime.NanoSeconds;
2322 aTempValue.Seconds = aTime.Seconds;
2323 aTempValue.Minutes = aTime.Minutes;
2324 aTempValue.Hours = aTime.Hours;
2328 if (rValue >>= aDateTime)
2330 rsType.append(
"date");
2346 rBuffer.setLength(0);
2347 rBuffer.ensureCapacity(nBytes * 2);
2348 auto pChars =
static_cast<const unsigned char*
>(pBytes);
2349 for (sal_Int32
i = 0;
i < nBytes; ++
i)
2351 sal_Int32 c = *pChars++;
2353 rBuffer.append(
'0');
2354 rBuffer.append(c, 16);
static bool parseTimeOrDateTime(css::util::DateTime &rDateTime, std::u16string_view rString)
convert XMLSchema-2 "time" or "dateTime" string to util::DateTime
static void convertDateTime(OUStringBuffer &rBuffer, const css::util::DateTime &rDateTime, sal_Int16 const *pTimeZoneOffset, bool bAddTimeIf0AM=false)
convert util::DateTime to XMLSchema-2 "date" or "dateTime" string
static void convertDouble(OUStringBuffer &rBuffer, double fNumber, bool bWriteUnits, sal_Int16 nSourceUnit, sal_Int16 nTargetUnit)
convert double number to string (using ::rtl::math) and DO convert from source unit to target unit
static bool convertMeasure(sal_Int32 &rValue, std::u16string_view rString, sal_Int16 nTargetUnit=css::util::MeasureUnit::MM_100TH, sal_Int32 nMin=SAL_MIN_INT32, sal_Int32 nMax=SAL_MAX_INT32)
convert string to measure using optional min and max values
static bool convertMeasurePx(sal_Int32 &rValue, std::u16string_view rString)
convert string to pixel measure unit
static bool convertPercent(sal_Int32 &rValue, std::u16string_view rString)
convert string to percent
static bool convertColor(sal_Int32 &rColor, std::u16string_view rValue)
convert string to rgb color
static void convertDuration(OUStringBuffer &rBuffer, const double fTime)
convert double to XMLSchema-2 "duration" string; negative durations allowed
static void convertTimeOrDateTime(OUStringBuffer &rBuffer, const css::util::DateTime &rDateTime)
convert util::DateTime to XMLSchema-2 "time" or "dateTime" string
static double GetConversionFactor(OUStringBuffer &rUnit, sal_Int16 nSourceUnit, sal_Int16 nTargetUnit)
static bool parseDateTime(css::util::DateTime &rDateTime, std::u16string_view rString)
convert XMLSchema-2 "date" or "dateTime" string to util::DateTime
static void convertBytesToHexBinary(OUStringBuffer &rBuffer, const void *pBytes, sal_Int32 nBytes)
convert specified byte sequence to xsd:hexBinary string
static sal_Int16 GetUnitFromString(std::u16string_view rString, sal_Int16 nDefaultUnit)
static bool convertNumber64(sal_Int64 &rValue, std::u16string_view aString, sal_Int64 nMin=SAL_MIN_INT64, sal_Int64 nMax=SAL_MAX_INT64)
convert string to number with optional min and max values
static bool parseDateOrDateTime(css::util::Date *pDate, css::util::DateTime &rDateTime, bool &rbDateTime, std::optional< sal_Int16 > *pTimeZoneOffset, std::u16string_view rString)
convert XMLSchema-2 "date" or "dateTime" string to util::DateTime or util::Date
static void convertAngle(OUStringBuffer &rBuffer, sal_Int16 nAngle, SvtSaveOptions::ODFSaneDefaultVersion nVersion)
convert number, 10th of degrees with range [0..3600] to SVG angle
static void convertDate(OUStringBuffer &rBuffer, const css::util::Date &rDate, sal_Int16 const *pTimeZoneOffset)
convert util::Date to XMLSchema-2 "date" string
static bool convertNumber(sal_Int32 &rValue, std::u16string_view aString, sal_Int32 nMin=SAL_MIN_INT32, sal_Int32 nMax=SAL_MAX_INT32)
convert string to number with optional min and max values
static sal_Int32 indexOfComma(std::u16string_view rStr, sal_Int32 nPos)
gets the position of the first comma after npos in the string rStr.
static bool convertBool(bool &rBool, std::u16string_view rString)
convert string to boolean
static bool convertAny(OUStringBuffer &rsValue, OUStringBuffer &rsType, const css::uno::Any &rValue)
convert an Any to string (typesafe)
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
OSQLColumns::const_iterator find(const OSQLColumns::const_iterator &first, const OSQLColumns::const_iterator &last, std::u16string_view _rVal, const ::comphelper::UStringMixEqual &_rCase)
std::basic_string_view< charT, traits > trim(std::basic_string_view< charT, traits > str)
constexpr Point convert(const Point &rPoint, o3tl::Length eFrom, o3tl::Length eTo)
double toDouble(std::u16string_view str)
static bool lcl_parseDate(bool &isNegative, sal_Int32 &nYear, sal_Int32 &nMonth, sal_Int32 &nDay, bool &bHaveTime, size_t &nPos, V string, bool const bIgnoreInvalidOrMissingDate)
convert ISO "date" or "dateTime" string to util::DateTime or util::Date
static sal_uInt16 lcl_MaxDaysPerMonth(const sal_Int32 nMonth, const sal_Int32 nYear)
static bool lcl_isLeapYear(const sal_uInt32 nYear)
const std::string_view gpsINCH
static Result readUnsignedNumber(V rString, size_t &io_rnPos, sal_Int32 &o_rNumber)
static int lcl_gethex(int nChar)
static bool convertDurationHelper(double &rfTime, V pStr)
helper function of Converter::convertDuration
static bool lcl_convertNumber64(sal_Int64 &rValue, V aString, sal_Int64 nMin, sal_Int64 nMax)
convert string to 64-bit number with optional min and max values
static bool lcl_parseDateTime(util::Date *const pDate, util::DateTime &rDateTime, bool &rbDateTime, std::optional< sal_Int16 > *const pTimeZoneOffset, V string, bool const bIgnoreInvalidOrMissingDate)
convert ISO "date" or "dateTime" string to util::DateTime or util::Date
static sal_Int16 lcl_GetUnitFromString(V rString, sal_Int16 nDefaultUnit)
static void convertTime(OUStringBuffer &i_rBuffer, const css::util::DateTime &i_rDateTime)
static sal_Int64 toInt64_WithLength(const sal_Unicode *str, sal_Int16 radix, sal_Int32 nStrLength)
static void lcl_ConvertToUTC(sal_Int16 &o_rYear, sal_uInt16 &o_rMonth, sal_uInt16 &o_rDay, sal_uInt16 &o_rHours, sal_uInt16 &o_rMinutes, int const nSourceOffset)
static Result readUnsignedNumberMaxDigits(int maxDigits, V rString, size_t &io_rnPos, sal_Int32 &o_rNumber)
const std::string_view gpsMM
const sal_Int8 XML_MAXDIGITSCOUNT_TIME
static bool readDateTimeComponent(V rString, size_t &io_rnPos, sal_Int32 &o_rnTarget, const sal_Int32 nMinLength, const bool bExactLength)
const std::string_view gpsPT
static void convertTimeZone(OUStringBuffer &i_rBuffer, const css::util::DateTime &i_rDateTime, sal_Int16 const *pTimeZoneOffset)
const std::string_view gpsPC
static bool readDurationT(V rString, size_t &io_rnPos)
static bool readDurationComponent(V rString, size_t &io_rnPos, sal_Int32 &io_rnTemp, bool &io_rbTimePart, sal_Int32 &o_rnTarget, const sal_Unicode cLower, const sal_Unicode cUpper)
static void lcl_AppendTimezone(OUStringBuffer &i_rBuffer, int const nOffset)
const std::string_view gpsCM
static bool lcl_convertColor(sal_Int32 &rColor, V rValue)
convert string to rgb color
static bool lcl_convertMeasure(sal_Int32 &rValue, V rString, sal_Int16 nTargetUnit, sal_Int32 nMin, sal_Int32 nMax)
convert string to measure using optional min and max values
SwNodeOffset abs(const SwNodeOffset &a)