• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
GetIsolate(IFXJS_Context * cc)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)
END_JS_STATIC_CONST()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 
~util(void)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 	(FX_LPCWSTR)L"mmmm", (FX_LPCWSTR)L"%B",
67 	(FX_LPCWSTR)L"mmm", (FX_LPCWSTR)L"%b",
68 	(FX_LPCWSTR)L"mm",  (FX_LPCWSTR)L"%m",
69 	//"m"
70 	(FX_LPCWSTR)L"dddd", (FX_LPCWSTR)L"%A",
71 	(FX_LPCWSTR)L"ddd", (FX_LPCWSTR)L"%a",
72 	(FX_LPCWSTR)L"dd",  (FX_LPCWSTR)L"%d",
73 	//"d",   "%w",
74 	(FX_LPCWSTR)L"yyyy", (FX_LPCWSTR)L"%Y",
75 	(FX_LPCWSTR)L"yy",  (FX_LPCWSTR)L"%y",
76 	(FX_LPCWSTR)L"HH",  (FX_LPCWSTR)L"%H",
77 	//"H"
78 	(FX_LPCWSTR)L"hh",  (FX_LPCWSTR)L"%I",
79 	//"h"
80 	(FX_LPCWSTR)L"MM",  (FX_LPCWSTR)L"%M",
81 	//"M"
82 	(FX_LPCWSTR)L"ss",  (FX_LPCWSTR)L"%S",
83 	//"s
84 	(FX_LPCWSTR)L"TT",  (FX_LPCWSTR)L"%p",
85 	//"t"
86 #if defined(_WIN32)
87 	(FX_LPCWSTR)L"tt",  (FX_LPCWSTR)L"%p",
88 	(FX_LPCWSTR)L"h",  (FX_LPCWSTR)L"%#I",
89 #else
90 	(FX_LPCWSTR)L"tt",  (FX_LPCWSTR)L"%P",
91 	(FX_LPCWSTR)L"h",  (FX_LPCWSTR)L"%l",
92 #endif
93 };
94 
95 #define UTIL_INT			0
96 #define UTIL_DOUBLE			1
97 #define UTIL_STRING			2
98 
ParstDataType(std::wstring * sFormat)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 
printf(OBJ_METHOD_PARAMS)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((FX_LPCWSTR)c_strFormat.c_str(),(int)params[iIndex]);
186 				break;
187 			case UTIL_DOUBLE:
188 				strSegment.Format((FX_LPCWSTR)c_strFormat.c_str(),(double)params[iIndex]);
189 				break;
190 			case UTIL_STRING:
191 				strSegment.Format((FX_LPCWSTR)c_strFormat.c_str(),(FX_LPCWSTR)params[iIndex].operator CFX_WideString());
192 				break;
193 			default:
194 				strSegment.Format((FX_LPCWSTR)L"%S", (FX_LPCWSTR)c_strFormat.c_str());
195 				break;
196 		}
197 		c_strResult += (wchar_t*)strSegment.GetBuffer(strSegment.GetLength()+1);
198 	}
199 
200 	c_strResult.erase(c_strResult.begin());
201 	vRet = (FX_LPCWSTR)c_strResult.c_str();
202 	return TRUE;
203 }
204 
printd(OBJ_METHOD_PARAMS)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((FX_LPCWSTR)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((FX_LPCWSTR)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((FX_LPCWSTR)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 = (wchar_t*)(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 			(FX_LPCWSTR)L"m", iMonth+1,
326 				(FX_LPCWSTR)L"d", iDay,
327 				(FX_LPCWSTR)L"H", iHour,
328 				(FX_LPCWSTR)L"h", iHour>12?iHour-12:iHour,
329 				(FX_LPCWSTR)L"M", iMin,
330 				(FX_LPCWSTR)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((FX_LPCWSTR)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((FX_LPCWSTR)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 = (FX_LPCWSTR)cFormat.c_str();
369 		//rtRet = strFormat.GetBuffer(strFormat.GetLength()+1);
370 		return TRUE;
371 	}
372 	return FALSE;
373 }
374 
printd(const std::wstring & cFormat2,CJS_Date jsDate,bool bXFAPicture,std::wstring & cPurpose)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 		(FX_LPCWSTR)L"m", iMonth+1,
422 			(FX_LPCWSTR)L"d", iDay,
423 			(FX_LPCWSTR)L"H", iHour,
424 			(FX_LPCWSTR)L"h", iHour>12?iHour-12:iHour,
425 			(FX_LPCWSTR)L"M", iMin,
426 			(FX_LPCWSTR)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((FX_LPCWSTR)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((FX_LPCWSTR)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 
printx(OBJ_METHOD_PARAMS)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 
printx(const std::string & cFormat,const std::string & cSource2,std::string & cPurpose)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 
scand(OBJ_METHOD_PARAMS)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 
FX_atoi64(const char * nptr)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 
byteToChar(OBJ_METHOD_PARAMS)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((FX_LPCWSTR)L"%c", cByte);
647 	vRet = csValue;
648 	return TRUE;
649 }
650