Completed
Push — master ( 9416b8...4b1dff )
by thomas
401:02 queued 398:24
created

Stack::all()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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