Binary   B
last analyzed

Complexity

Total Complexity 52

Size/Duplication

Total Lines 414
Duplicated Lines 13.77 %

Coupling/Cohesion

Components 2
Dependencies 4

Importance

Changes 0
Metric Value
dl 57
loc 414
rs 7.44
c 0
b 0
f 0
wmc 52
lcom 2
cbo 4

27 Methods

Rating   Name   Duplication   Size   Complexity  
A labels() 0 12 3
A parseLabels() 0 22 5
A bytes2int() 11 12 3
A LVnull() 0 4 1
A LV() 0 8 2
A i2b() 0 4 1
A int2bytes() 21 21 5
A byte() 0 4 1
A wordl() 0 4 1
A word() 0 4 1
A dwordl() 0 4 1
A dword() 0 4 1
A qwordl() 0 4 1
A qword() 0 4 1
A getByte() 0 6 1
A getChar() 0 6 1
A getWord() 0 6 1
A getStrWord() 8 9 2
A getDWord() 0 6 1
A getQword() 0 6 1
A getStrQWord() 8 9 2
A getString() 9 10 2
B getLV() 0 29 6
A b2i() 0 4 1
A flags2bitarray() 0 8 2
A bitmap2bytes() 0 12 4
A getbitmap() 0 4 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Binary often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Binary, and based on these observations, apply Extract Interface, too.

1
<?php
2
namespace PHPDaemon\Utils;
3
4
use PHPDaemon\Core\Daemon;
5
use PHPDaemon\Core\Debug;
6
7
/**
8
 * Binary
9
 * @package PHPDaemon\Utils
10
 * @author  Vasily Zorin <[email protected]>
11
 */
12
class Binary
13
{
14
    use \PHPDaemon\Traits\ClassWatchdog;
15
    use \PHPDaemon\Traits\StaticObjectWatchdog;
16
17
    /**
18
     * Build structure of labels
19
     * @param  string $q Dot-separated labels list
20
     * @return string
21
     */
22
    public static function labels($q)
23
    {
24
        $e = explode('.', $q);
25
        $r = '';
26
        for ($i = 0, $s = sizeof($e); $i < $s; ++$i) {
27
            $r .= chr(mb_orig_strlen($e[$i])) . $e[$i];
28
        }
29
        if (mb_orig_substr($r, -1) !== "\x00") {
30
            $r .= "\x00";
31
        }
32
        return $r;
33
    }
34
35
    /**
36
     * Parse structure of labels
37
     * @param  string &$data Binary data
38
     * @param  string $orig Original packet
0 ignored issues
show
Documentation introduced by
Should the type for parameter $orig not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
39
     * @return string        Dot-separated labels list
40
     */
41
    public static function parseLabels(&$data, $orig = null)
42
    {
43
        $str = '';
44
        while (mb_orig_strlen($data) > 0) {
45
            $l = ord($data[0]);
46
47
            if ($l >= 192) {
48
                $pos = Binary::bytes2int(chr($l - 192) . mb_orig_substr($data, 1, 1));
49
                $data = mb_orig_substr($data, 2);
50
                $ref = mb_orig_substr($orig, $pos);
51
                return $str . Binary::parseLabels($ref, $orig);
52
            }
53
54
            $p = mb_orig_substr($data, 1, $l);
55
            $str .= $p . (($l !== 0) ? '.' : '');
56
            $data = mb_orig_substr($data, $l + 1);
57
            if ($l === 0) {
58
                break;
59
            }
60
        }
61
        return $str;
62
    }
63
64
    /**
65
     * Convert bytes into integer
66
     * @param  string $str Bytes
67
     * @param  boolean $l Little endian? Default is false
68
     * @return integer
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...
69
     */
70 View Code Duplication
    public static function bytes2int($str, $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...
71
    {
72
        if ($l) {
73
            $str = strrev($str);
74
        }
75
        $dec = 0;
76
        $len = mb_orig_strlen($str);
77
        for ($i = 0; $i < $len; ++$i) {
78
            $dec += ord(mb_orig_substr($str, $i, 1)) * pow(0x100, $len - $i - 1);
79
        }
80
        return $dec;
81
    }
82
83
    /**
84
     * Build nul-terminated string, with 2-byte of length
85
     * @param string $str Data
86
     * @return string
87
     */
88
    public static function LVnull($str)
89
    {
90
        return static::LV($str . "\x00", 2, true);
91
    }
92
93
    /**
94
     * Build length-value binary snippet
95
     * @param string $str Data
96
     * @param integer $len Number of bytes to encode length. Default is 1
97
     * @param boolean $lrev Reverse?
98
     * @return string
99
     */
100
    public static function LV($str, $len = 1, $lrev = false)
101
    {
102
        $l = static::i2b($len, mb_orig_strlen($str));
103
        if ($lrev) {
104
            $l = strrev($l);
105
        }
106
        return $l . $str;
107
    }
108
109
    /**
110
     * Converts integer to binary string
111
     * @alias Binary::int2bytes
112
     * @param  integer $len Length
113
     * @param  integer $int Integer
114
     * @param  boolean $l Optional. Little endian. Default value - false
115
     * @return string       Resulting binary string
116
     */
117
    public static function i2b($len, $int = 0, $l = false)
118
    {
119
        return static::int2bytes($len, $int, $l);
120
    }
121
122
    /**
123
     * Converts integer to binary string
124
     * @param  integer $len Length
125
     * @param  integer $int Integer
126
     * @param  boolean $l Optional. Little endian. Default value - false
127
     * @return string       Resulting binary string
128
     */
129 View Code Duplication
    public static function int2bytes($len, $int = 0, $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...
130
    {
131
        $hexstr = dechex($int);
132
133
        if ($len === null) {
134
            if (mb_orig_strlen($hexstr) % 2) {
135
                $hexstr = "0" . $hexstr;
136
            }
137
        } else {
138
            $hexstr = str_repeat('0', $len * 2 - mb_orig_strlen($hexstr)) . $hexstr;
139
        }
140
141
        $bytes = mb_orig_strlen($hexstr) / 2;
142
        $bin = '';
143
144
        for ($i = 0; $i < $bytes; ++$i) {
145
            $bin .= chr(hexdec(substr($hexstr, $i * 2, 2)));
146
        }
147
148
        return $l ? strrev($bin) : $bin;
149
    }
150
151
    /**
152
     * Build byte
153
     * @param  integer $int Byte number
154
     * @return string
155
     */
156
    public static function byte($int)
157
    {
158
        return chr($int);
159
    }
160
161
    /**
162
     * Build word (2 bytes) little-endian
163
     * @param  integer $int Integer
164
     * @return string
165
     */
166
    public static function wordl($int)
167
    {
168
        return strrev(static::word($int));
169
    }
170
171
    /**
172
     * Build word (2 bytes) big-endian
173
     * @param  integer $int Integer
174
     * @return string
175
     */
176
    public static function word($int)
177
    {
178
        return static::i2b(2, $int);
179
    }
180
181
    /**
182
     * Build double word (4 bytes) little endian
183
     * @param  integer $int Integer
184
     * @return string
185
     */
186
    public static function dwordl($int)
187
    {
188
        return strrev(static::dword($int));
189
    }
190
191
    /**
192
     * Build double word (4 bytes) big-endian
193
     * @param  integer $int Integer
194
     * @return string
195
     */
196
    public static function dword($int)
197
    {
198
        return static::i2b(4, $int);
199
    }
200
201
    /**
202
     * Build quadro word (8 bytes) little endian
203
     * @param  integer $int Integer
204
     * @return string
205
     */
206
    public static function qwordl($int)
207
    {
208
        return strrev(static::qword($int));
209
    }
210
211
    /**
212
     * Build quadro word (8 bytes) big endian
213
     * @param  integer $int Integer
214
     * @return string
215
     */
216
    public static function qword($int)
217
    {
218
        return static::i2b(8, $int);
219
    }
220
221
    /**
222
     * Parse byte, and remove it
223
     * @param  string &$p Data
224
     * @return integer
225
     */
226
    public static function getByte(&$p)
227
    {
228
        $r = static::bytes2int($p[0]);
229
        $p = mb_orig_substr($p, 1);
230
        return (int)$r;
231
    }
232
233
    /**
234
     * Get single-byte character
235
     * @param  string &$p Data
236
     * @return string
237
     */
238
    public static function getChar(&$p)
239
    {
240
        $r = $p[0];
241
        $p = mb_orig_substr($p, 1);
242
        return $r;
243
    }
244
245
    /**
246
     * Parse word (2 bytes)
247
     * @param  string &$p Data
248
     * @param  boolean $l Little endian?
249
     * @return integer
250
     */
251
    public static function getWord(&$p, $l = false)
252
    {
253
        $r = static::bytes2int(mb_orig_substr($p, 0, 2), !!$l);
254
        $p = mb_orig_substr($p, 2);
255
        return (int)$r;
256
    }
257
258
    /**
259
     * Get word (2 bytes)
260
     * @param  string &$p Data
261
     * @param  boolean $l Little endian?
262
     * @return string
263
     */
264 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...
265
    {
266
        $r = mb_orig_substr($p, 0, 2);
267
        $p = mb_orig_substr($p, 2);
268
        if ($l) {
269
            $r = strrev($r);
270
        }
271
        return $r;
272
    }
273
274
    /**
275
     * Get double word (4 bytes)
276
     * @param  string &$p Data
277
     * @param  boolean $l Little endian?
278
     * @return integer
279
     */
280
    public static function getDWord(&$p, $l = false)
281
    {
282
        $r = static::bytes2int(mb_orig_substr($p, 0, 4), !!$l);
283
        $p = mb_orig_substr($p, 4);
284
        return (int)$r;
285
    }
286
287
    /**
288
     * Parse quadro word (8 bytes)
289
     * @param  string &$p Data
290
     * @param  boolean $l Little endian?
291
     * @return integer
292
     */
293
    public static function getQword(&$p, $l = false)
294
    {
295
        $r = static::bytes2int(mb_orig_substr($p, 0, 8), !!$l);
296
        $p = mb_orig_substr($p, 8);
297
        return (int)$r;
298
    }
299
300
    /**
301
     * Get quadro word (8 bytes)
302
     * @param  string &$p Data
303
     * @param  boolean $l Little endian?
304
     * @return string
305
     */
306 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...
307
    {
308
        $r = mb_orig_substr($p, 0, 8);
309
        if ($l) {
310
            $r = strrev($r);
311
        }
312
        $p = mb_orig_substr($p, 8);
313
        return $r;
314
    }
315
316
    /**
317
     * Parse nul-terminated string
318
     * @param  string &$str Data
319
     * @return string
320
     */
321 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...
322
    {
323
        $p = mb_orig_strpos($str, "\x00");
324
        if ($p === false) {
325
            return '';
326
        }
327
        $r = mb_orig_substr($str, 0, $p);
328
        $str = mb_orig_substr($str, $p + 1);
329
        return $r;
330
    }
331
332
    /**
333
     * Parse length-value structure
334
     * @param  string &$p Data
335
     * @param  integer $l Number of length bytes
336
     * @param  boolean $nul Nul-terminated? Default is false
337
     * @param  boolean $lrev Length is little endian?
338
     * @return string
339
     */
340
    public static function getLV(&$p, $l = 1, $nul = false, $lrev = false)
341
    {
342
        $s = static::b2i(mb_orig_substr($p, 0, $l), !!$lrev);
343
        $p = mb_orig_substr($p, $l);
344
        if ($s === 0) {
345
            return '';
346
        }
347
        $r = '';
348
        if (mb_orig_strlen($p) < $s) {
349
            Daemon::log('getLV error: buf length (' . mb_orig_strlen($p) . '): ' . Debug::exportBytes($p) . ', must be >= string length (' . $s . ")\n");
350
        } elseif ($nul) {
351
            $lastByte = mb_orig_substr($p, -1);
352
            if ($lastByte !== "\x00") {
353
                Daemon:
354
                log('getLV error: Wrong end of NUL-string (' . Debug::exportBytes($lastByte) . '), len ' . $s . "\n");
355
            } else {
356
                $d = $s - 1;
357
                if ($d < 0) {
358
                    $d = 0;
359
                }
360
                $r = mb_orig_substr($p, 0, $d);
361
                $p = mb_orig_substr($p, $s);
362
            }
363
        } else {
364
            $r = mb_orig_substr($p, 0, $s);
365
            $p = mb_orig_substr($p, $s);
366
        }
367
        return $r;
368
    }
369
370
    /**
371
     * Convert bytes into integer
372
     * @alias Binary::bytes2int
373
     * @param  string $str Bytes
0 ignored issues
show
Documentation introduced by
Should the type for parameter $str not be integer?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
374
     * @param  boolean $l Little endian? Default is false
375
     * @return integer
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...
376
     */
377
    public static function b2i($str = 0, $l = false)
378
    {
379
        return static::bytes2int($str, $l);
380
    }
381
382
    /**
383
     * Convert array of flags into bit array
384
     * @param  array $flags Flags
385
     * @param  integer $len Length. Default is 4
386
     * @return string
387
     */
388
    public static function flags2bitarray($flags, $len = 4)
389
    {
390
        $ret = 0;
391
        foreach ($flags as $v) {
392
            $ret |= $v;
393
        }
394
        return static::i2b($len, $ret);
395
    }
396
397
    /**
398
     * Convert bitmap into bytes
399
     * @param  string $bitmap Bitmap
400
     * @param  integer $check_len Check length?
401
     * @return string|false
402
     */
403
    public static function bitmap2bytes($bitmap, $check_len = 0)
404
    {
405
        $r = '';
406
        $bitmap = str_pad($bitmap, ceil(mb_orig_strlen($bitmap) / 8) * 8, '0', STR_PAD_LEFT);
407
        for ($i = 0, $n = mb_orig_strlen($bitmap) / 8; $i < $n; ++$i) {
408
            $r .= chr((int)bindec(mb_orig_substr($bitmap, $i * 8, 8)));
409
        }
410
        if ($check_len && (mb_orig_strlen($r) !== $check_len)) {
411
            return false;
412
        }
413
        return $r;
414
    }
415
416
    /**
417
     * Get bitmap
418
     * @param  integer $byte Byte
419
     * @return string
420
     */
421
    public static function getbitmap($byte)
422
    {
423
        return sprintf('%08b', $byte);
424
    }
425
}
426