RESOLVED FIXED Bug 239500
Replace String::replaceWithLiteral() with a String::replace() overload that takes in an ASCIILiteral
https://bugs.webkit.org/show_bug.cgi?id=239500
Summary Replace String::replaceWithLiteral() with a String::replace() overload that t...
Chris Dumez
Reported 2022-04-19 08:38:51 PDT
Replace String::replaceWithLiteral() with a String::replace() overload that takes in an ASCIILiteral.
Attachments
Patch (18.17 KB, patch)
2022-04-19 08:43 PDT, Chris Dumez
no flags
Patch (18.12 KB, patch)
2022-04-19 11:33 PDT, Chris Dumez
no flags
Patch (22.36 KB, patch)
2022-04-19 13:14 PDT, Chris Dumez
no flags
Patch (23.87 KB, patch)
2022-04-19 13:36 PDT, Chris Dumez
no flags
Patch (25.50 KB, patch)
2022-04-19 16:52 PDT, Chris Dumez
no flags
Chris Dumez
Comment 1 2022-04-19 08:43:01 PDT
Darin Adler
Comment 2 2022-04-19 10:44:55 PDT
Comment on attachment 457897 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=457897&action=review > Source/WTF/wtf/text/WTFString.h:198 > + String& replace(UChar target, ASCIILiteral); I would sort this up with the UChar/StringView overload above it. > Source/WebCore/editing/markup.cpp:423 > + return result.toString().replace('\0', ""_s); I wish it was clearer when to use ""_s and when to use emptyString(). I suppose that ideally the two would always generate identical code, the more optimal of the two. Another possibility would be to add a function named something like removeAll. Makes me realize that replace should maybe be named replaceAll. > Tools/TestWebKitAPI/Tests/WTF/WTFString.cpp:247 > + testString.replace('2', "3"_s); If there were a lot of callers like this we’d probably want a replace(UChar, UChar).
Chris Dumez
Comment 3 2022-04-19 11:33:14 PDT
Sam Weinig
Comment 4 2022-04-19 12:29:28 PDT
(In reply to Darin Adler from comment #2) > Comment on attachment 457897 [details] > Patch > > View in context: > https://bugs.webkit.org/attachment.cgi?id=457897&action=review > > > Another possibility would be to add a function named something like > removeAll. Makes me realize that replace should maybe be named replaceAll. Agree with both these. > > Tools/TestWebKitAPI/Tests/WTF/WTFString.cpp:247 > > + testString.replace('2', "3"_s); > > If there were a lot of callers like this we’d probably want a replace(UChar, > UChar). There is one!
Sam Weinig
Comment 5 2022-04-19 12:31:35 PDT
Should we = delete the overload that takes a const char* to ensure people aren't passing in a literal the other way?
Chris Dumez
Comment 6 2022-04-19 12:37:46 PDT
(In reply to Sam Weinig from comment #5) > Should we = delete the overload that takes a const char* to ensure people > aren't passing in a literal the other way? Sounds like a good idea. I'll look into that. We wouldn't want people to use the StringView overload when they have a string literal.
Chris Dumez
Comment 7 2022-04-19 12:46:22 PDT
(In reply to Chris Dumez from comment #6) > (In reply to Sam Weinig from comment #5) > > Should we = delete the overload that takes a const char* to ensure people > > aren't passing in a literal the other way? > > Sounds like a good idea. I'll look into that. We wouldn't want people to use > the StringView overload when they have a string literal. It even found bad call sites lol :)
Chris Dumez
Comment 8 2022-04-19 12:51:55 PDT
(In reply to Sam Weinig from comment #4) > (In reply to Darin Adler from comment #2) > > Comment on attachment 457897 [details] > > Patch > > > > View in context: > > https://bugs.webkit.org/attachment.cgi?id=457897&action=review > > > > > > Another possibility would be to add a function named something like > > removeAll. Makes me realize that replace should maybe be named replaceAll. > > Agree with both these. Same. Based on Darin's earlier feedback that it'd be nice if String didn't have functions that modify the String itself though, maybe free functions like: ``` makeStringByReplacingAll(const String&, UChar, ASCIILiteral/StringView/UChar) makeStringByRemovingAll(const String&, UChar) ``` It'd be consistent with the makeStringByInserting() that I recently added.
Chris Dumez
Comment 9 2022-04-19 13:14:47 PDT
Chris Dumez
Comment 10 2022-04-19 13:36:05 PDT
Chris Dumez
Comment 11 2022-04-19 16:52:18 PDT
EWS
Comment 12 2022-04-19 19:33:53 PDT
Committed r293056 (249789@main): <https://commits.webkit.org/249789@main> All reviewed patches have been landed. Closing bug and clearing flags on attachment 457943 [details].
Radar WebKit Bug Importer
Comment 13 2022-04-19 19:34:14 PDT
Sam Weinig
Comment 14 2022-04-20 10:59:30 PDT
(In reply to Chris Dumez from comment #8) > (In reply to Sam Weinig from comment #4) > > (In reply to Darin Adler from comment #2) > > > Comment on attachment 457897 [details] > > > Patch > > > > > > View in context: > > > https://bugs.webkit.org/attachment.cgi?id=457897&action=review > > > > > > > > > Another possibility would be to add a function named something like > > > removeAll. Makes me realize that replace should maybe be named replaceAll. > > > > Agree with both these. > > Same. Based on Darin's earlier feedback that it'd be nice if String didn't > have functions that modify the String itself though, maybe free functions > like: > ``` > makeStringByReplacingAll(const String&, UChar, ASCIILiteral/StringView/UChar) > makeStringByRemovingAll(const String&, UChar) > ``` > > It'd be consistent with the makeStringByInserting() that I recently added. Another option would be making the member functions const and have them return a new WARN_UNUSED_RETURN String. If we did that, we could consider names like: WARN_UNUSED_RETURN String stringByReplacingAll(UChar, ASCIILiteral/StringView/UChar) const WARN_UNUSED_RETURN String stringByRemovingAll(UChar) const
Chris Dumez
Comment 15 2022-04-21 18:47:11 PDT
(In reply to Sam Weinig from comment #14) > (In reply to Chris Dumez from comment #8) > > (In reply to Sam Weinig from comment #4) > > > (In reply to Darin Adler from comment #2) > > > > Comment on attachment 457897 [details] > > > > Patch > > > > > > > > View in context: > > > > https://bugs.webkit.org/attachment.cgi?id=457897&action=review > > > > > > > > > > > > Another possibility would be to add a function named something like > > > > removeAll. Makes me realize that replace should maybe be named replaceAll. > > > > > > Agree with both these. > > > > Same. Based on Darin's earlier feedback that it'd be nice if String didn't > > have functions that modify the String itself though, maybe free functions > > like: > > ``` > > makeStringByReplacingAll(const String&, UChar, ASCIILiteral/StringView/UChar) > > makeStringByRemovingAll(const String&, UChar) > > ``` > > > > It'd be consistent with the makeStringByInserting() that I recently added. > > Another option would be making the member functions const and have them > return a new WARN_UNUSED_RETURN String. If we did that, we could consider > names like: > > WARN_UNUSED_RETURN String stringByReplacingAll(UChar, > ASCIILiteral/StringView/UChar) const > WARN_UNUSED_RETURN String stringByRemovingAll(UChar) const The const member function with a WARN_UNUSED_RETURN is exactly what I suggested on the previous bug when we were updating insert(). Darin is the one who suggested a free function instead (and we went with makeStringByInserting()). I do not feel strongly either way but Darin had a preference for the free function. We should be consistent here.
Sam Weinig
Comment 16 2022-04-22 09:17:43 PDT
I also don’t have a strong preference here, so I agree.
Darin Adler
Comment 17 2022-04-22 10:54:33 PDT
The member functions have some advantages, easy to spot when looking over "what the String class has to offer", and a more-economical way to write these at the call sites that free functions. But I see at least two subtle advantages to the free functions (some of which would also apply to static member functions): One is that for the parameter type, instead of "this" we can often take a StringView, so a single function can operate on an existing String but even on a string literal or a buffer of UChar, and typically with better syntax than what we’d need if it was a StringView member function (I am not fond of "StringView { }."). We can always overload for specific types (String, or String&, or String&&) if we want a more efficient variant. Second is that the free functions can be organized logically, even put in separate headers, making String itself less of a single enormous class. We don’t have that kind of flexibility for member functions. The free functions dovetail nicely with the design of other functions, including ones that operate on more than one string like makeString itself. For certain "transform single character" cases, in addition to functions we might make some kind of manipulator object that works with the StringConcatenate mechanism. Not sure what the right names for those are. They could do some common operations in place, like ASCII lowercasing and uppercasing, without requiring any additional memory allocation.
Chris Dumez
Comment 18 2022-04-22 10:59:18 PDT
(In reply to Darin Adler from comment #17) > The member functions have some advantages, easy to spot when looking over > "what the String class has to offer", and a more-economical way to write > these at the call sites that free functions. But I see at least two subtle > advantages to the free functions (some of which would also apply to static > member functions): > > One is that for the parameter type, instead of "this" we can often take a > StringView, so a single function can operate on an existing String but even > on a string literal or a buffer of UChar, and typically with better syntax > than what we’d need if it was a StringView member function (I am not fond of > "StringView { }."). We can always overload for specific types (String, or > String&, or String&&) if we want a more efficient variant. > > Second is that the free functions can be organized logically, even put in > separate headers, making String itself less of a single enormous class. We > don’t have that kind of flexibility for member functions. The free functions > dovetail nicely with the design of other functions, including ones that > operate on more than one string like makeString itself. > > For certain "transform single character" cases, in addition to functions we > might make some kind of manipulator object that works with the > StringConcatenate mechanism. Not sure what the right names for those are. > They could do some common operations in place, like ASCII lowercasing and > uppercasing, without requiring any additional memory allocation. Note that in this patch, we deleted the overload taking a "const char*" and it was useful to find callers that could be optimized. How can we achieve this we free functions? I guess we could declare but not define the overload taking a `const char*` but this would lead to linking errors which is not great. Do you have a good proposal for this?
Darin Adler
Comment 19 2022-04-22 11:04:01 PDT
(In reply to Chris Dumez from comment #18) > Note that in this patch, we deleted the overload taking a "const char*" and > it was useful to find callers that could be optimized. > > How can we achieve this we free functions? I guess we could declare but not > define the overload taking a `const char*` but this would lead to linking > errors which is not great. Do you have a good proposal for this? Free functions can be deleted just like member functions.
Chris Dumez
Comment 20 2022-04-22 11:04:49 PDT
(In reply to Darin Adler from comment #19) > (In reply to Chris Dumez from comment #18) > > Note that in this patch, we deleted the overload taking a "const char*" and > > it was useful to find callers that could be optimized. > > > > How can we achieve this we free functions? I guess we could declare but not > > define the overload taking a `const char*` but this would lead to linking > > errors which is not great. Do you have a good proposal for this? > > Free functions can be deleted just like member functions. Today I Learn :) Sounds good to me then.
Note You need to log in before you can comment on or make changes to this bug.