Completed
Push — master ( e13b09...cea89c )
by thomas
35:03
created

Stack::next()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

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