Skip to content

Commit 59e791f

Browse files
author
Martin Brecht-Precht
committed
Fixed different major issues.
Added a lot of tests.
1 parent 750090e commit 59e791f

File tree

3 files changed

+179
-28
lines changed

3 files changed

+179
-28
lines changed

.travis.yml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,6 @@ branches:
66

77
php:
88
- '5.3'
9-
- '5.4'
10-
- '5.5'
11-
- '7.0'
12-
- hhvm
139

1410
matrix:
1511
allow_failures:

src/SimpleStringBuilder.php

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ public function charAt($position)
4343
$type = is_object($position) ? get_class($position) : gettype($position);
4444
throw new \InvalidArgumentException('Position invalid. Expected integer. Got ' . $type . '.');
4545
}
46-
if ($position > $this->length()) {
47-
return null;
46+
if ($position >= $this->length()) {
47+
throw new \InvalidArgumentException('Position invalid.');
4848
}
4949
return mb_substr($this->string, $position, 1);
5050
}
@@ -73,7 +73,7 @@ public function prepend($string)
7373
$type = is_object($string) ? get_class($string) : gettype($string);
7474
throw new \InvalidArgumentException('Expected a scalar value. Got ' . $type . '.');
7575
}
76-
$this->string = $this->string . (string)$string;
76+
$this->string = (string)$string . $this->string;
7777
return $this;
7878
}
7979

@@ -92,8 +92,8 @@ public function insert($position, $string)
9292
$type = is_object($string) ? get_class($string) : gettype($string);
9393
throw new \InvalidArgumentException('Expected a scalar value. Got ' . $type . '.');
9494
}
95-
if ($position > $this->length()) {
96-
$position = $this->length();
95+
if ($position >= $this->length()) {
96+
throw new \InvalidArgumentException('Position invalid.');
9797
}
9898
$this->string = mb_substr($this->string, 0, $position) . (string)$string . mb_substr($this->string, $position);
9999
return $this;
@@ -111,14 +111,14 @@ public function replace($position, $length, $string)
111111
$type = is_object($position) ? get_class($position) : gettype($position);
112112
throw new \InvalidArgumentException('Position invalid. Expected integer. Got ' . $type . '.');
113113
}
114-
if ($position > $this->length()) {
114+
if ($position >= $this->length()) {
115115
throw new \InvalidArgumentException('Position invalid.');
116116
}
117117
if (!is_int($length)) {
118118
$type = is_object($length) ? get_class($length) : gettype($length);
119119
throw new \InvalidArgumentException('Length invalid. Expected integer. Got ' . $type . '.');
120120
}
121-
if ($position + $length > $this->length()) {
121+
if ($position + $length >= $this->length()) {
122122
throw new \InvalidArgumentException('Length invalid.');
123123
}
124124
if (!is_scalar($string)) {
@@ -140,10 +140,16 @@ public function setCharAt($position, $string)
140140
$type = is_object($position) ? get_class($position) : gettype($position);
141141
throw new \InvalidArgumentException('Position invalid. Expected integer. Got ' . $type . '.');
142142
}
143+
if ($position >= $this->length()) {
144+
throw new \InvalidArgumentException('Position invalid.');
145+
}
143146
if (!is_scalar($string)) {
144147
$type = is_object($string) ? get_class($string) : gettype($string);
145148
throw new \InvalidArgumentException('Expected a scalar value. Got ' . $type . '.');
146149
}
150+
if (mb_strlen((string)$string) !== 1) {
151+
throw new \InvalidArgumentException('Expected a scalar value of length 1.');
152+
}
147153
$this->string = mb_substr($this->string, 0, $position) . (string)$string . mb_substr($this->string, $position + 1);
148154
return $this;
149155
}
@@ -153,7 +159,12 @@ public function setCharAt($position, $string)
153159
*/
154160
public function reverse()
155161
{
156-
$this->string = strrev($this->string);
162+
$length = $this->length();
163+
$reversed = '';
164+
while ($length-- > 0) {
165+
$reversed .= mb_substr($this->string, $length, 1, mb_detect_encoding($this->string));
166+
}
167+
$this->string = $reversed;
157168
return $this;
158169
}
159170

@@ -172,8 +183,8 @@ public function delete($position, $length = null)
172183
$type = is_object($length) ? get_class($length) : gettype($length);
173184
throw new \InvalidArgumentException('Length invalid. Expected integer. Got ' . $type . '.');
174185
}
175-
if ($position > $this->length()) {
176-
return $this;
186+
if ($position >= $this->length()) {
187+
throw new \InvalidArgumentException('Position invalid.');
177188
}
178189
if (is_null($length)) {
179190
$this->string = mb_substr($this->string, 0, $position);
@@ -193,8 +204,8 @@ public function deleteCharAt($position)
193204
$type = is_object($position) ? get_class($position) : gettype($position);
194205
throw new \InvalidArgumentException('Position invalid. Expected integer. Got ' . $type . '.');
195206
}
196-
if ($position > $this->length()) {
197-
return $this;
207+
if ($position >= $this->length()) {
208+
throw new \InvalidArgumentException('Position invalid.');
198209
}
199210
$this->string = mb_substr($this->string, 0, $position) . mb_substr($this->string, $position + 1);
200211
return $this;
@@ -224,11 +235,15 @@ public function indexOf($string, $offset = 0)
224235
$type = is_object($string) ? get_class($string) : gettype($string);
225236
throw new \InvalidArgumentException('Expected a scalar value. Got ' . $type . '.');
226237
}
238+
if (mb_strlen((string)$string) === 0) {
239+
throw new \InvalidArgumentException('Empty string is invalid.');
240+
}
227241
if (!is_int($offset)) {
228242
$type = is_object($offset) ? get_class($offset) : gettype($offset);
229243
throw new \InvalidArgumentException('Offset invalid. Expected integer. Got ' . $type . '.');
230244
}
231-
return strpos($this->string, (string)$string, $offset);
245+
$index = mb_strpos($this->string, (string)$string, $offset);
246+
return $index === false ? null : $index;
232247
}
233248

234249
/**
@@ -246,7 +261,8 @@ public function lastIndexOf($string, $offset = 0)
246261
$type = is_object($offset) ? get_class($offset) : gettype($offset);
247262
throw new \InvalidArgumentException('Offset invalid. Expected integer. Got ' . $type . '.');
248263
}
249-
return strrpos($this->string, (string)$string, $offset);
264+
$index = mb_strrpos($this->string, (string)$string, $offset);
265+
return $index === false ? null : $index;
250266
}
251267

252268
/**
@@ -262,7 +278,7 @@ public function size()
262278
*/
263279
public function length()
264280
{
265-
return mb_strlen($this->string);
281+
return mb_strlen($this->string, mb_detect_encoding($this->string));
266282
}
267283

268284
/**

test/SimpleStringBuilderTest.php

Lines changed: 148 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,41 @@ class SimpleStringBuilderTest extends \PHPUnit_Framework_TestCase
1414

1515
public function testBuilder()
1616
{
17+
$builder = new SimpleStringBuilder('Test');
18+
$this->assertEquals(4, $builder->size());
1719
$builder = new SimpleStringBuilder();
1820
$builder
1921
->append('a')
2022
->append(12)
2123
->append(false)
2224
->prepend('b')
23-
->append(true);
24-
$this->assertEquals('a12b1', $builder->build());
25-
$this->assertEquals('12b1', $builder->buildSubstring(1));
26-
$this->assertEquals('a1', $builder->buildSubstring(0, 2));
27-
$this->assertEquals(5, $builder->size());
28-
$this->assertEquals(5, $builder->length());
29-
$this->assertTrue($builder->contains('12b'));
25+
->append(true)
26+
->insert(1, 'qas')
27+
->replace(2, 2, 'we')
28+
->setCharAt(4, '2')
29+
->append('beö');
30+
$this->assertEquals('bqwe2121beö', $builder->build());
31+
$this->assertEquals('we2121beö', $builder->buildSubstring(2));
32+
$this->assertEquals('bq', $builder->buildSubstring(0, 2));
33+
$this->assertEquals('w', $builder->charAt(2));
34+
$this->assertEquals(12, $builder->size());
35+
$this->assertEquals(11, $builder->length());
36+
$this->assertEquals(3, $builder->indexOf('e'));
37+
$this->assertEquals(9, $builder->indexOf('e', 4));
38+
$this->assertNull($builder->indexOf('e', 10));
39+
$this->assertEquals(9, $builder->lastIndexOf('e'));
40+
$this->assertNull($builder->lastIndexOf('e',10));
41+
$this->assertTrue($builder->contains('21b'));
3042
$this->assertFalse($builder->contains('abc'));
43+
$this->assertEquals('öeb1212ewqb', $builder->reverse()->build());
44+
$builder = new SimpleStringBuilder('0123456');
45+
$builder->delete(4);
46+
$this->assertEquals('0123', $builder->build());
47+
$builder = new SimpleStringBuilder('0123456');
48+
$builder
49+
->delete(4, 1)
50+
->deleteCharAt(1);
51+
$this->assertEquals('02356', $builder->build());
3152
}
3253

3354
public function testBuilderAppendFail()
@@ -44,14 +65,51 @@ public function testBuilderPrependFail()
4465
$builder->prepend(new \DateTimeZone('Europe/Berlin'));
4566
}
4667

68+
public function testBuilderInsertFail1()
69+
{
70+
$this->setExpectedException(get_class(new \InvalidArgumentException()));
71+
$builder = new SimpleStringBuilder();
72+
$builder->insert('a', 'a');
73+
}
74+
75+
public function testBuilderInsertFail2()
76+
{
77+
$this->setExpectedException(get_class(new \InvalidArgumentException()));
78+
$builder = new SimpleStringBuilder();
79+
$builder->insert(0, array());
80+
}
81+
82+
public function testBuilderInsertFail3()
83+
{
84+
$this->setExpectedException(get_class(new \InvalidArgumentException()));
85+
$builder = new SimpleStringBuilder();
86+
$builder->insert(0, 'a');
87+
}
88+
4789
public function testBuilderReplaceFail1()
4890
{
4991
$this->setExpectedException(get_class(new \InvalidArgumentException()));
5092
$builder = new SimpleStringBuilder();
51-
$builder->replace(0, 1, 'a');
93+
$builder->replace('a', 1, 'a');
5294
}
5395

5496
public function testBuilderReplaceFail2()
97+
{
98+
$this->setExpectedException(get_class(new \InvalidArgumentException()));
99+
$builder = new SimpleStringBuilder();
100+
$builder->replace(0, 1, 'a');
101+
}
102+
103+
public function testBuilderReplaceFail3()
104+
{
105+
$this->setExpectedException(get_class(new \InvalidArgumentException()));
106+
$builder = new SimpleStringBuilder();
107+
$builder
108+
->append('a')
109+
->replace(0, 'a', 'a');
110+
}
111+
112+
public function testBuilderReplaceFail4()
55113
{
56114
$this->setExpectedException(get_class(new \InvalidArgumentException()));
57115
$builder = new SimpleStringBuilder();
@@ -60,7 +118,7 @@ public function testBuilderReplaceFail2()
60118
->replace(0, 2, 'a');
61119
}
62120

63-
public function testBuilderReplaceFail3()
121+
public function testBuilderReplaceFail5()
64122
{
65123
$this->setExpectedException(get_class(new \InvalidArgumentException()));
66124
$builder = new SimpleStringBuilder();
@@ -69,6 +127,87 @@ public function testBuilderReplaceFail3()
69127
->replace(0, 1, new \DateTimeZone('Europe/Berlin'));
70128
}
71129

130+
public function testBuilderSetCharAtFail1()
131+
{
132+
$this->setExpectedException(get_class(new \InvalidArgumentException()));
133+
$builder = new SimpleStringBuilder();
134+
$builder->setCharAt('a', 'a');
135+
}
136+
137+
public function testBuilderSetCharAtFail2()
138+
{
139+
$this->setExpectedException(get_class(new \InvalidArgumentException()));
140+
$builder = new SimpleStringBuilder();
141+
$builder
142+
->append('a')
143+
->setCharAt(0, array());
144+
}
145+
146+
public function testBuilderSetCharAtFail3()
147+
{
148+
$this->setExpectedException(get_class(new \InvalidArgumentException()));
149+
$builder = new SimpleStringBuilder();
150+
$builder
151+
->append('a')
152+
->setCharAt(1, 'a');
153+
}
154+
155+
public function testBuilderSetCharAtFail4()
156+
{
157+
$this->setExpectedException(get_class(new \InvalidArgumentException()));
158+
$builder = new SimpleStringBuilder();
159+
$builder->setCharAt(0, 'ab');
160+
}
161+
162+
public function testBuilderDeleteFail1()
163+
{
164+
$this->setExpectedException(get_class(new \InvalidArgumentException()));
165+
$builder = new SimpleStringBuilder('012345');
166+
$builder->delete('a');
167+
}
168+
169+
public function testBuilderDeleteFail2()
170+
{
171+
$this->setExpectedException(get_class(new \InvalidArgumentException()));
172+
$builder = new SimpleStringBuilder('012345');
173+
$builder->delete(0, 'a');
174+
}
175+
176+
public function testBuilderDeleteFail3()
177+
{
178+
$this->setExpectedException(get_class(new \InvalidArgumentException()));
179+
$builder = new SimpleStringBuilder('012345');
180+
$builder->delete(10);
181+
}
182+
183+
public function testBuilderDeleteCharAtFail1()
184+
{
185+
$this->setExpectedException(get_class(new \InvalidArgumentException()));
186+
$builder = new SimpleStringBuilder('012345');
187+
$builder->deleteCharAt('a');
188+
}
189+
190+
public function testBuilderDeleteCharAtFail2()
191+
{
192+
$this->setExpectedException(get_class(new \InvalidArgumentException()));
193+
$builder = new SimpleStringBuilder('012345');
194+
$builder->deleteCharAt(6);
195+
}
196+
197+
public function testBuilderCharAtFail1()
198+
{
199+
$this->setExpectedException(get_class(new \InvalidArgumentException()));
200+
$builder = new SimpleStringBuilder();
201+
$builder->charAt('a');
202+
}
203+
204+
public function testBuilderCharAtFail2()
205+
{
206+
$this->setExpectedException(get_class(new \InvalidArgumentException()));
207+
$builder = new SimpleStringBuilder();
208+
$builder->charAt(0);
209+
}
210+
72211
public function testBuilderContainsFail()
73212
{
74213
$this->setExpectedException(get_class(new \InvalidArgumentException()));

0 commit comments

Comments
 (0)