Issues (5)

src/ArrayHelpers/ByteArrayDispenser.php (1 issue)

Severity
1
<?php
2
/**
3
 * Trait ByteArrayDispenser
4
 *
5
 * @filesource   ByteArrayDispenser.php
6
 * @created      05.12.2017
7
 * @package      chillerlan\Traits\ArrayHelpers
8
 * @author       Smiley <[email protected]>
9
 * @copyright    2017 Smiley
10
 * @license      MIT
11
 */
12
13
namespace chillerlan\Traits\ArrayHelpers;
14
15
use chillerlan\Traits\TraitException;
16
use Exception, Traversable;
17
18
/**
19
 *
20
 */
21
class ByteArrayDispenser{
22
23
	/**
24
	 * @var string
25
	 */
26
	protected $byteArrayClass = ByteArray::class;
27
28
	/**
29
	 * @param int $int
30
	 *
31
	 * @return bool
32
	 */
33
	public function isAllowedInt(int $int):bool{
34
		return $int >= 0 && $int <= PHP_INT_MAX;
35
	}
36
37
	/**
38
	 * @param int $size
39
	 *
40
	 * @return \chillerlan\Traits\ArrayHelpers\ByteArray
41
	 * @throws \chillerlan\Traits\TraitException
42
	 */
43
	public function fromIntSize(int $size):ByteArray{
44
45
		if(!$this->isAllowedInt($size)){
46
			throw new TraitException('invalid size');
47
		}
48
49
		return new $this->byteArrayClass($size);
50
	}
51
52
	/**
53
	 * @param array $array
54
	 * @param bool  $save_indexes
55
	 *
56
	 * @return \chillerlan\Traits\ArrayHelpers\ByteArray
57
	 * @throws \chillerlan\Traits\TraitException
58
	 */
59
	public function fromArray(array $array, bool $save_indexes = null):ByteArray{
60
61
		try{
62
			$out = $this->fromIntSize(\count($array));
63
64
			$array = ($save_indexes ?? true) ? $array : \array_values($array);
65
66
			foreach($array as $k => $v){
67
				$out[$k] = $v;
68
			}
69
70
			return $out;
71
		}
72
		// this can be anything
73
		// @codeCoverageIgnoreStart
74
		catch(Exception $e){
75
			throw new TraitException($e->getMessage());
76
		}
77
		// @codeCoverageIgnoreEnd
78
79
	}
80
81
	/**
82
	 * @param int $len
83
	 *
84
	 * @param mixed $fill
85
	 *
86
	 * @return \chillerlan\Traits\ArrayHelpers\ByteArray
87
	 * @throws \chillerlan\Traits\TraitException
88
	 */
89
	public function fromArrayFill(int $len, $fill = null):ByteArray{
90
91
		if(!$this->isAllowedInt($len)){
92
			throw new TraitException('invalid length');
93
		}
94
95
		return $this->fromArray(\array_fill(0, $len, $fill));
96
	}
97
98
	/**
99
	 * @param string $str
100
	 *
101
	 * @return \chillerlan\Traits\ArrayHelpers\ByteArray
102
	 */
103
	public function fromString(string $str):ByteArray{
104
		return $this->fromArray(\unpack('C*', $str), false);
105
	}
106
107
	/**
108
	 * checks if the given string is a hex string: ab12cd34 (case insensitive, whitespace allowed)
109
	 *
110
	 * @param string $hex
111
	 *
112
	 * @return bool
113
	 */
114
	public function isAllowedHex(string $hex):bool{
115
		return \preg_match('/^[\s\r\n\t \da-f]+$/i', $hex) && \strlen($hex) % 2 === 0;
116
	}
117
118
	/**
119
	 * @param string $hex
120
	 *
121
	 * @return \chillerlan\Traits\ArrayHelpers\ByteArray|mixed
122
	 * @throws \chillerlan\Traits\TraitException
123
	 */
124
	public function fromHex(string $hex):ByteArray{
125
		$hex = \preg_replace('/[\s\r\n\t ]/', '', $hex);
126
127
		if(!$this->isAllowedHex($hex)){
128
			throw new TraitException('invalid hex string');
129
		}
130
131
		return $this->fromString(\pack('H*', $hex));
132
	}
133
134
	/**
135
	 * checks if the given (trimmed) JSON string is a an array that contains numbers: [1, 2, 3]
136
	 *
137
	 * @param string $json
138
	 *
139
	 * @return bool
140
	 */
141
	public function isAllowedJSON(string $json):bool{
142
		return \preg_match('/^\\[[\s\d,]+\\]$/', $json) > 0;
143
	}
144
145
	/**
146
	 * @param string $json
147
	 *
148
	 * @return \chillerlan\Traits\ArrayHelpers\ByteArray|mixed
149
	 * @throws \chillerlan\Traits\TraitException
150
	 */
151
	public function fromJSON(string $json):ByteArray{
152
		$json = \trim($json);
153
154
		if(!$this->isAllowedJSON($json)){
155
			throw new TraitException('invalid JSON array');
156
		}
157
158
		return $this->fromArray(\json_decode(\trim($json)));
159
	}
160
161
	/**
162
	 * checks if the given (trimmed) string is base64 encoded binary
163
	 *
164
	 * @param string $base64
165
	 *
166
	 * @return bool
167
	 */
168
	public function isAllowedBase64(string $base64):bool{
169
		return \preg_match('#^[a-z\d/]*={0,2}$#i', $base64) > 0;
170
	}
171
172
	/**
173
	 * @param string $base64
174
	 *
175
	 * @return \chillerlan\Traits\ArrayHelpers\ByteArray|mixed
176
	 * @throws \chillerlan\Traits\TraitException
177
	 */
178
	public function fromBase64(string $base64):ByteArray{
179
		$base64 = \trim($base64);
180
181
		if(!$this->isAllowedBase64($base64)){
182
			throw new TraitException('invalid base64 string');
183
		}
184
185
		return $this->fromString(\base64_decode($base64));
186
	}
187
188
	/**
189
	 * checks if the given (trimmed) string is a binary string: [01] in multiples of 8
190
	 *
191
	 * @param string $bin
192
	 *
193
	 * @return bool
194
	 */
195
	public function isAllowedBin(string $bin):bool{
196
		return \preg_match('/^[01]+$/', $bin) > 0 && \strlen($bin) % 8 === 0;
197
	}
198
199
	/**
200
	 * @param string $bin
201
	 *
202
	 * @return \chillerlan\Traits\ArrayHelpers\ByteArray
203
	 * @throws \chillerlan\Traits\TraitException
204
	 */
205
	public function fromBin(string $bin):ByteArray{
206
		$bin = \trim($bin);
207
208
		if(!$this->isAllowedBin($bin)){
209
			throw new TraitException('invalid binary string');
210
		}
211
212
		return $this->fromArray(\array_map('bindec', \str_split($bin, 8)));
213
	}
214
215
	/**
216
	 * @param string|array|\SplFixedArray $data
217
	 *
218
	 * @return \chillerlan\Traits\ArrayHelpers\ByteArray
219
	 * @throws \chillerlan\Traits\TraitException
220
	 */
221
	public function guessFrom($data):ByteArray{
222
223
		if($data instanceof Traversable){
224
			return $this->fromArray(\iterator_to_array($data));
225
		}
226
227
		if(\is_array($data)){
228
			return $this->fromArray($data);
229
		}
230
231
		if(\is_string($data)){
0 ignored issues
show
The condition is_string($data) is always true.
Loading history...
232
233
			foreach(['Bin', 'Hex', 'JSON', 'Base64'] as $type){
234
235
				if(\call_user_func_array([$this, 'isAllowed'.$type], [$data]) === true){
236
					return \call_user_func_array([$this, 'from'.$type], [$data]);
237
				}
238
239
			}
240
241
			return $this->fromString($data);
242
		}
243
244
		throw new TraitException('invalid input');
245
	}
246
247
}
248