Commit 6d2f1617 authored by Marius Wachtler's avatar Marius Wachtler

Implement str.replace maxreplaces

parent f58caf8c
...@@ -1516,30 +1516,34 @@ Box* strJoin(BoxedString* self, Box* rhs) { ...@@ -1516,30 +1516,34 @@ Box* strJoin(BoxedString* self, Box* rhs) {
} }
Box* strReplace(Box* _self, Box* _old, Box* _new, Box** _args) { Box* strReplace(Box* _self, Box* _old, Box* _new, Box** _args) {
RELEASE_ASSERT(_self->cls == str_cls, ""); if (_self->cls != str_cls)
raiseExcHelper(TypeError, "descriptor 'replace' requires a 'str' object but received a '%s'",
getTypeName(_self));
BoxedString* self = static_cast<BoxedString*>(_self); BoxedString* self = static_cast<BoxedString*>(_self);
RELEASE_ASSERT(_old->cls == str_cls, ""); if (_old->cls != str_cls)
raiseExcHelper(TypeError, "expected a character buffer object");
BoxedString* old = static_cast<BoxedString*>(_old); BoxedString* old = static_cast<BoxedString*>(_old);
RELEASE_ASSERT(_new->cls == str_cls, ""); if (_new->cls != str_cls)
raiseExcHelper(TypeError, "expected a character buffer object");
BoxedString* new_ = static_cast<BoxedString*>(_new); BoxedString* new_ = static_cast<BoxedString*>(_new);
Box* _count = _args[0]; Box* _maxreplace = _args[0];
if (!isSubclass(_maxreplace->cls, int_cls))
RELEASE_ASSERT(isSubclass(_count->cls, int_cls), "an integer is required"); raiseExcHelper(TypeError, "an integer is required");
BoxedInt* count = static_cast<BoxedInt*>(_count);
RELEASE_ASSERT(count->n < 0, "'count' argument unsupported");
BoxedString* rtn = new BoxedString(self->s); int max_replaces = static_cast<BoxedInt*>(_maxreplace)->n;
// From http://stackoverflow.com/questions/2896600/how-to-replace-all-occurrences-of-a-character-in-string
size_t start_pos = 0; size_t start_pos = 0;
while ((start_pos = rtn->s.find(old->s, start_pos)) != std::string::npos) { std::string s = self->s;
rtn->s.replace(start_pos, old->s.length(), new_->s); for (int num_replaced = 0; num_replaced < max_replaces || max_replaces < 0; ++num_replaced) {
start_pos = s.find(old->s, start_pos);
if (start_pos == std::string::npos)
break;
s.replace(start_pos, old->s.length(), new_->s);
start_pos += new_->s.length(); // Handles case where 'to' is a substring of 'from' start_pos += new_->s.length(); // Handles case where 'to' is a substring of 'from'
} }
return rtn; return new BoxedString(std::move(s));
} }
Box* strPartition(BoxedString* self, BoxedString* sep) { Box* strPartition(BoxedString* self, BoxedString* sep) {
......
...@@ -63,6 +63,10 @@ for i in ["", "a", "ab", "aa"]: ...@@ -63,6 +63,10 @@ for i in ["", "a", "ab", "aa"]:
print i, j, i.startswith(j), j.startswith(i), i.endswith(j), j.endswith(i), i.find(j), j.find(i), i.rfind(j), j.rfind(i) print i, j, i.startswith(j), j.startswith(i), i.endswith(j), j.endswith(i), i.find(j), j.find(i), i.rfind(j), j.rfind(i)
print "bananananananas".replace("anan", "an") print "bananananananas".replace("anan", "an")
print "bananananananas".replace("anan", "An", 0)
print "bananananananas".replace("anan", "An", -1)
print "bananananananas".replace("anan", "An", 1)
print "bananananananas".replace("anan", "An", 5)
translation_map = [chr(c) for c in xrange(256)] translation_map = [chr(c) for c in xrange(256)]
for c in "aeiou": for c in "aeiou":
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment