Completed
Pull Request — master (#335)
by thomas
04:22
created

Stack::push()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 4
ccs 0
cts 0
cp 0
crap 2
rs 10
1
<?php
2
3
namespace BitWasp\Bitcoin\Script\Interpreter;
4
5
use BitWasp\Buffertools\BufferInterface;
6
7
class Stack implements \Countable, \ArrayAccess, \Iterator
8
{
9 435
    /**
10
     * @var int
11 435
     */
12 435
    private $position = 0;
13
14 24
    /**
15
     * @var array
16 24
     */
17
    private $values = [];
18
19
    public function __construct()
20
    {
21
22
    }
23 21
24
    public function current()
25 21
    {
26
        return $this->values[$this->position];
27
    }
28 21
29
    public function next()
30
    {
31
        ++$this->position;
32
    }
33
34
    public function key()
35 276
    {
36
        return $this->position;
37 276
    }
38 276
39
    public function valid()
40
    {
41
        return isset($this->values[$this->position]);
42
    }
43
44
    public function rewind()
45
    {
46
        $this->position = 0;
47 12
    }
48
49 12
    public function count()
50 12
    {
51 12
        return count($this->values);
52 12
    }
53
54
    public function isEmpty()
55
    {
56
        return count($this->values) === 0;
57
    }
58
59 3
    public function bottom()
60
    {
61 3
        $count = count($this);
62 3
        if ($count < 1) {
63
            throw new \RuntimeException('No values in stack');
64
        }
65
66
        return $this->values[$count - 1];
67
    }
68
69 18
    /**
70
     * @see \ArrayAccess::offsetGet()
71 18
     * @param int $offset
72 18
     * @return \BitWasp\Buffertools\BufferInterface
73 15
     */
74
    public function offsetGet($offset)
75
    {
76
        $index = count($this) + $offset;
77
        if (!isset($this->values[$index])) {
78
            throw new \RuntimeException('No value at this position');
79 12
        }
80
81 12
        return $this->values[$index];
82 12
    }
83 12
84 12
    /**
85 12
     * @see \ArrayAccess::offsetSet()
86
     * @param int $offset
87
     * @param BufferInterface $value
88
     * @throws \InvalidArgumentException
89
     */
90
    public function offsetSet($offset, $value)
91 9
    {
92
        if (!$value instanceof BufferInterface) {
93 9
            throw new \InvalidArgumentException;
94
        }
95 9
96
        $count = count($this);
97
        $index = $count + $offset;
98
        if (isset($this->values[$index])) {
99
            $this->values[$index] = $value;
100
            return;
101
        }
102
103
        if ($index !== $count) {
104
            throw new \RuntimeException('Index must be end position');
105
        }
106
    }
107
108
    /**
109
     * @see \ArrayAccess::offsetExists()
110
     * @param int $offset
111 9
     * @return bool
112
     */
113 6
    public function offsetExists($offset)
114
    {
115
        $index = count($this) + $offset;
116
        return isset($this->values[$index]);
117
    }
118 405
119
    /**
120 405
     * @see \ArrayAccess::offsetUnset()
121 405
     * @param int $offset
122 405
     */
123
    public function offsetUnset($offset)
124
    {
125
        $count = count($this);
126
        $index = $count + $offset;
127
        if (!isset($this->values[$index])) {
128
            throw new \RuntimeException('Nothing at this position');
129
        }
130
131
        array_splice($this->values, $index, 1);
132 15
    }
133
134 15
    /**
135
     * @param int $first
136
     * @param int $second
137
     */
138 15
    public function swap($first, $second)
139 15
    {
140 10
        $val1 = $this->offsetGet($first);
141
        $val2 = $this->offsetGet($second);
142 15
        $this->offsetSet($second, $val1);
143
        $this->offsetSet($first, $val2);
144
    }
145
146
    /**
147
     * @param int $offset
148
     * @param BufferInterface $value
149
     */
150
    public function add($offset, $value)
151
    {
152
        $size = count($this);
153
        $index = $size + $offset;
154
        if ($index > $size) {
155
            throw new \RuntimeException('Invalid add position');
156
        }
157
158
        // Unwind current values, push provided value, reapply popped values
159
        $values = [];
160
        for ($i = $size; $i > $index; $i--) {
161
            $values[] = $this->pop();
162
        }
163
164
        $this->push($value);
165
        for ($i = count($values); $i > 0; $i--) {
166
            $this->push(array_pop($values));
167
        }
168
    }
169
170
    public function pop()
171
    {
172
        $count = count($this);
173
        if ($count === 0) {
174
            throw new \RuntimeException('Cannot pop from empty stack');
175
        }
176
177
        $value = array_pop($this->values);
178
        return $value;
179
    }
180
181
    public function push($buffer)
182
    {
183
        $this->values[] = $buffer;
184
    }
185
186
    /**
187
     * @return int
188
     */
189
    public function end()
190
    {
191
        $count = count($this);
192
        if ($count === 0) {
193
            return 0;
194
        }
195
196
        return $count - 1;
197
    }
198
199
    /**
200
     * @param int $length
201
     * @return $this
202
     */
203
    public function resize($length)
204
    {
205
        if ($length > count($this)) {
206
            throw new \RuntimeException('Invalid start or length');
207
        }
208
209
        while (count($this) > $length) {
210
            $this->pop();
211
        }
212
213
        return $this;
214
    }
215
}
216