From 6214ce98801c1f7a226781701ed290079b2a4031 Mon Sep 17 00:00:00 2001 From: Lei Zhang Date: Wed, 1 Aug 2018 17:45:17 +0000 Subject: Encapsulate some public static methods in CFXJSE_FormCalcContext. They are only used inside CFXJSE_FormCalcContext. Move into an anonymous namespace. Change-Id: Ib8a0ff9b90cf951459c04655bedada3bdb1979a4 Reviewed-on: https://pdfium-review.googlesource.com/39090 Commit-Queue: Lei Zhang Reviewed-by: Henrique Nakashima --- fxjs/cfxjse_formcalc_context.cpp | 4403 +++++++++++++++++++------------------- fxjs/cfxjse_formcalc_context.h | 37 - 2 files changed, 2191 insertions(+), 2249 deletions(-) (limited to 'fxjs') diff --git a/fxjs/cfxjse_formcalc_context.cpp b/fxjs/cfxjse_formcalc_context.cpp index 2b3db830c0..b2fa9707b1 100644 --- a/fxjs/cfxjse_formcalc_context.cpp +++ b/fxjs/cfxjse_formcalc_context.cpp @@ -622,611 +622,1530 @@ double ByteStringToDouble(const ByteStringView& szStringVal) { return dValue; } -} // namespace - -const FXJSE_CLASS_DESCRIPTOR kFormCalcFM2JSDescriptor = { - kClassTag, // tag - "XFA_FM2JS_FormCalcClass", // name - kFormCalcFM2JSFunctions, // methods - FX_ArraySize(kFormCalcFM2JSFunctions), // number of methods - nullptr, // dynamic prop type - nullptr, // dynamic prop getter - nullptr, // dynamic prop setter - nullptr, // dynamic prop method call -}; - -// static -void CFXJSE_FormCalcContext::Abs(CFXJSE_Value* pThis, - const ByteStringView& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 1) { - ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"Abs"); - return; - } - - std::unique_ptr argOne = args.GetValue(0); - if (ValueIsNull(pThis, argOne.get())) { - args.GetReturnValue()->SetNull(); - return; - } +bool IsIsoDateFormat(const char* pData, + int32_t iLength, + int32_t& iStyle, + int32_t& iYear, + int32_t& iMonth, + int32_t& iDay) { + iYear = 0; + iMonth = 1; + iDay = 1; - double dValue = ValueToDouble(pThis, argOne.get()); - if (dValue < 0) - dValue = -dValue; + if (iLength < 4) + return false; - args.GetReturnValue()->SetDouble(dValue); -} + char strYear[5]; + strYear[4] = '\0'; + for (int32_t i = 0; i < 4; ++i) { + if (!std::isdigit(pData[i])) + return false; -// static -void CFXJSE_FormCalcContext::Avg(CFXJSE_Value* pThis, - const ByteStringView& szFuncName, - CFXJSE_Arguments& args) { - int32_t argc = args.GetLength(); - if (argc < 1) { - args.GetReturnValue()->SetNull(); - return; + strYear[i] = pData[i]; } + iYear = FXSYS_atoi(strYear); + iStyle = 0; + if (iLength == 4) + return true; - v8::Isolate* pIsolate = ToFormCalcContext(pThis)->GetScriptRuntime(); - uint32_t uCount = 0; - double dSum = 0.0; - for (int32_t i = 0; i < argc; i++) { - std::unique_ptr argValue = args.GetValue(i); - if (argValue->IsNull()) - continue; - - if (!argValue->IsArray()) { - dSum += ValueToDouble(pThis, argValue.get()); - uCount++; - continue; - } + iStyle = pData[4] == '-' ? 1 : 0; - auto lengthValue = pdfium::MakeUnique(pIsolate); - argValue->GetObjectProperty("length", lengthValue.get()); - int32_t iLength = lengthValue->ToInteger(); + char strTemp[3]; + strTemp[2] = '\0'; + int32_t iPosOff = iStyle == 0 ? 4 : 5; + if (!std::isdigit(pData[iPosOff]) || !std::isdigit(pData[iPosOff + 1])) + return false; - if (iLength > 2) { - auto propertyValue = pdfium::MakeUnique(pIsolate); - argValue->GetObjectPropertyByIdx(1, propertyValue.get()); + strTemp[0] = pData[iPosOff]; + strTemp[1] = pData[iPosOff + 1]; + iMonth = FXSYS_atoi(strTemp); + if (iMonth > 12 || iMonth < 1) + return false; - auto jsObjectValue = pdfium::MakeUnique(pIsolate); - if (propertyValue->IsNull()) { - for (int32_t j = 2; j < iLength; j++) { - argValue->GetObjectPropertyByIdx(j, jsObjectValue.get()); - auto defaultPropValue = pdfium::MakeUnique(pIsolate); - GetObjectDefaultValue(jsObjectValue.get(), defaultPropValue.get()); - if (defaultPropValue->IsNull()) - continue; + if (iStyle == 0) { + iPosOff += 2; + if (iLength == 6) + return true; + } else { + iPosOff += 3; + if (iLength == 7) + return true; + } + if (!std::isdigit(pData[iPosOff]) || !std::isdigit(pData[iPosOff + 1])) + return false; - dSum += ValueToDouble(pThis, defaultPropValue.get()); - uCount++; - } - } else { - for (int32_t j = 2; j < iLength; j++) { - argValue->GetObjectPropertyByIdx(j, jsObjectValue.get()); - auto newPropertyValue = pdfium::MakeUnique(pIsolate); - jsObjectValue->GetObjectProperty( - propertyValue->ToString().AsStringView(), newPropertyValue.get()); - if (newPropertyValue->IsNull()) - continue; + strTemp[0] = pData[iPosOff]; + strTemp[1] = pData[iPosOff + 1]; + iDay = FXSYS_atoi(strTemp); + if (iPosOff + 2 < iLength) + return false; - dSum += ValueToDouble(pThis, newPropertyValue.get()); - uCount++; - } - } - } + if ((!(iYear % 4) && (iYear % 100)) || !(iYear % 400)) { + if (iMonth == 2 && iDay > 29) + return false; + } else { + if (iMonth == 2 && iDay > 28) + return false; } - if (uCount == 0) { - args.GetReturnValue()->SetNull(); - return; + if (iMonth != 2) { + if (iMonth < 8) { + if (iDay > (iMonth % 2 == 0 ? 30 : 31)) + return false; + } else if (iDay > (iMonth % 2 == 0 ? 31 : 30)) { + return false; + } } - - args.GetReturnValue()->SetDouble(dSum / uCount); + return true; } -// static -void CFXJSE_FormCalcContext::Ceil(CFXJSE_Value* pThis, - const ByteStringView& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 1) { - ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"Ceil"); - return; - } +bool IsIsoTimeFormat(const char* pData, + int32_t iLength, + int32_t& iHour, + int32_t& iMinute, + int32_t& iSecond, + int32_t& iMilliSecond, + int32_t& iZoneHour, + int32_t& iZoneMinute) { + iHour = 0; + iMinute = 0; + iSecond = 0; + iMilliSecond = 0; + iZoneHour = 0; + iZoneMinute = 0; + if (!pData) + return false; - std::unique_ptr argValue = GetSimpleValue(pThis, args, 0); - if (ValueIsNull(pThis, argValue.get())) { - args.GetReturnValue()->SetNull(); - return; + char strTemp[3]; + strTemp[2] = '\0'; + int32_t iZone = 0; + int32_t i = 0; + while (i < iLength) { + if (!std::isdigit(pData[i]) && pData[i] != ':') { + iZone = i; + break; + } + ++i; } + if (i == iLength) + iZone = iLength; - args.GetReturnValue()->SetFloat(ceil(ValueToFloat(pThis, argValue.get()))); -} - -// static -void CFXJSE_FormCalcContext::Count(CFXJSE_Value* pThis, - const ByteStringView& szFuncName, - CFXJSE_Arguments& args) { - CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis); - v8::Isolate* pIsolate = pContext->GetScriptRuntime(); - int32_t iCount = 0; - for (int32_t i = 0; i < args.GetLength(); i++) { - std::unique_ptr argValue = args.GetValue(i); - if (argValue->IsNull()) - continue; + int32_t iPos = 0; + int32_t iIndex = 0; + while (iIndex < iZone) { + if (!std::isdigit(pData[iIndex])) + return false; - if (argValue->IsArray()) { - auto lengthValue = pdfium::MakeUnique(pIsolate); - argValue->GetObjectProperty("length", lengthValue.get()); + strTemp[0] = pData[iIndex]; + if (!std::isdigit(pData[iIndex + 1])) + return false; - int32_t iLength = lengthValue->ToInteger(); - if (iLength <= 2) { - pContext->ThrowArgumentMismatchException(); - return; - } + strTemp[1] = pData[iIndex + 1]; + if (FXSYS_atoi(strTemp) > 60) + return false; - auto propertyValue = pdfium::MakeUnique(pIsolate); - auto jsObjectValue = pdfium::MakeUnique(pIsolate); - auto newPropertyValue = pdfium::MakeUnique(pIsolate); - argValue->GetObjectPropertyByIdx(1, propertyValue.get()); - argValue->GetObjectPropertyByIdx(2, jsObjectValue.get()); - if (propertyValue->IsNull()) { - for (int32_t j = 2; j < iLength; j++) { - argValue->GetObjectPropertyByIdx(j, jsObjectValue.get()); - GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get()); - if (!newPropertyValue->IsNull()) - iCount++; - } + if (pData[2] == ':') { + if (iPos == 0) { + iHour = FXSYS_atoi(strTemp); + ++iPos; + } else if (iPos == 1) { + iMinute = FXSYS_atoi(strTemp); + ++iPos; } else { - for (int32_t j = 2; j < iLength; j++) { - argValue->GetObjectPropertyByIdx(j, jsObjectValue.get()); - jsObjectValue->GetObjectProperty( - propertyValue->ToString().AsStringView(), newPropertyValue.get()); - iCount += newPropertyValue->IsNull() ? 0 : 1; - } + iSecond = FXSYS_atoi(strTemp); } - } else if (argValue->IsObject()) { - auto newPropertyValue = pdfium::MakeUnique(pIsolate); - GetObjectDefaultValue(argValue.get(), newPropertyValue.get()); - if (!newPropertyValue->IsNull()) - iCount++; + iIndex += 3; } else { - iCount++; + if (iPos == 0) { + iHour = FXSYS_atoi(strTemp); + ++iPos; + } else if (iPos == 1) { + iMinute = FXSYS_atoi(strTemp); + ++iPos; + } else if (iPos == 2) { + iSecond = FXSYS_atoi(strTemp); + ++iPos; + } + iIndex += 2; } } - args.GetReturnValue()->SetInteger(iCount); -} -// static -void CFXJSE_FormCalcContext::Floor(CFXJSE_Value* pThis, - const ByteStringView& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 1) { - ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"Floor"); - return; - } + if (iIndex < iLength && pData[iIndex] == '.') { + constexpr int kSubSecondLength = 3; + if (iIndex + kSubSecondLength >= iLength) + return false; - std::unique_ptr argValue = GetSimpleValue(pThis, args, 0); - if (ValueIsNull(pThis, argValue.get())) { - args.GetReturnValue()->SetNull(); - return; - } + ++iIndex; + char strSec[kSubSecondLength + 1]; + for (int i = 0; i < kSubSecondLength; ++i) { + char c = pData[iIndex + i]; + if (!std::isdigit(c)) + return false; + strSec[i] = c; + } + strSec[kSubSecondLength] = '\0'; - args.GetReturnValue()->SetFloat(floor(ValueToFloat(pThis, argValue.get()))); -} + iMilliSecond = FXSYS_atoi(strSec); + if (iMilliSecond > 100) { + iMilliSecond = 0; + return false; + } + iIndex += kSubSecondLength; + } -// static -void CFXJSE_FormCalcContext::Max(CFXJSE_Value* pThis, - const ByteStringView& szFuncName, - CFXJSE_Arguments& args) { - CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis); - v8::Isolate* pIsolate = pContext->GetScriptRuntime(); - uint32_t uCount = 0; - double dMaxValue = 0.0; - for (int32_t i = 0; i < args.GetLength(); i++) { - std::unique_ptr argValue = args.GetValue(i); - if (argValue->IsNull()) - continue; + if (iIndex < iLength && FXSYS_towlower(pData[iIndex]) == 'z') + return true; - if (argValue->IsArray()) { - auto lengthValue = pdfium::MakeUnique(pIsolate); - argValue->GetObjectProperty("length", lengthValue.get()); - int32_t iLength = lengthValue->ToInteger(); - if (iLength <= 2) { - pContext->ThrowArgumentMismatchException(); - return; - } + int32_t iSign = 1; + if (iIndex < iLength) { + if (pData[iIndex] == '+') { + ++iIndex; + } else if (pData[iIndex] == '-') { + iSign = -1; + ++iIndex; + } + } + iPos = 0; + while (iIndex < iLength) { + if (!std::isdigit(pData[iIndex])) + return false; - auto propertyValue = pdfium::MakeUnique(pIsolate); - auto jsObjectValue = pdfium::MakeUnique(pIsolate); - auto newPropertyValue = pdfium::MakeUnique(pIsolate); - argValue->GetObjectPropertyByIdx(1, propertyValue.get()); - argValue->GetObjectPropertyByIdx(2, jsObjectValue.get()); - if (propertyValue->IsNull()) { - for (int32_t j = 2; j < iLength; j++) { - argValue->GetObjectPropertyByIdx(j, jsObjectValue.get()); - GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get()); - if (newPropertyValue->IsNull()) - continue; + strTemp[0] = pData[iIndex]; + if (!std::isdigit(pData[iIndex + 1])) + return false; - uCount++; - double dValue = ValueToDouble(pThis, newPropertyValue.get()); - dMaxValue = (uCount == 1) ? dValue : std::max(dMaxValue, dValue); - } - } else { - for (int32_t j = 2; j < iLength; j++) { - argValue->GetObjectPropertyByIdx(j, jsObjectValue.get()); - jsObjectValue->GetObjectProperty( - propertyValue->ToString().AsStringView(), newPropertyValue.get()); - if (newPropertyValue->IsNull()) - continue; + strTemp[1] = pData[iIndex + 1]; + if (FXSYS_atoi(strTemp) > 60) + return false; - uCount++; - double dValue = ValueToDouble(pThis, newPropertyValue.get()); - dMaxValue = (uCount == 1) ? dValue : std::max(dMaxValue, dValue); - } + if (pData[2] == ':') { + if (iPos == 0) { + iZoneHour = FXSYS_atoi(strTemp); + } else if (iPos == 1) { + iZoneMinute = FXSYS_atoi(strTemp); } - } else if (argValue->IsObject()) { - auto newPropertyValue = pdfium::MakeUnique(pIsolate); - GetObjectDefaultValue(argValue.get(), newPropertyValue.get()); - if (newPropertyValue->IsNull()) - continue; - - uCount++; - double dValue = ValueToDouble(pThis, newPropertyValue.get()); - dMaxValue = (uCount == 1) ? dValue : std::max(dMaxValue, dValue); + iIndex += 3; } else { - uCount++; - double dValue = ValueToDouble(pThis, argValue.get()); - dMaxValue = (uCount == 1) ? dValue : std::max(dMaxValue, dValue); + if (!iPos) { + iZoneHour = FXSYS_atoi(strTemp); + ++iPos; + } else if (iPos == 1) { + iZoneMinute = FXSYS_atoi(strTemp); + ++iPos; + } + iIndex += 2; } } - if (uCount == 0) { - args.GetReturnValue()->SetNull(); - return; - } + if (iIndex < iLength) + return false; - args.GetReturnValue()->SetDouble(dMaxValue); + iZoneHour *= iSign; + return true; } -// static -void CFXJSE_FormCalcContext::Min(CFXJSE_Value* pThis, - const ByteStringView& szFuncName, - CFXJSE_Arguments& args) { - CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis); - v8::Isolate* pIsolate = pContext->GetScriptRuntime(); - uint32_t uCount = 0; - double dMinValue = 0.0; - for (int32_t i = 0; i < args.GetLength(); i++) { - std::unique_ptr argValue = args.GetValue(i); - if (argValue->IsNull()) - continue; - - if (argValue->IsArray()) { - auto lengthValue = pdfium::MakeUnique(pIsolate); - argValue->GetObjectProperty("length", lengthValue.get()); - int32_t iLength = lengthValue->ToInteger(); - if (iLength <= 2) { - pContext->ThrowArgumentMismatchException(); - return; - } +bool IsIsoDateTimeFormat(const char* pData, + int32_t iLength, + int32_t& iYear, + int32_t& iMonth, + int32_t& iDay, + int32_t& iHour, + int32_t& iMinute, + int32_t& iSecond, + int32_t& iMillionSecond, + int32_t& iZoneHour, + int32_t& iZoneMinute) { + iYear = 0; + iMonth = 0; + iDay = 0; + iHour = 0; + iMinute = 0; + iSecond = 0; + if (!pData) + return false; - auto propertyValue = pdfium::MakeUnique(pIsolate); - auto jsObjectValue = pdfium::MakeUnique(pIsolate); - auto newPropertyValue = pdfium::MakeUnique(pIsolate); - argValue->GetObjectPropertyByIdx(1, propertyValue.get()); - argValue->GetObjectPropertyByIdx(2, jsObjectValue.get()); - if (propertyValue->IsNull()) { - for (int32_t j = 2; j < iLength; j++) { - argValue->GetObjectPropertyByIdx(j, jsObjectValue.get()); - GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get()); - if (newPropertyValue->IsNull()) - continue; + int32_t iIndex = 0; + while (pData[iIndex] != 'T' && pData[iIndex] != 't') { + if (iIndex >= iLength) + return false; + ++iIndex; + } + if (iIndex != 8 && iIndex != 10) + return false; - uCount++; - double dValue = ValueToDouble(pThis, newPropertyValue.get()); - dMinValue = uCount == 1 ? dValue : std::min(dMinValue, dValue); - } - } else { - for (int32_t j = 2; j < iLength; j++) { - argValue->GetObjectPropertyByIdx(j, jsObjectValue.get()); - jsObjectValue->GetObjectProperty( - propertyValue->ToString().AsStringView(), newPropertyValue.get()); - if (newPropertyValue->IsNull()) - continue; + int32_t iStyle = -1; + if (!IsIsoDateFormat(pData, iIndex, iStyle, iYear, iMonth, iDay)) + return false; + if (pData[iIndex] != 'T' && pData[iIndex] != 't') + return true; - uCount++; - double dValue = ValueToDouble(pThis, newPropertyValue.get()); - dMinValue = uCount == 1 ? dValue : std::min(dMinValue, dValue); - } - } - } else if (argValue->IsObject()) { - auto newPropertyValue = pdfium::MakeUnique(pIsolate); - GetObjectDefaultValue(argValue.get(), newPropertyValue.get()); - if (newPropertyValue->IsNull()) - continue; + ++iIndex; + if (((iLength - iIndex > 13) && (iLength - iIndex < 6)) && + (iLength - iIndex != 15)) { + return true; + } + return IsIsoTimeFormat(pData + iIndex, iLength - iIndex, iHour, iMinute, + iSecond, iMillionSecond, iZoneHour, iZoneMinute); +} - uCount++; - double dValue = ValueToDouble(pThis, newPropertyValue.get()); - dMinValue = uCount == 1 ? dValue : std::min(dMinValue, dValue); - } else { - uCount++; - double dValue = ValueToDouble(pThis, argValue.get()); - dMinValue = uCount == 1 ? dValue : std::min(dMinValue, dValue); +int32_t DateString2Num(const ByteStringView& szDateString) { + int32_t iLength = szDateString.GetLength(); + int32_t iYear = 0; + int32_t iMonth = 0; + int32_t iDay = 0; + if (iLength <= 10) { + int32_t iStyle = -1; + if (!IsIsoDateFormat(szDateString.unterminated_c_str(), iLength, iStyle, + iYear, iMonth, iDay)) { + return 0; + } + } else { + int32_t iHour = 0; + int32_t iMinute = 0; + int32_t iSecond = 0; + int32_t iMilliSecond = 0; + int32_t iZoneHour = 0; + int32_t iZoneMinute = 0; + if (!IsIsoDateTimeFormat(szDateString.unterminated_c_str(), iLength, iYear, + iMonth, iDay, iHour, iMinute, iSecond, + iMilliSecond, iZoneHour, iZoneMinute)) { + return 0; } - } - if (uCount == 0) { - args.GetReturnValue()->SetNull(); - return; } - args.GetReturnValue()->SetDouble(dMinValue); -} + float dDays = 0; + int32_t i = 1; + if (iYear < 1900) + return 0; -// static -void CFXJSE_FormCalcContext::Mod(CFXJSE_Value* pThis, - const ByteStringView& szFuncName, - CFXJSE_Arguments& args) { - CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis); - if (args.GetLength() != 2) { - pContext->ThrowParamCountMismatchException(L"Mod"); - return; + while (iYear - i >= 1900) { + dDays += + ((!((iYear - i) % 4) && ((iYear - i) % 100)) || !((iYear - i) % 400)) + ? 366 + : 365; + ++i; } + i = 1; + while (i < iMonth) { + if (i == 2) + dDays += ((!(iYear % 4) && (iYear % 100)) || !(iYear % 400)) ? 29 : 28; + else if (i <= 7) + dDays += (i % 2 == 0) ? 30 : 31; + else + dDays += (i % 2 == 0) ? 31 : 30; - std::unique_ptr argOne = args.GetValue(0); - std::unique_ptr argTwo = args.GetValue(1); - if (argOne->IsNull() || argTwo->IsNull()) { - args.GetReturnValue()->SetNull(); - return; + ++i; } - - bool argOneResult; - double dDividend = ExtractDouble(pThis, argOne.get(), &argOneResult); - bool argTwoResult; - double dDivisor = ExtractDouble(pThis, argTwo.get(), &argTwoResult); - if (!argOneResult || !argTwoResult) { - pContext->ThrowArgumentMismatchException(); - return; + i = 0; + while (iDay - i > 0) { + dDays += 1; + ++i; } + return (int32_t)dDays; +} - if (dDivisor == 0.0) { - pContext->ThrowDivideByZeroException(); - return; - } +void GetLocalTimeZone(int32_t& iHour, int32_t& iMin, int32_t& iSec) { + time_t now; + time(&now); - args.GetReturnValue()->SetDouble(dDividend - - dDivisor * (int32_t)(dDividend / dDivisor)); + struct tm* pGmt = gmtime(&now); + struct tm* pLocal = localtime(&now); + iHour = pLocal->tm_hour - pGmt->tm_hour; + iMin = pLocal->tm_min - pGmt->tm_min; + iSec = pLocal->tm_sec - pGmt->tm_sec; } -// static -void CFXJSE_FormCalcContext::Round(CFXJSE_Value* pThis, - const ByteStringView& szFuncName, - CFXJSE_Arguments& args) { - CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis); - int32_t argc = args.GetLength(); - if (argc < 1 || argc > 2) { - pContext->ThrowParamCountMismatchException(L"Round"); - return; - } - - std::unique_ptr argOne = args.GetValue(0); - if (argOne->IsNull()) { - args.GetReturnValue()->SetNull(); - return; +bool HTMLSTR2Code(const WideStringView& pData, uint32_t* iCode) { + auto cmpFunc = [](const XFA_FMHtmlReserveCode& iter, + const WideStringView& val) { + // TODO(tsepez): check usage of c_str() below. + return wcscmp(val.unterminated_c_str(), iter.m_htmlReserve) > 0; + }; + const XFA_FMHtmlReserveCode* result = + std::lower_bound(std::begin(kReservesForDecode), + std::end(kReservesForDecode), pData, cmpFunc); + if (result != std::end(kReservesForEncode) && + !wcscmp(pData.unterminated_c_str(), result->m_htmlReserve)) { + *iCode = result->m_uCode; + return true; } + return false; +} - bool dValueRet; - double dValue = ExtractDouble(pThis, argOne.get(), &dValueRet); - if (!dValueRet) { - pContext->ThrowArgumentMismatchException(); - return; +bool HTMLCode2STR(uint32_t iCode, WideString* wsHTMLReserve) { + auto cmpFunc = [](const XFA_FMHtmlReserveCode iter, const uint32_t& val) { + return iter.m_uCode < val; + }; + const XFA_FMHtmlReserveCode* result = + std::lower_bound(std::begin(kReservesForEncode), + std::end(kReservesForEncode), iCode, cmpFunc); + if (result != std::end(kReservesForEncode) && result->m_uCode == iCode) { + *wsHTMLReserve = result->m_htmlReserve; + return true; } + return false; +} - uint8_t uPrecision = 0; - if (argc > 1) { - std::unique_ptr argTwo = args.GetValue(1); - if (argTwo->IsNull()) { - args.GetReturnValue()->SetNull(); - return; +WideString DecodeURL(const WideString& wsURLString) { + const wchar_t* pData = wsURLString.c_str(); + size_t i = 0; + CFX_WideTextBuf wsResultBuf; + while (i < wsURLString.GetLength()) { + wchar_t ch = pData[i]; + if ('%' != ch) { + wsResultBuf.AppendChar(ch); + ++i; + continue; } - bool dPrecisionRet; - double dPrecision = ExtractDouble(pThis, argTwo.get(), &dPrecisionRet); - if (!dPrecisionRet) { - pContext->ThrowArgumentMismatchException(); - return; + wchar_t chTemp = 0; + int32_t iCount = 0; + while (iCount < 2) { + ++i; + ch = pData[i]; + if (ch <= '9' && ch >= '0') { + // TODO(dsinclair): Premultiply and add rather then scale. + chTemp += (ch - '0') * (!iCount ? 16 : 1); + } else if (ch <= 'F' && ch >= 'A') { + chTemp += (ch - 'A' + 10) * (!iCount ? 16 : 1); + } else if (ch <= 'f' && ch >= 'a') { + chTemp += (ch - 'a' + 10) * (!iCount ? 16 : 1); + } else { + return WideString(); + } + ++iCount; } - - uPrecision = static_cast(pdfium::clamp(dPrecision, 0.0, 12.0)); + wsResultBuf.AppendChar(chTemp); + ++i; } - - CFX_Decimal decimalValue(static_cast(dValue), uPrecision); - args.GetReturnValue()->SetDouble(decimalValue); + wsResultBuf.AppendChar(0); + return wsResultBuf.MakeString(); } -// static -void CFXJSE_FormCalcContext::Sum(CFXJSE_Value* pThis, - const ByteStringView& szFuncName, - CFXJSE_Arguments& args) { - int32_t argc = args.GetLength(); - if (argc == 0) { - args.GetReturnValue()->SetNull(); - return; - } - - CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis); - v8::Isolate* pIsolate = pContext->GetScriptRuntime(); - uint32_t uCount = 0; - double dSum = 0.0; - for (int32_t i = 0; i < argc; i++) { - std::unique_ptr argValue = args.GetValue(i); - if (argValue->IsNull()) +WideString DecodeHTML(const WideString& wsHTMLString) { + wchar_t strString[9]; + size_t iStrIndex = 0; + size_t iLen = wsHTMLString.GetLength(); + size_t i = 0; + int32_t iCode = 0; + const wchar_t* pData = wsHTMLString.c_str(); + CFX_WideTextBuf wsResultBuf; + while (i < iLen) { + wchar_t ch = pData[i]; + if (ch != '&') { + wsResultBuf.AppendChar(ch); + ++i; continue; + } - if (argValue->IsArray()) { - auto lengthValue = pdfium::MakeUnique(pIsolate); - argValue->GetObjectProperty("length", lengthValue.get()); - int32_t iLength = lengthValue->ToInteger(); - if (iLength <= 2) { - pContext->ThrowArgumentMismatchException(); - return; + ++i; + ch = pData[i]; + if (ch == '#') { + ++i; + ch = pData[i]; + if (ch != 'x' && ch != 'X') { + return WideString(); } - auto propertyValue = pdfium::MakeUnique(pIsolate); - argValue->GetObjectPropertyByIdx(1, propertyValue.get()); - auto jsObjectValue = pdfium::MakeUnique(pIsolate); - auto newPropertyValue = pdfium::MakeUnique(pIsolate); - if (propertyValue->IsNull()) { - for (int32_t j = 2; j < iLength; j++) { - argValue->GetObjectPropertyByIdx(j, jsObjectValue.get()); - GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get()); - if (newPropertyValue->IsNull()) - continue; - - dSum += ValueToDouble(pThis, jsObjectValue.get()); - uCount++; - } - } else { - for (int32_t j = 2; j < iLength; j++) { - argValue->GetObjectPropertyByIdx(j, jsObjectValue.get()); - jsObjectValue->GetObjectProperty( - propertyValue->ToString().AsStringView(), newPropertyValue.get()); - if (newPropertyValue->IsNull()) - continue; - - dSum += ValueToDouble(pThis, newPropertyValue.get()); - uCount++; + ++i; + ch = pData[i]; + if ((ch >= '0' && ch <= '9') || (ch <= 'f' && ch >= 'a') || + (ch <= 'F' && ch >= 'A')) { + while (ch != ';' && i < iLen) { + if (ch >= '0' && ch <= '9') { + iCode += ch - '0'; + } else if (ch <= 'f' && ch >= 'a') { + iCode += ch - 'a' + 10; + } else if (ch <= 'F' && ch >= 'A') { + iCode += ch - 'A' + 10; + } else { + return WideString(); + } + ++i; + // TODO(dsinclair): Postmultiply seems wrong, start at zero + // and pre-multiply then can remove the post divide. + iCode *= 16; + ch = pData[i]; } + iCode /= 16; } - } else if (argValue->IsObject()) { - auto newPropertyValue = pdfium::MakeUnique(pIsolate); - GetObjectDefaultValue(argValue.get(), newPropertyValue.get()); - if (newPropertyValue->IsNull()) - continue; - - dSum += ValueToDouble(pThis, argValue.get()); - uCount++; } else { - dSum += ValueToDouble(pThis, argValue.get()); - uCount++; + while (ch != ';' && i < iLen) { + strString[iStrIndex++] = ch; + ++i; + ch = pData[i]; + } + strString[iStrIndex] = 0; } + uint32_t iData = 0; + if (HTMLSTR2Code(strString, &iData)) { + wsResultBuf.AppendChar((wchar_t)iData); + } else { + wsResultBuf.AppendChar(iCode); + } + iStrIndex = 0; + strString[iStrIndex] = 0; + ++i; } - if (uCount == 0) { - args.GetReturnValue()->SetNull(); - return; - } - - args.GetReturnValue()->SetDouble(dSum); -} - -// static -void CFXJSE_FormCalcContext::Date(CFXJSE_Value* pThis, - const ByteStringView& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 0) { - ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"Date"); - return; - } - - time_t currentTime; - time(¤tTime); - struct tm* pTmStruct = gmtime(¤tTime); + wsResultBuf.AppendChar(0); - args.GetReturnValue()->SetInteger(DateString2Num( - ByteString::Format("%d%02d%02d", pTmStruct->tm_year + 1900, - pTmStruct->tm_mon + 1, pTmStruct->tm_mday) - .AsStringView())); + return wsResultBuf.MakeString(); } -// static -void CFXJSE_FormCalcContext::Date2Num(CFXJSE_Value* pThis, - const ByteStringView& szFuncName, - CFXJSE_Arguments& args) { - int32_t argc = args.GetLength(); - if (argc < 1 || argc > 3) { - ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"Date2Num"); - return; - } +WideString DecodeXML(const WideString& wsXMLString) { + wchar_t strString[9]; + int32_t iStrIndex = 0; + int32_t iLen = wsXMLString.GetLength(); + int32_t i = 0; + int32_t iCode = 0; + wchar_t ch = 0; + const wchar_t* pData = wsXMLString.c_str(); + CFX_WideTextBuf wsResultBuf; + while (i < iLen) { + ch = pData[i]; + if (ch != '&') { + wsResultBuf.AppendChar(ch); + ++i; + continue; + } - std::unique_ptr dateValue = GetSimpleValue(pThis, args, 0); - if (ValueIsNull(pThis, dateValue.get())) { - args.GetReturnValue()->SetNull(); - return; - } + // TODO(dsinclair): This is very similar to DecodeHTML, can they be + // combined? + ++i; + ch = pData[i]; + if (ch == '#') { + ++i; + ch = pData[i]; + if (ch != 'x' && ch != 'X') { + return WideString(); + } - ByteString dateString = ValueToUTF8String(dateValue.get()); - ByteString formatString; - if (argc > 1) { - std::unique_ptr formatValue = GetSimpleValue(pThis, args, 1); - if (ValueIsNull(pThis, formatValue.get())) { - args.GetReturnValue()->SetNull(); - return; + ++i; + ch = pData[i]; + if ((ch >= '0' && ch <= '9') || (ch <= 'f' && ch >= 'a') || + (ch <= 'F' && ch >= 'A')) { + while (ch != ';') { + if (ch >= '0' && ch <= '9') { + iCode += ch - '0'; + } else if (ch <= 'f' && ch >= 'a') { + iCode += ch - 'a' + 10; + } else if (ch <= 'F' && ch >= 'A') { + iCode += ch - 'A' + 10; + } else { + return WideString(); + } + ++i; + iCode *= 16; + ch = pData[i]; + } + iCode /= 16; + } + } else { + while (ch != ';' && i < iLen) { + strString[iStrIndex++] = ch; + ++i; + ch = pData[i]; + } + strString[iStrIndex] = 0; } - formatString = ValueToUTF8String(formatValue.get()); - } - ByteString localString; - if (argc > 2) { - std::unique_ptr localValue = GetSimpleValue(pThis, args, 2); - if (ValueIsNull(pThis, localValue.get())) { - args.GetReturnValue()->SetNull(); - return; + const wchar_t* const strName[] = {L"quot", L"amp", L"apos", L"lt", L"gt"}; + int32_t iIndex = 0; + while (iIndex < 5) { + if (memcmp(strString, strName[iIndex], wcslen(strName[iIndex])) == 0) { + break; + } + ++iIndex; } - localString = ValueToUTF8String(localValue.get()); + switch (iIndex) { + case 0: + wsResultBuf.AppendChar('"'); + break; + case 1: + wsResultBuf.AppendChar('&'); + break; + case 2: + wsResultBuf.AppendChar('\''); + break; + case 3: + wsResultBuf.AppendChar('<'); + break; + case 4: + wsResultBuf.AppendChar('>'); + break; + default: + wsResultBuf.AppendChar(iCode); + break; + } + iStrIndex = 0; + strString[iStrIndex] = 0; + ++i; + iCode = 0; } - - ByteString szIsoDateString = - Local2IsoDate(pThis, dateString.AsStringView(), - formatString.AsStringView(), localString.AsStringView()); - args.GetReturnValue()->SetInteger( - DateString2Num(szIsoDateString.AsStringView())); + wsResultBuf.AppendChar(0); + return wsResultBuf.MakeString(); } -// static -void CFXJSE_FormCalcContext::DateFmt(CFXJSE_Value* pThis, - const ByteStringView& szFuncName, - CFXJSE_Arguments& args) { - int32_t argc = args.GetLength(); - if (argc > 2) { - ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"Date2Num"); - return; - } - - int32_t iStyle = 0; - if (argc > 0) { - std::unique_ptr argStyle = GetSimpleValue(pThis, args, 0); - if (argStyle->IsNull()) { - args.GetReturnValue()->SetNull(); - return; +WideString EncodeURL(const ByteString& szURLString) { + WideString wsURLString = WideString::FromUTF8(szURLString.AsStringView()); + CFX_WideTextBuf wsResultBuf; + wchar_t strEncode[4]; + strEncode[0] = '%'; + strEncode[3] = 0; + wchar_t strUnsafe[] = {' ', '<', '>', '"', '#', '%', '{', '}', + '|', '\\', '^', '~', '[', ']', '`'}; + wchar_t strReserved[] = {';', '/', '?', ':', '@', '=', '&'}; + wchar_t strSpecial[] = {'$', '-', '+', '!', '*', '\'', '(', ')', ','}; + const wchar_t* strCode = L"0123456789abcdef"; + for (auto ch : wsURLString) { + int32_t i = 0; + int32_t iCount = FX_ArraySize(strUnsafe); + while (i < iCount) { + if (ch == strUnsafe[i]) { + int32_t iIndex = ch / 16; + strEncode[1] = strCode[iIndex]; + strEncode[2] = strCode[ch - iIndex * 16]; + wsResultBuf << strEncode; + break; + } + ++i; } + if (i < iCount) + continue; - iStyle = (int32_t)ValueToFloat(pThis, argStyle.get()); - if (iStyle < 0 || iStyle > 4) - iStyle = 0; - } + i = 0; + iCount = FX_ArraySize(strReserved); + while (i < iCount) { + if (ch == strReserved[i]) { + int32_t iIndex = ch / 16; + strEncode[1] = strCode[iIndex]; + strEncode[2] = strCode[ch - iIndex * 16]; + wsResultBuf << strEncode; + break; + } + ++i; + } + if (i < iCount) + continue; - ByteString szLocal; - if (argc > 1) { - std::unique_ptr argLocal = GetSimpleValue(pThis, args, 1); - if (argLocal->IsNull()) { - args.GetReturnValue()->SetNull(); - return; + i = 0; + iCount = FX_ArraySize(strSpecial); + while (i < iCount) { + if (ch == strSpecial[i]) { + wsResultBuf.AppendChar(ch); + break; + } + ++i; } - szLocal = ValueToUTF8String(argLocal.get()); - } + if (i < iCount) + continue; - ByteString formatStr = - GetStandardDateFormat(pThis, iStyle, szLocal.AsStringView()); - args.GetReturnValue()->SetString(formatStr.AsStringView()); -} + if ((ch >= 0x80 && ch <= 0xff) || ch <= 0x1f || ch == 0x7f) { + int32_t iIndex = ch / 16; + strEncode[1] = strCode[iIndex]; + strEncode[2] = strCode[ch - iIndex * 16]; + wsResultBuf << strEncode; + } else if (ch >= 0x20 && ch <= 0x7e) { + wsResultBuf.AppendChar(ch); + } else { + const wchar_t iRadix = 16; + WideString strTmp; + while (ch >= iRadix) { + wchar_t tmp = strCode[ch % iRadix]; + ch /= iRadix; + strTmp += tmp; + } + strTmp += strCode[ch]; + int32_t iLen = strTmp.GetLength(); + if (iLen < 2) + break; -// static -void CFXJSE_FormCalcContext::IsoDate2Num(CFXJSE_Value* pThis, - const ByteStringView& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 1) { - ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"IsoDate2Num"); - return; - } + int32_t iIndex = 0; + if (iLen % 2 != 0) { + strEncode[1] = '0'; + strEncode[2] = strTmp[iLen - 1]; + iIndex = iLen - 2; + } else { + strEncode[1] = strTmp[iLen - 1]; + strEncode[2] = strTmp[iLen - 2]; + iIndex = iLen - 3; + } + wsResultBuf << strEncode; + while (iIndex > 0) { + strEncode[1] = strTmp[iIndex]; + strEncode[2] = strTmp[iIndex - 1]; + iIndex -= 2; + wsResultBuf << strEncode; + } + } + } + wsResultBuf.AppendChar(0); + return wsResultBuf.MakeString(); +} + +WideString EncodeHTML(const ByteString& szHTMLString) { + WideString wsHTMLString = WideString::FromUTF8(szHTMLString.AsStringView()); + const wchar_t* strCode = L"0123456789abcdef"; + wchar_t strEncode[9]; + strEncode[0] = '&'; + strEncode[1] = '#'; + strEncode[2] = 'x'; + strEncode[5] = ';'; + strEncode[6] = 0; + strEncode[7] = ';'; + strEncode[8] = 0; + CFX_WideTextBuf wsResultBuf; + int32_t iLen = wsHTMLString.GetLength(); + int32_t i = 0; + const wchar_t* pData = wsHTMLString.c_str(); + while (i < iLen) { + uint32_t ch = pData[i]; + WideString htmlReserve; + if (HTMLCode2STR(ch, &htmlReserve)) { + wsResultBuf.AppendChar(L'&'); + wsResultBuf << htmlReserve; + wsResultBuf.AppendChar(L';'); + } else if (ch >= 32 && ch <= 126) { + wsResultBuf.AppendChar((wchar_t)ch); + } else if (ch < 256) { + int32_t iIndex = ch / 16; + strEncode[3] = strCode[iIndex]; + strEncode[4] = strCode[ch - iIndex * 16]; + strEncode[5] = ';'; + strEncode[6] = 0; + wsResultBuf << strEncode; + } else { + int32_t iBigByte = ch / 256; + int32_t iLittleByte = ch % 256; + strEncode[3] = strCode[iBigByte / 16]; + strEncode[4] = strCode[iBigByte % 16]; + strEncode[5] = strCode[iLittleByte / 16]; + strEncode[6] = strCode[iLittleByte % 16]; + wsResultBuf << strEncode; + } + ++i; + } + wsResultBuf.AppendChar(0); + return wsResultBuf.MakeString(); +} + +WideString EncodeXML(const ByteString& szXMLString) { + WideString wsXMLString = WideString::FromUTF8(szXMLString.AsStringView()); + CFX_WideTextBuf wsResultBuf; + wchar_t strEncode[9]; + strEncode[0] = '&'; + strEncode[1] = '#'; + strEncode[2] = 'x'; + strEncode[5] = ';'; + strEncode[6] = 0; + strEncode[7] = ';'; + strEncode[8] = 0; + const wchar_t* strCode = L"0123456789abcdef"; + for (const auto& ch : wsXMLString) { + switch (ch) { + case '"': + wsResultBuf.AppendChar('&'); + wsResultBuf << WideStringView(L"quot"); + wsResultBuf.AppendChar(';'); + break; + case '&': + wsResultBuf.AppendChar('&'); + wsResultBuf << WideStringView(L"amp"); + wsResultBuf.AppendChar(';'); + break; + case '\'': + wsResultBuf.AppendChar('&'); + wsResultBuf << WideStringView(L"apos"); + wsResultBuf.AppendChar(';'); + break; + case '<': + wsResultBuf.AppendChar('&'); + wsResultBuf << WideStringView(L"lt"); + wsResultBuf.AppendChar(';'); + break; + case '>': + wsResultBuf.AppendChar('&'); + wsResultBuf << WideStringView(L"gt"); + wsResultBuf.AppendChar(';'); + break; + default: { + if (ch >= 32 && ch <= 126) { + wsResultBuf.AppendChar(ch); + } else if (ch < 256) { + int32_t iIndex = ch / 16; + strEncode[3] = strCode[iIndex]; + strEncode[4] = strCode[ch - iIndex * 16]; + strEncode[5] = ';'; + strEncode[6] = 0; + wsResultBuf << strEncode; + } else { + int32_t iBigByte = ch / 256; + int32_t iLittleByte = ch % 256; + strEncode[3] = strCode[iBigByte / 16]; + strEncode[4] = strCode[iBigByte % 16]; + strEncode[5] = strCode[iLittleByte / 16]; + strEncode[6] = strCode[iLittleByte % 16]; + wsResultBuf << strEncode; + } + break; + } + } + } + wsResultBuf.AppendChar(0); + return wsResultBuf.MakeString(); +} + +ByteString TrillionUS(const ByteStringView& szData) { + std::ostringstream strBuf; + ByteStringView pUnits[] = {"zero", "one", "two", "three", "four", + "five", "six", "seven", "eight", "nine"}; + ByteStringView pCapUnits[] = {"Zero", "One", "Two", "Three", "Four", + "Five", "Six", "Seven", "Eight", "Nine"}; + ByteStringView pTens[] = {"Ten", "Eleven", "Twelve", "Thirteen", + "Fourteen", "Fifteen", "Sixteen", "Seventeen", + "Eighteen", "Nineteen"}; + ByteStringView pLastTens[] = {"Twenty", "Thirty", "Forty", "Fifty", + "Sixty", "Seventy", "Eighty", "Ninety"}; + ByteStringView pComm[] = {" Hundred ", " Thousand ", " Million ", " Billion ", + "Trillion"}; + const char* pData = szData.unterminated_c_str(); + int32_t iLength = szData.GetLength(); + int32_t iComm = 0; + if (iLength > 12) + iComm = 4; + else if (iLength > 9) + iComm = 3; + else if (iLength > 6) + iComm = 2; + else if (iLength > 3) + iComm = 1; + + int32_t iFirstCount = iLength % 3; + if (iFirstCount == 0) + iFirstCount = 3; + + int32_t iIndex = 0; + if (iFirstCount == 3) { + if (pData[iIndex] != '0') { + strBuf << pCapUnits[pData[iIndex] - '0']; + strBuf << pComm[0]; + } + if (pData[iIndex + 1] == '0') { + strBuf << pCapUnits[pData[iIndex + 2] - '0']; + } else { + if (pData[iIndex + 1] > '1') { + strBuf << pLastTens[pData[iIndex + 1] - '2']; + strBuf << "-"; + strBuf << pUnits[pData[iIndex + 2] - '0']; + } else if (pData[iIndex + 1] == '1') { + strBuf << pTens[pData[iIndex + 2] - '0']; + } else if (pData[iIndex + 1] == '0') { + strBuf << pCapUnits[pData[iIndex + 2] - '0']; + } + } + iIndex += 3; + } else if (iFirstCount == 2) { + if (pData[iIndex] == '0') { + strBuf << pCapUnits[pData[iIndex + 1] - '0']; + } else { + if (pData[iIndex] > '1') { + strBuf << pLastTens[pData[iIndex] - '2']; + strBuf << "-"; + strBuf << pUnits[pData[iIndex + 1] - '0']; + } else if (pData[iIndex] == '1') { + strBuf << pTens[pData[iIndex + 1] - '0']; + } else if (pData[iIndex] == '0') { + strBuf << pCapUnits[pData[iIndex + 1] - '0']; + } + } + iIndex += 2; + } else if (iFirstCount == 1) { + strBuf << pCapUnits[pData[iIndex] - '0']; + iIndex += 1; + } + if (iLength > 3 && iFirstCount > 0) { + strBuf << pComm[iComm]; + --iComm; + } + while (iIndex < iLength) { + if (pData[iIndex] != '0') { + strBuf << pCapUnits[pData[iIndex] - '0']; + strBuf << pComm[0]; + } + if (pData[iIndex + 1] == '0') { + strBuf << pCapUnits[pData[iIndex + 2] - '0']; + } else { + if (pData[iIndex + 1] > '1') { + strBuf << pLastTens[pData[iIndex + 1] - '2']; + strBuf << "-"; + strBuf << pUnits[pData[iIndex + 2] - '0']; + } else if (pData[iIndex + 1] == '1') { + strBuf << pTens[pData[iIndex + 2] - '0']; + } else if (pData[iIndex + 1] == '0') { + strBuf << pCapUnits[pData[iIndex + 2] - '0']; + } + } + if (iIndex < iLength - 3) { + strBuf << pComm[iComm]; + --iComm; + } + iIndex += 3; + } + return ByteString(strBuf); +} + +ByteString WordUS(const ByteString& szData, int32_t iStyle) { + const char* pData = szData.c_str(); + int32_t iLength = szData.GetLength(); + if (iStyle < 0 || iStyle > 2) { + return ByteString(); + } + + std::ostringstream strBuf; + + int32_t iIndex = 0; + while (iIndex < iLength) { + if (pData[iIndex] == '.') + break; + ++iIndex; + } + int32_t iInteger = iIndex; + iIndex = 0; + while (iIndex < iInteger) { + int32_t iCount = (iInteger - iIndex) % 12; + if (!iCount && iInteger - iIndex > 0) + iCount = 12; + + strBuf << TrillionUS(ByteStringView(pData + iIndex, iCount)); + iIndex += iCount; + if (iIndex < iInteger) + strBuf << " Trillion "; + } + + if (iStyle > 0) + strBuf << " Dollars"; + + if (iStyle > 1 && iInteger < iLength) { + strBuf << " And "; + iIndex = iInteger + 1; + while (iIndex < iLength) { + int32_t iCount = (iLength - iIndex) % 12; + if (!iCount && iLength - iIndex > 0) + iCount = 12; + + strBuf << TrillionUS(ByteStringView(pData + iIndex, iCount)); + iIndex += iCount; + if (iIndex < iLength) + strBuf << " Trillion "; + } + strBuf << " Cents"; + } + return ByteString(strBuf); +} + +} // namespace + +const FXJSE_CLASS_DESCRIPTOR kFormCalcFM2JSDescriptor = { + kClassTag, // tag + "XFA_FM2JS_FormCalcClass", // name + kFormCalcFM2JSFunctions, // methods + FX_ArraySize(kFormCalcFM2JSFunctions), // number of methods + nullptr, // dynamic prop type + nullptr, // dynamic prop getter + nullptr, // dynamic prop setter + nullptr, // dynamic prop method call +}; + +// static +void CFXJSE_FormCalcContext::Abs(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 1) { + ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"Abs"); + return; + } + + std::unique_ptr argOne = args.GetValue(0); + if (ValueIsNull(pThis, argOne.get())) { + args.GetReturnValue()->SetNull(); + return; + } + + double dValue = ValueToDouble(pThis, argOne.get()); + if (dValue < 0) + dValue = -dValue; + + args.GetReturnValue()->SetDouble(dValue); +} + +// static +void CFXJSE_FormCalcContext::Avg(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + int32_t argc = args.GetLength(); + if (argc < 1) { + args.GetReturnValue()->SetNull(); + return; + } + + v8::Isolate* pIsolate = ToFormCalcContext(pThis)->GetScriptRuntime(); + uint32_t uCount = 0; + double dSum = 0.0; + for (int32_t i = 0; i < argc; i++) { + std::unique_ptr argValue = args.GetValue(i); + if (argValue->IsNull()) + continue; + + if (!argValue->IsArray()) { + dSum += ValueToDouble(pThis, argValue.get()); + uCount++; + continue; + } + + auto lengthValue = pdfium::MakeUnique(pIsolate); + argValue->GetObjectProperty("length", lengthValue.get()); + int32_t iLength = lengthValue->ToInteger(); + + if (iLength > 2) { + auto propertyValue = pdfium::MakeUnique(pIsolate); + argValue->GetObjectPropertyByIdx(1, propertyValue.get()); + + auto jsObjectValue = pdfium::MakeUnique(pIsolate); + if (propertyValue->IsNull()) { + for (int32_t j = 2; j < iLength; j++) { + argValue->GetObjectPropertyByIdx(j, jsObjectValue.get()); + auto defaultPropValue = pdfium::MakeUnique(pIsolate); + GetObjectDefaultValue(jsObjectValue.get(), defaultPropValue.get()); + if (defaultPropValue->IsNull()) + continue; + + dSum += ValueToDouble(pThis, defaultPropValue.get()); + uCount++; + } + } else { + for (int32_t j = 2; j < iLength; j++) { + argValue->GetObjectPropertyByIdx(j, jsObjectValue.get()); + auto newPropertyValue = pdfium::MakeUnique(pIsolate); + jsObjectValue->GetObjectProperty( + propertyValue->ToString().AsStringView(), newPropertyValue.get()); + if (newPropertyValue->IsNull()) + continue; + + dSum += ValueToDouble(pThis, newPropertyValue.get()); + uCount++; + } + } + } + } + if (uCount == 0) { + args.GetReturnValue()->SetNull(); + return; + } + + args.GetReturnValue()->SetDouble(dSum / uCount); +} + +// static +void CFXJSE_FormCalcContext::Ceil(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 1) { + ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"Ceil"); + return; + } + + std::unique_ptr argValue = GetSimpleValue(pThis, args, 0); + if (ValueIsNull(pThis, argValue.get())) { + args.GetReturnValue()->SetNull(); + return; + } + + args.GetReturnValue()->SetFloat(ceil(ValueToFloat(pThis, argValue.get()))); +} + +// static +void CFXJSE_FormCalcContext::Count(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis); + v8::Isolate* pIsolate = pContext->GetScriptRuntime(); + int32_t iCount = 0; + for (int32_t i = 0; i < args.GetLength(); i++) { + std::unique_ptr argValue = args.GetValue(i); + if (argValue->IsNull()) + continue; + + if (argValue->IsArray()) { + auto lengthValue = pdfium::MakeUnique(pIsolate); + argValue->GetObjectProperty("length", lengthValue.get()); + + int32_t iLength = lengthValue->ToInteger(); + if (iLength <= 2) { + pContext->ThrowArgumentMismatchException(); + return; + } + + auto propertyValue = pdfium::MakeUnique(pIsolate); + auto jsObjectValue = pdfium::MakeUnique(pIsolate); + auto newPropertyValue = pdfium::MakeUnique(pIsolate); + argValue->GetObjectPropertyByIdx(1, propertyValue.get()); + argValue->GetObjectPropertyByIdx(2, jsObjectValue.get()); + if (propertyValue->IsNull()) { + for (int32_t j = 2; j < iLength; j++) { + argValue->GetObjectPropertyByIdx(j, jsObjectValue.get()); + GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get()); + if (!newPropertyValue->IsNull()) + iCount++; + } + } else { + for (int32_t j = 2; j < iLength; j++) { + argValue->GetObjectPropertyByIdx(j, jsObjectValue.get()); + jsObjectValue->GetObjectProperty( + propertyValue->ToString().AsStringView(), newPropertyValue.get()); + iCount += newPropertyValue->IsNull() ? 0 : 1; + } + } + } else if (argValue->IsObject()) { + auto newPropertyValue = pdfium::MakeUnique(pIsolate); + GetObjectDefaultValue(argValue.get(), newPropertyValue.get()); + if (!newPropertyValue->IsNull()) + iCount++; + } else { + iCount++; + } + } + args.GetReturnValue()->SetInteger(iCount); +} + +// static +void CFXJSE_FormCalcContext::Floor(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 1) { + ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"Floor"); + return; + } + + std::unique_ptr argValue = GetSimpleValue(pThis, args, 0); + if (ValueIsNull(pThis, argValue.get())) { + args.GetReturnValue()->SetNull(); + return; + } + + args.GetReturnValue()->SetFloat(floor(ValueToFloat(pThis, argValue.get()))); +} + +// static +void CFXJSE_FormCalcContext::Max(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis); + v8::Isolate* pIsolate = pContext->GetScriptRuntime(); + uint32_t uCount = 0; + double dMaxValue = 0.0; + for (int32_t i = 0; i < args.GetLength(); i++) { + std::unique_ptr argValue = args.GetValue(i); + if (argValue->IsNull()) + continue; + + if (argValue->IsArray()) { + auto lengthValue = pdfium::MakeUnique(pIsolate); + argValue->GetObjectProperty("length", lengthValue.get()); + int32_t iLength = lengthValue->ToInteger(); + if (iLength <= 2) { + pContext->ThrowArgumentMismatchException(); + return; + } + + auto propertyValue = pdfium::MakeUnique(pIsolate); + auto jsObjectValue = pdfium::MakeUnique(pIsolate); + auto newPropertyValue = pdfium::MakeUnique(pIsolate); + argValue->GetObjectPropertyByIdx(1, propertyValue.get()); + argValue->GetObjectPropertyByIdx(2, jsObjectValue.get()); + if (propertyValue->IsNull()) { + for (int32_t j = 2; j < iLength; j++) { + argValue->GetObjectPropertyByIdx(j, jsObjectValue.get()); + GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get()); + if (newPropertyValue->IsNull()) + continue; + + uCount++; + double dValue = ValueToDouble(pThis, newPropertyValue.get()); + dMaxValue = (uCount == 1) ? dValue : std::max(dMaxValue, dValue); + } + } else { + for (int32_t j = 2; j < iLength; j++) { + argValue->GetObjectPropertyByIdx(j, jsObjectValue.get()); + jsObjectValue->GetObjectProperty( + propertyValue->ToString().AsStringView(), newPropertyValue.get()); + if (newPropertyValue->IsNull()) + continue; + + uCount++; + double dValue = ValueToDouble(pThis, newPropertyValue.get()); + dMaxValue = (uCount == 1) ? dValue : std::max(dMaxValue, dValue); + } + } + } else if (argValue->IsObject()) { + auto newPropertyValue = pdfium::MakeUnique(pIsolate); + GetObjectDefaultValue(argValue.get(), newPropertyValue.get()); + if (newPropertyValue->IsNull()) + continue; + + uCount++; + double dValue = ValueToDouble(pThis, newPropertyValue.get()); + dMaxValue = (uCount == 1) ? dValue : std::max(dMaxValue, dValue); + } else { + uCount++; + double dValue = ValueToDouble(pThis, argValue.get()); + dMaxValue = (uCount == 1) ? dValue : std::max(dMaxValue, dValue); + } + } + if (uCount == 0) { + args.GetReturnValue()->SetNull(); + return; + } + + args.GetReturnValue()->SetDouble(dMaxValue); +} + +// static +void CFXJSE_FormCalcContext::Min(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis); + v8::Isolate* pIsolate = pContext->GetScriptRuntime(); + uint32_t uCount = 0; + double dMinValue = 0.0; + for (int32_t i = 0; i < args.GetLength(); i++) { + std::unique_ptr argValue = args.GetValue(i); + if (argValue->IsNull()) + continue; + + if (argValue->IsArray()) { + auto lengthValue = pdfium::MakeUnique(pIsolate); + argValue->GetObjectProperty("length", lengthValue.get()); + int32_t iLength = lengthValue->ToInteger(); + if (iLength <= 2) { + pContext->ThrowArgumentMismatchException(); + return; + } + + auto propertyValue = pdfium::MakeUnique(pIsolate); + auto jsObjectValue = pdfium::MakeUnique(pIsolate); + auto newPropertyValue = pdfium::MakeUnique(pIsolate); + argValue->GetObjectPropertyByIdx(1, propertyValue.get()); + argValue->GetObjectPropertyByIdx(2, jsObjectValue.get()); + if (propertyValue->IsNull()) { + for (int32_t j = 2; j < iLength; j++) { + argValue->GetObjectPropertyByIdx(j, jsObjectValue.get()); + GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get()); + if (newPropertyValue->IsNull()) + continue; + + uCount++; + double dValue = ValueToDouble(pThis, newPropertyValue.get()); + dMinValue = uCount == 1 ? dValue : std::min(dMinValue, dValue); + } + } else { + for (int32_t j = 2; j < iLength; j++) { + argValue->GetObjectPropertyByIdx(j, jsObjectValue.get()); + jsObjectValue->GetObjectProperty( + propertyValue->ToString().AsStringView(), newPropertyValue.get()); + if (newPropertyValue->IsNull()) + continue; + + uCount++; + double dValue = ValueToDouble(pThis, newPropertyValue.get()); + dMinValue = uCount == 1 ? dValue : std::min(dMinValue, dValue); + } + } + } else if (argValue->IsObject()) { + auto newPropertyValue = pdfium::MakeUnique(pIsolate); + GetObjectDefaultValue(argValue.get(), newPropertyValue.get()); + if (newPropertyValue->IsNull()) + continue; + + uCount++; + double dValue = ValueToDouble(pThis, newPropertyValue.get()); + dMinValue = uCount == 1 ? dValue : std::min(dMinValue, dValue); + } else { + uCount++; + double dValue = ValueToDouble(pThis, argValue.get()); + dMinValue = uCount == 1 ? dValue : std::min(dMinValue, dValue); + } + } + if (uCount == 0) { + args.GetReturnValue()->SetNull(); + return; + } + + args.GetReturnValue()->SetDouble(dMinValue); +} + +// static +void CFXJSE_FormCalcContext::Mod(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis); + if (args.GetLength() != 2) { + pContext->ThrowParamCountMismatchException(L"Mod"); + return; + } + + std::unique_ptr argOne = args.GetValue(0); + std::unique_ptr argTwo = args.GetValue(1); + if (argOne->IsNull() || argTwo->IsNull()) { + args.GetReturnValue()->SetNull(); + return; + } + + bool argOneResult; + double dDividend = ExtractDouble(pThis, argOne.get(), &argOneResult); + bool argTwoResult; + double dDivisor = ExtractDouble(pThis, argTwo.get(), &argTwoResult); + if (!argOneResult || !argTwoResult) { + pContext->ThrowArgumentMismatchException(); + return; + } + + if (dDivisor == 0.0) { + pContext->ThrowDivideByZeroException(); + return; + } + + args.GetReturnValue()->SetDouble(dDividend - + dDivisor * (int32_t)(dDividend / dDivisor)); +} + +// static +void CFXJSE_FormCalcContext::Round(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis); + int32_t argc = args.GetLength(); + if (argc < 1 || argc > 2) { + pContext->ThrowParamCountMismatchException(L"Round"); + return; + } + + std::unique_ptr argOne = args.GetValue(0); + if (argOne->IsNull()) { + args.GetReturnValue()->SetNull(); + return; + } + + bool dValueRet; + double dValue = ExtractDouble(pThis, argOne.get(), &dValueRet); + if (!dValueRet) { + pContext->ThrowArgumentMismatchException(); + return; + } + + uint8_t uPrecision = 0; + if (argc > 1) { + std::unique_ptr argTwo = args.GetValue(1); + if (argTwo->IsNull()) { + args.GetReturnValue()->SetNull(); + return; + } + + bool dPrecisionRet; + double dPrecision = ExtractDouble(pThis, argTwo.get(), &dPrecisionRet); + if (!dPrecisionRet) { + pContext->ThrowArgumentMismatchException(); + return; + } + + uPrecision = static_cast(pdfium::clamp(dPrecision, 0.0, 12.0)); + } + + CFX_Decimal decimalValue(static_cast(dValue), uPrecision); + args.GetReturnValue()->SetDouble(decimalValue); +} + +// static +void CFXJSE_FormCalcContext::Sum(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + int32_t argc = args.GetLength(); + if (argc == 0) { + args.GetReturnValue()->SetNull(); + return; + } + + CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis); + v8::Isolate* pIsolate = pContext->GetScriptRuntime(); + uint32_t uCount = 0; + double dSum = 0.0; + for (int32_t i = 0; i < argc; i++) { + std::unique_ptr argValue = args.GetValue(i); + if (argValue->IsNull()) + continue; + + if (argValue->IsArray()) { + auto lengthValue = pdfium::MakeUnique(pIsolate); + argValue->GetObjectProperty("length", lengthValue.get()); + int32_t iLength = lengthValue->ToInteger(); + if (iLength <= 2) { + pContext->ThrowArgumentMismatchException(); + return; + } + + auto propertyValue = pdfium::MakeUnique(pIsolate); + argValue->GetObjectPropertyByIdx(1, propertyValue.get()); + auto jsObjectValue = pdfium::MakeUnique(pIsolate); + auto newPropertyValue = pdfium::MakeUnique(pIsolate); + if (propertyValue->IsNull()) { + for (int32_t j = 2; j < iLength; j++) { + argValue->GetObjectPropertyByIdx(j, jsObjectValue.get()); + GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get()); + if (newPropertyValue->IsNull()) + continue; + + dSum += ValueToDouble(pThis, jsObjectValue.get()); + uCount++; + } + } else { + for (int32_t j = 2; j < iLength; j++) { + argValue->GetObjectPropertyByIdx(j, jsObjectValue.get()); + jsObjectValue->GetObjectProperty( + propertyValue->ToString().AsStringView(), newPropertyValue.get()); + if (newPropertyValue->IsNull()) + continue; + + dSum += ValueToDouble(pThis, newPropertyValue.get()); + uCount++; + } + } + } else if (argValue->IsObject()) { + auto newPropertyValue = pdfium::MakeUnique(pIsolate); + GetObjectDefaultValue(argValue.get(), newPropertyValue.get()); + if (newPropertyValue->IsNull()) + continue; + + dSum += ValueToDouble(pThis, argValue.get()); + uCount++; + } else { + dSum += ValueToDouble(pThis, argValue.get()); + uCount++; + } + } + if (uCount == 0) { + args.GetReturnValue()->SetNull(); + return; + } + + args.GetReturnValue()->SetDouble(dSum); +} + +// static +void CFXJSE_FormCalcContext::Date(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 0) { + ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"Date"); + return; + } + + time_t currentTime; + time(¤tTime); + struct tm* pTmStruct = gmtime(¤tTime); + + args.GetReturnValue()->SetInteger(DateString2Num( + ByteString::Format("%d%02d%02d", pTmStruct->tm_year + 1900, + pTmStruct->tm_mon + 1, pTmStruct->tm_mday) + .AsStringView())); +} + +// static +void CFXJSE_FormCalcContext::Date2Num(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + int32_t argc = args.GetLength(); + if (argc < 1 || argc > 3) { + ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"Date2Num"); + return; + } + + std::unique_ptr dateValue = GetSimpleValue(pThis, args, 0); + if (ValueIsNull(pThis, dateValue.get())) { + args.GetReturnValue()->SetNull(); + return; + } + + ByteString dateString = ValueToUTF8String(dateValue.get()); + ByteString formatString; + if (argc > 1) { + std::unique_ptr formatValue = GetSimpleValue(pThis, args, 1); + if (ValueIsNull(pThis, formatValue.get())) { + args.GetReturnValue()->SetNull(); + return; + } + formatString = ValueToUTF8String(formatValue.get()); + } + + ByteString localString; + if (argc > 2) { + std::unique_ptr localValue = GetSimpleValue(pThis, args, 2); + if (ValueIsNull(pThis, localValue.get())) { + args.GetReturnValue()->SetNull(); + return; + } + localString = ValueToUTF8String(localValue.get()); + } + + ByteString szIsoDateString = + Local2IsoDate(pThis, dateString.AsStringView(), + formatString.AsStringView(), localString.AsStringView()); + args.GetReturnValue()->SetInteger( + DateString2Num(szIsoDateString.AsStringView())); +} + +// static +void CFXJSE_FormCalcContext::DateFmt(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + int32_t argc = args.GetLength(); + if (argc > 2) { + ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"Date2Num"); + return; + } + + int32_t iStyle = 0; + if (argc > 0) { + std::unique_ptr argStyle = GetSimpleValue(pThis, args, 0); + if (argStyle->IsNull()) { + args.GetReturnValue()->SetNull(); + return; + } + + iStyle = (int32_t)ValueToFloat(pThis, argStyle.get()); + if (iStyle < 0 || iStyle > 4) + iStyle = 0; + } + + ByteString szLocal; + if (argc > 1) { + std::unique_ptr argLocal = GetSimpleValue(pThis, args, 1); + if (argLocal->IsNull()) { + args.GetReturnValue()->SetNull(); + return; + } + szLocal = ValueToUTF8String(argLocal.get()); + } + + ByteString formatStr = + GetStandardDateFormat(pThis, iStyle, szLocal.AsStringView()); + args.GetReturnValue()->SetString(formatStr.AsStringView()); +} + +// static +void CFXJSE_FormCalcContext::IsoDate2Num(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 1) { + ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"IsoDate2Num"); + return; + } std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); if (argOne->IsNull()) { args.GetReturnValue()->SetNull(); @@ -1505,138 +2424,30 @@ void CFXJSE_FormCalcContext::Num2Date(CFXJSE_Value* pThis, } // static -void CFXJSE_FormCalcContext::Num2GMTime(CFXJSE_Value* pThis, - const ByteStringView& szFuncName, - CFXJSE_Arguments& args) { - int32_t argc = args.GetLength(); - if (argc < 1 || argc > 3) { - ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"Num2GMTime"); - return; - } - - std::unique_ptr timeValue = GetSimpleValue(pThis, args, 0); - if (timeValue->IsNull()) { - args.GetReturnValue()->SetNull(); - return; - } - int32_t iTime = (int32_t)ValueToFloat(pThis, timeValue.get()); - if (abs(iTime) < 1.0) { - args.GetReturnValue()->SetNull(); - return; - } - - ByteString formatString; - if (argc > 1) { - std::unique_ptr formatValue = GetSimpleValue(pThis, args, 1); - if (formatValue->IsNull()) { - args.GetReturnValue()->SetNull(); - return; - } - formatString = ValueToUTF8String(formatValue.get()); - } - - ByteString localString; - if (argc > 2) { - std::unique_ptr localValue = GetSimpleValue(pThis, args, 2); - if (localValue->IsNull()) { - args.GetReturnValue()->SetNull(); - return; - } - localString = ValueToUTF8String(localValue.get()); - } - - ByteString szGMTTimeString = - Num2AllTime(pThis, iTime, formatString.AsStringView(), - localString.AsStringView(), true); - args.GetReturnValue()->SetString(szGMTTimeString.AsStringView()); -} - -// static -void CFXJSE_FormCalcContext::Num2Time(CFXJSE_Value* pThis, - const ByteStringView& szFuncName, - CFXJSE_Arguments& args) { - int32_t argc = args.GetLength(); - if (argc < 1 || argc > 3) { - ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"Num2Time"); - return; - } - - std::unique_ptr timeValue = GetSimpleValue(pThis, args, 0); - if (timeValue->IsNull()) { - args.GetReturnValue()->SetNull(); - return; - } - float fTime = ValueToFloat(pThis, timeValue.get()); - if (fabs(fTime) < 1.0) { - args.GetReturnValue()->SetNull(); - return; - } - - ByteString formatString; - if (argc > 1) { - std::unique_ptr formatValue = GetSimpleValue(pThis, args, 1); - if (formatValue->IsNull()) { - args.GetReturnValue()->SetNull(); - return; - } - formatString = ValueToUTF8String(formatValue.get()); - } - - ByteString localString; - if (argc > 2) { - std::unique_ptr localValue = GetSimpleValue(pThis, args, 2); - if (localValue->IsNull()) { - args.GetReturnValue()->SetNull(); - return; - } - localString = ValueToUTF8String(localValue.get()); - } - - ByteString szLocalTimeString = Num2AllTime(pThis, static_cast(fTime), - formatString.AsStringView(), - localString.AsStringView(), false); - args.GetReturnValue()->SetString(szLocalTimeString.AsStringView()); -} - -// static -void CFXJSE_FormCalcContext::Time(CFXJSE_Value* pThis, - const ByteStringView& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 0) { - ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"Time"); - return; - } - - time_t now; - time(&now); - - struct tm* pGmt = gmtime(&now); - args.GetReturnValue()->SetInteger( - (pGmt->tm_hour * 3600 + pGmt->tm_min * 60 + pGmt->tm_sec) * 1000); -} - -// static -void CFXJSE_FormCalcContext::Time2Num(CFXJSE_Value* pThis, - const ByteStringView& szFuncName, - CFXJSE_Arguments& args) { +void CFXJSE_FormCalcContext::Num2GMTime(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { int32_t argc = args.GetLength(); if (argc < 1 || argc > 3) { - ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"Time2Num"); + ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"Num2GMTime"); return; } - ByteString timeString; std::unique_ptr timeValue = GetSimpleValue(pThis, args, 0); - if (ValueIsNull(pThis, timeValue.get())) { + if (timeValue->IsNull()) { + args.GetReturnValue()->SetNull(); + return; + } + int32_t iTime = (int32_t)ValueToFloat(pThis, timeValue.get()); + if (abs(iTime) < 1.0) { args.GetReturnValue()->SetNull(); return; } - timeString = ValueToUTF8String(timeValue.get()); ByteString formatString; if (argc > 1) { std::unique_ptr formatValue = GetSimpleValue(pThis, args, 1); - if (ValueIsNull(pThis, formatValue.get())) { + if (formatValue->IsNull()) { args.GetReturnValue()->SetNull(); return; } @@ -1646,362 +2457,203 @@ void CFXJSE_FormCalcContext::Time2Num(CFXJSE_Value* pThis, ByteString localString; if (argc > 2) { std::unique_ptr localValue = GetSimpleValue(pThis, args, 2); - if (ValueIsNull(pThis, localValue.get())) { + if (localValue->IsNull()) { args.GetReturnValue()->SetNull(); return; } localString = ValueToUTF8String(localValue.get()); } - CXFA_Document* pDoc = ToFormCalcContext(pThis)->GetDocument(); - CXFA_LocaleMgr* pMgr = pDoc->GetLocaleMgr(); - LocaleIface* pLocale = nullptr; - if (localString.IsEmpty()) { - CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject()); - ASSERT(pThisNode); - pLocale = pThisNode->GetLocale(); - } else { - pLocale = - pMgr->GetLocaleByName(WideString::FromUTF8(localString.AsStringView())); - } - - WideString wsFormat; - if (formatString.IsEmpty()) - wsFormat = pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Default); - else - wsFormat = WideString::FromUTF8(formatString.AsStringView()); - - wsFormat = L"time{" + wsFormat + L"}"; - CXFA_LocaleValue localeValue(XFA_VT_TIME, - WideString::FromUTF8(timeString.AsStringView()), - wsFormat, pLocale, pMgr); - if (!localeValue.IsValid()) { - args.GetReturnValue()->SetInteger(0); - return; - } - - CFX_DateTime uniTime = localeValue.GetTime(); - int32_t hour = uniTime.GetHour(); - int32_t min = uniTime.GetMinute(); - int32_t second = uniTime.GetSecond(); - int32_t milSecond = uniTime.GetMillisecond(); - int32_t mins = hour * 60 + min; - - mins -= (CXFA_TimeZoneProvider().GetTimeZone().tzHour * 60); - while (mins > 1440) - mins -= 1440; - - while (mins < 0) - mins += 1440; - - hour = mins / 60; - min = mins % 60; - args.GetReturnValue()->SetInteger(hour * 3600000 + min * 60000 + - second * 1000 + milSecond + 1); + ByteString szGMTTimeString = + Num2AllTime(pThis, iTime, formatString.AsStringView(), + localString.AsStringView(), true); + args.GetReturnValue()->SetString(szGMTTimeString.AsStringView()); } // static -void CFXJSE_FormCalcContext::TimeFmt(CFXJSE_Value* pThis, - const ByteStringView& szFuncName, - CFXJSE_Arguments& args) { +void CFXJSE_FormCalcContext::Num2Time(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { int32_t argc = args.GetLength(); - if (argc > 2) { - ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"TimeFmt"); + if (argc < 1 || argc > 3) { + ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"Num2Time"); return; } - int32_t iStyle = 0; - if (argc > 0) { - std::unique_ptr argStyle = GetSimpleValue(pThis, args, 0); - if (argStyle->IsNull()) { - args.GetReturnValue()->SetNull(); - return; - } - iStyle = (int32_t)ValueToFloat(pThis, argStyle.get()); - if (iStyle > 4 || iStyle < 0) - iStyle = 0; + std::unique_ptr timeValue = GetSimpleValue(pThis, args, 0); + if (timeValue->IsNull()) { + args.GetReturnValue()->SetNull(); + return; + } + float fTime = ValueToFloat(pThis, timeValue.get()); + if (fabs(fTime) < 1.0) { + args.GetReturnValue()->SetNull(); + return; } - ByteString szLocal; + ByteString formatString; if (argc > 1) { - std::unique_ptr argLocal = GetSimpleValue(pThis, args, 1); - if (argLocal->IsNull()) { + std::unique_ptr formatValue = GetSimpleValue(pThis, args, 1); + if (formatValue->IsNull()) { args.GetReturnValue()->SetNull(); return; } - szLocal = ValueToUTF8String(argLocal.get()); - } - - ByteString formatStr = - GetStandardTimeFormat(pThis, iStyle, szLocal.AsStringView()); - args.GetReturnValue()->SetString(formatStr.AsStringView()); -} - -// static -bool CFXJSE_FormCalcContext::IsIsoDateFormat(const char* pData, - int32_t iLength, - int32_t& iStyle, - int32_t& iYear, - int32_t& iMonth, - int32_t& iDay) { - iYear = 0; - iMonth = 1; - iDay = 1; - - if (iLength < 4) - return false; - - char strYear[5]; - strYear[4] = '\0'; - for (int32_t i = 0; i < 4; ++i) { - if (!std::isdigit(pData[i])) - return false; - - strYear[i] = pData[i]; - } - iYear = FXSYS_atoi(strYear); - iStyle = 0; - if (iLength == 4) - return true; - - iStyle = pData[4] == '-' ? 1 : 0; - - char strTemp[3]; - strTemp[2] = '\0'; - int32_t iPosOff = iStyle == 0 ? 4 : 5; - if (!std::isdigit(pData[iPosOff]) || !std::isdigit(pData[iPosOff + 1])) - return false; - - strTemp[0] = pData[iPosOff]; - strTemp[1] = pData[iPosOff + 1]; - iMonth = FXSYS_atoi(strTemp); - if (iMonth > 12 || iMonth < 1) - return false; - - if (iStyle == 0) { - iPosOff += 2; - if (iLength == 6) - return true; - } else { - iPosOff += 3; - if (iLength == 7) - return true; + formatString = ValueToUTF8String(formatValue.get()); } - if (!std::isdigit(pData[iPosOff]) || !std::isdigit(pData[iPosOff + 1])) - return false; - - strTemp[0] = pData[iPosOff]; - strTemp[1] = pData[iPosOff + 1]; - iDay = FXSYS_atoi(strTemp); - if (iPosOff + 2 < iLength) - return false; - if ((!(iYear % 4) && (iYear % 100)) || !(iYear % 400)) { - if (iMonth == 2 && iDay > 29) - return false; - } else { - if (iMonth == 2 && iDay > 28) - return false; - } - if (iMonth != 2) { - if (iMonth < 8) { - if (iDay > (iMonth % 2 == 0 ? 30 : 31)) - return false; - } else if (iDay > (iMonth % 2 == 0 ? 31 : 30)) { - return false; + ByteString localString; + if (argc > 2) { + std::unique_ptr localValue = GetSimpleValue(pThis, args, 2); + if (localValue->IsNull()) { + args.GetReturnValue()->SetNull(); + return; } + localString = ValueToUTF8String(localValue.get()); } - return true; + + ByteString szLocalTimeString = Num2AllTime(pThis, static_cast(fTime), + formatString.AsStringView(), + localString.AsStringView(), false); + args.GetReturnValue()->SetString(szLocalTimeString.AsStringView()); } // static -bool CFXJSE_FormCalcContext::IsIsoTimeFormat(const char* pData, - int32_t iLength, - int32_t& iHour, - int32_t& iMinute, - int32_t& iSecond, - int32_t& iMilliSecond, - int32_t& iZoneHour, - int32_t& iZoneMinute) { - iHour = 0; - iMinute = 0; - iSecond = 0; - iMilliSecond = 0; - iZoneHour = 0; - iZoneMinute = 0; - if (!pData) - return false; - - char strTemp[3]; - strTemp[2] = '\0'; - int32_t iZone = 0; - int32_t i = 0; - while (i < iLength) { - if (!std::isdigit(pData[i]) && pData[i] != ':') { - iZone = i; - break; - } - ++i; +void CFXJSE_FormCalcContext::Time(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 0) { + ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"Time"); + return; } - if (i == iLength) - iZone = iLength; - - int32_t iPos = 0; - int32_t iIndex = 0; - while (iIndex < iZone) { - if (!std::isdigit(pData[iIndex])) - return false; - strTemp[0] = pData[iIndex]; - if (!std::isdigit(pData[iIndex + 1])) - return false; - - strTemp[1] = pData[iIndex + 1]; - if (FXSYS_atoi(strTemp) > 60) - return false; - - if (pData[2] == ':') { - if (iPos == 0) { - iHour = FXSYS_atoi(strTemp); - ++iPos; - } else if (iPos == 1) { - iMinute = FXSYS_atoi(strTemp); - ++iPos; - } else { - iSecond = FXSYS_atoi(strTemp); - } - iIndex += 3; - } else { - if (iPos == 0) { - iHour = FXSYS_atoi(strTemp); - ++iPos; - } else if (iPos == 1) { - iMinute = FXSYS_atoi(strTemp); - ++iPos; - } else if (iPos == 2) { - iSecond = FXSYS_atoi(strTemp); - ++iPos; - } - iIndex += 2; - } + time_t now; + time(&now); + + struct tm* pGmt = gmtime(&now); + args.GetReturnValue()->SetInteger( + (pGmt->tm_hour * 3600 + pGmt->tm_min * 60 + pGmt->tm_sec) * 1000); +} + +// static +void CFXJSE_FormCalcContext::Time2Num(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + int32_t argc = args.GetLength(); + if (argc < 1 || argc > 3) { + ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"Time2Num"); + return; } - if (iIndex < iLength && pData[iIndex] == '.') { - constexpr int kSubSecondLength = 3; - if (iIndex + kSubSecondLength >= iLength) - return false; + ByteString timeString; + std::unique_ptr timeValue = GetSimpleValue(pThis, args, 0); + if (ValueIsNull(pThis, timeValue.get())) { + args.GetReturnValue()->SetNull(); + return; + } + timeString = ValueToUTF8String(timeValue.get()); - ++iIndex; - char strSec[kSubSecondLength + 1]; - for (int i = 0; i < kSubSecondLength; ++i) { - char c = pData[iIndex + i]; - if (!std::isdigit(c)) - return false; - strSec[i] = c; + ByteString formatString; + if (argc > 1) { + std::unique_ptr formatValue = GetSimpleValue(pThis, args, 1); + if (ValueIsNull(pThis, formatValue.get())) { + args.GetReturnValue()->SetNull(); + return; } - strSec[kSubSecondLength] = '\0'; + formatString = ValueToUTF8String(formatValue.get()); + } - iMilliSecond = FXSYS_atoi(strSec); - if (iMilliSecond > 100) { - iMilliSecond = 0; - return false; + ByteString localString; + if (argc > 2) { + std::unique_ptr localValue = GetSimpleValue(pThis, args, 2); + if (ValueIsNull(pThis, localValue.get())) { + args.GetReturnValue()->SetNull(); + return; } - iIndex += kSubSecondLength; + localString = ValueToUTF8String(localValue.get()); } - if (iIndex < iLength && FXSYS_towlower(pData[iIndex]) == 'z') - return true; + CXFA_Document* pDoc = ToFormCalcContext(pThis)->GetDocument(); + CXFA_LocaleMgr* pMgr = pDoc->GetLocaleMgr(); + LocaleIface* pLocale = nullptr; + if (localString.IsEmpty()) { + CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject()); + ASSERT(pThisNode); + pLocale = pThisNode->GetLocale(); + } else { + pLocale = + pMgr->GetLocaleByName(WideString::FromUTF8(localString.AsStringView())); + } - int32_t iSign = 1; - if (iIndex < iLength) { - if (pData[iIndex] == '+') { - ++iIndex; - } else if (pData[iIndex] == '-') { - iSign = -1; - ++iIndex; - } + WideString wsFormat; + if (formatString.IsEmpty()) + wsFormat = pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Default); + else + wsFormat = WideString::FromUTF8(formatString.AsStringView()); + + wsFormat = L"time{" + wsFormat + L"}"; + CXFA_LocaleValue localeValue(XFA_VT_TIME, + WideString::FromUTF8(timeString.AsStringView()), + wsFormat, pLocale, pMgr); + if (!localeValue.IsValid()) { + args.GetReturnValue()->SetInteger(0); + return; } - iPos = 0; - while (iIndex < iLength) { - if (!std::isdigit(pData[iIndex])) - return false; - strTemp[0] = pData[iIndex]; - if (!std::isdigit(pData[iIndex + 1])) - return false; + CFX_DateTime uniTime = localeValue.GetTime(); + int32_t hour = uniTime.GetHour(); + int32_t min = uniTime.GetMinute(); + int32_t second = uniTime.GetSecond(); + int32_t milSecond = uniTime.GetMillisecond(); + int32_t mins = hour * 60 + min; - strTemp[1] = pData[iIndex + 1]; - if (FXSYS_atoi(strTemp) > 60) - return false; + mins -= (CXFA_TimeZoneProvider().GetTimeZone().tzHour * 60); + while (mins > 1440) + mins -= 1440; - if (pData[2] == ':') { - if (iPos == 0) { - iZoneHour = FXSYS_atoi(strTemp); - } else if (iPos == 1) { - iZoneMinute = FXSYS_atoi(strTemp); - } - iIndex += 3; - } else { - if (!iPos) { - iZoneHour = FXSYS_atoi(strTemp); - ++iPos; - } else if (iPos == 1) { - iZoneMinute = FXSYS_atoi(strTemp); - ++iPos; - } - iIndex += 2; - } - } - if (iIndex < iLength) - return false; + while (mins < 0) + mins += 1440; - iZoneHour *= iSign; - return true; + hour = mins / 60; + min = mins % 60; + args.GetReturnValue()->SetInteger(hour * 3600000 + min * 60000 + + second * 1000 + milSecond + 1); } // static -bool CFXJSE_FormCalcContext::IsIsoDateTimeFormat(const char* pData, - int32_t iLength, - int32_t& iYear, - int32_t& iMonth, - int32_t& iDay, - int32_t& iHour, - int32_t& iMinute, - int32_t& iSecond, - int32_t& iMillionSecond, - int32_t& iZoneHour, - int32_t& iZoneMinute) { - iYear = 0; - iMonth = 0; - iDay = 0; - iHour = 0; - iMinute = 0; - iSecond = 0; - if (!pData) - return false; - - int32_t iIndex = 0; - while (pData[iIndex] != 'T' && pData[iIndex] != 't') { - if (iIndex >= iLength) - return false; - ++iIndex; +void CFXJSE_FormCalcContext::TimeFmt(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + int32_t argc = args.GetLength(); + if (argc > 2) { + ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"TimeFmt"); + return; } - if (iIndex != 8 && iIndex != 10) - return false; - int32_t iStyle = -1; - if (!IsIsoDateFormat(pData, iIndex, iStyle, iYear, iMonth, iDay)) - return false; - if (pData[iIndex] != 'T' && pData[iIndex] != 't') - return true; + int32_t iStyle = 0; + if (argc > 0) { + std::unique_ptr argStyle = GetSimpleValue(pThis, args, 0); + if (argStyle->IsNull()) { + args.GetReturnValue()->SetNull(); + return; + } + iStyle = (int32_t)ValueToFloat(pThis, argStyle.get()); + if (iStyle > 4 || iStyle < 0) + iStyle = 0; + } - ++iIndex; - if (((iLength - iIndex > 13) && (iLength - iIndex < 6)) && - (iLength - iIndex != 15)) { - return true; + ByteString szLocal; + if (argc > 1) { + std::unique_ptr argLocal = GetSimpleValue(pThis, args, 1); + if (argLocal->IsNull()) { + args.GetReturnValue()->SetNull(); + return; + } + szLocal = ValueToUTF8String(argLocal.get()); } - return IsIsoTimeFormat(pData + iIndex, iLength - iIndex, iHour, iMinute, - iSecond, iMillionSecond, iZoneHour, iZoneMinute); + + ByteString formatStr = + GetStandardTimeFormat(pThis, iStyle, szLocal.AsStringView()); + args.GetReturnValue()->SetString(formatStr.AsStringView()); } // static @@ -2056,80 +2708,22 @@ ByteString CFXJSE_FormCalcContext::IsoTime2Local( const ByteStringView& szTime, const ByteStringView& szFormat, const ByteStringView& szLocale) { - CXFA_Document* pDoc = ToFormCalcContext(pThis)->GetDocument(); - if (!pDoc) - return ByteString(); - - CXFA_LocaleMgr* pMgr = pDoc->GetLocaleMgr(); - LocaleIface* pLocale = LocaleFromString(pDoc, pMgr, szLocale); - if (!pLocale) - return ByteString(); - - WideString wsFormat = { - L"time{", FormatFromString(pLocale, szFormat).AsStringView(), L"}"}; - CXFA_LocaleValue widgetValue(XFA_VT_TIME, WideString::FromUTF8(szTime), pMgr); - WideString wsRet; - widgetValue.FormatPatterns(wsRet, wsFormat, pLocale, - XFA_VALUEPICTURE_Display); - return wsRet.UTF8Encode(); -} - -// static -int32_t CFXJSE_FormCalcContext::DateString2Num( - const ByteStringView& szDateString) { - int32_t iLength = szDateString.GetLength(); - int32_t iYear = 0; - int32_t iMonth = 0; - int32_t iDay = 0; - if (iLength <= 10) { - int32_t iStyle = -1; - if (!IsIsoDateFormat(szDateString.unterminated_c_str(), iLength, iStyle, - iYear, iMonth, iDay)) { - return 0; - } - } else { - int32_t iHour = 0; - int32_t iMinute = 0; - int32_t iSecond = 0; - int32_t iMilliSecond = 0; - int32_t iZoneHour = 0; - int32_t iZoneMinute = 0; - if (!IsIsoDateTimeFormat(szDateString.unterminated_c_str(), iLength, iYear, - iMonth, iDay, iHour, iMinute, iSecond, - iMilliSecond, iZoneHour, iZoneMinute)) { - return 0; - } - } - - float dDays = 0; - int32_t i = 1; - if (iYear < 1900) - return 0; - - while (iYear - i >= 1900) { - dDays += - ((!((iYear - i) % 4) && ((iYear - i) % 100)) || !((iYear - i) % 400)) - ? 366 - : 365; - ++i; - } - i = 1; - while (i < iMonth) { - if (i == 2) - dDays += ((!(iYear % 4) && (iYear % 100)) || !(iYear % 400)) ? 29 : 28; - else if (i <= 7) - dDays += (i % 2 == 0) ? 30 : 31; - else - dDays += (i % 2 == 0) ? 31 : 30; + CXFA_Document* pDoc = ToFormCalcContext(pThis)->GetDocument(); + if (!pDoc) + return ByteString(); - ++i; - } - i = 0; - while (iDay - i > 0) { - dDays += 1; - ++i; - } - return (int32_t)dDays; + CXFA_LocaleMgr* pMgr = pDoc->GetLocaleMgr(); + LocaleIface* pLocale = LocaleFromString(pDoc, pMgr, szLocale); + if (!pLocale) + return ByteString(); + + WideString wsFormat = { + L"time{", FormatFromString(pLocale, szFormat).AsStringView(), L"}"}; + CXFA_LocaleValue widgetValue(XFA_VT_TIME, WideString::FromUTF8(szTime), pMgr); + WideString wsRet; + widgetValue.FormatPatterns(wsRet, wsFormat, pLocale, + XFA_VALUEPICTURE_Display); + return wsRet.UTF8Encode(); } // static @@ -2205,20 +2799,6 @@ ByteString CFXJSE_FormCalcContext::Num2AllTime(CFXJSE_Value* pThis, szFormat, szLocale); } -// static -void CFXJSE_FormCalcContext::GetLocalTimeZone(int32_t& iHour, - int32_t& iMin, - int32_t& iSec) { - time_t now; - time(&now); - - struct tm* pGmt = gmtime(&now); - struct tm* pLocal = localtime(&now); - iHour = pLocal->tm_hour - pGmt->tm_hour; - iMin = pLocal->tm_min - pGmt->tm_min; - iSec = pLocal->tm_sec - pGmt->tm_sec; -} - // static void CFXJSE_FormCalcContext::Apr(CFXJSE_Value* pThis, const ByteStringView& szFuncName, @@ -2531,950 +3111,627 @@ void CFXJSE_FormCalcContext::PPmt(CFXJSE_Value* pThis, float nSum = 0; for (; i < iEnd; ++i) { nTemp = nPayment - nPrincipalAmount * nRateOfMonth; - nSum += nTemp; - nPrincipalAmount -= nTemp; - } - args.GetReturnValue()->SetFloat(nSum); -} - -// static -void CFXJSE_FormCalcContext::PV(CFXJSE_Value* pThis, - const ByteStringView& szFuncName, - CFXJSE_Arguments& args) { - CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis); - if (args.GetLength() != 3) { - pContext->ThrowParamCountMismatchException(L"PV"); - return; - } - - std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); - std::unique_ptr argTwo = GetSimpleValue(pThis, args, 1); - std::unique_ptr argThree = GetSimpleValue(pThis, args, 2); - if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) || - ValueIsNull(pThis, argThree.get())) { - args.GetReturnValue()->SetNull(); - return; - } - - double nAmount = ValueToDouble(pThis, argOne.get()); - double nRate = ValueToDouble(pThis, argTwo.get()); - double nPeriod = ValueToDouble(pThis, argThree.get()); - if ((nAmount <= 0) || (nRate < 0) || (nPeriod <= 0)) { - pContext->ThrowArgumentMismatchException(); - return; - } - - double nTemp = 1; - for (int32_t i = 0; i < nPeriod; ++i) - nTemp *= 1 + nRate; - - nTemp = 1 / nTemp; - args.GetReturnValue()->SetDouble(nAmount * ((1 - nTemp) / nRate)); -} - -// static -void CFXJSE_FormCalcContext::Rate(CFXJSE_Value* pThis, - const ByteStringView& szFuncName, - CFXJSE_Arguments& args) { - CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis); - if (args.GetLength() != 3) { - pContext->ThrowParamCountMismatchException(L"Rate"); - return; - } - - std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); - std::unique_ptr argTwo = GetSimpleValue(pThis, args, 1); - std::unique_ptr argThree = GetSimpleValue(pThis, args, 2); - if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) || - ValueIsNull(pThis, argThree.get())) { - args.GetReturnValue()->SetNull(); - return; - } - - float nFuture = ValueToFloat(pThis, argOne.get()); - float nPresent = ValueToFloat(pThis, argTwo.get()); - float nTotalNumber = ValueToFloat(pThis, argThree.get()); - if ((nFuture <= 0) || (nPresent < 0) || (nTotalNumber <= 0)) { - pContext->ThrowArgumentMismatchException(); - return; - } - - args.GetReturnValue()->SetFloat( - FXSYS_pow((float)(nFuture / nPresent), (float)(1 / nTotalNumber)) - 1); -} - -// static -void CFXJSE_FormCalcContext::Term(CFXJSE_Value* pThis, - const ByteStringView& szFuncName, - CFXJSE_Arguments& args) { - CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis); - if (args.GetLength() != 3) { - pContext->ThrowParamCountMismatchException(L"Term"); - return; - } - - std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); - std::unique_ptr argTwo = GetSimpleValue(pThis, args, 1); - std::unique_ptr argThree = GetSimpleValue(pThis, args, 2); - if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) || - ValueIsNull(pThis, argThree.get())) { - args.GetReturnValue()->SetNull(); - return; - } - - float nMount = ValueToFloat(pThis, argOne.get()); - float nRate = ValueToFloat(pThis, argTwo.get()); - float nFuture = ValueToFloat(pThis, argThree.get()); - if ((nMount <= 0) || (nRate <= 0) || (nFuture <= 0)) { - pContext->ThrowArgumentMismatchException(); - return; - } - - args.GetReturnValue()->SetFloat(log((float)(nFuture / nMount * nRate) + 1) / - log((float)(1 + nRate))); -} - -// static -void CFXJSE_FormCalcContext::Choose(CFXJSE_Value* pThis, - const ByteStringView& szFuncName, - CFXJSE_Arguments& args) { - CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis); - int32_t argc = args.GetLength(); - if (argc < 2) { - pContext->ThrowParamCountMismatchException(L"Choose"); - return; - } - - std::unique_ptr argOne = args.GetValue(0); - if (ValueIsNull(pThis, argOne.get())) { - args.GetReturnValue()->SetNull(); - return; - } - - int32_t iIndex = (int32_t)ValueToFloat(pThis, argOne.get()); - if (iIndex < 1) { - args.GetReturnValue()->SetString(""); - return; - } - - bool bFound = false; - bool bStopCounterFlags = false; - int32_t iArgIndex = 1; - int32_t iValueIndex = 0; - v8::Isolate* pIsolate = pContext->GetScriptRuntime(); - while (!bFound && !bStopCounterFlags && (iArgIndex < argc)) { - std::unique_ptr argIndexValue = args.GetValue(iArgIndex); - if (argIndexValue->IsArray()) { - auto lengthValue = pdfium::MakeUnique(pIsolate); - argIndexValue->GetObjectProperty("length", lengthValue.get()); - int32_t iLength = lengthValue->ToInteger(); - if (iLength > 3) - bStopCounterFlags = true; - - iValueIndex += (iLength - 2); - if (iValueIndex >= iIndex) { - auto propertyValue = pdfium::MakeUnique(pIsolate); - auto jsObjectValue = pdfium::MakeUnique(pIsolate); - auto newPropertyValue = pdfium::MakeUnique(pIsolate); - argIndexValue->GetObjectPropertyByIdx(1, propertyValue.get()); - argIndexValue->GetObjectPropertyByIdx( - (iLength - 1) - (iValueIndex - iIndex), jsObjectValue.get()); - if (propertyValue->IsNull()) { - GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get()); - } else { - jsObjectValue->GetObjectProperty( - propertyValue->ToString().AsStringView(), newPropertyValue.get()); - } - ByteString bsChosen = ValueToUTF8String(newPropertyValue.get()); - args.GetReturnValue()->SetString(bsChosen.AsStringView()); - bFound = true; - } - } else { - iValueIndex++; - if (iValueIndex == iIndex) { - ByteString bsChosen = ValueToUTF8String(argIndexValue.get()); - args.GetReturnValue()->SetString(bsChosen.AsStringView()); - bFound = true; - } - } - iArgIndex++; - } - if (!bFound) - args.GetReturnValue()->SetString(""); -} - -// static -void CFXJSE_FormCalcContext::Exists(CFXJSE_Value* pThis, - const ByteStringView& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 1) { - ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"Exists"); - return; - } - args.GetReturnValue()->SetInteger(args.GetValue(0)->IsObject()); -} - -// static -void CFXJSE_FormCalcContext::HasValue(CFXJSE_Value* pThis, - const ByteStringView& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 1) { - ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"HasValue"); - return; - } - - std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); - if (!argOne->IsString()) { - args.GetReturnValue()->SetInteger(argOne->IsNumber() || - argOne->IsBoolean()); - return; - } - - ByteString valueStr = argOne->ToString(); - valueStr.TrimLeft(); - args.GetReturnValue()->SetInteger(!valueStr.IsEmpty()); -} - -// static -void CFXJSE_FormCalcContext::Oneof(CFXJSE_Value* pThis, - const ByteStringView& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() < 2) { - ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"Oneof"); - return; - } - - bool bFlags = false; - std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); - std::vector> parameterValues; - unfoldArgs(pThis, args, ¶meterValues, 1); - for (const auto& value : parameterValues) { - if (simpleValueCompare(pThis, argOne.get(), value.get())) { - bFlags = true; - break; - } + nSum += nTemp; + nPrincipalAmount -= nTemp; } - - args.GetReturnValue()->SetInteger(bFlags); + args.GetReturnValue()->SetFloat(nSum); } // static -void CFXJSE_FormCalcContext::Within(CFXJSE_Value* pThis, - const ByteStringView& szFuncName, - CFXJSE_Arguments& args) { +void CFXJSE_FormCalcContext::PV(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis); if (args.GetLength() != 3) { - ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"Within"); + pContext->ThrowParamCountMismatchException(L"PV"); return; } std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); - if (argOne->IsNull()) { - args.GetReturnValue()->SetUndefined(); + std::unique_ptr argTwo = GetSimpleValue(pThis, args, 1); + std::unique_ptr argThree = GetSimpleValue(pThis, args, 2); + if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) || + ValueIsNull(pThis, argThree.get())) { + args.GetReturnValue()->SetNull(); return; } - std::unique_ptr argLow = GetSimpleValue(pThis, args, 1); - std::unique_ptr argHigh = GetSimpleValue(pThis, args, 2); - if (argOne->IsNumber()) { - float oneNumber = ValueToFloat(pThis, argOne.get()); - float lowNumber = ValueToFloat(pThis, argLow.get()); - float heightNumber = ValueToFloat(pThis, argHigh.get()); - args.GetReturnValue()->SetInteger((oneNumber >= lowNumber) && - (oneNumber <= heightNumber)); + double nAmount = ValueToDouble(pThis, argOne.get()); + double nRate = ValueToDouble(pThis, argTwo.get()); + double nPeriod = ValueToDouble(pThis, argThree.get()); + if ((nAmount <= 0) || (nRate < 0) || (nPeriod <= 0)) { + pContext->ThrowArgumentMismatchException(); return; } - ByteString oneString = ValueToUTF8String(argOne.get()); - ByteString lowString = ValueToUTF8String(argLow.get()); - ByteString heightString = ValueToUTF8String(argHigh.get()); - args.GetReturnValue()->SetInteger( - (oneString.Compare(lowString.AsStringView()) >= 0) && - (oneString.Compare(heightString.AsStringView()) <= 0)); -} - -// static -void CFXJSE_FormCalcContext::If(CFXJSE_Value* pThis, - const ByteStringView& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 3) { - ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"If"); - return; - } + double nTemp = 1; + for (int32_t i = 0; i < nPeriod; ++i) + nTemp *= 1 + nRate; - args.GetReturnValue()->Assign(GetSimpleValue(pThis, args, 0)->ToBoolean() - ? GetSimpleValue(pThis, args, 1).get() - : GetSimpleValue(pThis, args, 2).get()); + nTemp = 1 / nTemp; + args.GetReturnValue()->SetDouble(nAmount * ((1 - nTemp) / nRate)); } // static -void CFXJSE_FormCalcContext::Eval(CFXJSE_Value* pThis, +void CFXJSE_FormCalcContext::Rate(CFXJSE_Value* pThis, const ByteStringView& szFuncName, CFXJSE_Arguments& args) { CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis); - if (args.GetLength() != 1) { - pContext->ThrowParamCountMismatchException(L"Eval"); + if (args.GetLength() != 3) { + pContext->ThrowParamCountMismatchException(L"Rate"); return; } - v8::Isolate* pIsolate = pContext->GetScriptRuntime(); - std::unique_ptr scriptValue = GetSimpleValue(pThis, args, 0); - ByteString utf8ScriptString = ValueToUTF8String(scriptValue.get()); - if (utf8ScriptString.IsEmpty()) { + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + std::unique_ptr argTwo = GetSimpleValue(pThis, args, 1); + std::unique_ptr argThree = GetSimpleValue(pThis, args, 2); + if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) || + ValueIsNull(pThis, argThree.get())) { args.GetReturnValue()->SetNull(); return; } - CFX_WideTextBuf wsJavaScriptBuf; - if (!CFXJSE_FormCalcContext::Translate( - WideString::FromUTF8(utf8ScriptString.AsStringView()).AsStringView(), - &wsJavaScriptBuf)) { - pContext->ThrowCompilerErrorException(); + float nFuture = ValueToFloat(pThis, argOne.get()); + float nPresent = ValueToFloat(pThis, argTwo.get()); + float nTotalNumber = ValueToFloat(pThis, argThree.get()); + if ((nFuture <= 0) || (nPresent < 0) || (nTotalNumber <= 0)) { + pContext->ThrowArgumentMismatchException(); return; } - std::unique_ptr pNewContext( - CFXJSE_Context::Create(pIsolate, nullptr, nullptr)); - - auto returnValue = pdfium::MakeUnique(pIsolate); - pNewContext->ExecuteScript( - FX_UTF8Encode(wsJavaScriptBuf.AsStringView()).c_str(), returnValue.get()); - - args.GetReturnValue()->Assign(returnValue.get()); + args.GetReturnValue()->SetFloat( + FXSYS_pow((float)(nFuture / nPresent), (float)(1 / nTotalNumber)) - 1); } // static -void CFXJSE_FormCalcContext::Ref(CFXJSE_Value* pThis, - const ByteStringView& szFuncName, - CFXJSE_Arguments& args) { +void CFXJSE_FormCalcContext::Term(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis); - v8::Isolate* pIsolate = pContext->GetScriptRuntime(); - if (args.GetLength() != 1) { - pContext->ThrowParamCountMismatchException(L"Ref"); + if (args.GetLength() != 3) { + pContext->ThrowParamCountMismatchException(L"Term"); return; } - std::unique_ptr argOne = args.GetValue(0); - if (!argOne->IsArray() && !argOne->IsObject() && !argOne->IsBoolean() && - !argOne->IsString() && !argOne->IsNull() && !argOne->IsNumber()) { - pContext->ThrowArgumentMismatchException(); + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + std::unique_ptr argTwo = GetSimpleValue(pThis, args, 1); + std::unique_ptr argThree = GetSimpleValue(pThis, args, 2); + if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) || + ValueIsNull(pThis, argThree.get())) { + args.GetReturnValue()->SetNull(); return; } - if (argOne->IsBoolean() || argOne->IsString() || argOne->IsNumber()) { - args.GetReturnValue()->Assign(argOne.get()); + float nMount = ValueToFloat(pThis, argOne.get()); + float nRate = ValueToFloat(pThis, argTwo.get()); + float nFuture = ValueToFloat(pThis, argThree.get()); + if ((nMount <= 0) || (nRate <= 0) || (nFuture <= 0)) { + pContext->ThrowArgumentMismatchException(); return; } - std::vector> values; - for (int32_t i = 0; i < 3; i++) - values.push_back(pdfium::MakeUnique(pIsolate)); - - int intVal = 3; - if (argOne->IsNull()) { - // TODO(dsinclair): Why is this 4 when the others are all 3? - intVal = 4; - values[2]->SetNull(); - } else if (argOne->IsArray()) { -#ifndef NDEBUG - auto lengthValue = pdfium::MakeUnique(pIsolate); - argOne->GetObjectProperty("length", lengthValue.get()); - ASSERT(lengthValue->ToInteger() >= 3); -#endif - - auto propertyValue = pdfium::MakeUnique(pIsolate); - auto jsObjectValue = pdfium::MakeUnique(pIsolate); - argOne->GetObjectPropertyByIdx(1, propertyValue.get()); - argOne->GetObjectPropertyByIdx(2, jsObjectValue.get()); - if (!propertyValue->IsNull() || jsObjectValue->IsNull()) { - pContext->ThrowArgumentMismatchException(); - return; - } - - values[2]->Assign(jsObjectValue.get()); - } else if (argOne->IsObject()) { - values[2]->Assign(argOne.get()); - } - - values[0]->SetInteger(intVal); - values[1]->SetNull(); - args.GetReturnValue()->SetArray(values); + args.GetReturnValue()->SetFloat(log((float)(nFuture / nMount * nRate) + 1) / + log((float)(1 + nRate))); } // static -void CFXJSE_FormCalcContext::UnitType(CFXJSE_Value* pThis, - const ByteStringView& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 1) { - ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"UnitType"); +void CFXJSE_FormCalcContext::Choose(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis); + int32_t argc = args.GetLength(); + if (argc < 2) { + pContext->ThrowParamCountMismatchException(L"Choose"); return; } - std::unique_ptr unitspanValue = GetSimpleValue(pThis, args, 0); - if (unitspanValue->IsNull()) { + std::unique_ptr argOne = args.GetValue(0); + if (ValueIsNull(pThis, argOne.get())) { args.GetReturnValue()->SetNull(); return; } - ByteString unitspanString = ValueToUTF8String(unitspanValue.get()); - if (unitspanString.IsEmpty()) { - args.GetReturnValue()->SetString("in"); + int32_t iIndex = (int32_t)ValueToFloat(pThis, argOne.get()); + if (iIndex < 1) { + args.GetReturnValue()->SetString(""); return; } - enum XFA_FM2JS_VALUETYPE_ParserStatus { - VALUETYPE_START, - VALUETYPE_HAVEINVALIDCHAR, - VALUETYPE_HAVEDIGIT, - VALUETYPE_HAVEDIGITWHITE, - VALUETYPE_ISCM, - VALUETYPE_ISMM, - VALUETYPE_ISPT, - VALUETYPE_ISMP, - VALUETYPE_ISIN, - }; - unitspanString.MakeLower(); - WideString wsTypeString = WideString::FromUTF8(unitspanString.AsStringView()); - const wchar_t* pData = wsTypeString.c_str(); - int32_t u = 0; - int32_t uLen = wsTypeString.GetLength(); - while (IsWhitespace(pData[u])) - u++; + bool bFound = false; + bool bStopCounterFlags = false; + int32_t iArgIndex = 1; + int32_t iValueIndex = 0; + v8::Isolate* pIsolate = pContext->GetScriptRuntime(); + while (!bFound && !bStopCounterFlags && (iArgIndex < argc)) { + std::unique_ptr argIndexValue = args.GetValue(iArgIndex); + if (argIndexValue->IsArray()) { + auto lengthValue = pdfium::MakeUnique(pIsolate); + argIndexValue->GetObjectProperty("length", lengthValue.get()); + int32_t iLength = lengthValue->ToInteger(); + if (iLength > 3) + bStopCounterFlags = true; - XFA_FM2JS_VALUETYPE_ParserStatus eParserStatus = VALUETYPE_START; - wchar_t typeChar; - // TODO(dsinclair): Cleanup this parser, figure out what the various checks - // are for. - while (u < uLen) { - typeChar = pData[u]; - if (IsWhitespace(typeChar)) { - if (eParserStatus != VALUETYPE_HAVEDIGIT && - eParserStatus != VALUETYPE_HAVEDIGITWHITE) { - eParserStatus = VALUETYPE_ISIN; - break; - } - eParserStatus = VALUETYPE_HAVEDIGITWHITE; - } else if (IsPartOfNumberW(typeChar)) { - if (eParserStatus == VALUETYPE_HAVEDIGITWHITE) { - eParserStatus = VALUETYPE_ISIN; - break; - } - eParserStatus = VALUETYPE_HAVEDIGIT; - } else if ((typeChar == 'c' || typeChar == 'p') && (u + 1 < uLen)) { - wchar_t nextChar = pData[u + 1]; - if ((eParserStatus == VALUETYPE_START || - eParserStatus == VALUETYPE_HAVEDIGIT || - eParserStatus == VALUETYPE_HAVEDIGITWHITE) && - !IsPartOfNumberW(nextChar)) { - eParserStatus = (typeChar == 'c') ? VALUETYPE_ISCM : VALUETYPE_ISPT; - break; - } - eParserStatus = VALUETYPE_HAVEINVALIDCHAR; - } else if (typeChar == 'm' && (u + 1 < uLen)) { - wchar_t nextChar = pData[u + 1]; - if ((eParserStatus == VALUETYPE_START || - eParserStatus == VALUETYPE_HAVEDIGIT || - eParserStatus == VALUETYPE_HAVEDIGITWHITE) && - !IsPartOfNumberW(nextChar)) { - eParserStatus = VALUETYPE_ISMM; - if (nextChar == 'p' || ((u + 5 < uLen) && pData[u + 1] == 'i' && - pData[u + 2] == 'l' && pData[u + 3] == 'l' && - pData[u + 4] == 'i' && pData[u + 5] == 'p')) { - eParserStatus = VALUETYPE_ISMP; + iValueIndex += (iLength - 2); + if (iValueIndex >= iIndex) { + auto propertyValue = pdfium::MakeUnique(pIsolate); + auto jsObjectValue = pdfium::MakeUnique(pIsolate); + auto newPropertyValue = pdfium::MakeUnique(pIsolate); + argIndexValue->GetObjectPropertyByIdx(1, propertyValue.get()); + argIndexValue->GetObjectPropertyByIdx( + (iLength - 1) - (iValueIndex - iIndex), jsObjectValue.get()); + if (propertyValue->IsNull()) { + GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get()); + } else { + jsObjectValue->GetObjectProperty( + propertyValue->ToString().AsStringView(), newPropertyValue.get()); } - break; + ByteString bsChosen = ValueToUTF8String(newPropertyValue.get()); + args.GetReturnValue()->SetString(bsChosen.AsStringView()); + bFound = true; } } else { - eParserStatus = VALUETYPE_HAVEINVALIDCHAR; + iValueIndex++; + if (iValueIndex == iIndex) { + ByteString bsChosen = ValueToUTF8String(argIndexValue.get()); + args.GetReturnValue()->SetString(bsChosen.AsStringView()); + bFound = true; + } } - u++; - } - switch (eParserStatus) { - case VALUETYPE_ISCM: - args.GetReturnValue()->SetString("cm"); - break; - case VALUETYPE_ISMM: - args.GetReturnValue()->SetString("mm"); - break; - case VALUETYPE_ISPT: - args.GetReturnValue()->SetString("pt"); - break; - case VALUETYPE_ISMP: - args.GetReturnValue()->SetString("mp"); - break; - default: - args.GetReturnValue()->SetString("in"); - break; + iArgIndex++; } + if (!bFound) + args.GetReturnValue()->SetString(""); } // static -void CFXJSE_FormCalcContext::UnitValue(CFXJSE_Value* pThis, - const ByteStringView& szFuncName, - CFXJSE_Arguments& args) { - int32_t argc = args.GetLength(); - if (argc < 1 || argc > 2) { - ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"UnitValue"); +void CFXJSE_FormCalcContext::Exists(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 1) { + ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"Exists"); return; } + args.GetReturnValue()->SetInteger(args.GetValue(0)->IsObject()); +} - std::unique_ptr unitspanValue = GetSimpleValue(pThis, args, 0); - if (unitspanValue->IsNull()) { - args.GetReturnValue()->SetNull(); +// static +void CFXJSE_FormCalcContext::HasValue(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 1) { + ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"HasValue"); return; } - ByteString unitspanString = ValueToUTF8String(unitspanValue.get()); - const char* pData = unitspanString.c_str(); - if (!pData) { - args.GetReturnValue()->SetInteger(0); + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + if (!argOne->IsString()) { + args.GetReturnValue()->SetInteger(argOne->IsNumber() || + argOne->IsBoolean()); return; } - size_t u = 0; - while (IsWhitespace(pData[u])) - ++u; + ByteString valueStr = argOne->ToString(); + valueStr.TrimLeft(); + args.GetReturnValue()->SetInteger(!valueStr.IsEmpty()); +} - while (u < unitspanString.GetLength()) { - if (!IsPartOfNumber(pData[u])) - break; - ++u; +// static +void CFXJSE_FormCalcContext::Oneof(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() < 2) { + ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"Oneof"); + return; } - char* pTemp = nullptr; - double dFirstNumber = strtod(pData, &pTemp); - while (IsWhitespace(pData[u])) - ++u; - - size_t uLen = unitspanString.GetLength(); - ByteString strFirstUnit; - while (u < uLen) { - if (pData[u] == ' ') + bool bFlags = false; + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + std::vector> parameterValues; + unfoldArgs(pThis, args, ¶meterValues, 1); + for (const auto& value : parameterValues) { + if (simpleValueCompare(pThis, argOne.get(), value.get())) { + bFlags = true; break; - - strFirstUnit += pData[u]; - ++u; + } } - strFirstUnit.MakeLower(); - - ByteString strUnit; - if (argc > 1) { - std::unique_ptr unitValue = GetSimpleValue(pThis, args, 1); - ByteString unitTempString = ValueToUTF8String(unitValue.get()); - const char* pChar = unitTempString.c_str(); - size_t uVal = 0; - while (IsWhitespace(pChar[uVal])) - ++uVal; - while (uVal < unitTempString.GetLength()) { - if (!std::isdigit(pChar[uVal]) && pChar[uVal] != '.') - break; - ++uVal; - } - while (IsWhitespace(pChar[uVal])) - ++uVal; + args.GetReturnValue()->SetInteger(bFlags); +} - size_t uValLen = unitTempString.GetLength(); - while (uVal < uValLen) { - if (pChar[uVal] == ' ') - break; +// static +void CFXJSE_FormCalcContext::Within(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 3) { + ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"Within"); + return; + } - strUnit += pChar[uVal]; - ++uVal; - } - strUnit.MakeLower(); - } else { - strUnit = strFirstUnit; + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + if (argOne->IsNull()) { + args.GetReturnValue()->SetUndefined(); + return; } - double dResult = 0; - if (strFirstUnit == "in" || strFirstUnit == "inches") { - if (strUnit == "mm" || strUnit == "millimeters") - dResult = dFirstNumber * 25.4; - else if (strUnit == "cm" || strUnit == "centimeters") - dResult = dFirstNumber * 2.54; - else if (strUnit == "pt" || strUnit == "points") - dResult = dFirstNumber / 72; - else if (strUnit == "mp" || strUnit == "millipoints") - dResult = dFirstNumber / 72000; - else - dResult = dFirstNumber; - } else if (strFirstUnit == "mm" || strFirstUnit == "millimeters") { - if (strUnit == "mm" || strUnit == "millimeters") - dResult = dFirstNumber; - else if (strUnit == "cm" || strUnit == "centimeters") - dResult = dFirstNumber / 10; - else if (strUnit == "pt" || strUnit == "points") - dResult = dFirstNumber / 25.4 / 72; - else if (strUnit == "mp" || strUnit == "millipoints") - dResult = dFirstNumber / 25.4 / 72000; - else - dResult = dFirstNumber / 25.4; - } else if (strFirstUnit == "cm" || strFirstUnit == "centimeters") { - if (strUnit == "mm" || strUnit == "millimeters") - dResult = dFirstNumber * 10; - else if (strUnit == "cm" || strUnit == "centimeters") - dResult = dFirstNumber; - else if (strUnit == "pt" || strUnit == "points") - dResult = dFirstNumber / 2.54 / 72; - else if (strUnit == "mp" || strUnit == "millipoints") - dResult = dFirstNumber / 2.54 / 72000; - else - dResult = dFirstNumber / 2.54; - } else if (strFirstUnit == "pt" || strFirstUnit == "points") { - if (strUnit == "mm" || strUnit == "millimeters") - dResult = dFirstNumber / 72 * 25.4; - else if (strUnit == "cm" || strUnit == "centimeters") - dResult = dFirstNumber / 72 * 2.54; - else if (strUnit == "pt" || strUnit == "points") - dResult = dFirstNumber; - else if (strUnit == "mp" || strUnit == "millipoints") - dResult = dFirstNumber * 1000; - else - dResult = dFirstNumber / 72; - } else if (strFirstUnit == "mp" || strFirstUnit == "millipoints") { - if (strUnit == "mm" || strUnit == "millimeters") - dResult = dFirstNumber / 72000 * 25.4; - else if (strUnit == "cm" || strUnit == "centimeters") - dResult = dFirstNumber / 72000 * 2.54; - else if (strUnit == "pt" || strUnit == "points") - dResult = dFirstNumber / 1000; - else if (strUnit == "mp" || strUnit == "millipoints") - dResult = dFirstNumber; - else - dResult = dFirstNumber / 72000; + std::unique_ptr argLow = GetSimpleValue(pThis, args, 1); + std::unique_ptr argHigh = GetSimpleValue(pThis, args, 2); + if (argOne->IsNumber()) { + float oneNumber = ValueToFloat(pThis, argOne.get()); + float lowNumber = ValueToFloat(pThis, argLow.get()); + float heightNumber = ValueToFloat(pThis, argHigh.get()); + args.GetReturnValue()->SetInteger((oneNumber >= lowNumber) && + (oneNumber <= heightNumber)); + return; } - args.GetReturnValue()->SetDouble(dResult); + + ByteString oneString = ValueToUTF8String(argOne.get()); + ByteString lowString = ValueToUTF8String(argLow.get()); + ByteString heightString = ValueToUTF8String(argHigh.get()); + args.GetReturnValue()->SetInteger( + (oneString.Compare(lowString.AsStringView()) >= 0) && + (oneString.Compare(heightString.AsStringView()) <= 0)); } // static -void CFXJSE_FormCalcContext::At(CFXJSE_Value* pThis, +void CFXJSE_FormCalcContext::If(CFXJSE_Value* pThis, const ByteStringView& szFuncName, CFXJSE_Arguments& args) { - if (args.GetLength() != 2) { - ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"At"); + if (args.GetLength() != 3) { + ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"If"); return; } - std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); - std::unique_ptr argTwo = GetSimpleValue(pThis, args, 1); - if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get())) { + args.GetReturnValue()->Assign(GetSimpleValue(pThis, args, 0)->ToBoolean() + ? GetSimpleValue(pThis, args, 1).get() + : GetSimpleValue(pThis, args, 2).get()); +} + +// static +void CFXJSE_FormCalcContext::Eval(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis); + if (args.GetLength() != 1) { + pContext->ThrowParamCountMismatchException(L"Eval"); + return; + } + + v8::Isolate* pIsolate = pContext->GetScriptRuntime(); + std::unique_ptr scriptValue = GetSimpleValue(pThis, args, 0); + ByteString utf8ScriptString = ValueToUTF8String(scriptValue.get()); + if (utf8ScriptString.IsEmpty()) { args.GetReturnValue()->SetNull(); return; } - ByteString stringTwo = ValueToUTF8String(argTwo.get()); - if (stringTwo.IsEmpty()) { - args.GetReturnValue()->SetInteger(1); - return; - } + CFX_WideTextBuf wsJavaScriptBuf; + if (!CFXJSE_FormCalcContext::Translate( + WideString::FromUTF8(utf8ScriptString.AsStringView()).AsStringView(), + &wsJavaScriptBuf)) { + pContext->ThrowCompilerErrorException(); + return; + } + + std::unique_ptr pNewContext( + CFXJSE_Context::Create(pIsolate, nullptr, nullptr)); - ByteString stringOne = ValueToUTF8String(argOne.get()); - auto pos = stringOne.Find(stringTwo.AsStringView()); - args.GetReturnValue()->SetInteger(pos.has_value() ? pos.value() + 1 : 0); + auto returnValue = pdfium::MakeUnique(pIsolate); + pNewContext->ExecuteScript( + FX_UTF8Encode(wsJavaScriptBuf.AsStringView()).c_str(), returnValue.get()); + + args.GetReturnValue()->Assign(returnValue.get()); } // static -void CFXJSE_FormCalcContext::Concat(CFXJSE_Value* pThis, - const ByteStringView& szFuncName, - CFXJSE_Arguments& args) { - int32_t argc = args.GetLength(); - if (argc < 1) { - ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"Concat"); +void CFXJSE_FormCalcContext::Ref(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis); + v8::Isolate* pIsolate = pContext->GetScriptRuntime(); + if (args.GetLength() != 1) { + pContext->ThrowParamCountMismatchException(L"Ref"); return; } - ByteString resultString; - bool bAllNull = true; - for (int32_t i = 0; i < argc; i++) { - std::unique_ptr value = GetSimpleValue(pThis, args, i); - if (ValueIsNull(pThis, value.get())) - continue; - - bAllNull = false; - resultString += ValueToUTF8String(value.get()); + std::unique_ptr argOne = args.GetValue(0); + if (!argOne->IsArray() && !argOne->IsObject() && !argOne->IsBoolean() && + !argOne->IsString() && !argOne->IsNull() && !argOne->IsNumber()) { + pContext->ThrowArgumentMismatchException(); + return; } - if (bAllNull) { - args.GetReturnValue()->SetNull(); + if (argOne->IsBoolean() || argOne->IsString() || argOne->IsNumber()) { + args.GetReturnValue()->Assign(argOne.get()); return; } - args.GetReturnValue()->SetString(resultString.AsStringView()); -} + std::vector> values; + for (int32_t i = 0; i < 3; i++) + values.push_back(pdfium::MakeUnique(pIsolate)); -// static -void CFXJSE_FormCalcContext::Decode(CFXJSE_Value* pThis, - const ByteStringView& szFuncName, - CFXJSE_Arguments& args) { - int32_t argc = args.GetLength(); - if (argc < 1 || argc > 2) { - ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"Decode"); - return; - } + int intVal = 3; + if (argOne->IsNull()) { + // TODO(dsinclair): Why is this 4 when the others are all 3? + intVal = 4; + values[2]->SetNull(); + } else if (argOne->IsArray()) { +#ifndef NDEBUG + auto lengthValue = pdfium::MakeUnique(pIsolate); + argOne->GetObjectProperty("length", lengthValue.get()); + ASSERT(lengthValue->ToInteger() >= 3); +#endif - if (argc == 1) { - std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); - if (ValueIsNull(pThis, argOne.get())) { - args.GetReturnValue()->SetNull(); + auto propertyValue = pdfium::MakeUnique(pIsolate); + auto jsObjectValue = pdfium::MakeUnique(pIsolate); + argOne->GetObjectPropertyByIdx(1, propertyValue.get()); + argOne->GetObjectPropertyByIdx(2, jsObjectValue.get()); + if (!propertyValue->IsNull() || jsObjectValue->IsNull()) { + pContext->ThrowArgumentMismatchException(); return; } - WideString decoded = DecodeURL( - WideString::FromUTF8(ValueToUTF8String(argOne.get()).AsStringView())); + values[2]->Assign(jsObjectValue.get()); + } else if (argOne->IsObject()) { + values[2]->Assign(argOne.get()); + } - args.GetReturnValue()->SetString( - FX_UTF8Encode(decoded.AsStringView()).AsStringView()); + values[0]->SetInteger(intVal); + values[1]->SetNull(); + args.GetReturnValue()->SetArray(values); +} + +// static +void CFXJSE_FormCalcContext::UnitType(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 1) { + ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"UnitType"); return; } - std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); - std::unique_ptr argTwo = GetSimpleValue(pThis, args, 1); - if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get())) { + std::unique_ptr unitspanValue = GetSimpleValue(pThis, args, 0); + if (unitspanValue->IsNull()) { args.GetReturnValue()->SetNull(); return; } - ByteString toDecodeString = ValueToUTF8String(argOne.get()); - ByteString identifyString = ValueToUTF8String(argTwo.get()); - WideString decoded; - - WideString toDecodeWideString = - WideString::FromUTF8(toDecodeString.AsStringView()); - - if (identifyString.EqualNoCase("html")) - decoded = DecodeHTML(toDecodeWideString); - else if (identifyString.EqualNoCase("xml")) - decoded = DecodeXML(toDecodeWideString); - else - decoded = DecodeURL(toDecodeWideString); - - args.GetReturnValue()->SetString( - FX_UTF8Encode(decoded.AsStringView()).AsStringView()); -} - -// static -WideString CFXJSE_FormCalcContext::DecodeURL(const WideString& wsURLString) { - const wchar_t* pData = wsURLString.c_str(); - size_t i = 0; - CFX_WideTextBuf wsResultBuf; - while (i < wsURLString.GetLength()) { - wchar_t ch = pData[i]; - if ('%' != ch) { - wsResultBuf.AppendChar(ch); - ++i; - continue; - } - - wchar_t chTemp = 0; - int32_t iCount = 0; - while (iCount < 2) { - ++i; - ch = pData[i]; - if (ch <= '9' && ch >= '0') { - // TODO(dsinclair): Premultiply and add rather then scale. - chTemp += (ch - '0') * (!iCount ? 16 : 1); - } else if (ch <= 'F' && ch >= 'A') { - chTemp += (ch - 'A' + 10) * (!iCount ? 16 : 1); - } else if (ch <= 'f' && ch >= 'a') { - chTemp += (ch - 'a' + 10) * (!iCount ? 16 : 1); - } else { - return WideString(); - } - ++iCount; - } - wsResultBuf.AppendChar(chTemp); - ++i; + ByteString unitspanString = ValueToUTF8String(unitspanValue.get()); + if (unitspanString.IsEmpty()) { + args.GetReturnValue()->SetString("in"); + return; } - wsResultBuf.AppendChar(0); - return wsResultBuf.MakeString(); -} -// static -WideString CFXJSE_FormCalcContext::DecodeHTML(const WideString& wsHTMLString) { - wchar_t strString[9]; - size_t iStrIndex = 0; - size_t iLen = wsHTMLString.GetLength(); - size_t i = 0; - int32_t iCode = 0; - const wchar_t* pData = wsHTMLString.c_str(); - CFX_WideTextBuf wsResultBuf; - while (i < iLen) { - wchar_t ch = pData[i]; - if (ch != '&') { - wsResultBuf.AppendChar(ch); - ++i; - continue; - } + enum XFA_FM2JS_VALUETYPE_ParserStatus { + VALUETYPE_START, + VALUETYPE_HAVEINVALIDCHAR, + VALUETYPE_HAVEDIGIT, + VALUETYPE_HAVEDIGITWHITE, + VALUETYPE_ISCM, + VALUETYPE_ISMM, + VALUETYPE_ISPT, + VALUETYPE_ISMP, + VALUETYPE_ISIN, + }; + unitspanString.MakeLower(); + WideString wsTypeString = WideString::FromUTF8(unitspanString.AsStringView()); + const wchar_t* pData = wsTypeString.c_str(); + int32_t u = 0; + int32_t uLen = wsTypeString.GetLength(); + while (IsWhitespace(pData[u])) + u++; - ++i; - ch = pData[i]; - if (ch == '#') { - ++i; - ch = pData[i]; - if (ch != 'x' && ch != 'X') { - return WideString(); + XFA_FM2JS_VALUETYPE_ParserStatus eParserStatus = VALUETYPE_START; + wchar_t typeChar; + // TODO(dsinclair): Cleanup this parser, figure out what the various checks + // are for. + while (u < uLen) { + typeChar = pData[u]; + if (IsWhitespace(typeChar)) { + if (eParserStatus != VALUETYPE_HAVEDIGIT && + eParserStatus != VALUETYPE_HAVEDIGITWHITE) { + eParserStatus = VALUETYPE_ISIN; + break; } - - ++i; - ch = pData[i]; - if ((ch >= '0' && ch <= '9') || (ch <= 'f' && ch >= 'a') || - (ch <= 'F' && ch >= 'A')) { - while (ch != ';' && i < iLen) { - if (ch >= '0' && ch <= '9') { - iCode += ch - '0'; - } else if (ch <= 'f' && ch >= 'a') { - iCode += ch - 'a' + 10; - } else if (ch <= 'F' && ch >= 'A') { - iCode += ch - 'A' + 10; - } else { - return WideString(); - } - ++i; - // TODO(dsinclair): Postmultiply seems wrong, start at zero - // and pre-multiply then can remove the post divide. - iCode *= 16; - ch = pData[i]; + eParserStatus = VALUETYPE_HAVEDIGITWHITE; + } else if (IsPartOfNumberW(typeChar)) { + if (eParserStatus == VALUETYPE_HAVEDIGITWHITE) { + eParserStatus = VALUETYPE_ISIN; + break; + } + eParserStatus = VALUETYPE_HAVEDIGIT; + } else if ((typeChar == 'c' || typeChar == 'p') && (u + 1 < uLen)) { + wchar_t nextChar = pData[u + 1]; + if ((eParserStatus == VALUETYPE_START || + eParserStatus == VALUETYPE_HAVEDIGIT || + eParserStatus == VALUETYPE_HAVEDIGITWHITE) && + !IsPartOfNumberW(nextChar)) { + eParserStatus = (typeChar == 'c') ? VALUETYPE_ISCM : VALUETYPE_ISPT; + break; + } + eParserStatus = VALUETYPE_HAVEINVALIDCHAR; + } else if (typeChar == 'm' && (u + 1 < uLen)) { + wchar_t nextChar = pData[u + 1]; + if ((eParserStatus == VALUETYPE_START || + eParserStatus == VALUETYPE_HAVEDIGIT || + eParserStatus == VALUETYPE_HAVEDIGITWHITE) && + !IsPartOfNumberW(nextChar)) { + eParserStatus = VALUETYPE_ISMM; + if (nextChar == 'p' || ((u + 5 < uLen) && pData[u + 1] == 'i' && + pData[u + 2] == 'l' && pData[u + 3] == 'l' && + pData[u + 4] == 'i' && pData[u + 5] == 'p')) { + eParserStatus = VALUETYPE_ISMP; } - iCode /= 16; - } - } else { - while (ch != ';' && i < iLen) { - strString[iStrIndex++] = ch; - ++i; - ch = pData[i]; + break; } - strString[iStrIndex] = 0; - } - uint32_t iData = 0; - if (HTMLSTR2Code(strString, &iData)) { - wsResultBuf.AppendChar((wchar_t)iData); } else { - wsResultBuf.AppendChar(iCode); + eParserStatus = VALUETYPE_HAVEINVALIDCHAR; } - iStrIndex = 0; - strString[iStrIndex] = 0; - ++i; + u++; + } + switch (eParserStatus) { + case VALUETYPE_ISCM: + args.GetReturnValue()->SetString("cm"); + break; + case VALUETYPE_ISMM: + args.GetReturnValue()->SetString("mm"); + break; + case VALUETYPE_ISPT: + args.GetReturnValue()->SetString("pt"); + break; + case VALUETYPE_ISMP: + args.GetReturnValue()->SetString("mp"); + break; + default: + args.GetReturnValue()->SetString("in"); + break; } - wsResultBuf.AppendChar(0); - - return wsResultBuf.MakeString(); } // static -WideString CFXJSE_FormCalcContext::DecodeXML(const WideString& wsXMLString) { - wchar_t strString[9]; - int32_t iStrIndex = 0; - int32_t iLen = wsXMLString.GetLength(); - int32_t i = 0; - int32_t iCode = 0; - wchar_t ch = 0; - const wchar_t* pData = wsXMLString.c_str(); - CFX_WideTextBuf wsResultBuf; - while (i < iLen) { - ch = pData[i]; - if (ch != '&') { - wsResultBuf.AppendChar(ch); - ++i; - continue; - } +void CFXJSE_FormCalcContext::UnitValue(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + int32_t argc = args.GetLength(); + if (argc < 1 || argc > 2) { + ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"UnitValue"); + return; + } - // TODO(dsinclair): This is very similar to DecodeHTML, can they be - // combined? - ++i; - ch = pData[i]; - if (ch == '#') { - ++i; - ch = pData[i]; - if (ch != 'x' && ch != 'X') { - return WideString(); - } + std::unique_ptr unitspanValue = GetSimpleValue(pThis, args, 0); + if (unitspanValue->IsNull()) { + args.GetReturnValue()->SetNull(); + return; + } - ++i; - ch = pData[i]; - if ((ch >= '0' && ch <= '9') || (ch <= 'f' && ch >= 'a') || - (ch <= 'F' && ch >= 'A')) { - while (ch != ';') { - if (ch >= '0' && ch <= '9') { - iCode += ch - '0'; - } else if (ch <= 'f' && ch >= 'a') { - iCode += ch - 'a' + 10; - } else if (ch <= 'F' && ch >= 'A') { - iCode += ch - 'A' + 10; - } else { - return WideString(); - } - ++i; - iCode *= 16; - ch = pData[i]; - } - iCode /= 16; - } - } else { - while (ch != ';' && i < iLen) { - strString[iStrIndex++] = ch; - ++i; - ch = pData[i]; - } - strString[iStrIndex] = 0; - } + ByteString unitspanString = ValueToUTF8String(unitspanValue.get()); + const char* pData = unitspanString.c_str(); + if (!pData) { + args.GetReturnValue()->SetInteger(0); + return; + } - const wchar_t* const strName[] = {L"quot", L"amp", L"apos", L"lt", L"gt"}; - int32_t iIndex = 0; - while (iIndex < 5) { - if (memcmp(strString, strName[iIndex], wcslen(strName[iIndex])) == 0) { + size_t u = 0; + while (IsWhitespace(pData[u])) + ++u; + + while (u < unitspanString.GetLength()) { + if (!IsPartOfNumber(pData[u])) + break; + ++u; + } + + char* pTemp = nullptr; + double dFirstNumber = strtod(pData, &pTemp); + while (IsWhitespace(pData[u])) + ++u; + + size_t uLen = unitspanString.GetLength(); + ByteString strFirstUnit; + while (u < uLen) { + if (pData[u] == ' ') + break; + + strFirstUnit += pData[u]; + ++u; + } + strFirstUnit.MakeLower(); + + ByteString strUnit; + if (argc > 1) { + std::unique_ptr unitValue = GetSimpleValue(pThis, args, 1); + ByteString unitTempString = ValueToUTF8String(unitValue.get()); + const char* pChar = unitTempString.c_str(); + size_t uVal = 0; + while (IsWhitespace(pChar[uVal])) + ++uVal; + + while (uVal < unitTempString.GetLength()) { + if (!std::isdigit(pChar[uVal]) && pChar[uVal] != '.') break; - } - ++iIndex; + ++uVal; } - switch (iIndex) { - case 0: - wsResultBuf.AppendChar('"'); - break; - case 1: - wsResultBuf.AppendChar('&'); - break; - case 2: - wsResultBuf.AppendChar('\''); - break; - case 3: - wsResultBuf.AppendChar('<'); - break; - case 4: - wsResultBuf.AppendChar('>'); - break; - default: - wsResultBuf.AppendChar(iCode); + while (IsWhitespace(pChar[uVal])) + ++uVal; + + size_t uValLen = unitTempString.GetLength(); + while (uVal < uValLen) { + if (pChar[uVal] == ' ') break; + + strUnit += pChar[uVal]; + ++uVal; } - iStrIndex = 0; - strString[iStrIndex] = 0; - ++i; - iCode = 0; + strUnit.MakeLower(); + } else { + strUnit = strFirstUnit; } - wsResultBuf.AppendChar(0); - return wsResultBuf.MakeString(); -} -// static -void CFXJSE_FormCalcContext::Encode(CFXJSE_Value* pThis, - const ByteStringView& szFuncName, - CFXJSE_Arguments& args) { - int32_t argc = args.GetLength(); - if (argc < 1 || argc > 2) { - ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"Encode"); - return; + double dResult = 0; + if (strFirstUnit == "in" || strFirstUnit == "inches") { + if (strUnit == "mm" || strUnit == "millimeters") + dResult = dFirstNumber * 25.4; + else if (strUnit == "cm" || strUnit == "centimeters") + dResult = dFirstNumber * 2.54; + else if (strUnit == "pt" || strUnit == "points") + dResult = dFirstNumber / 72; + else if (strUnit == "mp" || strUnit == "millipoints") + dResult = dFirstNumber / 72000; + else + dResult = dFirstNumber; + } else if (strFirstUnit == "mm" || strFirstUnit == "millimeters") { + if (strUnit == "mm" || strUnit == "millimeters") + dResult = dFirstNumber; + else if (strUnit == "cm" || strUnit == "centimeters") + dResult = dFirstNumber / 10; + else if (strUnit == "pt" || strUnit == "points") + dResult = dFirstNumber / 25.4 / 72; + else if (strUnit == "mp" || strUnit == "millipoints") + dResult = dFirstNumber / 25.4 / 72000; + else + dResult = dFirstNumber / 25.4; + } else if (strFirstUnit == "cm" || strFirstUnit == "centimeters") { + if (strUnit == "mm" || strUnit == "millimeters") + dResult = dFirstNumber * 10; + else if (strUnit == "cm" || strUnit == "centimeters") + dResult = dFirstNumber; + else if (strUnit == "pt" || strUnit == "points") + dResult = dFirstNumber / 2.54 / 72; + else if (strUnit == "mp" || strUnit == "millipoints") + dResult = dFirstNumber / 2.54 / 72000; + else + dResult = dFirstNumber / 2.54; + } else if (strFirstUnit == "pt" || strFirstUnit == "points") { + if (strUnit == "mm" || strUnit == "millimeters") + dResult = dFirstNumber / 72 * 25.4; + else if (strUnit == "cm" || strUnit == "centimeters") + dResult = dFirstNumber / 72 * 2.54; + else if (strUnit == "pt" || strUnit == "points") + dResult = dFirstNumber; + else if (strUnit == "mp" || strUnit == "millipoints") + dResult = dFirstNumber * 1000; + else + dResult = dFirstNumber / 72; + } else if (strFirstUnit == "mp" || strFirstUnit == "millipoints") { + if (strUnit == "mm" || strUnit == "millimeters") + dResult = dFirstNumber / 72000 * 25.4; + else if (strUnit == "cm" || strUnit == "centimeters") + dResult = dFirstNumber / 72000 * 2.54; + else if (strUnit == "pt" || strUnit == "points") + dResult = dFirstNumber / 1000; + else if (strUnit == "mp" || strUnit == "millipoints") + dResult = dFirstNumber; + else + dResult = dFirstNumber / 72000; } + args.GetReturnValue()->SetDouble(dResult); +} - if (argc == 1) { - std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); - if (ValueIsNull(pThis, argOne.get())) { - args.GetReturnValue()->SetNull(); - return; - } - - WideString encoded = EncodeURL(ValueToUTF8String(argOne.get())); - args.GetReturnValue()->SetString( - FX_UTF8Encode(encoded.AsStringView()).AsStringView()); +// static +void CFXJSE_FormCalcContext::At(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 2) { + ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"At"); return; } @@ -3485,265 +3742,138 @@ void CFXJSE_FormCalcContext::Encode(CFXJSE_Value* pThis, return; } - ByteString toEncodeString = ValueToUTF8String(argOne.get()); - ByteString identifyString = ValueToUTF8String(argTwo.get()); - WideString encoded; - if (identifyString.EqualNoCase("html")) - encoded = EncodeHTML(toEncodeString); - else if (identifyString.EqualNoCase("xml")) - encoded = EncodeXML(toEncodeString); - else - encoded = EncodeURL(toEncodeString); + ByteString stringTwo = ValueToUTF8String(argTwo.get()); + if (stringTwo.IsEmpty()) { + args.GetReturnValue()->SetInteger(1); + return; + } - args.GetReturnValue()->SetString( - FX_UTF8Encode(encoded.AsStringView()).AsStringView()); + ByteString stringOne = ValueToUTF8String(argOne.get()); + auto pos = stringOne.Find(stringTwo.AsStringView()); + args.GetReturnValue()->SetInteger(pos.has_value() ? pos.value() + 1 : 0); } // static -WideString CFXJSE_FormCalcContext::EncodeURL(const ByteString& szURLString) { - WideString wsURLString = WideString::FromUTF8(szURLString.AsStringView()); - CFX_WideTextBuf wsResultBuf; - wchar_t strEncode[4]; - strEncode[0] = '%'; - strEncode[3] = 0; - wchar_t strUnsafe[] = {' ', '<', '>', '"', '#', '%', '{', '}', - '|', '\\', '^', '~', '[', ']', '`'}; - wchar_t strReserved[] = {';', '/', '?', ':', '@', '=', '&'}; - wchar_t strSpecial[] = {'$', '-', '+', '!', '*', '\'', '(', ')', ','}; - const wchar_t* strCode = L"0123456789abcdef"; - for (auto ch : wsURLString) { - int32_t i = 0; - int32_t iCount = FX_ArraySize(strUnsafe); - while (i < iCount) { - if (ch == strUnsafe[i]) { - int32_t iIndex = ch / 16; - strEncode[1] = strCode[iIndex]; - strEncode[2] = strCode[ch - iIndex * 16]; - wsResultBuf << strEncode; - break; - } - ++i; - } - if (i < iCount) - continue; - - i = 0; - iCount = FX_ArraySize(strReserved); - while (i < iCount) { - if (ch == strReserved[i]) { - int32_t iIndex = ch / 16; - strEncode[1] = strCode[iIndex]; - strEncode[2] = strCode[ch - iIndex * 16]; - wsResultBuf << strEncode; - break; - } - ++i; - } - if (i < iCount) - continue; +void CFXJSE_FormCalcContext::Concat(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + int32_t argc = args.GetLength(); + if (argc < 1) { + ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"Concat"); + return; + } - i = 0; - iCount = FX_ArraySize(strSpecial); - while (i < iCount) { - if (ch == strSpecial[i]) { - wsResultBuf.AppendChar(ch); - break; - } - ++i; - } - if (i < iCount) + ByteString resultString; + bool bAllNull = true; + for (int32_t i = 0; i < argc; i++) { + std::unique_ptr value = GetSimpleValue(pThis, args, i); + if (ValueIsNull(pThis, value.get())) continue; - if ((ch >= 0x80 && ch <= 0xff) || ch <= 0x1f || ch == 0x7f) { - int32_t iIndex = ch / 16; - strEncode[1] = strCode[iIndex]; - strEncode[2] = strCode[ch - iIndex * 16]; - wsResultBuf << strEncode; - } else if (ch >= 0x20 && ch <= 0x7e) { - wsResultBuf.AppendChar(ch); - } else { - const wchar_t iRadix = 16; - WideString strTmp; - while (ch >= iRadix) { - wchar_t tmp = strCode[ch % iRadix]; - ch /= iRadix; - strTmp += tmp; - } - strTmp += strCode[ch]; - int32_t iLen = strTmp.GetLength(); - if (iLen < 2) - break; - - int32_t iIndex = 0; - if (iLen % 2 != 0) { - strEncode[1] = '0'; - strEncode[2] = strTmp[iLen - 1]; - iIndex = iLen - 2; - } else { - strEncode[1] = strTmp[iLen - 1]; - strEncode[2] = strTmp[iLen - 2]; - iIndex = iLen - 3; - } - wsResultBuf << strEncode; - while (iIndex > 0) { - strEncode[1] = strTmp[iIndex]; - strEncode[2] = strTmp[iIndex - 1]; - iIndex -= 2; - wsResultBuf << strEncode; - } - } + bAllNull = false; + resultString += ValueToUTF8String(value.get()); } - wsResultBuf.AppendChar(0); - return wsResultBuf.MakeString(); -} -// static -WideString CFXJSE_FormCalcContext::EncodeHTML(const ByteString& szHTMLString) { - WideString wsHTMLString = WideString::FromUTF8(szHTMLString.AsStringView()); - const wchar_t* strCode = L"0123456789abcdef"; - wchar_t strEncode[9]; - strEncode[0] = '&'; - strEncode[1] = '#'; - strEncode[2] = 'x'; - strEncode[5] = ';'; - strEncode[6] = 0; - strEncode[7] = ';'; - strEncode[8] = 0; - CFX_WideTextBuf wsResultBuf; - int32_t iLen = wsHTMLString.GetLength(); - int32_t i = 0; - const wchar_t* pData = wsHTMLString.c_str(); - while (i < iLen) { - uint32_t ch = pData[i]; - WideString htmlReserve; - if (HTMLCode2STR(ch, &htmlReserve)) { - wsResultBuf.AppendChar(L'&'); - wsResultBuf << htmlReserve; - wsResultBuf.AppendChar(L';'); - } else if (ch >= 32 && ch <= 126) { - wsResultBuf.AppendChar((wchar_t)ch); - } else if (ch < 256) { - int32_t iIndex = ch / 16; - strEncode[3] = strCode[iIndex]; - strEncode[4] = strCode[ch - iIndex * 16]; - strEncode[5] = ';'; - strEncode[6] = 0; - wsResultBuf << strEncode; - } else { - int32_t iBigByte = ch / 256; - int32_t iLittleByte = ch % 256; - strEncode[3] = strCode[iBigByte / 16]; - strEncode[4] = strCode[iBigByte % 16]; - strEncode[5] = strCode[iLittleByte / 16]; - strEncode[6] = strCode[iLittleByte % 16]; - wsResultBuf << strEncode; - } - ++i; + if (bAllNull) { + args.GetReturnValue()->SetNull(); + return; } - wsResultBuf.AppendChar(0); - return wsResultBuf.MakeString(); + + args.GetReturnValue()->SetString(resultString.AsStringView()); } // static -WideString CFXJSE_FormCalcContext::EncodeXML(const ByteString& szXMLString) { - WideString wsXMLString = WideString::FromUTF8(szXMLString.AsStringView()); - CFX_WideTextBuf wsResultBuf; - wchar_t strEncode[9]; - strEncode[0] = '&'; - strEncode[1] = '#'; - strEncode[2] = 'x'; - strEncode[5] = ';'; - strEncode[6] = 0; - strEncode[7] = ';'; - strEncode[8] = 0; - const wchar_t* strCode = L"0123456789abcdef"; - for (const auto& ch : wsXMLString) { - switch (ch) { - case '"': - wsResultBuf.AppendChar('&'); - wsResultBuf << WideStringView(L"quot"); - wsResultBuf.AppendChar(';'); - break; - case '&': - wsResultBuf.AppendChar('&'); - wsResultBuf << WideStringView(L"amp"); - wsResultBuf.AppendChar(';'); - break; - case '\'': - wsResultBuf.AppendChar('&'); - wsResultBuf << WideStringView(L"apos"); - wsResultBuf.AppendChar(';'); - break; - case '<': - wsResultBuf.AppendChar('&'); - wsResultBuf << WideStringView(L"lt"); - wsResultBuf.AppendChar(';'); - break; - case '>': - wsResultBuf.AppendChar('&'); - wsResultBuf << WideStringView(L"gt"); - wsResultBuf.AppendChar(';'); - break; - default: { - if (ch >= 32 && ch <= 126) { - wsResultBuf.AppendChar(ch); - } else if (ch < 256) { - int32_t iIndex = ch / 16; - strEncode[3] = strCode[iIndex]; - strEncode[4] = strCode[ch - iIndex * 16]; - strEncode[5] = ';'; - strEncode[6] = 0; - wsResultBuf << strEncode; - } else { - int32_t iBigByte = ch / 256; - int32_t iLittleByte = ch % 256; - strEncode[3] = strCode[iBigByte / 16]; - strEncode[4] = strCode[iBigByte % 16]; - strEncode[5] = strCode[iLittleByte / 16]; - strEncode[6] = strCode[iLittleByte % 16]; - wsResultBuf << strEncode; - } - break; - } +void CFXJSE_FormCalcContext::Decode(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + int32_t argc = args.GetLength(); + if (argc < 1 || argc > 2) { + ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"Decode"); + return; + } + + if (argc == 1) { + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + if (ValueIsNull(pThis, argOne.get())) { + args.GetReturnValue()->SetNull(); + return; } + + WideString decoded = DecodeURL( + WideString::FromUTF8(ValueToUTF8String(argOne.get()).AsStringView())); + + args.GetReturnValue()->SetString( + FX_UTF8Encode(decoded.AsStringView()).AsStringView()); + return; } - wsResultBuf.AppendChar(0); - return wsResultBuf.MakeString(); -} -// static -bool CFXJSE_FormCalcContext::HTMLSTR2Code(const WideStringView& pData, - uint32_t* iCode) { - auto cmpFunc = [](const XFA_FMHtmlReserveCode& iter, - const WideStringView& val) { - // TODO(tsepez): check usage of c_str() below. - return wcscmp(val.unterminated_c_str(), iter.m_htmlReserve) > 0; - }; - const XFA_FMHtmlReserveCode* result = - std::lower_bound(std::begin(kReservesForDecode), - std::end(kReservesForDecode), pData, cmpFunc); - if (result != std::end(kReservesForEncode) && - !wcscmp(pData.unterminated_c_str(), result->m_htmlReserve)) { - *iCode = result->m_uCode; - return true; + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + std::unique_ptr argTwo = GetSimpleValue(pThis, args, 1); + if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get())) { + args.GetReturnValue()->SetNull(); + return; } - return false; + + ByteString toDecodeString = ValueToUTF8String(argOne.get()); + ByteString identifyString = ValueToUTF8String(argTwo.get()); + WideString decoded; + + WideString toDecodeWideString = + WideString::FromUTF8(toDecodeString.AsStringView()); + + if (identifyString.EqualNoCase("html")) + decoded = DecodeHTML(toDecodeWideString); + else if (identifyString.EqualNoCase("xml")) + decoded = DecodeXML(toDecodeWideString); + else + decoded = DecodeURL(toDecodeWideString); + + args.GetReturnValue()->SetString( + FX_UTF8Encode(decoded.AsStringView()).AsStringView()); } // static -bool CFXJSE_FormCalcContext::HTMLCode2STR(uint32_t iCode, - WideString* wsHTMLReserve) { - auto cmpFunc = [](const XFA_FMHtmlReserveCode iter, const uint32_t& val) { - return iter.m_uCode < val; - }; - const XFA_FMHtmlReserveCode* result = - std::lower_bound(std::begin(kReservesForEncode), - std::end(kReservesForEncode), iCode, cmpFunc); - if (result != std::end(kReservesForEncode) && result->m_uCode == iCode) { - *wsHTMLReserve = result->m_htmlReserve; - return true; +void CFXJSE_FormCalcContext::Encode(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + int32_t argc = args.GetLength(); + if (argc < 1 || argc > 2) { + ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"Encode"); + return; } - return false; + + if (argc == 1) { + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + if (ValueIsNull(pThis, argOne.get())) { + args.GetReturnValue()->SetNull(); + return; + } + + WideString encoded = EncodeURL(ValueToUTF8String(argOne.get())); + args.GetReturnValue()->SetString( + FX_UTF8Encode(encoded.AsStringView()).AsStringView()); + return; + } + + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + std::unique_ptr argTwo = GetSimpleValue(pThis, args, 1); + if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get())) { + args.GetReturnValue()->SetNull(); + return; + } + + ByteString toEncodeString = ValueToUTF8String(argOne.get()); + ByteString identifyString = ValueToUTF8String(argTwo.get()); + WideString encoded; + if (identifyString.EqualNoCase("html")) + encoded = EncodeHTML(toEncodeString); + else if (identifyString.EqualNoCase("xml")) + encoded = EncodeXML(toEncodeString); + else + encoded = EncodeURL(toEncodeString); + + args.GetReturnValue()->SetString( + FX_UTF8Encode(encoded.AsStringView()).AsStringView()); } // static @@ -4492,157 +4622,6 @@ void CFXJSE_FormCalcContext::WordNum(CFXJSE_Value* pThis, WordUS(ByteString::Format("%.2f", fNumber), iIdentifier).AsStringView()); } -// static -ByteString CFXJSE_FormCalcContext::TrillionUS(const ByteStringView& szData) { - std::ostringstream strBuf; - ByteStringView pUnits[] = {"zero", "one", "two", "three", "four", - "five", "six", "seven", "eight", "nine"}; - ByteStringView pCapUnits[] = {"Zero", "One", "Two", "Three", "Four", - "Five", "Six", "Seven", "Eight", "Nine"}; - ByteStringView pTens[] = {"Ten", "Eleven", "Twelve", "Thirteen", - "Fourteen", "Fifteen", "Sixteen", "Seventeen", - "Eighteen", "Nineteen"}; - ByteStringView pLastTens[] = {"Twenty", "Thirty", "Forty", "Fifty", - "Sixty", "Seventy", "Eighty", "Ninety"}; - ByteStringView pComm[] = {" Hundred ", " Thousand ", " Million ", " Billion ", - "Trillion"}; - const char* pData = szData.unterminated_c_str(); - int32_t iLength = szData.GetLength(); - int32_t iComm = 0; - if (iLength > 12) - iComm = 4; - else if (iLength > 9) - iComm = 3; - else if (iLength > 6) - iComm = 2; - else if (iLength > 3) - iComm = 1; - - int32_t iFirstCount = iLength % 3; - if (iFirstCount == 0) - iFirstCount = 3; - - int32_t iIndex = 0; - if (iFirstCount == 3) { - if (pData[iIndex] != '0') { - strBuf << pCapUnits[pData[iIndex] - '0']; - strBuf << pComm[0]; - } - if (pData[iIndex + 1] == '0') { - strBuf << pCapUnits[pData[iIndex + 2] - '0']; - } else { - if (pData[iIndex + 1] > '1') { - strBuf << pLastTens[pData[iIndex + 1] - '2']; - strBuf << "-"; - strBuf << pUnits[pData[iIndex + 2] - '0']; - } else if (pData[iIndex + 1] == '1') { - strBuf << pTens[pData[iIndex + 2] - '0']; - } else if (pData[iIndex + 1] == '0') { - strBuf << pCapUnits[pData[iIndex + 2] - '0']; - } - } - iIndex += 3; - } else if (iFirstCount == 2) { - if (pData[iIndex] == '0') { - strBuf << pCapUnits[pData[iIndex + 1] - '0']; - } else { - if (pData[iIndex] > '1') { - strBuf << pLastTens[pData[iIndex] - '2']; - strBuf << "-"; - strBuf << pUnits[pData[iIndex + 1] - '0']; - } else if (pData[iIndex] == '1') { - strBuf << pTens[pData[iIndex + 1] - '0']; - } else if (pData[iIndex] == '0') { - strBuf << pCapUnits[pData[iIndex + 1] - '0']; - } - } - iIndex += 2; - } else if (iFirstCount == 1) { - strBuf << pCapUnits[pData[iIndex] - '0']; - iIndex += 1; - } - if (iLength > 3 && iFirstCount > 0) { - strBuf << pComm[iComm]; - --iComm; - } - while (iIndex < iLength) { - if (pData[iIndex] != '0') { - strBuf << pCapUnits[pData[iIndex] - '0']; - strBuf << pComm[0]; - } - if (pData[iIndex + 1] == '0') { - strBuf << pCapUnits[pData[iIndex + 2] - '0']; - } else { - if (pData[iIndex + 1] > '1') { - strBuf << pLastTens[pData[iIndex + 1] - '2']; - strBuf << "-"; - strBuf << pUnits[pData[iIndex + 2] - '0']; - } else if (pData[iIndex + 1] == '1') { - strBuf << pTens[pData[iIndex + 2] - '0']; - } else if (pData[iIndex + 1] == '0') { - strBuf << pCapUnits[pData[iIndex + 2] - '0']; - } - } - if (iIndex < iLength - 3) { - strBuf << pComm[iComm]; - --iComm; - } - iIndex += 3; - } - return ByteString(strBuf); -} - -// static -ByteString CFXJSE_FormCalcContext::WordUS(const ByteString& szData, - int32_t iStyle) { - const char* pData = szData.c_str(); - int32_t iLength = szData.GetLength(); - if (iStyle < 0 || iStyle > 2) { - return ByteString(); - } - - std::ostringstream strBuf; - - int32_t iIndex = 0; - while (iIndex < iLength) { - if (pData[iIndex] == '.') - break; - ++iIndex; - } - int32_t iInteger = iIndex; - iIndex = 0; - while (iIndex < iInteger) { - int32_t iCount = (iInteger - iIndex) % 12; - if (!iCount && iInteger - iIndex > 0) - iCount = 12; - - strBuf << TrillionUS(ByteStringView(pData + iIndex, iCount)); - iIndex += iCount; - if (iIndex < iInteger) - strBuf << " Trillion "; - } - - if (iStyle > 0) - strBuf << " Dollars"; - - if (iStyle > 1 && iInteger < iLength) { - strBuf << " And "; - iIndex = iInteger + 1; - while (iIndex < iLength) { - int32_t iCount = (iLength - iIndex) % 12; - if (!iCount && iLength - iIndex > 0) - iCount = 12; - - strBuf << TrillionUS(ByteStringView(pData + iIndex, iCount)); - iIndex += iCount; - if (iIndex < iLength) - strBuf << " Trillion "; - } - strBuf << " Cents"; - } - return ByteString(strBuf); -} - // static void CFXJSE_FormCalcContext::Get(CFXJSE_Value* pThis, const ByteStringView& szFuncName, diff --git a/fxjs/cfxjse_formcalc_context.h b/fxjs/cfxjse_formcalc_context.h index 8a92d9b0f1..f60560315e 100644 --- a/fxjs/cfxjse_formcalc_context.h +++ b/fxjs/cfxjse_formcalc_context.h @@ -98,31 +98,6 @@ class CFXJSE_FormCalcContext : public CFXJSE_HostObject { const ByteStringView& szFuncName, CFXJSE_Arguments& args); - static bool IsIsoDateFormat(const char* pData, - int32_t iLength, - int32_t& iStyle, - int32_t& iYear, - int32_t& iMonth, - int32_t& iDay); - static bool IsIsoTimeFormat(const char* pData, - int32_t iLength, - int32_t& iHour, - int32_t& iMinute, - int32_t& iSecond, - int32_t& iMilliSecond, - int32_t& iZoneHour, - int32_t& iZoneMinute); - static bool IsIsoDateTimeFormat(const char* pData, - int32_t iLength, - int32_t& iYear, - int32_t& iMonth, - int32_t& iDay, - int32_t& iHour, - int32_t& iMinute, - int32_t& iSecond, - int32_t& iMillionSecond, - int32_t& iZoneHour, - int32_t& iZoneMinute); static ByteString Local2IsoDate(CFXJSE_Value* pThis, const ByteStringView& szDate, const ByteStringView& szFormat, @@ -135,7 +110,6 @@ class CFXJSE_FormCalcContext : public CFXJSE_HostObject { const ByteStringView& szTime, const ByteStringView& szFormat, const ByteStringView& szLocale); - static int32_t DateString2Num(const ByteStringView& szDateString); static ByteString GetLocalDateFormat(CFXJSE_Value* pThis, int32_t iStyle, const ByteStringView& szLocalStr, @@ -155,7 +129,6 @@ class CFXJSE_FormCalcContext : public CFXJSE_HostObject { const ByteStringView& szFormat, const ByteStringView& szLocale, bool bGM); - static void GetLocalTimeZone(int32_t& iHour, int32_t& iMin, int32_t& iSec); static void Apr(CFXJSE_Value* pThis, const ByteStringView& szFuncName, @@ -227,17 +200,9 @@ class CFXJSE_FormCalcContext : public CFXJSE_HostObject { static void Decode(CFXJSE_Value* pThis, const ByteStringView& szFuncName, CFXJSE_Arguments& args); - static WideString DecodeURL(const WideString& wsURLString); - static WideString DecodeHTML(const WideString& wsHTMLString); - static WideString DecodeXML(const WideString& wsXMLString); static void Encode(CFXJSE_Value* pThis, const ByteStringView& szFuncName, CFXJSE_Arguments& args); - static WideString EncodeURL(const ByteString& szURLString); - static WideString EncodeHTML(const ByteString& szHTMLString); - static WideString EncodeXML(const ByteString& szXMLString); - static bool HTMLSTR2Code(const WideStringView& pData, uint32_t* iCode); - static bool HTMLCode2STR(uint32_t iCode, WideString* wsHTMLReserve); static void Format(CFXJSE_Value* pThis, const ByteStringView& szFuncName, CFXJSE_Arguments& args); @@ -286,8 +251,6 @@ class CFXJSE_FormCalcContext : public CFXJSE_HostObject { static void WordNum(CFXJSE_Value* pThis, const ByteStringView& szFuncName, CFXJSE_Arguments& args); - static ByteString TrillionUS(const ByteStringView& szData); - static ByteString WordUS(const ByteString& szData, int32_t iStyle); static void Get(CFXJSE_Value* pThis, const ByteStringView& szFuncName, -- cgit v1.2.3