Completed
Push — master ( 9369e3...7c941d )
by thomas
33:44 queued 16:13
created

Stack::valid()   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 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 2
cts 2
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 2280
    public function __construct()
20
    {
21
22 2280
    }
23
24 1329
    public function current()
25
    {
26 1329
        return $this->values[$this->position];
27
    }
28
29 1329
    public function next()
30
    {
31 1329
        ++$this->position;
32 1329
    }
33
34
    public function key()
35
    {
36
        return $this->position;
37
    }
38
39 2241
    public function valid()
40
    {
41 2241
        return isset($this->values[$this->position]);
42
    }
43
44 2241
    public function rewind()
45
    {
46 2241
        $this->position = 0;
47 2241
    }
48
49 2219
    public function count()
50
    {
51 2219
        return count($this->values);
52
    }
53
54 1815
    public function isEmpty()
55
    {
56 1815
        return count($this->values) === 0;
57
    }
58
59 82
    public function bottom()
60
    {
61 82
        $count = count($this);
62 82
        if ($count < 1) {
63
            throw new \RuntimeException('No values in stack');
64
        }
65
66 82
        return $this->values[$count - 1];
67
    }
68
69
    /**
70
     * @see \ArrayAccess::offsetGet()
71
     * @param int $offset
72
     * @return \BitWasp\Buffertools\BufferInterface
73
     */
74 1723
    public function offsetGet($offset)
75
    {
76 1723
        $index = count($this) + $offset;
77 1723
        if (!isset($this->values[$index])) {
78 2
            throw new \RuntimeException('No value at this position');
79
        }
80
81 1723
        return $this->values[$index];
82
    }
83
84
    /**
85
     * @see \ArrayAccess::offsetSet()
86
     * @param int $offset
87
     * @param BufferInterface $value
88
     * @throws \InvalidArgumentException
89
     */
90 37
    public function offsetSet($offset, $value)
91
    {
92 37
        if (!$value instanceof BufferInterface) {
93
            throw new \InvalidArgumentException;
94
        }
95
96 37
        $count = count($this);
97 37
        $index = $count + $offset;
98 37
        if (isset($this->values[$index])) {
99 37
            $this->values[$index] = $value;
100 37
            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
     * @return bool
112
     */
113 3
    public function offsetExists($offset)
114
    {
115 3
        $index = count($this) + $offset;
116 3
        return isset($this->values[$index]);
117
    }
118
119
    /**
120
     * @see \ArrayAccess::offsetUnset()
121
     * @param int $offset
122
     */
123 48
    public function offsetUnset($offset)
124
    {
125 48
        $count = count($this);
126 48
        $index = $count + $offset;
127 48
        if (!isset($this->values[$index])) {
128 3
            throw new \RuntimeException('Nothing at this position');
129
        }
130
131 45
        array_splice($this->values, $index, 1);
132 45
    }
133
134
    /**
135
     * @param int $first
136
     * @param int $second
137
     */
138 37
    public function swap($first, $second)
139
    {
140 37
        $val1 = $this->offsetGet($first);
141 37
        $val2 = $this->offsetGet($second);
142 37
        $this->offsetSet($second, $val1);
143 37
        $this->offsetSet($first, $val2);
144 37
    }
145
146
    /**
147
     * @param int $offset
148
     * @param BufferInterface $value
149
     */
150 12
    public function add($offset, $value)
151
    {
152 12
        $size = count($this);
153 12
        $index = $size + $offset;
154 12
        if ($index > $size) {
155
            throw new \RuntimeException('Invalid add position');
156
        }
157
158
        // Unwind current values, push provided value, reapply popped values
159 12
        $values = [];
160 12
        for ($i = $size; $i > $index; $i--) {
161 12
            $values[] = $this->pop();
162 7
        }
163
164 12
        $this->push($value);
165 12
        for ($i = count($values); $i > 0; $i--) {
166 12
            $this->push(array_pop($values));
167 7
        }
168 12
    }
169
170 1540
    public function pop()
171
    {
172 1540
        $count = count($this);
173 1540
        if ($count === 0) {
174 3
            throw new \RuntimeException('Cannot pop from empty stack');
175
        }
176
177 1537
        $value = array_pop($this->values);
178 1537
        return $value;
179
    }
180
181 2114
    public function push($buffer)
182
    {
183 2114
        $this->values[] = $buffer;
184 2114
    }
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 23
    public function resize($length)
204
    {
205 23
        if ($length > count($this)) {
206
            throw new \RuntimeException('Invalid start or length');
207
        }
208
209 23
        while (count($this) > $length) {
210 23
            $this->pop();
211 14
        }
212
213 23
        return $this;
214
    }
215
}
216