From 8eb0a830da652b035cdc7e8a728fada8cb9b54af Mon Sep 17 00:00:00 2001 From: Paul Bissonnette Date: Mon, 19 Aug 2013 00:35:18 -0700 Subject: [PATCH] Updating ext_string for benchmark optimizations String optimizations, this gives us a 40% reduction in cycles for the revcomp benchmark. Differential Revision: D934224 --- hphp/runtime/base/array-util.cpp | 5 +- hphp/runtime/base/builtin-functions.cpp | 5 +- hphp/runtime/base/stream-wrapper-registry.cpp | 10 +- hphp/runtime/base/string-util.cpp | 163 ------ hphp/runtime/base/string-util.h | 34 -- hphp/runtime/debugger/cmd/cmd_info.cpp | 3 +- hphp/runtime/debugger/debugger_client.cpp | 19 +- hphp/runtime/ext/ext_domdocument.cpp | 3 +- hphp/runtime/ext/ext_hash.cpp | 7 +- hphp/runtime/ext/ext_mb.cpp | 5 +- hphp/runtime/ext/ext_pdo.cpp | 5 +- hphp/runtime/ext/ext_process.cpp | 7 +- hphp/runtime/ext/ext_reflection.cpp | 7 +- hphp/runtime/ext/ext_soap.cpp | 7 +- hphp/runtime/ext/ext_spl.cpp | 3 +- hphp/runtime/ext/ext_string.cpp | 519 +++++++++++++++++- hphp/runtime/ext/soap/encoding.cpp | 5 +- hphp/runtime/server/http-protocol.cpp | 5 +- .../server/libevent-server-with-takeover.cpp | 5 +- hphp/test/ext/test_cpp_base.cpp | 3 +- hphp/test/quick/string-util.php | 27 + hphp/test/quick/string-util.php.expect | 10 + 22 files changed, 591 insertions(+), 266 deletions(-) create mode 100644 hphp/test/quick/string-util.php create mode 100644 hphp/test/quick/string-util.php.expect diff --git a/hphp/runtime/base/array-util.cpp b/hphp/runtime/base/array-util.cpp index 7d31d7eb3..8ed04e5b9 100644 --- a/hphp/runtime/base/array-util.cpp +++ b/hphp/runtime/base/array-util.cpp @@ -21,6 +21,7 @@ #include "hphp/runtime/base/runtime-error.h" #include "hphp/runtime/ext/ext_math.h" #include "hphp/runtime/ext/ext_json.h" +#include "hphp/runtime/ext/ext_string.h" namespace HPHP { /////////////////////////////////////////////////////////////////////////////// @@ -479,9 +480,9 @@ Variant ArrayUtil::ChangeKeyCase(CArrRef input, bool lower) { Variant key(iter.first()); if (key.isString()) { if (lower) { - ret.set(StringUtil::ToLower(key.toString()), iter.secondRef()); + ret.set(f_strtolower(key.toString()), iter.secondRef()); } else { - ret.set(StringUtil::ToUpper(key.toString()), iter.secondRef()); + ret.set(f_strtoupper(key.toString()), iter.secondRef()); } } else { ret.set(key, iter.secondRef()); diff --git a/hphp/runtime/base/builtin-functions.cpp b/hphp/runtime/base/builtin-functions.cpp index 7b932dc20..a2c4d4908 100644 --- a/hphp/runtime/base/builtin-functions.cpp +++ b/hphp/runtime/base/builtin-functions.cpp @@ -31,6 +31,7 @@ #include "hphp/runtime/ext/ext_function.h" #include "hphp/runtime/ext/ext_file.h" #include "hphp/runtime/ext/ext_collections.h" +#include "hphp/runtime/ext/ext_string.h" #include "hphp/util/logger.h" #include "hphp/util/util.h" #include "hphp/util/process.h" @@ -1057,7 +1058,7 @@ AutoloadHandler::Result AutoloadHandler::loadFromMap(CStrRef name, CVarRef &type_map = m_map.get()->get(kind); auto const typeMapCell = type_map.asCell(); if (typeMapCell->m_type != KindOfArray) return Failure; - String canonicalName = toLower ? StringUtil::ToLower(name) : name; + String canonicalName = toLower ? f_strtolower(name) : name; CVarRef &file = typeMapCell->m_data.parr->get(canonicalName); bool ok = false; if (file.isString()) { @@ -1222,7 +1223,7 @@ String AutoloadHandler::getSignature(CVarRef handler) { if (!f_is_callable(handler, false, ref(name))) { return null_string; } - String lName = StringUtil::ToLower(name.toString()); + String lName = f_strtolower(name.toString()); if (handler.isArray()) { Variant first = handler.getArrayData()->get(int64_t(0)); if (first.isObject()) { diff --git a/hphp/runtime/base/stream-wrapper-registry.cpp b/hphp/runtime/base/stream-wrapper-registry.cpp index 03e5fc2df..a7ab5e39c 100644 --- a/hphp/runtime/base/stream-wrapper-registry.cpp +++ b/hphp/runtime/base/stream-wrapper-registry.cpp @@ -16,11 +16,11 @@ #include "hphp/runtime/base/stream-wrapper-registry.h" #include "hphp/runtime/base/file.h" -#include "hphp/runtime/base/string-util.h" #include "hphp/runtime/base/file-stream-wrapper.h" #include "hphp/runtime/base/php-stream-wrapper.h" #include "hphp/runtime/base/http-stream-wrapper.h" #include "hphp/runtime/base/request-local.h" +#include "hphp/runtime/ext/ext_string.h" #include #include @@ -60,7 +60,7 @@ const StaticString s_compress_zlib("compress.zlib"); bool disableWrapper(CStrRef scheme) { - String lscheme = StringUtil::ToLower(scheme); + String lscheme = f_strtolower(scheme); if (lscheme.same(s_file)) { // Zend quietly succeeds, but does nothing @@ -94,7 +94,7 @@ bool disableWrapper(CStrRef scheme) { } bool restoreWrapper(CStrRef scheme) { - String lscheme = StringUtil::ToLower(scheme); + String lscheme = f_strtolower(scheme); bool ret = false; // Unregister request-specific wrapper @@ -117,7 +117,7 @@ bool restoreWrapper(CStrRef scheme) { } bool registerRequestWrapper(CStrRef scheme, std::unique_ptr wrapper) { - String lscheme = StringUtil::ToLower(scheme); + String lscheme = f_strtolower(scheme); // Global, non-disabled wrapper if ((s_wrappers.find(lscheme.data()) != s_wrappers.end()) && @@ -156,7 +156,7 @@ Array enumWrappers() { } Wrapper* getWrapper(CStrRef scheme) { - String lscheme = StringUtil::ToLower(scheme); + String lscheme = f_strtolower(scheme); // Request local wrapper? { diff --git a/hphp/runtime/base/string-util.cpp b/hphp/runtime/base/string-util.cpp index 14fca8d4b..dd6db51cb 100644 --- a/hphp/runtime/base/string-util.cpp +++ b/hphp/runtime/base/string-util.cpp @@ -26,65 +26,6 @@ namespace HPHP { /////////////////////////////////////////////////////////////////////////////// // manipulations -String StringUtil::ToLower(CStrRef input, - ToLowerType type /*= ToLowerType::All */) { - if (input.empty()) return input; - - int len = input.size(); - char *ret = nullptr; - switch (type) { - case ToLowerType::All: - ret = string_to_lower(input.data(), len); - break; - case ToLowerType::First: - ret = string_to_lower_first(input.data(), len); - break; - case ToLowerType::Words: - ret = string_to_lower_words(input.data(), len); - break; - default: - assert(false); - break; - } - return String(ret, len, AttachString); -} - -String StringUtil::ToUpper(CStrRef input, - ToUpperType type /*= ToUpperType::All */) { - if (input.empty()) return input; - - int len = input.size(); - char *ret = nullptr; - switch (type) { - case ToUpperType::All: - ret = string_to_upper(input.data(), len); - break; - case ToUpperType::First: - ret = string_to_upper_first(input.data(), len); - break; - case ToUpperType::Words: - ret = string_to_upper_words(input.data(), len); - break; - default: - assert(false); - break; - } - return String(ret, len, AttachString); -} - -String StringUtil::Trim(CStrRef input, TrimType type /* = TrimType::Both */, - CStrRef charlist /* = k_HPHP_TRIM_CHARLIST */) { - if (input.empty()) return input; - int len = input.size(); - char *ret = string_trim(input.data(), len, - charlist.data(), charlist.length(), - static_cast(type)); - if (!ret) { - return input; - } - return String(ret, len, AttachString); -} - String StringUtil::Pad(CStrRef input, int final_length, CStrRef pad_string /* = " " */, PadType type /* = PadType::Right */) { @@ -95,41 +36,6 @@ String StringUtil::Pad(CStrRef input, int final_length, return String(); } -String StringUtil::Reverse(CStrRef input) { - if (input.empty()) return input; - int len = input.size(); - return String(string_reverse(input.data(), len), len, AttachString); -} - -String StringUtil::Repeat(CStrRef input, int count) { - if (count < 0) { - raise_warning("Second argument has to be greater than or equal to 0"); - return String(); - } - if (count == 0) { - return ""; - } - if (!input.empty()) { - int len = input.size(); - char *ret = string_repeat(input.data(), len, count); - if (ret) { - return String(ret, len, AttachString); - } - } - return input; -} - -String StringUtil::Shuffle(CStrRef input) { - if (!input.empty()) { - int len = input.size(); - char *ret = string_shuffle(input.data(), len); - if (ret) { - return String(ret, len, AttachString); - } - } - return input; -} - String StringUtil::StripHTMLTags(CStrRef input, CStrRef allowable_tags /* = "" */) { if (input.empty()) return input; @@ -139,21 +45,6 @@ String StringUtil::StripHTMLTags(CStrRef input, return String(ret, len, AttachString); } -String StringUtil::WordWrap(CStrRef input, int width, - CStrRef wordbreak /* = "\n" */, - bool cut /* = false */) { - if (!input.empty()) { - int len = input.size(); - char *ret = string_wordwrap(input.data(), len, width, wordbreak.data(), - wordbreak.size(), cut); - if (ret) { - return String(ret, len, AttachString); - } - return String(); - } - return input; -} - /////////////////////////////////////////////////////////////////////////////// // splits/joins @@ -303,46 +194,6 @@ Variant StringUtil::ChunkSplit(CStrRef body, int chunklen /* = 76 */, /////////////////////////////////////////////////////////////////////////////// // encoding/decoding -String StringUtil::CEncode(CStrRef input, CStrRef charlist) { - String chars = charlist; - if (chars.isNull()) { - chars = String("\\\x00\x01..\x1f\x7f..\xff", 10, CopyString); - } - if (input.empty() || chars.empty()) return input; - int len = input.size(); - char *ret = string_addcslashes(input.c_str(), len, chars.data(), - chars.size()); - return String(ret, len, AttachString); -} - -String StringUtil::CDecode(CStrRef input) { - if (input.empty()) return input; - int len = input.size(); - char *ret = string_stripcslashes(input.c_str(), len); - return String(ret, len, AttachString); -} - -String StringUtil::SqlEncode(CStrRef input) { - if (input.empty()) return input; - int len = input.size(); - char *ret = string_addslashes(input.c_str(), len); - return String(ret, len, AttachString); -} - -String StringUtil::SqlDecode(CStrRef input) { - if (input.empty()) return input; - int len = input.size(); - char *ret = string_stripslashes(input.c_str(), len); - return String(ret, len, AttachString); -} - -String StringUtil::RegExEncode(CStrRef input) { - if (input.empty()) return input; - int len = input.size(); - char *ret = string_quotemeta(input.c_str(), len); - return String(ret, len, AttachString); -} - String StringUtil::HtmlEncode(CStrRef input, QuoteStyle quoteStyle, const char *charset, bool nbsp) { if (input.empty()) return input; @@ -485,20 +336,6 @@ String StringUtil::QuotedPrintableDecode(CStrRef input) { return String(ret, len, AttachString); } -String StringUtil::HexEncode(CStrRef input) { - if (input.empty()) return input; - int len = input.size(); - char *ret = string_bin2hex(input.data(), len); - return String(ret, len, AttachString); -} - -String StringUtil::HexDecode(CStrRef input) { - if (input.empty()) return input; - int len = input.size(); - char *ret = string_hex2bin(input.data(), len); - return String(ret, len, AttachString); -} - String StringUtil::UUEncode(CStrRef input) { if (input.empty()) return input; diff --git a/hphp/runtime/base/string-util.h b/hphp/runtime/base/string-util.h index 66e2bbbb9..ab48420d1 100644 --- a/hphp/runtime/base/string-util.h +++ b/hphp/runtime/base/string-util.h @@ -30,24 +30,6 @@ extern const StaticString k_HPHP_TRIM_CHARLIST; */ class StringUtil { public: - enum class ToUpperType { - All, - First, - Words - }; - - enum class ToLowerType { - All, - First, - Words - }; - - enum class TrimType { - Left = 1, - Right = 2, - Both = 3 - }; - enum class PadType { Left = 0, Right = 1, @@ -67,18 +49,9 @@ public: * Manipulations. Note, all these functions will create a new string than * modifying input, although names of these functions sound like mutating. */ - static String ToLower(CStrRef input, ToLowerType type = ToLowerType::All); - static String ToUpper(CStrRef input, ToUpperType type = ToUpperType::All); - static String Trim(CStrRef input, TrimType type = TrimType::Both, - CStrRef charlist = k_HPHP_TRIM_CHARLIST); static String Pad(CStrRef input, int final_length, CStrRef pad_string = " ", PadType type = PadType::Right); - static String Reverse(CStrRef input); - static String Repeat(CStrRef input, int count); - static String Shuffle(CStrRef input); static String StripHTMLTags(CStrRef input, CStrRef allowable_tags = ""); - static String WordWrap(CStrRef input, int width, - CStrRef wordbreak = "\n", bool cut = false); /** * Split/joins. @@ -93,11 +66,6 @@ public: /** * Encoding/decoding. */ - static String CEncode(CStrRef input, CStrRef charlist); - static String CDecode(CStrRef input); - static String SqlEncode(CStrRef input); - static String SqlDecode(CStrRef input); - static String RegExEncode(CStrRef input); static String HtmlEncode(CStrRef input, QuoteStyle quoteStyle, const char *charset, bool nbsp); static String HtmlEncodeExtra(CStrRef input, QuoteStyle quoteStyle, @@ -106,8 +74,6 @@ public: const char *charset, bool all); static String QuotedPrintableEncode(CStrRef input); static String QuotedPrintableDecode(CStrRef input); - static String HexEncode(CStrRef input); - static String HexDecode(CStrRef input); static String UUEncode(CStrRef input); static String UUDecode(CStrRef input); static String Base64Encode(CStrRef input); diff --git a/hphp/runtime/debugger/cmd/cmd_info.cpp b/hphp/runtime/debugger/cmd/cmd_info.cpp index 08f4289c6..83982faf5 100644 --- a/hphp/runtime/debugger/cmd/cmd_info.cpp +++ b/hphp/runtime/debugger/cmd/cmd_info.cpp @@ -17,6 +17,7 @@ #include "hphp/runtime/debugger/cmd/cmd_info.h" #include "hphp/runtime/debugger/cmd/cmd_variable.h" #include "hphp/runtime/ext/ext_reflection.h" +#include "hphp/runtime/ext/ext_string.h" #include "hphp/runtime/base/preg.h" #include "hphp/util/logger.h" @@ -292,7 +293,7 @@ void CmdInfo::PrintDocComments(StringBuffer &sb, CArrRef info) { space1 = matches1[1].toString().size(); space2 = matches2[1].toString().size(); } - String spaces = StringUtil::Repeat(" ", space2 - space1 - 1); + String spaces = f_str_repeat(" ", space2 - space1 - 1); sb.printf("%s%s\n", spaces.data(), doc.data()); } } diff --git a/hphp/runtime/debugger/debugger_client.cpp b/hphp/runtime/debugger/debugger_client.cpp index 99821d2ba..37ed96516 100644 --- a/hphp/runtime/debugger/debugger_client.cpp +++ b/hphp/runtime/debugger/debugger_client.cpp @@ -24,6 +24,7 @@ #include "hphp/runtime/ext/ext_json.h" #include "hphp/runtime/ext/ext_socket.h" #include "hphp/runtime/ext/ext_network.h" +#include "hphp/runtime/ext/ext_string.h" #include "hphp/util/text-color.h" #include "hphp/util/text-art.h" #include "hphp/util/logger.h" @@ -384,7 +385,7 @@ String DebuggerClient::FormatInfoVec(const IDebuggable::InfoVec &info, String DebuggerClient::FormatTitle(const char *title) { TRACE(2, "DebuggerClient::FormatTitle\n"); - String dash = StringUtil::Repeat(BOX_H, (LineWidth - strlen(title)) / 2 - 4); + String dash = f_str_repeat(BOX_H, (LineWidth - strlen(title)) / 2 - 4); StringBuffer sb; sb.append("\n"); @@ -1309,7 +1310,7 @@ IMPLEMENT_COLOR_OUTPUT(error, stderr, ErrorColor); string DebuggerClient::wrap(const std::string &s) { TRACE(2, "DebuggerClient::wrap\n"); - String ret = StringUtil::WordWrap(String(s.c_str(), s.size(), CopyString), + String ret = f_wordwrap(String(s.c_str(), s.size(), CopyString), LineWidth - 4, "\n", true); return string(ret.data(), ret.size()); } @@ -1368,8 +1369,8 @@ void DebuggerClient::helpCmds(const std::vector &cmds) { continue; } - cmd = StringUtil::WordWrap(cmd, left, "\n", true); - desc = StringUtil::WordWrap(desc, right, "\n", true); + cmd = f_wordwrap(cmd, left, "\n", true); + desc = f_wordwrap(desc, right, "\n", true); Array lines1 = StringUtil::Explode(cmd, "\n").toArray(); Array lines2 = StringUtil::Explode(desc, "\n").toArray(); for (int n = 0; n < lines1.size() || n < lines2.size(); n++) { @@ -1381,7 +1382,7 @@ void DebuggerClient::helpCmds(const std::vector &cmds) { line.append(" "); line.append(lines2[n].toString()); - sb.append(StringUtil::Trim(line.detach(), StringUtil::TrimType::Right)); + sb.append(f_rtrim(line.detach())); sb.append("\n"); } } @@ -1406,20 +1407,20 @@ void DebuggerClient::tutorial(const char *text) { if (m_tutorial < 0) return; String ret = String(text).replace("\t", " "); - ret = StringUtil::WordWrap(ret, LineWidth - 4, "\n", true); + ret = f_wordwrap(ret, LineWidth - 4, "\n", true); Array lines = StringUtil::Explode(ret, "\n").toArray(); StringBuffer sb; String header = " Tutorial - '[h]elp [t]utorial off|auto' to turn off "; - String hr = StringUtil::Repeat(BOX_H, LineWidth - 2); + String hr = f_str_repeat(BOX_H, LineWidth - 2); sb.append(BOX_UL); sb.append(hr); sb.append(BOX_UR); sb.append("\n"); int wh = (LineWidth - 2 - header.size()) / 2; sb.append(BOX_V); - sb.append(StringUtil::Repeat(" ", wh)); + sb.append(f_str_repeat(" ", wh)); sb.append(header); - sb.append(StringUtil::Repeat(" ", wh)); + sb.append(f_str_repeat(" ", wh)); sb.append(BOX_V); sb.append("\n"); diff --git a/hphp/runtime/ext/ext_domdocument.cpp b/hphp/runtime/ext/ext_domdocument.cpp index 8b71b4510..5308ef500 100644 --- a/hphp/runtime/ext/ext_domdocument.cpp +++ b/hphp/runtime/ext/ext_domdocument.cpp @@ -18,6 +18,7 @@ #include "hphp/runtime/ext/ext_domdocument.h" #include "hphp/runtime/ext/ext_file.h" #include "hphp/runtime/ext/ext_class.h" +#include "hphp/runtime/ext/ext_string.h" #include "hphp/runtime/base/runtime-error.h" #include "hphp/runtime/ext/ext_function.h" #include "hphp/runtime/ext/ext_simplexml.h" @@ -3431,7 +3432,7 @@ bool c_DOMDocument::t_registernodeclass(CStrRef baseclass, baseclass.data()); return false; } - m_classmap.set(StringUtil::ToLower(baseclass), extendedclass); + m_classmap.set(f_strtolower(baseclass), extendedclass); return true; } diff --git a/hphp/runtime/ext/ext_hash.cpp b/hphp/runtime/ext/ext_hash.cpp index 080f00062..5166d32d0 100644 --- a/hphp/runtime/ext/ext_hash.cpp +++ b/hphp/runtime/ext/ext_hash.cpp @@ -17,6 +17,7 @@ #include "hphp/runtime/ext/ext_hash.h" #include "hphp/runtime/ext/ext_file.h" +#include "hphp/runtime/ext/ext_string.h" #include "hphp/runtime/ext/hash/hash_md.h" #include "hphp/runtime/ext/hash/hash_sha.h" #include "hphp/runtime/ext/hash/hash_ripemd.h" @@ -170,7 +171,7 @@ Array HHVM_FUNCTION(hash_algos) { static HashEnginePtr php_hash_fetch_ops(CStrRef algo) { HashEngineMap::const_iterator iter = - HashEngines.find(StringUtil::ToLower(algo).data()); + HashEngines.find(f_strtolower(algo).data()); if (iter == HashEngines.end()) { return HashEnginePtr(); } @@ -215,7 +216,7 @@ static Variant php_hash_do_hash(CStrRef algo, CStrRef data, bool isfilename, if (raw_output) { return raw; } - return StringUtil::HexEncode(raw); + return f_bin2hex(raw); } Variant HHVM_FUNCTION(hash, CStrRef algo, CStrRef data, @@ -316,7 +317,7 @@ String HHVM_FUNCTION(hash_final, CResRef context, if (raw_output) { return raw; } - return StringUtil::HexEncode(raw); + return f_bin2hex(raw); } int64_t HHVM_FUNCTION(furchash_hphp_ext, CStrRef key, diff --git a/hphp/runtime/ext/ext_mb.cpp b/hphp/runtime/ext/ext_mb.cpp index a79bb0323..b5d6999b8 100644 --- a/hphp/runtime/ext/ext_mb.cpp +++ b/hphp/runtime/ext/ext_mb.cpp @@ -21,6 +21,7 @@ #include "hphp/runtime/ext/php_unicode.h" #include "hphp/runtime/ext/unicode_data.h" #include "hphp/runtime/ext/ext_process.h" +#include "hphp/runtime/ext/ext_string.h" #include "hphp/runtime/base/zend-url.h" #include "hphp/runtime/base/zend-string.h" #include "hphp/runtime/base/ini-setting.h" @@ -3839,7 +3840,7 @@ static int _php_mbstr_parse_mail_headers(Array &ht, const char *str, if (!fld_name.empty() && !fld_val.empty()) { /* FIXME: some locale free implementation is * really required here,,, */ - ht.set(StringUtil::ToUpper(fld_name), fld_val); + ht.set(f_strtoupper(fld_name), fld_val); } state = 1; } @@ -3872,7 +3873,7 @@ out: if (!fld_name.empty() && !fld_val.empty()) { /* FIXME: some locale free implementation is * really required here,,, */ - ht.set(StringUtil::ToUpper(fld_name), fld_val); + ht.set(f_strtoupper(fld_name), fld_val); } } return state; diff --git a/hphp/runtime/ext/ext_pdo.cpp b/hphp/runtime/ext/ext_pdo.cpp index 94e3dae3e..6738ec4bb 100644 --- a/hphp/runtime/ext/ext_pdo.cpp +++ b/hphp/runtime/ext/ext_pdo.cpp @@ -21,6 +21,7 @@ #include "hphp/runtime/ext/ext_class.h" #include "hphp/runtime/ext/ext_function.h" #include "hphp/runtime/ext/ext_stream.h" +#include "hphp/runtime/ext/ext_string.h" #include "hphp/runtime/base/class-info.h" #include "hphp/runtime/base/ini-setting.h" #include "hphp/runtime/base/string-buffer.h" @@ -653,10 +654,10 @@ static bool pdo_stmt_describe_columns(sp_PDOStatement stmt) { stmt->dbh->desired_case != PDO_CASE_NATURAL) { switch (stmt->dbh->desired_case) { case PDO_CASE_UPPER: - name = StringUtil::ToUpper(name); + name = f_strtoupper(name); break; case PDO_CASE_LOWER: - name = StringUtil::ToLower(name); + name = f_strtolower(name); break; default:; } diff --git a/hphp/runtime/ext/ext_process.cpp b/hphp/runtime/ext/ext_process.cpp index 68f5db472..62dcb0ae4 100644 --- a/hphp/runtime/ext/ext_process.cpp +++ b/hphp/runtime/ext/ext_process.cpp @@ -18,6 +18,7 @@ #include "hphp/runtime/ext/ext_process.h" #include "hphp/runtime/ext/ext_file.h" #include "hphp/runtime/ext/ext_function.h" +#include "hphp/runtime/ext/ext_string.h" #include "hphp/runtime/base/string-buffer.h" #include "hphp/runtime/base/zend-string.h" #include "hphp/runtime/base/thread-init-fini.h" @@ -466,8 +467,7 @@ String f_exec(CStrRef command, VRefParam output /* = null */, return String(); } - return StringUtil::Trim(lines[count - 1].toString(), - StringUtil::TrimType::Right); + return f_rtrim(lines[count - 1].toString()); } void f_passthru(CStrRef command, VRefParam return_var /* = null */) { @@ -514,8 +514,7 @@ String f_system(CStrRef command, VRefParam return_var /* = null */) { return String(); } - return StringUtil::Trim(lines[count - 1].toString(), - StringUtil::TrimType::Right); + return f_rtrim(lines[count - 1].toString()); } /////////////////////////////////////////////////////////////////////////////// diff --git a/hphp/runtime/ext/ext_reflection.cpp b/hphp/runtime/ext/ext_reflection.cpp index fbbbcc37a..cab92a405 100644 --- a/hphp/runtime/ext/ext_reflection.cpp +++ b/hphp/runtime/ext/ext_reflection.cpp @@ -18,6 +18,7 @@ #include "hphp/runtime/ext/ext_reflection.h" #include "hphp/runtime/ext/ext_closure.h" #include "hphp/runtime/ext/ext_misc.h" +#include "hphp/runtime/ext/ext_string.h" #include "hphp/runtime/base/externals.h" #include "hphp/runtime/base/class-info.h" #include "hphp/runtime/base/runtime-option.h" @@ -692,7 +693,7 @@ static Array get_class_info(const ClassInfo *cls) { ClassInfo::MethodInfo *m = *iter; Array info = Array::Create(); set_method_info(info, m, cls); - arr.set(StringUtil::ToLower(m->name), info); + arr.set(f_strtolower(m->name), info); } ret.set(s_methods, VarNR(arr)); } @@ -829,7 +830,7 @@ Array f_hphp_get_class_info(CVarRef name) { if (m->isGenerated()) continue; Array info = Array::Create(); set_method_info(info, m); - arr.set(StringUtil::ToLower(m->nameRef()), VarNR(info)); + arr.set(f_strtolower(m->nameRef()), VarNR(info)); } Func* const* clsMethods = cls->methods(); @@ -840,7 +841,7 @@ Array f_hphp_get_class_info(CVarRef name) { if (m->isGenerated()) continue; Array info = Array::Create(); set_method_info(info, m); - arr.set(StringUtil::ToLower(m->nameRef()), VarNR(info)); + arr.set(f_strtolower(m->nameRef()), VarNR(info)); } ret.set(s_methods, VarNR(arr)); } diff --git a/hphp/runtime/ext/ext_soap.cpp b/hphp/runtime/ext/ext_soap.cpp index 3170c0b9d..33c1a6f48 100644 --- a/hphp/runtime/ext/ext_soap.cpp +++ b/hphp/runtime/ext/ext_soap.cpp @@ -29,6 +29,7 @@ #include "hphp/runtime/ext/ext_class.h" #include "hphp/runtime/ext/ext_output.h" #include "hphp/runtime/ext/ext_stream.h" +#include "hphp/runtime/ext/ext_string.h" #include "hphp/system/systemlib.h" @@ -728,7 +729,7 @@ static sdlFunctionPtr get_doc_function(sdl *sdl, xmlNodePtr params) { static sdlFunctionPtr get_function(sdl *sdl, const char *function_name) { if (sdl) { - String lowered = StringUtil::ToLower(function_name); + String lowered = f_strtolower(function_name); sdlFunctionMap::iterator iter = sdl->functions.find(lowered.data()); if (iter == sdl->functions.end()) { iter = sdl->requests.find(lowered.data()); @@ -2012,7 +2013,7 @@ void c_SoapServer::t_addfunction(CVarRef func) { function_name.data()); return; } - m_soap_functions.ft.set(StringUtil::ToLower(function_name), 1); + m_soap_functions.ft.set(f_strtolower(function_name), 1); m_soap_functions.ftOriginal.set(function_name, 1); } } @@ -2052,7 +2053,7 @@ static bool valid_function(c_SoapServer *server, Object &soap_obj, } else if (server->m_soap_functions.functions_all) { return f_function_exists(fn_name); } else if (!server->m_soap_functions.ft.empty()) { - return server->m_soap_functions.ft.exists(StringUtil::ToLower(fn_name)); + return server->m_soap_functions.ft.exists(f_strtolower(fn_name)); } HPHP::Func* f = cls->lookupMethod(fn_name.get()); return (f && f->isPublic()); diff --git a/hphp/runtime/ext/ext_spl.cpp b/hphp/runtime/ext/ext_spl.cpp index 95ebf14a6..04adc1486 100644 --- a/hphp/runtime/ext/ext_spl.cpp +++ b/hphp/runtime/ext/ext_spl.cpp @@ -18,6 +18,7 @@ #include "hphp/runtime/ext/ext_spl.h" #include "hphp/runtime/ext/ext_math.h" #include "hphp/runtime/ext/ext_class.h" +#include "hphp/runtime/ext/ext_string.h" #include "hphp/system/systemlib.h" @@ -341,7 +342,7 @@ void f_spl_autoload(CStrRef class_name, Array ext = file_extensions.isNull() ? s_extension_list->extensions : StringUtil::Explode(file_extensions, ",").toArray(); - String lClass = StringUtil::ToLower(class_name); + String lClass = f_strtolower(class_name); bool found = false; for (ArrayIter iter(ext); iter; ++iter) { String fileName = lClass + iter.second().toString(); diff --git a/hphp/runtime/ext/ext_string.cpp b/hphp/runtime/ext/ext_string.cpp index a9c09fc0e..53ec3147a 100644 --- a/hphp/runtime/ext/ext_string.cpp +++ b/hphp/runtime/ext/ext_string.cpp @@ -33,71 +33,402 @@ namespace HPHP { static Mutex s_mutex; /////////////////////////////////////////////////////////////////////////////// +template inline ALWAYS_INLINE +String stringForEachBuffered(uint32_t bufLen, CStrRef str, Op action) { + StringBuffer sb(bufLen); + StringSlice sl = str.slice(); + const char* src = sl.begin(); + const char* end = sl.end(); + + for (; src < end; ++src) { + action(sb, src, end); + } + + return sb.detach(); +} + +template inline ALWAYS_INLINE +String stringForEach(uint32_t len, CStrRef str, Op action) { + String ret = mutate ? str : String(len, ReserveString); + + StringSlice srcSlice = str.slice(); + MutableSlice dstSlice = ret.mutableSlice(); + + const char* src = srcSlice.begin(); + const char* end = srcSlice.end(); + + char* dst = dstSlice.begin(); + + for (; src != end; ++src, ++dst) { + *dst = action(*src); + } + + if (!mutate) ret->setSize(len); + return ret; +} + +template inline ALWAYS_INLINE +String stringForEachFast(CStrRef str, Op action) { + if (str.empty()) { + return str; + } + + if (str->getCount() == 1) { + return stringForEach(str.size(), str, action); + } + + return stringForEach(str.size(), str, action); +} + String f_addcslashes(CStrRef str, CStrRef charlist) { - return StringUtil::CEncode(str, charlist); + if (str.empty() || (!charlist.isNull() && charlist->empty())) { + return str; + } + + int masklen = charlist.isNull() ? 10 : charlist.size(); + const char* list = charlist.isNull() ? "\\\x00\x01..\x1f\x7f..\xff" + : charlist.c_str(); + + char flags[256]; + string_charmask(list, masklen, flags); + + return stringForEachBuffered(str.size(), str, + [&] (StringBuffer& ret, const char* src, const char* end) { + int c = (unsigned char)*src; + + if (flags[c]) { + ret.append('\\'); + if ((c < 32) || (c > 126)) { + switch (c) { + case '\n': ret.append('n'); break; + case '\t': ret.append('t'); break; + case '\r': ret.append('r'); break; + case '\a': ret.append('a'); break; + case '\v': ret.append('v'); break; + case '\b': ret.append('b'); break; + case '\f': ret.append('f'); break; + default: ret.append((char)('0' + (c / 64))); c %= 64; + ret.append((char)('0' + (c / 8))); c %= 8; + ret.append((char)('0' + c)); + } + return; + } + } + ret.append((char)c); + }); } + String f_stripcslashes(CStrRef str) { - return StringUtil::CDecode(str); + if (str.empty()) { + return str; + } + + return stringForEachBuffered(str.size(), str, + [&] (StringBuffer& ret, const char*& src, const char* end) { + char c; + const char* p; + + if (*src != '\\' || src + 1 == end) { + ret.append(*src); + return; + } + + switch (*++src) { + case 'n': ret.append('\n'); break; + case 'r': ret.append('\r'); break; + case 'a': ret.append('\a'); break; + case 't': ret.append('\t'); break; + case 'v': ret.append('\v'); break; + case 'b': ret.append('\b'); break; + case 'f': ret.append('\f'); break; + case '\\': ret.append('\\'); break; + case 'x': + if (src + 1 == end || !isxdigit(src[1])) { + ret.append(*src); + break; + } + + for (c = 0, ++src, p = src + 2; src < p && src < end && + isxdigit(*src); ++src) { + c *= 16; + c += (*src < 'A' ? *src - '0' : + *src < 'a' ? *src - 'A' + 10 : + *src - 'a' + 10); + } + ret.append(c); + src--; + break; + + default: + if (*src < '0' || '7' < *src) { + // The character after the slash is nothing special. Append it + // unchanged to the result. + ret.append(*src); + break; + } + + // Decode a base 8 number up to 3 characters long. + for (c = 0, p = src + 3; src < p && src < end && '0' <= *src && + *src < '8'; ++src) { + c *= 8; + c += (*src - '0'); + } + ret.append(c); + src--; + } + }); } + String f_addslashes(CStrRef str) { - return StringUtil::SqlEncode(str); + if (str.empty()) { + return str; + } + + return stringForEachBuffered(str.size(), str, + [&] (StringBuffer& ret, const char* src, const char* end) { + switch (*src) { + case '\0': + ret.append('\\'); + ret.append('0'); + break; + case '\\': case '\"': case '\'': + ret.append('\\'); + /* fall through */ + default: + ret.append(*src); + } + }); } + String f_stripslashes(CStrRef str) { - return StringUtil::SqlDecode(str); + if (str.empty()) { + return str; + } + + return stringForEachBuffered(str.size(), str, + [&] (StringBuffer& ret, const char*& src, const char* end) { + if (*src == '\\' && *++src == '0') { + ret.append('\0'); + return; + } + ret.append(*src); + }); } + String f_bin2hex(CStrRef str) { - return StringUtil::HexEncode(str); + if (str.empty()) { + return str; + } + + return stringForEachBuffered(str.size(), str, + [&] (StringBuffer& ret, const char* src, const char* end) { + static char hexconvtab[] = "0123456789abcdef"; + ret.append(hexconvtab[(unsigned char)*src >> 4]); + ret.append(hexconvtab[(unsigned char)*src & 15]); + }); } + Variant f_hex2bin(CStrRef str) { - try { - return StringUtil::HexDecode(str); - } catch (...) { + if (str.empty()) { + return str; + } + + if (str.size() % 2) { raise_warning("hex2bin: malformed input"); return false; } + + StringBuffer ret(str.size() / 2 + 1); + + StringSlice sl = str.slice(); + const char* src = sl.begin(); + const char* end = sl.end(); + + for (; src != end; ++src) { + int val; + if (isdigit(*src)) val = 16 * (*src++ - '0'); + else if ('a' <= *src && *src <= 'f') val = 16 * (*src++ - 'a' + 10); + else if ('A' <= *src && *src <= 'F') val = 16 * (*src++ - 'A' + 10); + else { + raise_warning("hex2bin: malformed input"); + return false; + } + + if (isdigit(*src)) val += (*src - '0'); + else if ('a' <= *src && *src <= 'f') val += (*src - 'a' + 10); + else if ('A' <= *src && *src <= 'F') val += (*src - 'A' + 10); + else { + raise_warning("hex2bin: malformed input"); + return false; + } + + ret.append((char)val); + } + + return ret.detach(); } + String f_nl2br(CStrRef str) { return str.replace("\n", "
\n"); } + String f_quotemeta(CStrRef str) { - return StringUtil::RegExEncode(str); + if (str.empty()) { + return str; + } + + return stringForEachBuffered(str.size(), str, + [&] (StringBuffer& ret, const char* src, const char* end) { + switch (*src) { + case '.': case '\\': case '+': case '*': case '?': case '[': case ']': + case '^': case '$': case '(': case ')': + ret.append('\\'); + /* fall through */ + default: + ret.append(*src); + } + }); } + String f_str_shuffle(CStrRef str) { - return StringUtil::Shuffle(str); + if (str.size() <= 1) { + return str; + } + + String ret = str->getCount() == 1 ? str : String(str, CopyString); + char* buf = ret->mutableData(); + int left = ret->size(); + + while (--left) { + int idx = rand() % left; + char temp = buf[left]; + buf[left] = buf[idx]; + buf[idx] = temp; + } + + return ret; } + String f_strrev(CStrRef str) { - return StringUtil::Reverse(str); + auto len = str.size(); + + if (str->getCount() == 1) { + char* sdata = str->mutableData(); + for (int i = 0; i < len / 2; ++i) { + char temp = sdata[i]; + sdata[i] = sdata[len - i - 1]; + sdata[len - i - 1] = temp; + } + return str; + } + + String ret(len, ReserveString); + + const char* data = str.data(); + char* dest = ret->mutableData(); + + for (int i = 0; i < len; ++i) { + dest[i] = data[len - i - 1]; + } + + ret->setSize(len); + return ret; } + String f_strtolower(CStrRef str) { - return StringUtil::ToLower(str); + return stringForEachFast(str, tolower); } + String f_strtoupper(CStrRef str) { - return StringUtil::ToUpper(str, StringUtil::ToUpperType::All); + return stringForEachFast(str, toupper); } + +template inline ALWAYS_INLINE +String stringToCaseFirst(CStrRef str, OpTo tocase, OpIs iscase) { + if (str.empty() || iscase(str[0])) { + return str; + } + + if (str->getCount() == 1) { + char* sdata = str->mutableData(); + sdata[0] = tocase(sdata[0]); + return str; + } + + String ret(str, CopyString); + char* first = ret->mutableData(); + + *first = tocase(*first); + return ret; +} + String f_ucfirst(CStrRef str) { - return StringUtil::ToUpper(str, StringUtil::ToUpperType::First); + return stringToCaseFirst(str, toupper, isupper); } + String f_lcfirst(CStrRef str) { - return StringUtil::ToLower(str, StringUtil::ToLowerType::First); + return stringToCaseFirst(str, tolower, islower); } + String f_ucwords(CStrRef str) { - return StringUtil::ToUpper(str, StringUtil::ToUpperType::Words); + char last = ' '; + return stringForEachFast(str, [&] (char c) { + char ret = isspace(last) ? toupper(c) : c; + last = c; + return ret; + }); } + String f_strip_tags(CStrRef str, CStrRef allowable_tags /* = "" */) { return StringUtil::StripHTMLTags(str, allowable_tags); } + +template inline ALWAYS_INLINE +String stringTrim(CStrRef str, CStrRef charlist) { + char flags[256]; + string_charmask(charlist.c_str(), charlist.size(), flags); + + auto len = str.size(); + int start = 0, end = len - 1; + + if (left) { + for (; start < len && flags[(unsigned char)str[start]]; ++start) + /* do nothing */; + } + + if (right) { + for (; end >= start && flags[(unsigned char)str[end]]; --end) {} + } + + if (str->getCount() == 1) { + int slen = end - start + 1; + if (start) { + char* sdata = str->mutableData(); + for (int idx = 0; start < len;) sdata[idx++] = sdata[start++]; + } + str->setSize(slen); + return str; + } + + return str.substr(start, end - start + 1); +} + String f_trim(CStrRef str, CStrRef charlist /* = k_HPHP_TRIM_CHARLIST */) { - return StringUtil::Trim(str, StringUtil::TrimType::Both, charlist); + return stringTrim(str, charlist); } + String f_ltrim(CStrRef str, CStrRef charlist /* = k_HPHP_TRIM_CHARLIST */) { - return StringUtil::Trim(str, StringUtil::TrimType::Left, charlist); + return stringTrim(str, charlist); } + String f_rtrim(CStrRef str, CStrRef charlist /* = k_HPHP_TRIM_CHARLIST */) { - return StringUtil::Trim(str, StringUtil::TrimType::Right, charlist); + return stringTrim(str, charlist); } + String f_chop(CStrRef str, CStrRef charlist /* = k_HPHP_TRIM_CHARLIST */) { - return StringUtil::Trim(str, StringUtil::TrimType::Right, charlist); + return stringTrim(str, charlist); } + Variant f_explode(CStrRef delimiter, CStrRef str, int limit /* = 0x7FFFFFFF */) { return StringUtil::Explode(str, delimiter, limit); } @@ -121,9 +452,11 @@ String f_implode(CVarRef arg1, CVarRef arg2 /* = null_variant */) { String f_join(CVarRef glue, CVarRef pieces /* = null_variant */) { return f_implode(glue, pieces); } + Variant f_str_split(CStrRef str, int split_length /* = 1 */) { return StringUtil::Split(str, split_length); } + Variant f_chunk_split(CStrRef body, int chunklen /* = 76 */, CStrRef end /* = "\r\n" */) { return StringUtil::ChunkSplit(body, chunklen, end); @@ -327,19 +660,140 @@ Variant f_substr(CStrRef str, int start, int length /* = 0x7FFFFFFF */) { if (ret.isNull()) return false; return ret; } + String f_str_pad(CStrRef input, int pad_length, CStrRef pad_string /* = " " */, int pad_type /* = k_STR_PAD_RIGHT */) { return StringUtil::Pad(input, pad_length, pad_string, (StringUtil::PadType)pad_type); } + String f_str_repeat(CStrRef input, int multiplier) { - return StringUtil::Repeat(input, multiplier); + if (input.empty()) { + return input; + } + + if (multiplier < 0) { + raise_warning("Second argument has to be greater than or equal to 0"); + return String(); + } + + if (multiplier == 0) { + return String("", CopyString); + } + + if (input.size() == 1) { + String ret(input.size() * multiplier, ReserveString); + + memset(ret->mutableData(), *input->data(), multiplier); + ret->setSize(multiplier); + return ret; + } + + StringBuffer ret(input.size() * multiplier); + + while (multiplier--) { + ret.append(input); + } + + return ret.detach(); } + Variant f_wordwrap(CStrRef str, int width /* = 75 */, CStrRef wordbreak /* = "\n" */, bool cut /* = false */) { - String ret = StringUtil::WordWrap(str, width, wordbreak, cut); - if (ret.isNull()) return false; - return ret; + + if (str.empty()) { + return str; + } + + if (UNLIKELY(wordbreak.empty())) { + throw_invalid_argument("wordbreak: (empty)"); + return false; + } + + if (UNLIKELY(width == 0 && cut)) { + throw_invalid_argument("width: can't force cut when width = 0"); + return false; + } + + uint32_t pos = 0; + auto len = str.size(); + auto brkLen = wordbreak.size(); + auto bufLen = !cut && brkLen == 1 ? str.size() + : str.size() + brkLen * str.size() / (width ?: 1); + + StringBuffer ret(bufLen); + + const char* brk = wordbreak.data(); + const char* src = str.data(); + +next_line: + while (pos < len) { + int lineWidth, spaceWidth = -1; + + for (lineWidth = 0; pos + lineWidth < len && + lineWidth < width; ++lineWidth) { + if (lineWidth >= brkLen && !bcmp(&src[pos + lineWidth - brkLen], + brk, brkLen)) { + ret.append(&src[pos], lineWidth); + pos += lineWidth; + goto next_line; + } + + if (src[pos + lineWidth] == ' ') spaceWidth = lineWidth; + } + + if (pos + lineWidth == len) { + ret.append(&src[pos], lineWidth); + break; + } + + if (src[pos + lineWidth] == ' ') { + ret.append(&src[pos], lineWidth); + ret.append(wordbreak); + pos += lineWidth + 1; + continue; + } + + if (spaceWidth != -1) { + ret.append(&src[pos], spaceWidth); + ret.append(wordbreak); + pos += spaceWidth + 1; + continue; + } + + if (cut) { + ret.append(&src[pos], lineWidth); + ret.append(wordbreak); + pos += lineWidth; + + if (!lineWidth) { // zend is weird + ret.append(src[pos++]); + } + continue; + } + + for (; pos + lineWidth < len && src[pos + lineWidth] != ' '; + ++lineWidth) { + if (lineWidth >= brkLen && !bcmp(&src[pos + lineWidth - brkLen], + brk, brkLen)) { + ret.append(&src[pos], lineWidth); + pos += lineWidth; + lineWidth = -1; + goto next_line; + } + } + + if (pos + lineWidth == len) { + ret.append(&src[pos], lineWidth); + break; + } + + ret.append(&src[pos], lineWidth); + ret.append(wordbreak); + pos += lineWidth + 1; + } + + return ret.detach(); } /////////////////////////////////////////////////////////////////////////////// @@ -351,6 +805,7 @@ Variant f_printf(int _argc, CStrRef format, CArrRef _argv /* = null_array */) { echo(output); free(output); return len; } + Variant f_vprintf(CStrRef format, CArrRef args) { int len = 0; char *output = string_printf(format.data(), format.size(), args, &len); @@ -358,12 +813,14 @@ Variant f_vprintf(CStrRef format, CArrRef args) { echo(output); free(output); return len; } + Variant f_sprintf(int _argc, CStrRef format, CArrRef _argv /* = null_array */) { int len = 0; char *output = string_printf(format.data(), format.size(), _argv, &len); if (output == NULL) return false; return String(output, len, AttachString); } + Variant f_vsprintf(CStrRef format, CArrRef args) { int len = 0; char *output = string_printf(format.data(), format.size(), args, &len); @@ -433,6 +890,7 @@ String f_number_format(double number, int decimals /* = 0 */, int64_t f_strcmp(CStrRef str1, CStrRef str2) { return string_strcmp(str1.data(), str1.size(), str2.data(), str2.size()); } + Variant f_strncmp(CStrRef str1, CStrRef str2, int len) { if (len < 0) { raise_warning("Length must be greater than or equal to 0"); @@ -441,6 +899,7 @@ Variant f_strncmp(CStrRef str1, CStrRef str2, int len) { return string_strncmp(str1.data(), str1.size(), str2.data(), str2.size(), len); } + int64_t f_strnatcmp(CStrRef str1, CStrRef str2) { return string_natural_cmp(str1.data(), str1.size(), str2.data(), str2.size(), false); @@ -874,11 +1333,13 @@ String f_htmlentities(CStrRef str, int quote_style /* = k_ENT_COMPAT */, return StringUtil::HtmlEncode(str, (StringUtil::QuoteStyle)quote_style, scharset, true); } + String f_htmlspecialchars_decode(CStrRef str, int quote_style /* = k_ENT_COMPAT */) { return StringUtil::HtmlDecode(str, (StringUtil::QuoteStyle)quote_style, "UTF-8", false); } + String f_htmlspecialchars(CStrRef str, int quote_style /* = k_ENT_COMPAT */, CStrRef charset /* = "ISO-8859-1" */, bool double_encode /* = true */) { @@ -888,18 +1349,22 @@ String f_htmlspecialchars(CStrRef str, int quote_style /* = k_ENT_COMPAT */, return StringUtil::HtmlEncode(str, (StringUtil::QuoteStyle)quote_style, scharset, false); } + String f_fb_htmlspecialchars(CStrRef str, int quote_style /* = k_ENT_COMPAT */, CStrRef charset /* = "ISO-8859-1" */, CArrRef extra /* = Array() */) { return StringUtil::HtmlEncodeExtra(str, (StringUtil::QuoteStyle)quote_style, charset.data(), false, extra); } + String f_quoted_printable_encode(CStrRef str) { return StringUtil::QuotedPrintableEncode(str); } + String f_quoted_printable_decode(CStrRef str) { return StringUtil::QuotedPrintableDecode(str); } + Variant f_convert_uudecode(CStrRef data) { String ret = StringUtil::UUDecode(data); if (ret.isNull()) { @@ -907,22 +1372,28 @@ Variant f_convert_uudecode(CStrRef data) { } return ret; } + Variant f_convert_uuencode(CStrRef data) { if (data.empty()) return false; return StringUtil::UUEncode(data); } + String f_str_rot13(CStrRef str) { return StringUtil::ROT13(str); } + int64_t f_crc32(CStrRef str) { return (uint32_t)StringUtil::CRC32(str); } + String f_crypt(CStrRef str, CStrRef salt /* = "" */) { return StringUtil::Crypt(str, salt.c_str()); } + String f_md5(CStrRef str, bool raw_output /* = false */) { return StringUtil::MD5(str, raw_output); } + String f_sha1(CStrRef str, bool raw_output /* = false */) { return StringUtil::SHA1(str, raw_output); } diff --git a/hphp/runtime/ext/soap/encoding.cpp b/hphp/runtime/ext/soap/encoding.cpp index 8ada9f544..95de4aa9b 100644 --- a/hphp/runtime/ext/soap/encoding.cpp +++ b/hphp/runtime/ext/soap/encoding.cpp @@ -18,6 +18,7 @@ #include "hphp/runtime/ext/soap/encoding.h" #include "hphp/runtime/ext/soap/soap.h" #include "hphp/runtime/ext/ext_soap.h" +#include "hphp/runtime/ext/ext_string.h" #include "hphp/runtime/base/string-buffer.h" namespace HPHP { @@ -874,7 +875,7 @@ static Variant to_zval_hexbin(encodeTypePtr type, xmlNodePtr data) { throw SoapException("Encoding: Violation of encoding rules"); } String str = - StringUtil::HexDecode(String((const char*)data->children->content)); + f_hex2bin(String((const char*)data->children->content)); if (str.isNull()) { throw SoapException("Encoding: Violation of encoding rules"); } @@ -978,7 +979,7 @@ static xmlNodePtr to_xml_hexbin(encodeTypePtr type, CVarRef data, int style, xmlAddChild(parent, ret); FIND_ZVAL_NULL(data, ret, style); - String str = StringUtil::HexEncode(data.toString()); + String str = f_bin2hex(data.toString()); xmlAddChild(ret, xmlNewTextLen(BAD_CAST(str.data()), str.size())); if (style == SOAP_ENCODED) { diff --git a/hphp/runtime/server/http-protocol.cpp b/hphp/runtime/server/http-protocol.cpp index 82bb462fe..77bae054f 100644 --- a/hphp/runtime/server/http-protocol.cpp +++ b/hphp/runtime/server/http-protocol.cpp @@ -29,6 +29,7 @@ #include "hphp/runtime/server/replay-transport.h" #include "hphp/runtime/server/virtual-host.h" #include "hphp/runtime/base/http-client.h" +#include "hphp/runtime/ext/ext_string.h" #define DEFAULT_POST_CONTENT_TYPE "application/x-www-form-urlencoded" @@ -267,7 +268,7 @@ void HttpProtocol::PrepareSystemVariables(Transport *transport, // they are security-critical. if (RuntimeOption::LogHeaderMangle != 0) { String key = "HTTP_"; - key += StringUtil::ToUpper(iter->first).replace("-","_"); + key += f_strtoupper(iter->first).replace("-","_"); if (server.asArrRef().exists(key)) { if (!(++bad_request_count % RuntimeOption::LogHeaderMangle)) { Logger::Warning( @@ -283,7 +284,7 @@ void HttpProtocol::PrepareSystemVariables(Transport *transport, for (unsigned int i = 0; i < values.size(); i++) { String key = "HTTP_"; - key += StringUtil::ToUpper(iter->first).replace("-", "_"); + key += f_strtoupper(iter->first).replace("-", "_"); server.set(key, String(values[i])); } } diff --git a/hphp/runtime/server/libevent-server-with-takeover.cpp b/hphp/runtime/server/libevent-server-with-takeover.cpp index 465167f53..99d336c15 100644 --- a/hphp/runtime/server/libevent-server-with-takeover.cpp +++ b/hphp/runtime/server/libevent-server-with-takeover.cpp @@ -17,6 +17,7 @@ #include "hphp/runtime/server/libevent-server-with-takeover.h" #include "hphp/util/logger.h" #include "hphp/runtime/base/string-util.h" +#include "hphp/runtime/ext/ext_string.h" #include "folly/String.h" #include @@ -243,7 +244,7 @@ int LibEventServerWithTakeover::getAcceptSocket() { Logger::Error( "AFDT did not receive a file descriptor: " "response = '%s'", - StringUtil::CEncode(resp, null_string).data()); + f_addcslashes(resp, null_string).data()); errno = EADDRINUSE; return -1; } @@ -309,7 +310,7 @@ void LibEventServerWithTakeover::start() { Logger::Error( "Old server could not shut down: " "response = '%s'", - StringUtil::CEncode(resp, null_string).data()); + f_addcslashes(resp, null_string).data()); } else { Logger::Info("takeover: old satellites have shut down"); } diff --git a/hphp/test/ext/test_cpp_base.cpp b/hphp/test/ext/test_cpp_base.cpp index 581b40c3b..79b73a084 100644 --- a/hphp/test/ext/test_cpp_base.cpp +++ b/hphp/test/ext/test_cpp_base.cpp @@ -28,6 +28,7 @@ #include "hphp/runtime/server/ip-block-map.h" #include "hphp/test/ext/test_mysql_info.h" #include "hphp/system/systemlib.h" +#include "hphp/runtime/ext/ext_string.h" /////////////////////////////////////////////////////////////////////////////// @@ -170,7 +171,7 @@ bool TestCppBase::TestString() { // manipulations { - String s = StringUtil::ToLower("Test"); + String s = f_strtolower("Test"); VS(s.c_str(), "test"); } diff --git a/hphp/test/quick/string-util.php b/hphp/test/quick/string-util.php new file mode 100644 index 000000000..5db9f2d5e --- /dev/null +++ b/hphp/test/quick/string-util.php @@ -0,0 +1,27 @@ +