MergePrefix::mergeStrings()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 5
c 1
b 0
f 0
dl 0
loc 10
ccs 6
cts 6
cp 1
rs 10
cc 2
nc 2
nop 1
crap 2
1
<?php declare(strict_types=1);
2
3
/**
4
* @package   s9e\RegexpBuilder
5
* @copyright Copyright (c) 2016-2022 The s9e authors
6
* @license   http://www.opensource.org/licenses/mit-license.php The MIT License
7
*/
8
namespace s9e\RegexpBuilder\Passes;
9
10
/**
11
* Replaces (?:axx|ayy) with a(?:xx|yy)
12
*/
13
class MergePrefix extends AbstractPass
14
{
15
	/**
16
	* {@inheritdoc}
17
	*/
18 5
	protected function runPass(array $strings): array
19
	{
20 5
		$newStrings = [];
21 5
		foreach ($this->getStringsByPrefix($strings) as $prefix => $strings)
22
		{
23 4
			$newStrings[] = (isset($strings[1])) ? $this->mergeStrings($strings) : $strings[0];
24
		}
25
26 5
		return $newStrings;
27
	}
28
29
	/**
30
	* Get the number of leading elements common to all given strings
31
	*
32
	* @param  array[] $strings
33
	* @return integer
34
	*/
35 4
	protected function getPrefixLength(array $strings): int
36
	{
37 4
		$len = 1;
38 4
		$cnt = count($strings[0]);
39 4
		while ($len < $cnt && $this->stringsMatch($strings, $len))
40
		{
41 3
			++$len;
42
		}
43
44 4
		return $len;
45
	}
46
47
	/**
48
	* Return given strings grouped by their first element
49
	*
50
	* NOTE: assumes that this pass is run before the first element of any string could be replaced
51
	*
52
	* @param  array[] $strings
53
	* @return array[]
54
	*/
55 5
	protected function getStringsByPrefix(array $strings): array
56
	{
57 5
		$byPrefix = [];
58 5
		foreach ($strings as $string)
59
		{
60 4
			$byPrefix[$string[0]][] = $string;
61
		}
62
63 5
		return $byPrefix;
64
	}
65
66
	/**
67
	* Merge given strings into a new single string
68
	*
69
	* @param  array[] $strings
70
	* @return array
71
	*/
72 4
	protected function mergeStrings(array $strings): array
73
	{
74 4
		$len       = $this->getPrefixLength($strings);
75 4
		$newString = array_slice($strings[0], 0, $len);
76 4
		foreach ($strings as $string)
77
		{
78 4
			$newString[$len][] = array_slice($string, $len);
79
		}
80
81 4
		return $newString;
82
	}
83
84
	/**
85
	* Test whether all given strings' elements match at given position
86
	*
87
	* @param  array[] $strings
88
	* @param  integer $pos
89
	* @return bool
90
	*/
91 3
	protected function stringsMatch(array $strings, int $pos): bool
92
	{
93 3
		$value = $strings[0][$pos];
94 3
		foreach ($strings as $string)
95
		{
96 3
			if (!isset($string[$pos]) || $string[$pos] !== $value)
97
			{
98 2
				return false;
99
			}
100
		}
101
102 3
		return true;
103
	}
104
}