Decoder   A
last analyzed

Complexity

Total Complexity 16

Size/Duplication

Total Lines 182
Duplicated Lines 15.93 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 0
Metric Value
wmc 16
lcom 1
cbo 1
dl 29
loc 182
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A decode() 0 7 1
A process() 0 15 5
A getCurrentType() 0 20 3
A decodeString() 0 10 1
A decodeInteger() 0 17 2
A decodeDictionary() 15 15 2
A decodeList() 14 14 2

How to fix   Duplicated Code   

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:

1
<?php namespace Cornford\Bencoded;
2
3
use Cornford\Bencoded\Contracts\DecodableInterface;
4
use Cornford\Bencoded\Exceptions\InvalidBencodedDelimiterException;
5
6
class Decoder implements DecodableInterface
7
{
8
    const TYPE_END = 0;
9
    const TYPE_DICTIONARY = 1;
10
    const TYPE_INTEGER = 2;
11
    const TYPE_LIST = 3;
12
    const TYPE_STRING = 4;
13
14
    const DELIMITER_END = 'e';
15
    const DELIMITER_DICTIONARY = 'd';
16
    const DELIMITER_INTEGER = 'i';
17
    const DELIMITER_LIST = 'l';
18
    const DELIMITER_STRING = '[0-9]';
19
20
    const SEPARATOR = ':';
21
22
    /**
23
     * Content.
24
     *
25
     * @var string
26
     */
27
    private $content;
28
29
    /**
30
     * Current pointer position.
31
     *
32
     * @var integer
33
     */
34
    private $pointer = 0;
35
36
    /**
37
     * BDecode content.
38
     *
39
     * @param string $content
40
     *
41
     * @throws InvalidBencodedDelimiterException
42
     *
43
     * @return string
44
     */
45
    public function decode($content)
46
    {
47
        $this->content = $content;
48
        $this->pointer = 0;
49
50
        return $this->process();
51
    }
52
53
    /**
54
     * Process from the current position.
55
     *
56
     * @throws InvalidBencodedDelimiterException
57
     *
58
     * @return mixed
59
     */
60
    private function process()
61
    {
62
        switch ($this->getCurrentType()) {
63
            case self::TYPE_DICTIONARY:
64
                return self::decodeDictionary();
65
            case self::TYPE_INTEGER:
66
                return $this->decodeInteger();
67
            case self::TYPE_LIST:
68
                return $this->decodeList();
69
            case self::TYPE_STRING:
70
                return $this->decodeString();
71
            default:
72
                return null;
73
        }
74
    }
75
76
    /**
77
     * Get type of the value at the current pointer.
78
     *
79
     * @throws InvalidBencodedDelimiterException
80
     *
81
     * @return int
82
     */
83
    private function getCurrentType()
84
    {
85
        $current = substr($this->content, $this->pointer, 1);
86
87
        $map = array(
88
            self::TYPE_END  => self::DELIMITER_END,
89
            self::TYPE_DICTIONARY => self::DELIMITER_DICTIONARY,
90
            self::TYPE_INTEGER  => self::DELIMITER_INTEGER,
91
            self::TYPE_LIST => self::DELIMITER_LIST,
92
            self::TYPE_STRING  => self::DELIMITER_STRING,
93
        );
94
95
        foreach ($map as $type => $pattern) {
96
            if (preg_match('/^' . $pattern . '$/', $current)) {
97
                return $type;
98
            }
99
        }
100
101
        throw new InvalidBencodedDelimiterException('Invalid type delimiter encountered: "' . $current . '"');
102
    }
103
104
    /**
105
     * Decode string.
106
     *
107
     * @return string
108
     */
109
    private function decodeString()
110
    {
111
        $separatorPosition = strpos($this->content, self::SEPARATOR, $this->pointer);
112
        $length = (int) substr($this->content, $this->pointer, $separatorPosition -  $this->pointer);
113
        $value = substr($this->content, $separatorPosition + 1, $length);
114
115
        $this->pointer = $separatorPosition + $length + 1;
116
117
        return $value;
118
    }
119
120
    /**
121
     * Decode integer.
122
     *
123
     * @return int|float
124
     */
125
    private function decodeInteger()
126
    {
127
        $this->pointer++;
128
129
        $endPosition = strpos($this->content, self::DELIMITER_END, $this->pointer);
130
        $value = substr($this->content, $this->pointer, $endPosition - $this->pointer);
131
132
        if (strstr($value, '.')) {
133
            $value = (float) $value;
134
        } else {
135
            $value = (int) $value;
136
        }
137
138
        $this->pointer = $endPosition + 1;
139
140
        return $value;
141
    }
142
143
    /**
144
     * BDecode dictionary.
145
     *
146
     * @throws InvalidBencodedDelimiterException
147
     *
148
     * @return array
149
     */
150 View Code Duplication
    private function decodeDictionary()
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...
151
    {
152
        $output = [];
153
154
        $this->pointer++;
155
156
        do {
157
            $key = $this->decodeString();
158
            $output[$key] = $this->process();
159
        } while ($this->getCurrentType() !== self::TYPE_END);
160
161
        $this->pointer++;
162
163
        return $output;
164
    }
165
166
    /**
167
     * Decode list.
168
     *
169
     * @throws InvalidBencodedDelimiterException
170
     *
171
     * @return array
172
     */
173 View Code Duplication
    private function decodeList()
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...
174
    {
175
        $output = [];
176
177
        $this->pointer++;
178
179
        do {
180
            $output[] = $this->process();
181
        } while ($this->getCurrentType() !== self::TYPE_END);
182
183
        $this->pointer++;
184
185
        return $output;
186
    }
187
}
188