1
|
|
|
<?php declare(strict_types=1); |
2
|
|
|
|
3
|
|
|
/* |
4
|
|
|
* This file is part of the pinepain/php-object-maps PHP library. |
5
|
|
|
* |
6
|
|
|
* Copyright (c) 2016-2017 Bogdan Padalko <[email protected]> |
7
|
|
|
* |
8
|
|
|
* Licensed under the MIT license: http://opensource.org/licenses/MIT |
9
|
|
|
* |
10
|
|
|
* For the full copyright and license information, please view the LICENSE |
11
|
|
|
* file that was distributed with this source code or visit http://opensource.org/licenses/MIT |
12
|
|
|
*/ |
13
|
|
|
|
14
|
|
|
|
15
|
|
|
namespace Pinepain\ObjectMaps; |
16
|
|
|
|
17
|
|
|
|
18
|
|
|
use OutOfBoundsException; |
19
|
|
|
use OverflowException; |
20
|
|
|
use Ref\WeakReference; |
21
|
|
|
|
22
|
|
|
|
23
|
|
|
class ObjectBiMap implements ObjectBiMapInterface |
24
|
|
|
{ |
25
|
|
|
const WEAK_KEY = 1 << 0; |
26
|
|
|
const WEAK_VALUE = 1 << 1; |
27
|
|
|
const WEAK_KEY_VALUE = self::WEAK_KEY | self::WEAK_VALUE; |
28
|
|
|
|
29
|
|
|
protected $behavior = 0; |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* @var ObjectMap |
33
|
|
|
*/ |
34
|
|
|
protected $keys; |
35
|
|
|
/** |
36
|
|
|
* @var ObjectMap |
37
|
|
|
*/ |
38
|
|
|
protected $values; |
39
|
|
|
|
40
|
|
|
public function __construct(int $behavior = 0) |
41
|
|
|
{ |
42
|
|
|
$key_behavior = 0; |
43
|
|
|
$value_behavior = 0; |
44
|
|
|
|
45
|
|
|
if ($behavior & self::WEAK_KEY) { |
46
|
|
|
$key_behavior |= self::WEAK_KEY; |
47
|
|
|
$value_behavior |= self::WEAK_VALUE; |
48
|
|
|
} |
49
|
|
|
|
50
|
|
|
if ($behavior & self::WEAK_VALUE) { |
51
|
|
|
$key_behavior |= self::WEAK_VALUE; |
52
|
|
|
$value_behavior |= self::WEAK_KEY; |
53
|
|
|
} |
54
|
|
|
|
55
|
|
|
$this->keys = new ObjectMap($key_behavior); |
56
|
|
|
$this->values = new ObjectMap($value_behavior); |
57
|
|
|
|
58
|
|
|
$this->behavior = $behavior; |
59
|
|
|
} |
60
|
|
|
|
61
|
|
|
public function values(): ObjectBiMapInterface |
62
|
|
|
{ |
63
|
|
|
$new_behavior = 0; |
64
|
|
|
|
65
|
|
|
if ($this->behavior & self::WEAK_KEY) { |
66
|
|
|
$new_behavior |= self::WEAK_VALUE; |
67
|
|
|
} |
68
|
|
|
|
69
|
|
|
if ($this->behavior & self::WEAK_VALUE) { |
70
|
|
|
$new_behavior |= self::WEAK_KEY; |
71
|
|
|
} |
72
|
|
|
|
73
|
|
|
$new = new static($new_behavior); |
74
|
|
|
|
75
|
|
|
$new->keys = $this->values; |
76
|
|
|
$new->values = $this->keys; |
77
|
|
|
|
78
|
|
|
return $new; |
79
|
|
|
} |
80
|
|
|
|
81
|
|
View Code Duplication |
public function put($key, $value) |
|
|
|
|
82
|
|
|
{ |
83
|
|
|
if ($this->keys->has($key)) { |
84
|
|
|
throw new OverflowException('Value with such key already exists'); |
85
|
|
|
} |
86
|
|
|
|
87
|
|
|
if ($this->values->has($value)) { |
88
|
|
|
throw new OverflowException('Key with such value already exists'); |
89
|
|
|
} |
90
|
|
|
|
91
|
|
|
$this->keys->put($key, $value); |
92
|
|
|
$this->values->put($value, $key); |
93
|
|
|
} |
94
|
|
|
|
95
|
|
|
public function get($key) |
96
|
|
|
{ |
97
|
|
|
return $this->keys->get($key); |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
public function has($key): bool |
101
|
|
|
{ |
102
|
|
|
return $this->keys->has($key); |
103
|
|
|
} |
104
|
|
|
|
105
|
|
View Code Duplication |
public function remove($key) |
|
|
|
|
106
|
|
|
{ |
107
|
|
|
if ($this->keys->has($key)) { |
108
|
|
|
throw new OutOfBoundsException('Value with such key not found'); |
109
|
|
|
} |
110
|
|
|
|
111
|
|
|
$value = $this->keys->remove($key); |
112
|
|
|
|
113
|
|
|
if ($this->values->has($value)) { |
114
|
|
|
// UNEXPECTED |
115
|
|
|
throw new OutOfBoundsException('Key with such value not found'); |
116
|
|
|
} |
117
|
|
|
|
118
|
|
|
$this->values->remove($value); |
119
|
|
|
|
120
|
|
|
return $value; |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
public function clear() |
124
|
|
|
{ |
125
|
|
|
$this->keys->clear(); |
126
|
|
|
$this->values->clear(); |
127
|
|
|
} |
128
|
|
|
|
129
|
|
|
public function count() |
130
|
|
|
{ |
131
|
|
|
return count($this->keys); |
132
|
|
|
} |
133
|
|
|
} |
134
|
|
|
|
135
|
|
|
|
136
|
|
|
|
137
|
|
|
|
138
|
|
|
|
139
|
|
|
|
140
|
|
|
|
141
|
|
|
|
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.