summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortsepez <tsepez@chromium.org>2016-03-28 14:13:16 -0700
committerCommit bot <commit-bot@chromium.org>2016-03-28 14:13:16 -0700
commit4f1f41f338ce0899e48605c82375a72883f4eb7c (patch)
treea89cc3f1d8b981fa12d7fd423ef6883c7a502798
parent4678e283c5b48a8954bd0db3565b1376bd9c6b27 (diff)
downloadpdfium-4f1f41f338ce0899e48605c82375a72883f4eb7c.tar.xz
Added test for util.printx() and make it match spec.
R=dsinclair@chromium.org Review URL: https://codereview.chromium.org/1837543002
-rw-r--r--fpdfsdk/javascript/PublicMethods.cpp39
-rw-r--r--fpdfsdk/javascript/util.cpp161
-rw-r--r--fpdfsdk/javascript/util.h5
-rw-r--r--testing/resources/javascript/util_printx.in88
-rw-r--r--testing/resources/javascript/util_printx_expected.txt35
5 files changed, 226 insertions, 102 deletions
diff --git a/fpdfsdk/javascript/PublicMethods.cpp b/fpdfsdk/javascript/PublicMethods.cpp
index b85111bed7..a4c13564c8 100644
--- a/fpdfsdk/javascript/PublicMethods.cpp
+++ b/fpdfsdk/javascript/PublicMethods.cpp
@@ -1424,39 +1424,31 @@ FX_BOOL CJS_PublicMethods::AFSpecial_Format(
return FALSE;
}
- std::string cFormat;
- int iIndex = params[0].ToInt();
-
CJS_EventHandler* pEvent = pContext->GetEventHandler();
if (!pEvent->m_pValue)
return FALSE;
- CFX_WideString& Value = pEvent->Value();
- std::string strSrc = CFX_ByteString::FromUnicode(Value).c_str();
- switch (iIndex) {
+ CFX_WideString wsSource = pEvent->Value();
+ CFX_WideString wsFormat;
+ switch (params[0].ToInt()) {
case 0:
- cFormat = "99999";
+ wsFormat = L"99999";
break;
case 1:
- cFormat = "99999-9999";
+ wsFormat = L"99999-9999";
break;
- case 2: {
- std::string NumberStr;
- util::printx("9999999999", strSrc, NumberStr);
- if (NumberStr.length() >= 10)
- cFormat = "(999) 999-9999";
+ case 2:
+ if (util::printx(L"9999999999", wsSource).GetLength() >= 10)
+ wsFormat = L"(999) 999-9999";
else
- cFormat = "999-9999";
+ wsFormat = L"999-9999";
break;
- }
case 3:
- cFormat = "999-99-9999";
+ wsFormat = L"999-99-9999";
break;
}
- std::string strDes;
- util::printx(cFormat, strSrc, strDes);
- Value = CFX_WideString::FromLocal(strDes.c_str());
+ pEvent->Value() = util::printx(wsFormat, wsSource);
return TRUE;
}
@@ -1578,22 +1570,15 @@ FX_BOOL CJS_PublicMethods::AFSpecial_Keystroke(
cFormat = "99999";
break;
case 1:
- // cFormat = "99999-9999";
cFormat = "999999999";
break;
- case 2: {
- std::string NumberStr;
- util::printx("9999999999", strSrc, NumberStr);
+ case 2:
if (strSrc.length() + wstrChange.length() > 7)
- // cFormat = "(999) 999-9999";
cFormat = "9999999999";
else
- // cFormat = "999-9999";
cFormat = "9999999";
break;
- }
case 3:
- // cFormat = "999-99-9999";
cFormat = "999999999";
break;
}
diff --git a/fpdfsdk/javascript/util.cpp b/fpdfsdk/javascript/util.cpp
index 30656cd766..f7b2d7fbfa 100644
--- a/fpdfsdk/javascript/util.cpp
+++ b/fpdfsdk/javascript/util.cpp
@@ -309,96 +309,113 @@ FX_BOOL util::printx(IJS_Context* cc,
const std::vector<CJS_Value>& params,
CJS_Value& vRet,
CFX_WideString& sError) {
- int iSize = params.size();
- if (iSize < 2)
+ if (params.size() < 2) {
+ sError = JSGetStringFromID((CJS_Context*)cc, IDS_STRING_JSPARAMERROR);
return FALSE;
- CFX_WideString sFormat = params[0].ToCFXWideString();
- CFX_WideString sSource = params[1].ToCFXWideString();
- std::string cFormat = CFX_ByteString::FromUnicode(sFormat).c_str();
- std::string cSource = CFX_ByteString::FromUnicode(sSource).c_str();
- std::string cDest;
- printx(cFormat, cSource, cDest);
- vRet = cDest.c_str();
+ }
+ vRet = printx(params[0].ToCFXWideString(), params[1].ToCFXWideString());
return TRUE;
}
-void util::printx(const std::string& cFormat,
- const std::string& cSource2,
- std::string& cPurpose) {
- std::string cSource(cSource2);
- if (!cPurpose.empty())
- // cPurpose.clear();
- cPurpose.erase();
- int itSource = 0;
- int iSize = cSource.size();
- for (int iIndex = 0; iIndex < (int)cFormat.size() && itSource < iSize;
- iIndex++) {
- char letter = cFormat[iIndex];
- switch (letter) {
- case '?':
- cPurpose += cSource[itSource];
- itSource++;
- break;
+enum CaseMode { kPreserveCase, kUpperCase, kLowerCase };
+
+static FX_WCHAR TranslateCase(FX_WCHAR input, CaseMode eMode) {
+ if (eMode == kLowerCase && input >= 'A' && input <= 'Z')
+ return input | 0x20;
+ if (eMode == kUpperCase && input >= 'a' && input <= 'z')
+ return input & ~0x20;
+ return input;
+}
+
+CFX_WideString util::printx(const CFX_WideString& wsFormat,
+ const CFX_WideString& wsSource) {
+ CFX_WideString wsResult;
+ FX_STRSIZE iSourceIdx = 0;
+ FX_STRSIZE iFormatIdx = 0;
+ CaseMode eCaseMode = kPreserveCase;
+ bool bEscaped = false;
+ while (iFormatIdx < wsFormat.GetLength()) {
+ if (bEscaped) {
+ bEscaped = false;
+ wsResult += wsFormat[iFormatIdx];
+ ++iFormatIdx;
+ continue;
+ }
+ switch (wsFormat[iFormatIdx]) {
+ case '\\': {
+ bEscaped = true;
+ ++iFormatIdx;
+ } break;
+ case '<': {
+ eCaseMode = kLowerCase;
+ ++iFormatIdx;
+ } break;
+ case '>': {
+ eCaseMode = kUpperCase;
+ ++iFormatIdx;
+ } break;
+ case '=': {
+ eCaseMode = kPreserveCase;
+ ++iFormatIdx;
+ } break;
+ case '?': {
+ if (iSourceIdx < wsSource.GetLength()) {
+ wsResult += TranslateCase(wsSource[iSourceIdx], eCaseMode);
+ ++iSourceIdx;
+ }
+ ++iFormatIdx;
+ } break;
case 'X': {
- while (itSource < iSize) {
- if (std::isdigit(cSource[itSource]) ||
- (cSource[itSource] >= 'a' && cSource[itSource] <= 'z') ||
- (cSource[itSource] >= 'A' && cSource[itSource] <= 'Z')) {
- cPurpose += cSource[itSource];
- itSource++;
- break;
+ if (iSourceIdx < wsSource.GetLength()) {
+ if ((wsSource[iSourceIdx] >= '0' && wsSource[iSourceIdx] <= '9') ||
+ (wsSource[iSourceIdx] >= 'a' && wsSource[iSourceIdx] <= 'z') ||
+ (wsSource[iSourceIdx] >= 'A' && wsSource[iSourceIdx] <= 'Z')) {
+ wsResult += TranslateCase(wsSource[iSourceIdx], eCaseMode);
+ ++iFormatIdx;
}
- itSource++;
+ ++iSourceIdx;
+ } else {
+ ++iFormatIdx;
}
- break;
} break;
case 'A': {
- while (itSource < iSize) {
- if ((cSource[itSource] >= 'a' && cSource[itSource] <= 'z') ||
- (cSource[itSource] >= 'A' && cSource[itSource] <= 'Z')) {
- cPurpose += cSource[itSource];
- itSource++;
- break;
+ if (iSourceIdx < wsSource.GetLength()) {
+ if ((wsSource[iSourceIdx] >= 'a' && wsSource[iSourceIdx] <= 'z') ||
+ (wsSource[iSourceIdx] >= 'A' && wsSource[iSourceIdx] <= 'Z')) {
+ wsResult += TranslateCase(wsSource[iSourceIdx], eCaseMode);
+ ++iFormatIdx;
}
- itSource++;
+ ++iSourceIdx;
+ } else {
+ ++iFormatIdx;
}
- break;
} break;
case '9': {
- while (itSource < iSize) {
- if (std::isdigit(cSource[itSource])) {
- cPurpose += cSource[itSource];
- itSource++;
- break;
+ if (iSourceIdx < wsSource.GetLength()) {
+ if (wsSource[iSourceIdx] >= '0' && wsSource[iSourceIdx] <= '9') {
+ wsResult += wsSource[iSourceIdx];
+ ++iFormatIdx;
}
- itSource++;
+ ++iSourceIdx;
+ } else {
+ ++iFormatIdx;
}
- break;
- }
+ } break;
case '*': {
- cPurpose.append(cSource, itSource, iSize - itSource);
- itSource = iSize - 1;
- break;
- }
- case '\\':
- break;
- case '>': {
- for (char& c : cSource)
- c = toupper(c);
- break;
- }
- case '<': {
- for (char& c : cSource)
- c = tolower(c);
- break;
- }
- case '=':
- break;
- default:
- cPurpose += letter;
- break;
+ if (iSourceIdx < wsSource.GetLength()) {
+ wsResult += TranslateCase(wsSource[iSourceIdx], eCaseMode);
+ ++iSourceIdx;
+ } else {
+ ++iFormatIdx;
+ }
+ } break;
+ default: {
+ wsResult += wsFormat[iFormatIdx];
+ ++iFormatIdx;
+ } break;
}
}
+ return wsResult;
}
FX_BOOL util::scand(IJS_Context* cc,
diff --git a/fpdfsdk/javascript/util.h b/fpdfsdk/javascript/util.h
index 17f252d6dc..3022efece2 100644
--- a/fpdfsdk/javascript/util.h
+++ b/fpdfsdk/javascript/util.h
@@ -38,9 +38,8 @@ class util : public CJS_EmbedObj {
CJS_Value& vRet,
CFX_WideString& sError);
- static void printx(const std::string& cFormat,
- const std::string& cSource,
- std::string& cPurpose);
+ static CFX_WideString printx(const CFX_WideString& cFormat,
+ const CFX_WideString& cSource);
};
class CJS_Util : public CJS_Object {
diff --git a/testing/resources/javascript/util_printx.in b/testing/resources/javascript/util_printx.in
new file mode 100644
index 0000000000..7085edc3ea
--- /dev/null
+++ b/testing/resources/javascript/util_printx.in
@@ -0,0 +1,88 @@
+{{header}}
+{{object 1 0}} <<
+ /Type /Catalog
+ /Pages 2 0 R
+ /OpenAction 10 0 R
+>>
+endobj
+{{object 2 0}} <<
+ /Type /Pages
+ /Count 1
+ /Kids [
+ 3 0 R
+ ]
+>>
+endobj
+% Page number 0.
+{{object 3 0}} <<
+ /Type /Page
+ /Parent 2 0 R
+ /Resources <<
+ /Font <</F1 15 0 R>>
+ >>
+ /Contents [21 0 R]
+ /MediaBox [0 0 612 792]
+>>
+% OpenAction action
+{{object 10 0}} <<
+ /Type /Action
+ /S /JavaScript
+ /JS 11 0 R
+>>
+endobj
+% JS program to exexute
+{{object 11 0}} <<
+>>
+stream
+function TestOneFormat(fmt, src) {
+ var title = "('" + fmt + "', '" + src + "')";
+ try {
+ app.alert(title + " => '" + util.printx(fmt, src) + "'");
+ }
+ catch (e) {
+ app.alert(title + ": Caught error: " + e);
+ }
+}
+TestOneFormat("", "");
+TestOneFormat("", "123");
+TestOneFormat("??", "");
+TestOneFormat("??", "f2");
+TestOneFormat("??", "f27");
+TestOneFormat("XXX", "");
+TestOneFormat("XXX", "1afp3.");
+TestOneFormat("XXX", "-1Afp3.d33F$");
+TestOneFormat("AAA", "");
+TestOneFormat("AAA", "-1Afp3.");
+TestOneFormat("AAA", "-1Afp3.d33F$");
+TestOneFormat("999", "");
+TestOneFormat("999", "-1Afp3.");
+TestOneFormat("999", "-1Afp3.d33F$");
+TestOneFormat("9*9", "");
+TestOneFormat("9*9", "-1Afp3.");
+TestOneFormat("[*]X", "-1Afp3.");
+TestOneFormat("<*", "-1Afp3.d33F$");
+TestOneFormat(">*", "-1Afp3.d33F$");
+TestOneFormat("<[AAAAAAAAAAA]", "-1Afp3.d33F$");
+TestOneFormat(">[AAAAAAAAAAA]", "-1Afp3.d33F$");
+TestOneFormat("<[XXXXXXXXXXX]", "-1Afp3.d33F$");
+TestOneFormat(">[XXXXXXXXXXX]", "-1Afp3.d33F$");
+TestOneFormat("<[XXXXXXXXXXX]", "-1Afp3.d33F$");
+TestOneFormat(">[???????????]", "-1Afp3.d33F$");
+TestOneFormat("<[???????????]", "-1Afp3.d33F$");
+TestOneFormat("\\>[\\**]", "-1Afp3.d33F$");
+TestOneFormat("\\>[\\\\**]", "-1Afp3.d33F$");
+TestOneFormat("=*", "-1Afp3.d33F$");
+TestOneFormat("<??????=*", "-1Afp3.d33F$");
+TestOneFormat(">??????=*", "-1Afp3.d33F$");
+TestOneFormat(">??????<*", "-1Afp3.d33F$");
+TestOneFormat("clams", "-1Afp3.d33F$");
+TestOneFormat("cl9ms", "-1Afp3.d33F$");
+TestOneFormat("cl\\9ms", "-1Afp3.d33F$");
+endstream
+endobj
+{{xref}}
+trailer <<
+ /Root 1 0 R
+>>
+{{startxref}}
+%%EOF
diff --git a/testing/resources/javascript/util_printx_expected.txt b/testing/resources/javascript/util_printx_expected.txt
new file mode 100644
index 0000000000..124767d5fd
--- /dev/null
+++ b/testing/resources/javascript/util_printx_expected.txt
@@ -0,0 +1,35 @@
+Alert: ('', '') => ''
+Alert: ('', '123') => ''
+Alert: ('??', '') => ''
+Alert: ('??', 'f2') => 'f2'
+Alert: ('??', 'f27') => 'f2'
+Alert: ('XXX', '') => ''
+Alert: ('XXX', '1afp3.') => '1af'
+Alert: ('XXX', '-1Afp3.d33F$') => '1Af'
+Alert: ('AAA', '') => ''
+Alert: ('AAA', '-1Afp3.') => 'Afp'
+Alert: ('AAA', '-1Afp3.d33F$') => 'Afp'
+Alert: ('999', '') => ''
+Alert: ('999', '-1Afp3.') => '13'
+Alert: ('999', '-1Afp3.d33F$') => '133'
+Alert: ('9*9', '') => ''
+Alert: ('9*9', '-1Afp3.') => '1Afp3.'
+Alert: ('[*]X', '-1Afp3.') => '[-1Afp3.]'
+Alert: ('<*', '-1Afp3.d33F$') => '-1afp3.d33f$'
+Alert: ('>*', '-1Afp3.d33F$') => '-1AFP3.D33F$'
+Alert: ('<[AAAAAAAAAAA]', '-1Afp3.d33F$') => '[afpdf]'
+Alert: ('>[AAAAAAAAAAA]', '-1Afp3.d33F$') => '[AFPDF]'
+Alert: ('<[XXXXXXXXXXX]', '-1Afp3.d33F$') => '[1afp3d33f]'
+Alert: ('>[XXXXXXXXXXX]', '-1Afp3.d33F$') => '[1AFP3D33F]'
+Alert: ('<[XXXXXXXXXXX]', '-1Afp3.d33F$') => '[1afp3d33f]'
+Alert: ('>[???????????]', '-1Afp3.d33F$') => '[-1AFP3.D33F]'
+Alert: ('<[???????????]', '-1Afp3.d33F$') => '[-1afp3.d33f]'
+Alert: ('\>[\**]', '-1Afp3.d33F$') => '>[*-1Afp3.d33F$]'
+Alert: ('\>[\\**]', '-1Afp3.d33F$') => '>[\-1Afp3.d33F$]'
+Alert: ('=*', '-1Afp3.d33F$') => '-1Afp3.d33F$'
+Alert: ('<??????=*', '-1Afp3.d33F$') => '-1afp3.d33F$'
+Alert: ('>??????=*', '-1Afp3.d33F$') => '-1AFP3.d33F$'
+Alert: ('>??????<*', '-1Afp3.d33F$') => '-1AFP3.d33f$'
+Alert: ('clams', '-1Afp3.d33F$') => 'clams'
+Alert: ('cl9ms', '-1Afp3.d33F$') => 'cl1ms'
+Alert: ('cl\9ms', '-1Afp3.d33F$') => 'cl9ms'