Removing unnecessary casts from wchar_t* to wchar_t*, by various names.
[pdfium.git] / fpdfsdk / src / javascript / util.cpp
1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4  
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "../../include/javascript/JavaScript.h"
8 #include "../../include/javascript/IJavaScript.h"
9 #include "../../include/javascript/JS_Define.h"
10 #include "../../include/javascript/JS_Object.h"
11 #include "../../include/javascript/JS_Value.h"
12 #include "../../include/javascript/util.h"
13 #include "../../include/javascript/PublicMethods.h"
14 #include "../../include/javascript/resource.h"
15 #include "../../include/javascript/JS_Context.h"
16 #include "../../include/javascript/JS_EventHandler.h"
17 #include "../../include/javascript/JS_Runtime.h"
18
19 #if _FX_OS_  == _FX_ANDROID_
20 #include <ctype.h>
21 #endif
22
23 static v8::Isolate* GetIsolate(IFXJS_Context* cc)
24 {
25         CJS_Context* pContext = (CJS_Context *)cc;
26         ASSERT(pContext != NULL);
27
28         CJS_Runtime* pRuntime = pContext->GetJSRuntime();
29         ASSERT(pRuntime != NULL);
30
31         return pRuntime->GetIsolate();
32 }
33
34 BEGIN_JS_STATIC_CONST(CJS_Util)
35 END_JS_STATIC_CONST()
36
37 BEGIN_JS_STATIC_PROP(CJS_Util)
38 END_JS_STATIC_PROP()
39
40 BEGIN_JS_STATIC_METHOD(CJS_Util)
41         JS_STATIC_METHOD_ENTRY(printd, 3)
42         JS_STATIC_METHOD_ENTRY(printf, 20)
43         JS_STATIC_METHOD_ENTRY(printx, 2)
44         JS_STATIC_METHOD_ENTRY(scand, 2)
45         JS_STATIC_METHOD_ENTRY(byteToChar, 1)
46 END_JS_STATIC_METHOD()
47
48 IMPLEMENT_JS_CLASS(CJS_Util,util)
49
50 util::util(CJS_Object *pJSObject) : CJS_EmbedObj(pJSObject)
51 {
52 }
53
54 util::~util(void)
55 {
56 }
57
58
59 struct stru_TbConvert
60 {
61         FX_LPCWSTR lpszJSMark;
62         FX_LPCWSTR lpszCppMark;
63 };
64
65 const stru_TbConvert fcTable[] = {
66         { L"mmmm", L"%B" },
67         { L"mmm", L"%b" },
68         { L"mm",  L"%m" },
69         //"m"
70         { L"dddd", L"%A" },
71         { L"ddd", L"%a" },
72         { L"dd",  L"%d" },
73         //"d",   "%w",
74         { L"yyyy", L"%Y" },
75         { L"yy",  L"%y" },
76         { L"HH",  L"%H" },
77         //"H"
78         { L"hh",  L"%I" },
79         //"h"
80         { L"MM",  L"%M" },
81         //"M"
82         { L"ss",  L"%S" },
83         //"s
84         { L"TT",  L"%p" },
85         //"t"
86 #if defined(_WIN32)
87         { L"tt",  L"%p" },
88         { L"h",  L"%#I" },
89 #else
90         { L"tt",  L"%P" },
91         { L"h",  L"%l" },
92 #endif
93 };
94
95 #define UTIL_INT                        0
96 #define UTIL_DOUBLE                     1
97 #define UTIL_STRING                     2
98
99 int util::ParstDataType(std::wstring* sFormat)
100 {
101         size_t i = 0;
102         bool bPercent = FALSE;
103         for (i=0; i<sFormat->length(); ++i)
104         {
105                 wchar_t c = (*sFormat)[i];
106                 if (c == L'%')
107                 {
108                         bPercent = true;
109                         continue;
110                 }
111
112                 if (bPercent)
113                 {
114                         if (c == L'c' || c == L'C' || c == L'd' || c == L'i' || c == L'o' || c == L'u' || c == L'x' || c == L'X')
115                         {
116                                 return UTIL_INT;
117                         }
118                         else if (c == L'e' || c == L'E' || c == L'f' || c == L'g' || c == L'G')
119                         {
120                                 return UTIL_DOUBLE;
121                         }
122                         else if (c == L's' || c == L'S')
123                         {
124                                 // Map s to S since we always deal internally
125                                 // with wchar_t strings.
126                                 (*sFormat)[i] = L'S';
127                                 return UTIL_STRING;
128                         }
129                         else if (c == L'.' || c == L'+' || c == L'-' || c == L'#' || c == L' ' || CJS_PublicMethods::IsDigit(c))
130                         {
131                                 continue;
132                         }
133                         else break;
134                 }
135         }
136
137         return -1;
138 }
139
140 FX_BOOL util::printf(OBJ_METHOD_PARAMS)
141 {
142         int iSize = params.size();
143         if (iSize < 1)
144                 return FALSE;
145         std::wstring  c_ConvChar((const wchar_t*)(FX_LPCWSTR)params[0].operator CFX_WideString());
146         std::vector<std::wstring> c_strConvers;
147         int iOffset = 0;
148         int iOffend = 0;
149         c_ConvChar.insert(c_ConvChar.begin(),L'S');
150         while(iOffset != -1)
151         {
152                 iOffend = c_ConvChar.find(L"%",iOffset+1);
153                 std::wstring strSub;
154                 if (iOffend == -1)
155                         strSub = c_ConvChar.substr(iOffset);                    
156                 else
157                         strSub = c_ConvChar.substr(iOffset ,iOffend - iOffset);
158                 c_strConvers.push_back(strSub);
159                 iOffset = iOffend ;
160         }
161
162         std::wstring c_strResult;
163
164         //for(int iIndex = 1;iIndex < params.size();iIndex++)
165         std::wstring c_strFormat;
166         for(int iIndex = 0;iIndex < (int)c_strConvers.size();iIndex++)
167         {
168                 c_strFormat = c_strConvers[iIndex];
169                 if (iIndex == 0)
170                 {
171                         c_strResult = c_strFormat;
172                         continue;
173                 }
174
175
176                 CFX_WideString strSegment;
177                 if (iIndex >= iSize) {
178                         c_strResult += c_strFormat;
179                         continue;
180                 }
181
182                 switch (ParstDataType(&c_strFormat))
183                 {
184                         case UTIL_INT:
185                                 strSegment.Format(c_strFormat.c_str(),(int)params[iIndex]);
186                                 break;
187                         case UTIL_DOUBLE:
188                                 strSegment.Format(c_strFormat.c_str(),(double)params[iIndex]);
189                                 break;
190                         case UTIL_STRING:
191                                 strSegment.Format(c_strFormat.c_str(),(FX_LPCWSTR)params[iIndex].operator CFX_WideString());
192                                 break;
193                         default:
194                                 strSegment.Format(L"%S", c_strFormat.c_str());
195                                 break;
196                 }
197                 c_strResult += strSegment.GetBuffer(strSegment.GetLength()+1);
198         }
199
200         c_strResult.erase(c_strResult.begin());
201         vRet = c_strResult.c_str();
202         return TRUE;
203 }
204
205 FX_BOOL util::printd(OBJ_METHOD_PARAMS)
206 {
207         v8::Isolate* isolate = GetIsolate(cc);
208
209         int iSize = params.size();
210         if (iSize < 2)
211                 return FALSE;
212
213         CJS_Value p1(isolate);
214         p1 = params[0];
215
216         CJS_Value p2 = params[1];
217         CJS_Date jsDate(isolate);
218         if (!p2.ConvertToDate(jsDate))
219         {
220                 sError = JSGetStringFromID((CJS_Context*)cc, IDS_STRING_JSPRINT1);
221                 return FALSE;
222         }
223
224         if (!jsDate.IsValidDate())
225         {
226                 sError = JSGetStringFromID((CJS_Context*)cc, IDS_STRING_JSPRINT2);
227                 return FALSE;
228         }
229
230         if (p1.GetType() == VT_number)
231         {
232                 int nFormat = p1;
233
234                 CFX_WideString swResult;
235
236                 switch (nFormat)
237                 {
238                 case 0:
239                         swResult.Format(L"D:%04d%02d%02d%02d%02d%02d", 
240                                 jsDate.GetYear(),
241                                 jsDate.GetMonth() + 1,
242                                 jsDate.GetDay(),
243                                 jsDate.GetHours(),
244                                 jsDate.GetMinutes(),
245                                 jsDate.GetSeconds());
246                         break;
247                 case 1:
248                         swResult.Format(L"%04d.%02d.%02d %02d:%02d:%02d", 
249                                 jsDate.GetYear(),
250                                 jsDate.GetMonth() + 1,
251                                 jsDate.GetDay(),
252                                 jsDate.GetHours(),
253                                 jsDate.GetMinutes(),
254                                 jsDate.GetSeconds());
255                         break;
256                 case 2:
257                         swResult.Format(L"%04d/%02d/%02d %02d:%02d:%02d", 
258                                 jsDate.GetYear(),
259                                 jsDate.GetMonth() + 1,
260                                 jsDate.GetDay(),
261                                 jsDate.GetHours(),
262                                 jsDate.GetMinutes(),
263                                 jsDate.GetSeconds());
264                         break;
265                 default:
266                         return FALSE;
267                 }
268
269                 vRet = swResult;
270                 return TRUE;
271         }
272         else if (p1.GetType() == VT_string)
273         {
274                 std::basic_string<wchar_t> cFormat = (FX_LPCWSTR)p1.operator CFX_WideString();          
275
276                 bool bXFAPicture = false;
277                 if (iSize > 2)
278                 {
279                         //CJS_Value value;
280                         bXFAPicture = params[2];
281                 }
282
283                 if (bXFAPicture)
284                 {
285                         return FALSE; //currently, it doesn't support XFAPicture.
286                 }
287
288         int iIndex;
289                 for(iIndex = 0;iIndex<sizeof(fcTable)/sizeof(stru_TbConvert);iIndex++)
290                 {
291                         int iStart = 0;
292                         int iEnd;
293                         while((iEnd = cFormat.find((CFX_WideString)fcTable[iIndex].lpszJSMark, iStart)) != -1)
294                         {
295                                 cFormat.replace(iEnd, FXSYS_wcslen(fcTable[iIndex].lpszJSMark), (CFX_WideString)fcTable[iIndex].lpszCppMark);
296                                 iStart = iEnd;
297                         }
298                 }
299
300                 int iYear,iMonth,iDay,iHour,iMin,iSec;
301                 iYear = jsDate.GetYear();
302                 iMonth = jsDate.GetMonth();
303                 iDay = jsDate.GetDay();
304                 iHour = jsDate.GetHours();
305                 iMin = jsDate.GetMinutes();
306                 iSec = jsDate.GetSeconds();
307
308                 struct tm time = {0};
309                 time.tm_year = iYear-1900;
310                 time.tm_mon = iMonth;
311                 time.tm_mday = iDay;
312                 time.tm_hour = iHour;
313                 time.tm_min = iMin;
314                 time.tm_sec = iSec;
315                 //COleDateTime cppTm(iYear,iMonth+1,iDay,iHour,iMin,iSec);
316                 //CString strFormat = cppTm.Format(cFormat.c_str());
317
318                 struct stru_TbConvertAd
319                 {
320                         FX_LPCWSTR lpszJSMark;
321                         int     iValue;
322                 };
323
324                 stru_TbConvertAd cTableAd[] ={
325                         { L"m", iMonth+1 },
326                         { L"d", iDay },
327                         { L"H", iHour },
328                         { L"h", iHour>12?iHour-12:iHour },
329                         { L"M", iMin },
330                         { L"s", iSec },
331                 };
332
333                 //cFormat = strFormat.GetBuffer(strFormat.GetLength()+1);
334                 for(iIndex = 0;iIndex<sizeof(cTableAd)/sizeof(stru_TbConvertAd);iIndex++)
335                 {
336                         wchar_t tszValue[10];
337                         //_itot(cTableAd[iIndex].iValue,tszValue,10);
338                         CFX_WideString sValue;
339                         sValue.Format(L"%d",cTableAd[iIndex].iValue);
340                         memcpy(tszValue, (wchar_t *)sValue.GetBuffer(sValue.GetLength()+1),
341                                (sValue.GetLength()+1)*sizeof(wchar_t));
342
343                         //strFormat.Replace(cTableAd[iIndex].lpszJSMark,"%d");
344                         //strFormat.Format(strFormat,cTableAd[iIndex].iValue);
345                         int iStart = 0;
346                         int iEnd;
347                         while((iEnd = cFormat.find((CFX_WideString)cTableAd[iIndex].lpszJSMark,iStart)) != -1)
348                         {
349                                 if (iEnd > 0)
350                                 {
351                                         if (cFormat[iEnd-1] == L'%')
352                                         {
353                                                 iStart = iEnd+1;
354                                                 continue;
355                                         }
356                                 }
357                                 cFormat.replace(iEnd, FXSYS_wcslen(cTableAd[iIndex].lpszJSMark), tszValue);
358                                 iStart = iEnd;
359                         }
360                 }
361
362                 CFX_WideString strFormat;
363 //              strFormat.Format(L"%d,%d,%d,%d,%d,%d",iYear, iMonth, iDay, iHour, iMin, iSec);
364 //              CString strFormat = cppTm.Format(cFormat.c_str());
365                 wchar_t buf[64] = {0};
366                 strFormat = wcsftime(buf, 64, cFormat.c_str(), &time);
367                 cFormat = buf;
368                 vRet = cFormat.c_str();
369                 //rtRet = strFormat.GetBuffer(strFormat.GetLength()+1);
370                 return TRUE;
371         }
372         return FALSE;
373 }
374
375 void util::printd(const std::wstring &cFormat2, CJS_Date jsDate, bool bXFAPicture, std::wstring &cPurpose)
376 {
377         std::wstring cFormat = cFormat2;
378             
379         if (bXFAPicture)
380         {
381                 return ; //currently, it doesn't support XFAPicture.
382         }
383
384     int iIndex;
385         for(iIndex = 0;iIndex<sizeof(fcTable)/sizeof(stru_TbConvert);iIndex++)
386         {
387                 int iStart = 0;
388                 int iEnd;
389                 while((iEnd = cFormat.find((CFX_WideString)fcTable[iIndex].lpszJSMark,iStart)) != -1)
390                 {
391                         cFormat.replace(iEnd,FXSYS_wcslen(fcTable[iIndex].lpszJSMark), (CFX_WideString)fcTable[iIndex].lpszCppMark);
392                         iStart = iEnd;
393                 }
394         }
395
396         int iYear,iMonth,iDay,iHour,iMin,iSec;
397         iYear = jsDate.GetYear();
398         iMonth = jsDate.GetMonth();
399         iDay = jsDate.GetDay();
400         iHour = jsDate.GetHours();
401         iMin = jsDate.GetMinutes();
402         iSec = jsDate.GetSeconds();
403
404         struct tm time = {0};
405         time.tm_year = iYear-1900;
406         time.tm_mon = iMonth;
407         time.tm_mday = iDay;
408         time.tm_hour = iHour;
409         time.tm_min = iMin;
410         time.tm_sec = iSec;
411 //      COleDateTime cppTm(iYear,iMonth+1,iDay,iHour,iMin,iSec);
412         //CString strFormat = cppTm.Format(cFormat.c_str());
413
414         struct stru_TbConvertAd
415         {
416                 FX_LPCWSTR lpszJSMark;
417                 int     iValue;
418         };
419
420         stru_TbConvertAd cTableAd[] ={
421                 { L"m", iMonth+1 },
422                 { L"d", iDay },
423                 { L"H", iHour },
424                 { L"h", iHour>12?iHour-12:iHour },
425                 { L"M", iMin },
426                 { L"s", iSec },
427         };
428
429         //cFormat = strFormat.GetBuffer(strFormat.GetLength()+1);
430         for(iIndex = 0;iIndex<sizeof(cTableAd)/sizeof(stru_TbConvertAd);iIndex++)
431         {
432                 wchar_t tszValue[10];
433                 //_itot(cTableAd[iIndex].iValue,tszValue,10);
434                 CFX_WideString sValue;
435                 sValue.Format(L"%d",cTableAd[iIndex].iValue);
436                 memcpy(tszValue, (wchar_t *)sValue.GetBuffer(sValue.GetLength()+1),sValue.GetLength()*sizeof(wchar_t));
437
438
439                 //strFormat.Replace(cTableAd[iIndex].lpszJSMark,"%d");
440                 //strFormat.Format(strFormat,cTableAd[iIndex].iValue);
441                 int iStart = 0;
442                 int iEnd;
443                 while((iEnd = cFormat.find((CFX_WideString)cTableAd[iIndex].lpszJSMark,iStart)) != -1)
444                 {
445                         if (iEnd > 0)
446                         {
447                                 if (cFormat[iEnd-1] == L'%')
448                                 {
449                                         iStart = iEnd+1;
450                                         continue;
451                                 }
452                         }
453                         cFormat.replace(iEnd,FXSYS_wcslen(cTableAd[iIndex].lpszJSMark),tszValue);
454                         iStart = iEnd;
455                 }
456         }
457
458                 CFX_WideString strFormat;
459 //              strFormat.Format(L"%d,%d,%d,%d,%d,%d",iYear, iMonth, iDay, iHour, iMin, iSec);
460 //              CString strFormat = cppTm.Format(cFormat.c_str());
461                 wchar_t buf[64] = {0};
462                 strFormat = wcsftime(buf, 64, cFormat.c_str(), &time);
463                 cFormat = buf;
464                 cPurpose = cFormat;
465 }
466
467 FX_BOOL util::printx(OBJ_METHOD_PARAMS)
468 {
469         int iSize = params.size();
470         if (iSize<2)
471                 return FALSE;
472         CFX_WideString sFormat = params[0].operator CFX_WideString();
473         CFX_WideString sSource = params[1].operator CFX_WideString();
474         std::string cFormat = (FX_LPCSTR)CFX_ByteString::FromUnicode(sFormat);
475         std::string cSource = (FX_LPCSTR)CFX_ByteString::FromUnicode(sSource);
476         std::string cDest;
477         printx(cFormat,cSource,cDest);
478         vRet = cDest.c_str();
479         return TRUE;
480 }
481
482 void util::printx(const std::string &cFormat,const std::string &cSource2,std::string &cPurpose)
483 {
484         std::string cSource(cSource2);
485         if (!cPurpose.empty())
486                 //cPurpose.clear();
487                 cPurpose.erase();
488         int itSource = 0;
489         int iSize = cSource.size();
490         for(int iIndex = 0; iIndex < (int)cFormat.size() && itSource<iSize; iIndex++)
491         {
492                 char letter = cFormat[iIndex];
493                 switch(letter)
494                 {
495                 case '?':
496                         //cPurpose.push_back(cSource[itSource]);
497                         cPurpose += cSource[itSource];
498                         itSource++;
499                         break;
500                 case 'X':
501                         {
502                                 while(itSource < iSize)
503                                 {
504                                         if ((cSource[itSource]>='0'&&cSource[itSource]<='9') || (cSource[itSource]>='a' && cSource[itSource]<='z') || (cSource[itSource]>='A' && cSource[itSource]<='Z'))
505                                         {
506                                                 //cPurpose.push_back(cSource[itSource]);
507                                                 cPurpose += cSource[itSource];
508                                                 itSource++;
509                                                 break;
510                                         }
511                                         itSource++;
512                                 }
513                                 break;
514                         }
515                         break;
516                 case 'A':
517                         {
518                                 while(itSource < iSize)
519                                 {
520                                         if ((cSource[itSource]>='a' && cSource[itSource]<='z') || (cSource[itSource]>='A' && cSource[itSource]<='Z'))
521                                         {
522                                                 //cPurpose.push_back(cSource[itSource]);
523                                                 cPurpose += cSource[itSource];
524                                                 itSource++;
525                                                 break;
526                                         }
527                                         itSource++;
528                                 }
529                                 break;
530                         }
531                         break;
532                 case '9':
533                         {
534                                 while(itSource < iSize)
535                                 {
536                                         if (cSource[itSource]>='0'&&cSource[itSource]<='9')
537                                         {
538                                                 //cPurpose.push_back(cSource[itSource]);
539                                                 cPurpose += cSource[itSource];
540                                                 itSource++;
541                                                 break;
542                                         }
543                                         itSource++;
544                                 }
545                                 break;
546                         }
547                 case '*':
548                         {
549                                 cPurpose.append(cSource,itSource,iSize-itSource);
550                                 itSource = iSize-1;
551                                 break;
552                         }
553                 case '\\':
554                         break;
555                 case '>':
556                         {
557                                 for(std::string::iterator it = cSource.begin();it != cSource.end(); it++)
558                                 {
559                                         *it = toupper(*it);
560                                 }
561                                 break;
562                         }
563                 case '<':
564                         {
565                                 for(std::string::iterator it = cSource.begin();it != cSource.end(); it++)
566                                 {
567                                         *it = tolower(*it);
568                                 }
569                                 break;
570                         }
571                 case '=':
572                         break;
573                 default:
574                         //cPurpose.push_back(letter);
575                         cPurpose += letter;
576                         break;
577                 }
578         }
579 }
580
581 FX_BOOL util::scand(OBJ_METHOD_PARAMS)
582 {
583         v8::Isolate* isolate = GetIsolate(cc);
584         int iSize = params.size();
585         if (iSize < 2)
586                 return FALSE;
587         CFX_WideString sFormat = params[0].operator CFX_WideString();
588         CFX_WideString sDate = params[1].operator CFX_WideString();
589
590         double dDate = JS_GetDateTime();
591         if (sDate.GetLength() > 0)
592         {
593                 FX_BOOL bWrongFormat = FALSE;
594                 dDate = CJS_PublicMethods::MakeRegularDate(sDate,sFormat,bWrongFormat);
595         }       
596         
597         if (!JS_PortIsNan(dDate))
598         {
599                 CJS_Date date(isolate,dDate);
600                 vRet = date;
601         }
602         else
603         {
604                 vRet.SetNull();
605         }
606
607         return TRUE;
608 }
609
610 FX_INT64 FX_atoi64(const char *nptr)
611 {
612         int c;              /* current char */
613         FX_INT64 total;      /* current total */
614         int sign;           /* if '-', then negative, otherwise positive */
615
616         /* skip whitespace */
617         while ( isspace((int)(unsigned char)*nptr) )
618             ++nptr;
619
620         c = (int)(unsigned char)*nptr++;
621         sign = c;           /* save sign indication */
622         if (c == '-' || c == '+')
623             c = (int)(unsigned char)*nptr++;    /* skip sign */
624
625         total = 0;
626
627         while (isdigit(c)) {
628             total = 10 * total + (c - '0');     /* accumulate digit */
629             c = (int)(unsigned char)*nptr++;    /* get next char */
630         }
631
632         if (sign == '-')
633             return -total;
634         else
635             return total;   /* return result, negated if necessary */
636 }
637
638 FX_BOOL util::byteToChar(OBJ_METHOD_PARAMS)
639 {
640         int iSize = params.size();
641         if (iSize == 0)
642                 return FALSE;
643         int nByte = (int)params[0];
644         unsigned char cByte = (unsigned char)nByte;
645         CFX_WideString csValue;
646         csValue.Format(L"%c", cByte);
647         vRet = csValue; 
648         return TRUE;
649 }