Completed
Push — master ( 21bf70...cc5276 )
by Kamil
05:50
created

BinarySupport::parseLabels()   B

Complexity

Conditions 5
Paths 6

Size

Total Lines 24
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 0
Metric Value
dl 0
loc 24
ccs 0
cts 21
cp 0
rs 8.5125
c 0
b 0
f 0
cc 5
eloc 15
nc 6
nop 2
crap 30
1
<?php
2
3
namespace Dazzle\MySQL\Protocol\Support;
4
5
use Exception;
6
7
class BinarySupport
8
{
9
    /**
10
     * Build structure of labels.
11
     *
12
     * @param string $q dot-separated labels list.
13
     * @return string
14
     */
15
    public static function labels($q)
16
    {
17
        $e = explode('.', $q);
18
        $r = '';
19
        for ($i = 0, $s = sizeof($e); $i < $s; ++$i)
20
        {
21
            $r .= chr(strlen($e[$i])) . $e[$i];
22
        }
23
        if (static::binarySubstr($r, -1) !== "\x00") {
24
            $r .= "\x00";
25
        }
26
        return $r;
27
    }
28
29
    /**
30
     * Parse structure of labels.
31
     *
32
     * @param string $data
33
     * @param string $orig
34
     * @return string Dot-separated labels list.
35
     */
36
    public static function parseLabels(&$data, $orig = null)
37
    {
38
        $str = '';
39
        while (strlen($data) > 0)
40
        {
41
            $l = ord($data[0]);
42
43
            if ($l >= 192) {
44
                $pos  = static::bytes2int(chr($l - 192) . static::binarySubstr($data, 1, 1));
45
                $data = static::binarySubstr($data, 2);
46
                $ref  = static::binarySubstr($orig, $pos);
47
48
                return $str . static::parseLabels($ref);
49
            }
50
51
            $p = substr($data, 1, $l);
52
            $str .= $p . (($l !== 0) ? '.' : '');
53
            $data = substr($data, $l + 1);
54
            if ($l === 0) {
55
                break;
56
            }
57
        }
58
        return $str;
59
    }
60
61
    /**
62
     * Build length-value binary snippet.
63
     *
64
     * @param string $str Data.
65
     * @param int $len Number of bytes to encode length, defaults to 1.
66
     * @return string
67
     */
68
    public static function LV($str, $len = 1, $lrev = false)
69
    {
70
        $l = static::i2b($len, strlen($str));
71
        if ($lrev) {
72
            $l = strrev($l);
73
        }
74
        return $l . $str;
75
    }
76
77
    /**
78
     * Build null-terminated string, with 2-byte of length.
79
     *
80
     * @param string $str Data.
81
     * @return string
82
     */
83
    public static function LVnull($str)
84
    {
85
        return static::LV($str . "\x00", 2, true);
86
    }
87
88
    /**
89
     * Build byte.
90
     *
91
     * @param int $int
92
     * @return string
93
     */
94
    public static function byte($int)
95
    {
96
        return chr($int);
97
    }
98
99
    /**
100
     * Build word (2 bytes) big-endian.
101
     *
102
     * @param int $int
103
     * @return string
104
     */
105
    public static function word($int)
106
    {
107
        return static::i2b(2, $int);
108
    }
109
110
    /**
111
     * Build word (2 bytes) little-endian.
112
     *
113
     * @param int $int
114
     * @return string
115
     */
116
    public static function wordl($int)
117
    {
118
        return strrev(static::word($int));
119
    }
120
121
    /**
122
     * Build double word (4 bytes) big-endian.
123
     *
124
     * @param int $int
125
     * @return string
126
     */
127
    public static function dword($int)
128
    {
129
        return static::i2b(4, $int);
130
    }
131
132
    /**
133
     * Build double word (4 bytes) little endian.
134
     *
135
     * @param int $int
136
     * @return string
137
     */
138
    public static function dwordl($int)
139
    {
140
        return strrev(static::dword($int));
141
    }
142
143
    /**
144
     * Build quadro word (8 bytes) big endian.
145
     *
146
     * @param int $int
147
     * @return string
148
     */
149
    public static function qword($int)
150
    {
151
        return static::i2b(8, $int);
152
    }
153
154
    /**
155
     * Build quadro word (8 bytes) little endian.
156
     * 
157
     * @param int $int
158
     * @return string
159
     */
160
    public static function qwordl($int)
161
    {
162
        return strrev(static::qword($int));
163
    }
164
165
    /**
166
     * Parse byte, and remove it.
167
     *
168
     * @param &string $p Data
0 ignored issues
show
Documentation introduced by
The doc-type &string could not be parsed: Unknown type name "&string" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
169
     * @return int
170
     */
171
    public static function getByte(&$p)
172
    {
173
        $r = static::bytes2int($p{0});
174
        $p = static::binarySubstr($p, 1);
175
176
        return (int) $r;
177
    }
178
179
    /**
180
     * Get single-byte character.
181
     *
182
     * @param &string $p Data
0 ignored issues
show
Documentation introduced by
The doc-type &string could not be parsed: Unknown type name "&string" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
183
     * @return string
184
     */
185
    public static function getChar(&$p)
186
    {
187
        $r = $p{0};
188
        $p = static::binarySubstr($p, 1);
189
190
        return $r;
191
    }
192
193
    /**
194
     * Parse word (2 bytes)
195
     *
196
     * @param &string $p Data.
0 ignored issues
show
Documentation introduced by
The doc-type &string could not be parsed: Unknown type name "&string" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
197
     * @param bool $l Little-endian, defaults to false.
198
     * @return int
199
     */
200 View Code Duplication
    public static function getWord(&$p, $l = false)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
201
    {
202
        $r = static::bytes2int(static::binarySubstr($p, 0, 2), !!$l);
203
        $p = static::binarySubstr($p, 2);
204
205
        return intval($r);
206
    }
207
208
    /**
209
     * Get word (2 bytes).
210
     *
211
     * @param &string $p Data
0 ignored issues
show
Documentation introduced by
The doc-type &string could not be parsed: Unknown type name "&string" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
212
     * @param bool $l Little-endian, defaults to false.
213
     * @return string
214
     */
215 View Code Duplication
    public static function getStrWord(&$p, $l = false)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
216
    {
217
        $r = static::binarySubstr($p, 0, 2);
218
        $p = static::binarySubstr($p, 2);
219
        if ($l) {
220
            $r = strrev($r);
221
        }
222
        return $r;
223
    }
224
225
    /**
226
     * Get double word (4 bytes).
227
     *
228
     * @param &string $p Data.
0 ignored issues
show
Documentation introduced by
The doc-type &string could not be parsed: Unknown type name "&string" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
229
     * @param bool $l Little-endian, defaults to false.
230
     * @return int
231
     */
232 View Code Duplication
    public static function getDWord(&$p, $l = false)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
233
    {
234
        $r = static::bytes2int(static::binarySubstr($p, 0, 4), !!$l);
235
        $p = static::binarySubstr($p, 4);
236
237
        return intval($r);
238
    }
239
240
    /**
241
     * Parse quadro word (8 bytes).
242
     *
243
     * @param &string $p Data
0 ignored issues
show
Documentation introduced by
The doc-type &string could not be parsed: Unknown type name "&string" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
244
     * @param bool $l Little-endian, defaults to false.
245
     * @return int
246
     */
247 View Code Duplication
    public static function getQword(&$p, $l = false)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
248
    {
249
        $r = static::bytes2int(static::binarySubstr($p, 0, 8), !!$l);
250
        $p = static::binarySubstr($p, 8);
251
252
        return intval($r);
253
    }
254
255
    /**
256
     * Get quadro word (8 bytes).
257
     *
258
     * @param &string $p Data.
0 ignored issues
show
Documentation introduced by
The doc-type &string could not be parsed: Unknown type name "&string" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
259
     * @param bool $l Little-endian, defaults to false.
260
     * @return string
261
     */
262 View Code Duplication
    public static function getStrQWord(&$p, $l = false)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
263
    {
264
        $r = static::binarySubstr($p, 0, 8);
265
        if ($l) {
266
            $r = strrev($r);
267
        }
268
        $p = static::binarySubstr($p, 8);
269
270
        return $r;
271
    }
272
273
    /**
274
     * Parse null-terminated string.
275
     *
276
     * @param &string $str
0 ignored issues
show
Documentation introduced by
The doc-type &string could not be parsed: Unknown type name "&string" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
277
     * @return string
278
     */
279 View Code Duplication
    public static function getString(&$str)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
280
    {
281
        $p = strpos($str, "\x00");
282
        if ($p === false) {
283
            return '';
284
        }
285
        $r   = static::binarySubstr($str, 0, $p);
286
        $str = static::binarySubstr($str, $p + 1);
287
288
        return $r;
289
    }
290
291
    /**
292
     * Parse length-value structure.
293
     *
294
     * @param &string $p
0 ignored issues
show
Documentation introduced by
The doc-type &string could not be parsed: Unknown type name "&string" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
295
     * @param int $l number of length bytes.
296
     * @param bool $nul Null-terminated, defaults to false.
297
     * @param bool $lrev Little-endian, default to false.
298
     * @return string
299
     */
300
    public static function getLV(&$p, $l = 1, $nul = false, $lrev = false)
301
    {
302
        $s = static::b2i(static::binarySubstr($p, 0, $l), !!$lrev);
303
        $p = static::binarySubstr($p, $l);
304
305
        if ($s == 0) {
306
            return '';
307
        }
308
309
        $r = '';
310
311
        if (strlen($p) < $s) {
312
            echo("getLV error: buf length (" . strlen($p) . "): " . Debug::exportBytes($p) . ", must be >= string length (" . $s . ")\n");
313
314
        } else if ($nul) {
315
            if ($p{$s - 1} != "\x00") {
316
                echo("getLV error: Wrong end of NUL-string (" . Debug::exportBytes($p{$s - 1}) . "), len " . $s . "\n");
317
            } else {
318
                $d = $s - 1;
319
                if ($d < 0)
320
                {
321
                    $d = 0;
322
                }
323
                $r = static::binarySubstr($p, 0, $d);
324
                $p = static::binarySubstr($p, $s);
325
            }
326
327
        } else {
328
            $r = static::binarySubstr($p, 0, $s);
329
            $p = static::binarySubstr($p, $s);
330
        }
331
332
        return $r;
333
    }
334
335
    /**
336
     * Converts integer to binary string.
337
     *
338
     * @param int $len
339
     * @param int $int
340
     * @param bool $l Little-endian, defaults to false.
341
     * @return string
342
     */
343
    public static function int2bytes($len, $int = 0, $l = false)
344
    {
345
        $hexstr = dechex($int);
346
347
        if ($len === null) {
348
            if (strlen($hexstr) % 2) {
349
                $hexstr = "0" . $hexstr;
350
            }
351
        } else {
352
            $hexstr = str_repeat('0', $len * 2 - strlen($hexstr)) . $hexstr;
353
        }
354
355
        $bytes = strlen($hexstr) / 2;
356
        $bin   = '';
357
358
        for ($i = 0; $i < $bytes; ++$i)
359
        {
360
            $bin .= chr(hexdec(substr($hexstr, $i * 2, 2)));
361
        }
362
363
        return $l ? strrev($bin) : $bin;
364
    }
365
366
    /**
367
     * Convert array of flags into bit array.
368
     *
369
     * @param array $flags
370
     * @param int $len defaults to 4.
371
     * @return string
372
     */
373
    public static function flags2bitarray($flags, $len = 4)
374
    {
375
        $ret = 0;
376
        foreach ($flags as $v)
377
        {
378
            $ret |= $v;
379
        }
380
        return static::i2b($len, $ret);
381
    }
382
383
    /**
384
     * @see BinarySupport::int2bytes
385
     */
386
    public static function i2b($bytes, $int = 0, $l = false)
387
    {
388
        return static::int2bytes($bytes, $int, $l);
389
    }
390
391
    /**
392
     * Convert bytes into integer.
393
     *
394
     * @param string $str
395
     * @param bool $l little-endian encoding, defaults to false
396
     * @return int
0 ignored issues
show
Documentation introduced by
Should the return type not be integer|double?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
397
     */
398
    public static function bytes2int($str, $l = false)
399
    {
400
        if ($l) {
401
            $str = strrev($str);
402
        }
403
404
        $dec = 0;
405
        $len = strlen($str);
406
407
        for ($i = 0; $i < $len; ++$i)
408
        {
409
            $dec += ord(static::binarySubstr($str, $i, 1)) * pow(0x100, $len - $i - 1);
410
        }
411
412
        return $dec;
413
    }
414
415
    /**
416
     * @see BinarySupport::bytes2int
417
     */
418
    public static function b2i($hex = 0, $l = false)
419
    {
420
        return static::bytes2int($hex, $l);
421
    }
422
423
    /**
424
     * Convert bitmap into bytes.
425
     *
426
     * @param string $bitmap
427
     * @param int $checkLen
428
     * @return string
429
     * @throws Exception
430
     */
431
    public static function bitmap2bytes($bitmap, $checkLen = 0)
432
    {
433
        $r = '';
434
        $bitmap = str_pad($bitmap, ceil(strlen($bitmap) / 8) * 8, '0', STR_PAD_LEFT);
435
436
        for ($i = 0, $n = strlen($bitmap) / 8; $i < $n; ++$i)
437
        {
438
            $r .= chr((int) bindec(static::binarySubstr($bitmap, $i * 8, 8)));
439
        }
440
        if ($checkLen && (strlen($r) != $checkLen)) {
441
            throw new Exception('Warning! Bitmap incorrect.');
442
        }
443
444
        return $r;
445
    }
446
447
    /**
448
     * Get bitmap.
449
     *
450
     * @param string $byte
451
     * @return string
452
     */
453
    public static function getBitmap($byte)
454
    {
455
        return sprintf('%08b', $byte);
456
    }
457
458
    /**
459
     * Binary Substring.
460
     *
461
     * @param string $s
462
     * @param string $p
463
     * @param int|null $len
464
     * @return string
465
     */
466
    protected static function binarySubstr($s, $p, $len = null)
467
    {
468
        if ($len === null) {
469
            $ret = substr($s, $p);
470
        } else {
471
            $ret = substr($s, $p, $len);
472
        }
473
474
        if ($ret === false) {
475
            $ret = '';
476
        }
477
478
        return $ret;
479
    }
480
}
481