7#include "fxjs/cjs_util.h"
16#include "build/build_config.h"
17#include "core/fxcrt/fx_extension.h"
18#include "fxjs/cjs_event_context.h"
19#include "fxjs/cjs_object.h"
20#include "fxjs/cjs_publicmethods.h"
21#include "fxjs/cjs_runtime.h"
22#include "fxjs/fx_date_helpers.h"
24#include "fxjs/js_define.h"
25#include "fxjs/js_resources.h"
26#include "third_party/base/check_op.h"
27#include "third_party/base/containers/span.h"
28#include "v8/include/v8-date.h"
30#if BUILDFLAG(IS_ANDROID)
39 const wchar_t* lpszJSMark;
40 const wchar_t* lpszCppMark;
45struct TbConvertAdditional {
50const TbConvert TbConvertTable[] = {
51 {L"mmmm", L"%B"}, {L"mmm", L"%b"}, {L"mm", L"%m"}, {L"dddd", L"%A"},
52 {L"ddd", L"%a"}, {L"dd", L"%d"}, {L"yyyy", L"%Y"}, {L"yy", L"%y"},
53 {L"HH", L"%H"}, {L"hh", L"%I"}, {L"MM", L"%M"}, {L"ss", L"%S"},
56 {L"tt", L"%p"}, {L"h", L"%#I"},
58 {L"tt", L"%P"}, {L"h", L"%l"},
62enum CaseMode { kPreserveCase, kUpperCase, kLowerCase };
64wchar_t TranslateCase(
wchar_t input, CaseMode eMode) {
75 {
"printd", printd_static},
76 {
"printf", printf_static},
77 {
"printx", printx_static},
78 {
"scand", scand_static},
79 {
"byteToChar", byteToChar_static}};
81uint32_t CJS_Util::ObjDefnID = 0;
82const char CJS_Util::kName[] =
"util";
92 JSConstructor<CJS_Util>, JSDestructor);
96CJS_Util::
CJS_Util(v8::Local<v8::Object> pObject, CJS_Runtime* pRuntime)
101CJS_Result CJS_Util::printf(CJS_Runtime* pRuntime,
102 pdfium::span<v8::Local<v8::Value>> params) {
103 const size_t num_params = params.size();
109 WideString unsafe_fmt_string = L'S' + pRuntime->ToWideString(params[0]);
110 std::vector<WideString> unsafe_conversion_specifiers;
115 absl::optional<size_t> offset_end =
116 unsafe_fmt_string.Find(L"%", offset + 1);
117 if (!offset_end.has_value()) {
118 unsafe_conversion_specifiers.push_back(
119 unsafe_fmt_string.Last(unsafe_fmt_string.GetLength() - offset));
123 unsafe_conversion_specifiers.push_back(
124 unsafe_fmt_string.Substr(offset, offset_end.value() - offset));
125 offset = offset_end.value();
129 WideString result = unsafe_conversion_specifiers[0];
130 for (size_t i = 1; i < unsafe_conversion_specifiers.size(); ++i) {
131 WideString fmt = unsafe_conversion_specifiers[i];
132 if (i >= num_params) {
140 segment = WideString::Format(fmt.c_str(), pRuntime->ToInt32(params[i]));
142 case DataType::kDouble:
144 WideString::Format(fmt.c_str(), pRuntime->ToDouble(params[i]));
146 case DataType::kString:
147 segment = WideString::Format(fmt.c_str(),
148 pRuntime->ToWideString(params[i]).c_str());
158 DCHECK_EQ(L'S', result
[0
]);
159 auto result_view = result.AsStringView();
161 pRuntime->NewString(result_view.Last(result_view.GetLength() - 1))
);
164CJS_Result CJS_Util::printd(CJS_Runtime* pRuntime,
165 pdfium::span<v8::Local<v8::Value>> params) {
166 const size_t iSize = params.size();
170 if (!fxv8::IsDate(params[1]))
173 v8::Local<v8::Date> v8_date = params[1].As<v8::Date>();
174 if (v8_date.IsEmpty() || isnan(pRuntime->ToDouble(v8_date)))
177 double date = FX_LocalTime(pRuntime->ToDouble(v8_date));
185 if (params[0]->IsNumber()) {
187 switch (pRuntime->ToInt32(params[0])) {
189 swResult
= WideString
::Format(L"D:%04d%02d%02d%02d%02d%02d"
, year
,
190 month
, day
, hour
, min
, sec
);
193 swResult
= WideString
::Format(L"%04d.%02d.%02d %02d:%02d:%02d"
, year
,
194 month
, day
, hour
, min
, sec
);
197 swResult
= WideString
::Format(L"%04d/%02d/%02d %02d:%02d:%02d"
, year
,
198 month
, day
, hour
, min
, sec
);
207 if (!params[0]->IsString())
211 if (iSize > 2 && pRuntime->ToBoolean(params[2]))
216 std::wstring cFormat = pRuntime->ToWideString(params[0]).c_str();
217 cFormat.erase(
std::remove(cFormat.begin(), cFormat.end(),
'%'),
220 for (size_t i = 0; i <
std::size(TbConvertTable); ++i) {
223 nFound = cFormat.find(TbConvertTable[i].lpszJSMark, nFound);
224 if (nFound == std::wstring::npos)
227 cFormat.replace(nFound, wcslen(TbConvertTable[i].lpszJSMark),
228 TbConvertTable[i].lpszCppMark);
235 const TbConvertAdditional cTableAd[] = {
236 {L'm', month}, {L'd', day},
237 {L'H', hour}, {L'h', hour > 12 ? hour - 12 : hour},
238 {L'M', min}, {L's', sec},
241 for (size_t i = 0; i <
std::size(cTableAd); ++i) {
244 nFound = cFormat.find(cTableAd[i].js_mark, nFound);
245 if (nFound == std::wstring::npos)
248 if (nFound != 0 && cFormat[nFound - 1] == L'%') {
252 cFormat.replace(nFound, 1,
258 time.tm_year = year - 1900;
259 time.tm_mon = month - 1;
265 wchar_t buf[64] = {};
271CJS_Result CJS_Util::printx(CJS_Runtime* pRuntime,
272 pdfium::span<v8::Local<v8::Value>> params) {
273 if (params.size() < 2)
276 return CJS_Result::Success(
277 pRuntime->NewString(StringPrintx(pRuntime->ToWideString(params[0]),
278 pRuntime->ToWideString(params[1]))
284 const WideString& wsSource) {
286 wsResult.Reserve(wsFormat.GetLength());
287 size_t iSourceIdx = 0;
288 size_t iFormatIdx = 0;
289 CaseMode eCaseMode = kPreserveCase;
290 bool bEscaped =
false;
291 while (iFormatIdx < wsFormat.GetLength()) {
294 wsResult += wsFormat[iFormatIdx];
298 switch (wsFormat[iFormatIdx]) {
304 eCaseMode = kLowerCase;
308 eCaseMode = kUpperCase;
312 eCaseMode = kPreserveCase;
316 if (iSourceIdx < wsSource.GetLength()) {
317 wsResult += TranslateCase(wsSource[iSourceIdx], eCaseMode);
323 if (iSourceIdx < wsSource.GetLength()) {
324 if (isascii(wsSource[iSourceIdx]) && isalnum(wsSource[iSourceIdx])) {
325 wsResult += TranslateCase(wsSource[iSourceIdx], eCaseMode);
334 if (iSourceIdx < wsSource.GetLength()) {
335 if (isascii(wsSource[iSourceIdx]) && isalpha(wsSource[iSourceIdx])) {
336 wsResult += TranslateCase(wsSource[iSourceIdx], eCaseMode);
345 if (iSourceIdx < wsSource.GetLength()) {
346 if (FXSYS_IsDecimalDigit(wsSource[iSourceIdx])) {
347 wsResult += wsSource[iSourceIdx];
356 if (iSourceIdx < wsSource.GetLength()) {
357 wsResult += TranslateCase(wsSource[iSourceIdx], eCaseMode);
364 wsResult += wsFormat[iFormatIdx];
372CJS_Result CJS_Util::scand(CJS_Runtime* pRuntime,
373 pdfium::span<v8::Local<v8::Value>> params) {
374 if (params.size() < 2)
377 WideString sFormat = pRuntime->ToWideString(params[0]);
378 WideString sDate = pRuntime->ToWideString(params[1]);
380 if (sDate.GetLength() > 0)
381 dDate = CJS_PublicMethods::ParseDateUsingFormat(pRuntime->GetIsolate(),
382 sDate, sFormat,
nullptr);
389CJS_Result CJS_Util::byteToChar(CJS_Runtime* pRuntime,
390 pdfium::span<v8::Local<v8::Value>> params) {
391 if (params.size() < 1)
394 int arg = pRuntime->ToInt32(params[0]);
395 if (arg < 0 || arg > 255)
398 WideString wStr
(static_cast<
wchar_t>(arg)
);
404 enum State { kBefore, kFlags, kWidth, kPrecision, kSpecifier, kAfter };
407 State state = kBefore;
408 size_t precision_digits = 0;
410 while (i < sFormat->GetLength()) {
411 wchar_t c = (*sFormat)[i];
418 if (c == L'+' || c == L'-' || c == L'#' || c == L' ') {
430 }
else if (c == L'.') {
449 if (c == L'c' || c == L'C' || c == L'd' || c == L'i' || c == L'o' ||
450 c == L'u' || c == L'x' || c == L'X') {
452 }
else if (c == L'e' || c == L'E' || c == L'f' || c == L'g' ||
455 }
else if (c == L's' || c == L'S') {
459 sFormat->SetAt(i, L'S');
static void DefineMethods(CFXJS_Engine *pEngine, uint32_t nObjDefnID, pdfium::span< const JSMethodSpec > consts)
static CJS_Result Success()
static CJS_Result Failure(JSMessage id)
CJS_Util(v8::Local< v8::Object > pObject, CJS_Runtime *pRuntime)
static uint32_t GetObjDefnID()
static void DefineJSObjects(CFXJS_Engine *pEngine)
static DataType ParseDataType(WideString *sFormat)
static WideString StringPrintx(const WideString &cFormat, const WideString &cSource)
WideString & operator+=(const WideString &str)
static WideString Format(const wchar_t *pFormat,...)
WideString & operator=(WideString &&that) noexcept
CharType operator[](const size_t index) const
const wchar_t * c_str() const
static WideString FormatInteger(int i)
bool FXSYS_IsDecimalDigit(wchar_t c)
bool FXSYS_iswlower(int32_t c)
bool FXSYS_iswupper(int32_t c)
@ kSecondParamNotDateError
@ kSecondParamInvalidDateError
int FX_GetMonthFromTime(double dt)
int FX_GetYearFromTime(double dt)
int FX_GetDayFromTime(double dt)
int FX_GetSecFromTime(double dt)
int FX_GetHourFromTime(double dt)
int FX_GetMinFromTime(double dt)