Skip to content

Commit

Permalink
Merge pull request #298 from RobertBendun/master
Browse files Browse the repository at this point in the history
String strip! family
  • Loading branch information
seven1m authored Dec 18, 2021
2 parents 87dc125 + b43e120 commit fcfb573
Show file tree
Hide file tree
Showing 7 changed files with 61 additions and 6 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ coverage-report

# Editor tools
.ccls
.ccls-cache
compile_commands.json
tags
.gdb_history
3 changes: 3 additions & 0 deletions include/natalie/string_object.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,15 +152,18 @@ class StringObject : public Object {
Value force_encoding(Env *, Value);
Value ljust(Env *, Value, Value);
Value lstrip(Env *) const;
Value lstrip_in_place(Env *);
Value match(Env *, Value);
Value mul(Env *, Value) const;
Value ord(Env *);
Value ref(Env *, Value);
Value reverse(Env *);
Value rstrip(Env *) const;
Value rstrip_in_place(Env *);
Value size(Env *);
Value split(Env *, Value, Value);
Value strip(Env *) const;
Value strip_in_place(Env *);
Value to_i(Env *, Value) const;
Value upcase(Env *);
Value uplus(Env *);
Expand Down
3 changes: 3 additions & 0 deletions lib/natalie/compiler/binding_gen.rb
Original file line number Diff line number Diff line change
Expand Up @@ -744,14 +744,17 @@ def generate_name
gen.binding('String', 'length', 'StringObject', 'length', argc: 0, pass_env: false, pass_block: false, return_type: :size_t)
gen.binding('String', 'ljust', 'StringObject', 'ljust', argc: 1..2, pass_env: true, pass_block: false, return_type: :Object)
gen.binding('String', 'lstrip', 'StringObject', 'lstrip', argc: 0, pass_env: true, pass_block: false, return_type: :Object)
gen.binding('String', 'lstrip!', 'StringObject', 'lstrip_in_place', argc: 0, pass_env: true, pass_block: false, return_type: :Object)
gen.binding('String', 'match', 'StringObject', 'match', argc: 1, pass_env: true, pass_block: false, return_type: :Object)
gen.binding('String', 'ord', 'StringObject', 'ord', argc: 0, pass_env: true, pass_block: false, return_type: :Object)
gen.binding('String', 'reverse', 'StringObject', 'reverse', argc: 0, pass_env: true, pass_block: false, return_type: :Object)
gen.binding('String', 'rstrip', 'StringObject', 'rstrip', argc: 0, pass_env: true, pass_block: false, return_type: :Object)
gen.binding('String', 'rstrip!', 'StringObject', 'rstrip_in_place', argc: 0, pass_env: true, pass_block: false, return_type: :Object)
gen.binding('String', 'size', 'StringObject', 'size', argc: 0, pass_env: true, pass_block: false, return_type: :Object)
gen.binding('String', 'split', 'StringObject', 'split', argc: 0..2, pass_env: true, pass_block: false, return_type: :Object)
gen.binding('String', 'start_with?', 'StringObject', 'start_with', argc: 1, pass_env: true, pass_block: false, return_type: :bool)
gen.binding('String', 'strip', 'StringObject', 'strip', argc: 0, pass_env: true, pass_block: false, return_type: :Object)
gen.binding('String', 'strip!', 'StringObject', 'strip_in_place', argc: 0, pass_env: true, pass_block: false, return_type: :Object)
gen.binding('String', 'sub', 'StringObject', 'sub', argc: 1..2, pass_env: true, pass_block: true, return_type: :Object)
gen.binding('String', 'succ', 'StringObject', 'successive', argc: 0, pass_env: true, pass_block: false, return_type: :Object)
gen.binding('String', 'to_i', 'StringObject', 'to_i', argc: 0..1, pass_env: true, pass_block: false, return_type: :Object)
Expand Down
3 changes: 1 addition & 2 deletions spec/core/string/lstrip_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@
end
end

# NATFIXME: implement mutating lstrip! method
xdescribe "String#lstrip!" do
describe "String#lstrip!" do
it "modifies self in place and returns self" do
a = " hello "
a.lstrip!.should equal(a)
Expand Down
3 changes: 1 addition & 2 deletions spec/core/string/rstrip_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@
end
end

# NATFIXME: implement mutating rstrip! method
xdescribe "String#rstrip!" do
describe "String#rstrip!" do
it "modifies self in place and returns self" do
a = " hello "
a.rstrip!.should equal(a)
Expand Down
3 changes: 1 addition & 2 deletions spec/core/string/strip_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@
end
end

# NATFIXME: implement mutating strip! method
xdescribe "String#strip!" do
describe "String#strip!" do
it "modifies self in place and returns self" do
a = " hello "
a.strip!.should equal(a)
Expand Down
51 changes: 51 additions & 0 deletions src/string_object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,14 @@ Value StringObject::strip(Env *env) const {
}
}

Value StringObject::strip_in_place(Env *env) {
// right side needs to go first beacuse then we have less to move in
// on the left side
auto r = rstrip_in_place(env);
auto l = lstrip_in_place(env);
return l->is_nil() && r->is_nil() ? Value(NilObject::the()) : Value(this);
}

Value StringObject::lstrip(Env *env) const {
if (length() == 0)
return new StringObject {};
Expand All @@ -671,6 +679,28 @@ Value StringObject::lstrip(Env *env) const {
}
}

Value StringObject::lstrip_in_place(Env *env) {
assert_not_frozen(env);
if (length() == 0)
return NilObject::the();

assert(length() < NAT_INT_MAX);
nat_int_t first_char;
nat_int_t len = static_cast<nat_int_t>(length());
for (first_char = 0; first_char < len; first_char++) {
char c = c_str()[first_char];
if (!is_strippable_whitespace(c))
break;
}

if (first_char == 0)
return NilObject::the();

memmove(&m_string[0], &m_string[0] + first_char, len - first_char);
m_string.truncate(len - first_char);
return this;
}

Value StringObject::rstrip(Env *env) const {
if (length() == 0)
return new StringObject {};
Expand All @@ -690,6 +720,27 @@ Value StringObject::rstrip(Env *env) const {
}
}

Value StringObject::rstrip_in_place(Env *env) {
assert_not_frozen(env);
if (length() == 0)
return NilObject::the();

assert(length() < NAT_INT_MAX);
nat_int_t last_char;
nat_int_t len = static_cast<nat_int_t>(length());
for (last_char = len - 1; last_char >= 0; last_char--) {
char c = c_str()[last_char];
if (!is_strippable_whitespace(c))
break;
}

if (last_char == len - 1)
return NilObject::the();

m_string.truncate(last_char < 0 ? 0 : last_char + 1);
return this;
}

Value StringObject::downcase(Env *env) {
auto ary = chars(env);
auto str = new StringObject {};
Expand Down

0 comments on commit fcfb573

Please sign in to comment.