Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(169)

Side by Side Diff: fpdfsdk/src/javascript/PublicMethods.cpp

Issue 1586203006: Bugs in CJS_PublicMethods::ParseNumber() (Closed) Base URL: https://pdfium.googlesource.com/pdfium.git@master
Patch Set: Remove entirely, pass "NaN" as NaN. Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 PDFium Authors. All rights reserved. 1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 6
7 #include "PublicMethods.h" 7 #include "PublicMethods.h"
8 8
9 #include <algorithm> 9 #include <algorithm>
10 10
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
187 while (p > pStr && *(p - 1) == L' ') 187 while (p > pStr && *(p - 1) == L' ')
188 p--; 188 p--;
189 189
190 return CFX_ByteString(pStr, p - pStr); 190 return CFX_ByteString(pStr, p - pStr);
191 } 191 }
192 192
193 CFX_ByteString CJS_PublicMethods::StrTrim(const FX_CHAR* pStr) { 193 CFX_ByteString CJS_PublicMethods::StrTrim(const FX_CHAR* pStr) {
194 return StrRTrim(StrLTrim(pStr)); 194 return StrRTrim(StrLTrim(pStr));
195 } 195 }
196 196
197 double CJS_PublicMethods::ParseNumber(const FX_WCHAR* swSource,
198 FX_BOOL& bAllDigits,
199 FX_BOOL& bDot,
200 FX_BOOL& bSign,
201 FX_BOOL& bKXJS) {
202 bDot = FALSE;
203 bSign = FALSE;
204 bKXJS = FALSE;
205
206 FX_BOOL bDigitExist = FALSE;
207
208 const FX_WCHAR* p = swSource;
209 wchar_t c;
210
211 const FX_WCHAR* pStart = NULL;
212 const FX_WCHAR* pEnd = NULL;
213
214 while ((c = *p)) {
215 if (!pStart && c != L' ') {
216 pStart = p;
217 }
218
219 pEnd = p;
220 p++;
221 }
222
223 if (!pStart) {
224 bAllDigits = FALSE;
225 return 0;
226 }
227
228 while (pEnd != pStart) {
229 if (*pEnd == L' ')
230 pEnd--;
231 else
232 break;
233 }
234
235 double dRet = 0;
236 p = pStart;
237 bAllDigits = TRUE;
238 CFX_WideString swDigits;
239
240 while (p <= pEnd) {
241 c = *p;
242
243 if (FXSYS_iswdigit(c)) {
244 swDigits += c;
245 bDigitExist = TRUE;
246 } else {
247 switch (c) {
248 case L' ':
249 bAllDigits = FALSE;
250 break;
251 case L'.':
252 case L',':
253 if (!bDot) {
254 if (bDigitExist) {
255 swDigits += L'.';
256 } else {
257 swDigits += L'0';
258 swDigits += L'.';
259 bDigitExist = TRUE;
260 }
261
262 bDot = TRUE;
263 break;
264 }
265 case 'e':
266 case 'E':
267 if (!bKXJS) {
268 p++;
269 c = *p;
270 if (c == '+' || c == '-') {
271 bKXJS = TRUE;
272 swDigits += 'e';
273 swDigits += c;
274 }
275 break;
276 }
277 case L'-':
278 if (!bDigitExist && !bSign) {
279 swDigits += c;
280 bSign = TRUE;
281 break;
282 }
283 default:
284 bAllDigits = FALSE;
285
286 if (p != pStart && !bDot && bDigitExist) {
287 swDigits += L'.';
288 bDot = TRUE;
289 } else {
290 bDot = FALSE;
291 bDigitExist = FALSE;
292 swDigits = L"";
293 }
294 break;
295 }
296 }
297
298 p++;
299 }
300
301 if (swDigits.GetLength() > 0 && swDigits.GetLength() < 17) {
302 CFX_ByteString sDigits = swDigits.UTF8Encode();
303
304 if (bKXJS) {
305 dRet = atof(sDigits);
306 } else {
307 if (bDot) {
308 char* pStopString;
309 dRet = ::strtod(sDigits, &pStopString);
310 } else {
311 dRet = atol(sDigits);
312 }
313 }
314 }
315
316 return dRet;
317 }
318
319 double CJS_PublicMethods::ParseStringToNumber(const FX_WCHAR* swSource) {
320 FX_BOOL bAllDigits = FALSE;
321 FX_BOOL bDot = FALSE;
322 FX_BOOL bSign = FALSE;
323 FX_BOOL bKXJS = FALSE;
324
325 return ParseNumber(swSource, bAllDigits, bDot, bSign, bKXJS);
326 }
327
328 FX_BOOL CJS_PublicMethods::ConvertStringToNumber(const FX_WCHAR* swSource,
329 double& dRet,
330 FX_BOOL& bDot) {
331 FX_BOOL bAllDigits = FALSE;
332 FX_BOOL bSign = FALSE;
333 FX_BOOL bKXJS = FALSE;
334
335 dRet = ParseNumber(swSource, bAllDigits, bDot, bSign, bKXJS);
336
337 return bAllDigits;
338 }
339
340 CJS_Array CJS_PublicMethods::AF_MakeArrayFromList(CJS_Runtime* pRuntime, 197 CJS_Array CJS_PublicMethods::AF_MakeArrayFromList(CJS_Runtime* pRuntime,
341 CJS_Value val) { 198 CJS_Value val) {
342 CJS_Array StrArray(pRuntime); 199 CJS_Array StrArray(pRuntime);
343 if (val.IsArrayObject()) { 200 if (val.IsArrayObject()) {
344 val.ConvertToArray(StrArray); 201 val.ConvertToArray(StrArray);
345 return StrArray; 202 return StrArray;
346 } 203 }
347 CFX_WideString wsStr = val.ToCFXWideString(); 204 CFX_WideString wsStr = val.ToCFXWideString();
348 CFX_ByteString t = CFX_ByteString::FromUnicode(wsStr); 205 CFX_ByteString t = CFX_ByteString::FromUnicode(wsStr);
349 const char* p = (const char*)t; 206 const char* p = (const char*)t;
(...skipping 987 matching lines...) Expand 10 before | Expand all | Expand 10 after
1337 sFormat.c_str()); 1194 sFormat.c_str());
1338 Alert(pContext, swMsg.c_str()); 1195 Alert(pContext, swMsg.c_str());
1339 return FALSE; 1196 return FALSE;
1340 } 1197 }
1341 1198
1342 val = MakeFormatDate(dDate, sFormat); 1199 val = MakeFormatDate(dDate, sFormat);
1343 return TRUE; 1200 return TRUE;
1344 } 1201 }
1345 1202
1346 double CJS_PublicMethods::MakeInterDate(CFX_WideString strValue) { 1203 double CJS_PublicMethods::MakeInterDate(CFX_WideString strValue) {
1347 int nHour;
1348 int nMin;
1349 int nSec;
1350 int nYear;
1351 int nMonth;
1352 int nDay;
1353
1354 CFX_WideStringArray wsArray; 1204 CFX_WideStringArray wsArray;
1355 CFX_WideString sMonth = L"";
1356 CFX_WideString sTemp = L""; 1205 CFX_WideString sTemp = L"";
1357 int nSize = strValue.GetLength(); 1206 for (int i = 0; i < strValue.GetLength(); ++i) {
1358
1359 for (int i = 0; i < nSize; i++) {
1360 FX_WCHAR c = strValue.GetAt(i); 1207 FX_WCHAR c = strValue.GetAt(i);
1361 if (c == L' ' || c == L':') { 1208 if (c == L' ' || c == L':') {
1362 wsArray.Add(sTemp); 1209 wsArray.Add(sTemp);
1363 sTemp = L""; 1210 sTemp = L"";
1364 continue; 1211 continue;
1365 } 1212 }
1366
1367 sTemp += c; 1213 sTemp += c;
1368 } 1214 }
1369
1370 wsArray.Add(sTemp); 1215 wsArray.Add(sTemp);
1371 if (wsArray.GetSize() != 8) 1216 if (wsArray.GetSize() != 8)
1372 return 0; 1217 return 0;
1373 1218
1219 int nMonth = 1;
1374 sTemp = wsArray[1]; 1220 sTemp = wsArray[1];
1375 if (sTemp.Compare(L"Jan") == 0) 1221 if (sTemp.Compare(L"Jan") == 0)
1376 nMonth = 1; 1222 nMonth = 1;
1377 if (sTemp.Compare(L"Feb") == 0) 1223 else if (sTemp.Compare(L"Feb") == 0)
1378 nMonth = 2; 1224 nMonth = 2;
1379 if (sTemp.Compare(L"Mar") == 0) 1225 else if (sTemp.Compare(L"Mar") == 0)
1380 nMonth = 3; 1226 nMonth = 3;
1381 if (sTemp.Compare(L"Apr") == 0) 1227 else if (sTemp.Compare(L"Apr") == 0)
1382 nMonth = 4; 1228 nMonth = 4;
1383 if (sTemp.Compare(L"May") == 0) 1229 else if (sTemp.Compare(L"May") == 0)
1384 nMonth = 5; 1230 nMonth = 5;
1385 if (sTemp.Compare(L"Jun") == 0) 1231 else if (sTemp.Compare(L"Jun") == 0)
1386 nMonth = 6; 1232 nMonth = 6;
1387 if (sTemp.Compare(L"Jul") == 0) 1233 else if (sTemp.Compare(L"Jul") == 0)
1388 nMonth = 7; 1234 nMonth = 7;
1389 if (sTemp.Compare(L"Aug") == 0) 1235 else if (sTemp.Compare(L"Aug") == 0)
1390 nMonth = 8; 1236 nMonth = 8;
1391 if (sTemp.Compare(L"Sep") == 0) 1237 else if (sTemp.Compare(L"Sep") == 0)
1392 nMonth = 9; 1238 nMonth = 9;
1393 if (sTemp.Compare(L"Oct") == 0) 1239 else if (sTemp.Compare(L"Oct") == 0)
1394 nMonth = 10; 1240 nMonth = 10;
1395 if (sTemp.Compare(L"Nov") == 0) 1241 else if (sTemp.Compare(L"Nov") == 0)
1396 nMonth = 11; 1242 nMonth = 11;
1397 if (sTemp.Compare(L"Dec") == 0) 1243 else if (sTemp.Compare(L"Dec") == 0)
1398 nMonth = 12; 1244 nMonth = 12;
1399 1245
1400 nDay = (int)ParseStringToNumber(wsArray[2].c_str()); 1246 int nDay = FX_atof(wsArray[2]);
1401 nHour = (int)ParseStringToNumber(wsArray[3].c_str()); 1247 int nHour = FX_atof(wsArray[3]);
1402 nMin = (int)ParseStringToNumber(wsArray[4].c_str()); 1248 int nMin = FX_atof(wsArray[4]);
1403 nSec = (int)ParseStringToNumber(wsArray[5].c_str()); 1249 int nSec = FX_atof(wsArray[5]);
1404 nYear = (int)ParseStringToNumber(wsArray[7].c_str()); 1250 int nYear = FX_atof(wsArray[7]);
1405
1406 double dRet = JS_MakeDate(JS_MakeDay(nYear, nMonth - 1, nDay), 1251 double dRet = JS_MakeDate(JS_MakeDay(nYear, nMonth - 1, nDay),
1407 JS_MakeTime(nHour, nMin, nSec, 0)); 1252 JS_MakeTime(nHour, nMin, nSec, 0));
1408 1253 if (JS_PortIsNan(dRet))
1409 if (JS_PortIsNan(dRet)) {
1410 dRet = JS_DateParse(strValue.c_str()); 1254 dRet = JS_DateParse(strValue.c_str());
1411 }
1412 1255
1413 return dRet; 1256 return dRet;
1414 } 1257 }
1415 1258
1416 // AFDate_KeystrokeEx(cFormat) 1259 // AFDate_KeystrokeEx(cFormat)
1417 FX_BOOL CJS_PublicMethods::AFDate_KeystrokeEx( 1260 FX_BOOL CJS_PublicMethods::AFDate_KeystrokeEx(
1418 IJS_Context* cc, 1261 IJS_Context* cc,
1419 const std::vector<CJS_Value>& params, 1262 const std::vector<CJS_Value>& params,
1420 CJS_Value& vRet, 1263 CJS_Value& vRet,
1421 CFX_WideString& sError) { 1264 CFX_WideString& sError) {
(...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after
1859 1702
1860 vRet = (double)AF_Simple(params[0].ToCFXWideString().c_str(), 1703 vRet = (double)AF_Simple(params[0].ToCFXWideString().c_str(),
1861 params[1].ToDouble(), params[2].ToDouble()); 1704 params[1].ToDouble(), params[2].ToDouble());
1862 return TRUE; 1705 return TRUE;
1863 } 1706 }
1864 1707
1865 FX_BOOL CJS_PublicMethods::AFMakeNumber(IJS_Context* cc, 1708 FX_BOOL CJS_PublicMethods::AFMakeNumber(IJS_Context* cc,
1866 const std::vector<CJS_Value>& params, 1709 const std::vector<CJS_Value>& params,
1867 CJS_Value& vRet, 1710 CJS_Value& vRet,
1868 CFX_WideString& sError) { 1711 CFX_WideString& sError) {
1712 CJS_Context* pContext = (CJS_Context*)cc;
1869 if (params.size() != 1) { 1713 if (params.size() != 1) {
1870 CJS_Context* pContext = (CJS_Context*)cc;
1871 ASSERT(pContext);
1872
1873 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR); 1714 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1874 return FALSE; 1715 return FALSE;
1875 } 1716 }
1876 vRet = ParseStringToNumber(params[0].ToCFXWideString().c_str()); 1717 CFX_WideString ws = params[0].ToCFXWideString();
1718 ws.Replace(L",", L".");
jochen (gone - plz use gerrit) 2016/01/19 17:16:25 that's kinda odd, why is this needed? wouldn't tha
Tom Sepez 2016/01/19 22:19:16 We don't know if we're in europe so we make a gues
1719 vRet = ws;
1720 vRet.MaybeCoerceToNumber();
1721 if (vRet.GetType() != CJS_Value::VT_number)
1722 vRet = 0;
Charles Lew 2016/01/19 18:01:45 Actually the Adobe implementation of these functio
1877 return TRUE; 1723 return TRUE;
1878 } 1724 }
1879 1725
1880 FX_BOOL CJS_PublicMethods::AFSimple_Calculate( 1726 FX_BOOL CJS_PublicMethods::AFSimple_Calculate(
1881 IJS_Context* cc, 1727 IJS_Context* cc,
1882 const std::vector<CJS_Value>& params, 1728 const std::vector<CJS_Value>& params,
1883 CJS_Value& vRet, 1729 CJS_Value& vRet,
1884 CFX_WideString& sError) { 1730 CFX_WideString& sError) {
1885 CJS_Context* pContext = (CJS_Context*)cc; 1731 CJS_Context* pContext = (CJS_Context*)cc;
1886 if (params.size() != 2) { 1732 if (params.size() != 2) {
(...skipping 19 matching lines...) Expand all
1906 int nFieldsCount = 0; 1752 int nFieldsCount = 0;
1907 1753
1908 for (int i = 0, isz = FieldNameArray.GetLength(); i < isz; i++) { 1754 for (int i = 0, isz = FieldNameArray.GetLength(); i < isz; i++) {
1909 CJS_Value jsValue(pRuntime); 1755 CJS_Value jsValue(pRuntime);
1910 FieldNameArray.GetElement(i, jsValue); 1756 FieldNameArray.GetElement(i, jsValue);
1911 CFX_WideString wsFieldName = jsValue.ToCFXWideString(); 1757 CFX_WideString wsFieldName = jsValue.ToCFXWideString();
1912 1758
1913 for (int j = 0, jsz = pInterForm->CountFields(wsFieldName); j < jsz; j++) { 1759 for (int j = 0, jsz = pInterForm->CountFields(wsFieldName); j < jsz; j++) {
1914 if (CPDF_FormField* pFormField = pInterForm->GetField(j, wsFieldName)) { 1760 if (CPDF_FormField* pFormField = pInterForm->GetField(j, wsFieldName)) {
1915 double dTemp = 0.0; 1761 double dTemp = 0.0;
1916
1917 switch (pFormField->GetFieldType()) { 1762 switch (pFormField->GetFieldType()) {
1918 case FIELDTYPE_TEXTFIELD: 1763 case FIELDTYPE_TEXTFIELD:
1919 case FIELDTYPE_COMBOBOX: { 1764 case FIELDTYPE_COMBOBOX: {
1920 dTemp = ParseStringToNumber(pFormField->GetValue().c_str()); 1765 CFX_WideString trimmed = pFormField->GetValue();
1921 break; 1766 trimmed.TrimRight();
1922 } 1767 trimmed.TrimLeft();
1768 dTemp = FX_atof(trimmed);
1769 } break;
1923 case FIELDTYPE_PUSHBUTTON: { 1770 case FIELDTYPE_PUSHBUTTON: {
1924 dTemp = 0.0; 1771 dTemp = 0.0;
1925 break; 1772 } break;
1926 }
1927 case FIELDTYPE_CHECKBOX: 1773 case FIELDTYPE_CHECKBOX:
1928 case FIELDTYPE_RADIOBUTTON: { 1774 case FIELDTYPE_RADIOBUTTON: {
1929 dTemp = 0.0; 1775 dTemp = 0.0;
1930 for (int c = 0, csz = pFormField->CountControls(); c < csz; c++) { 1776 for (int c = 0, csz = pFormField->CountControls(); c < csz; c++) {
1931 if (CPDF_FormControl* pFormCtrl = pFormField->GetControl(c)) { 1777 if (CPDF_FormControl* pFormCtrl = pFormField->GetControl(c)) {
1932 if (pFormCtrl->IsChecked()) { 1778 if (pFormCtrl->IsChecked()) {
1933 dTemp += 1779 CFX_WideString trimmed = pFormCtrl->GetExportValue();
1934 ParseStringToNumber(pFormCtrl->GetExportValue().c_str()); 1780 trimmed.TrimRight();
1781 trimmed.TrimLeft();
1782 dTemp = FX_atof(trimmed);
1935 break; 1783 break;
1936 } 1784 }
1937 } 1785 }
1938 } 1786 }
1939 break; 1787 } break;
1940 }
1941 case FIELDTYPE_LISTBOX: { 1788 case FIELDTYPE_LISTBOX: {
1942 if (pFormField->CountSelectedItems() > 1) 1789 if (pFormField->CountSelectedItems() <= 1) {
1943 break; 1790 CFX_WideString trimmed = pFormField->GetValue();
1944 1791 trimmed.TrimRight();
1945 dTemp = ParseStringToNumber(pFormField->GetValue().c_str()); 1792 trimmed.TrimLeft();
1946 break; 1793 dTemp = FX_atof(trimmed);
1947 } 1794 }
1795 } break;
1948 default: 1796 default:
1949 break; 1797 break;
1950 } 1798 }
1951 1799
1952 if (i == 0 && j == 0 && (wcscmp(sFunction.c_str(), L"MIN") == 0 || 1800 if (i == 0 && j == 0 && (wcscmp(sFunction.c_str(), L"MIN") == 0 ||
1953 wcscmp(sFunction.c_str(), L"MAX") == 0)) 1801 wcscmp(sFunction.c_str(), L"MAX") == 0))
1954 dValue = dTemp; 1802 dValue = dTemp;
1955 1803
1956 dValue = AF_Simple(sFunction.c_str(), dValue, dTemp); 1804 dValue = AF_Simple(sFunction.c_str(), dValue, dTemp);
1957 1805
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
2058 nums.SetElement(nIndex, CJS_Value(pRuntime, sPart.c_str())); 1906 nums.SetElement(nIndex, CJS_Value(pRuntime, sPart.c_str()));
2059 } 1907 }
2060 1908
2061 if (nums.GetLength() > 0) 1909 if (nums.GetLength() > 0)
2062 vRet = nums; 1910 vRet = nums;
2063 else 1911 else
2064 vRet.SetNull(); 1912 vRet.SetNull();
2065 1913
2066 return TRUE; 1914 return TRUE;
2067 } 1915 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698