Skip to content

Commit 9001835

Browse files
authored
Merge pull request #66 from marc-mabe/enumset_produce
EnumSet: added methods union(), intersect(), diff() and symDiff()
2 parents 6b5f052 + ac9aa5b commit 9001835

File tree

2 files changed

+230
-0
lines changed

2 files changed

+230
-0
lines changed

src/EnumSet.php

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,106 @@ public function isSuperset(EnumSet $other)
245245
return ($thisBitset | $other->getBinaryBitsetLe()) === $thisBitset;
246246
}
247247

248+
/**
249+
* Produce a new set with enumerators from both this and other (this | other)
250+
* @param EnumSet ...$other Other EnumSet(s) of the same enumeration to produce the union
251+
* @return EnumSet
252+
*/
253+
public function union(EnumSet $other)
254+
{
255+
$bitset = $this->bitset;
256+
foreach (func_get_args() as $other) {
257+
if (!$other instanceof self || $this->enumeration !== $other->enumeration) {
258+
throw new InvalidArgumentException(sprintf(
259+
"Others should be an instance of %s of the same enumeration as this %s",
260+
__CLASS__,
261+
$this->enumeration
262+
));
263+
}
264+
265+
$bitset |= $other->bitset;
266+
}
267+
268+
$clone = clone $this;
269+
$clone->bitset = $bitset;
270+
return $clone;
271+
}
272+
273+
/**
274+
* Produce a new set with enumerators common to both this and other (this & other)
275+
* @param EnumSet ...$other Other EnumSet(s) of the same enumeration to produce the union
276+
* @return EnumSet
277+
*/
278+
public function intersect(EnumSet $other)
279+
{
280+
$bitset = $this->bitset;
281+
foreach (func_get_args() as $other) {
282+
if (!$other instanceof self || $this->enumeration !== $other->enumeration) {
283+
throw new InvalidArgumentException(sprintf(
284+
"Others should be an instance of %s of the same enumeration as this %s",
285+
__CLASS__,
286+
$this->enumeration
287+
));
288+
}
289+
290+
$bitset &= $other->bitset;
291+
}
292+
293+
$clone = clone $this;
294+
$clone->bitset = $bitset;
295+
return $clone;
296+
}
297+
298+
/**
299+
* Produce a new set with enumerators in this but not in other (this - other)
300+
* @param EnumSet ...$other Other EnumSet(s) of the same enumeration to produce the union
301+
* @return EnumSet
302+
*/
303+
public function diff(EnumSet $other)
304+
{
305+
$bitset = '';
306+
foreach (func_get_args() as $other) {
307+
if (!$other instanceof self || $this->enumeration !== $other->enumeration) {
308+
throw new InvalidArgumentException(sprintf(
309+
"Others should be an instance of %s of the same enumeration as this %s",
310+
__CLASS__,
311+
$this->enumeration
312+
));
313+
}
314+
315+
$bitset |= $other->bitset;
316+
}
317+
318+
$clone = clone $this;
319+
$clone->bitset = $this->bitset & ~$bitset;
320+
return $clone;
321+
}
322+
323+
/**
324+
* Produce a new set with enumerators in either this and other but not in both (this ^ (other | other))
325+
* @param EnumSet ...$other Other EnumSet(s) of the same enumeration to produce the union
326+
* @return EnumSet
327+
*/
328+
public function symDiff(EnumSet $other)
329+
{
330+
$bitset = '';
331+
foreach (func_get_args() as $other) {
332+
if (!$other instanceof self || $this->enumeration !== $other->enumeration) {
333+
throw new InvalidArgumentException(sprintf(
334+
"Others should be an instance of %s of the same enumeration as this %s",
335+
__CLASS__,
336+
$this->enumeration
337+
));
338+
}
339+
340+
$bitset |= $other->bitset;
341+
}
342+
343+
$clone = clone $this;
344+
$clone->bitset = $this->bitset ^ $bitset;
345+
return $clone;
346+
}
347+
248348
/**
249349
* Get ordinal numbers of the defined enumerators as array
250350
* @return int[]

tests/MabeEnumTest/EnumSetTest.php

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,4 +672,134 @@ public function testGetNamesDoesNotEffectIteratorPosition()
672672
$set->getNames();
673673
$this->assertSame(EnumBasic::TWO, $set->current()->getValue());
674674
}
675+
676+
public function testUnion()
677+
{
678+
$set1 = new EnumSet('MabeEnumTest\TestAsset\EnumBasic');
679+
$set1->attach(EnumBasic::ONE);
680+
$set1->attach(EnumBasic::TWO);
681+
682+
$set2 = new EnumSet('MabeEnumTest\TestAsset\EnumBasic');
683+
$set2->attach(EnumBasic::TWO);
684+
$set2->attach(EnumBasic::THREE);
685+
686+
$set3 = new EnumSet('MabeEnumTest\TestAsset\EnumBasic');
687+
$set3->attach(EnumBasic::THREE);
688+
$set3->attach(EnumBasic::FOUR);
689+
690+
$rs = $set1->union($set2, $set3);
691+
$this->assertSame(array(
692+
EnumBasic::ONE,
693+
EnumBasic::TWO,
694+
EnumBasic::THREE,
695+
EnumBasic::FOUR,
696+
), $rs->getValues());
697+
}
698+
699+
public function testUnionThrowsInvalidArgumentException()
700+
{
701+
$set1 = new EnumSet('MabeEnumTest\TestAsset\EnumBasic');
702+
$set2 = new EnumSet('MabeEnumTest\TestAsset\Enum32');
703+
704+
$this->setExpectedException('InvalidArgumentException');
705+
$set1->union($set2);
706+
}
707+
708+
public function testIntersect()
709+
{
710+
$set1 = new EnumSet('MabeEnumTest\TestAsset\EnumBasic');
711+
$set1->attach(EnumBasic::ONE);
712+
$set1->attach(EnumBasic::TWO);
713+
$set1->attach(EnumBasic::THREE);
714+
715+
$set2 = new EnumSet('MabeEnumTest\TestAsset\EnumBasic');
716+
$set2->attach(EnumBasic::TWO);
717+
$set2->attach(EnumBasic::THREE);
718+
$set2->attach(EnumBasic::FOUR);
719+
720+
$set3 = new EnumSet('MabeEnumTest\TestAsset\EnumBasic');
721+
$set3->attach(EnumBasic::THREE);
722+
$set3->attach(EnumBasic::FOUR);
723+
$set3->attach(EnumBasic::FIVE);
724+
725+
$rs = $set1->intersect($set2, $set3);
726+
$this->assertSame(array(
727+
EnumBasic::THREE,
728+
), $rs->getValues());
729+
}
730+
731+
public function testIntersectThrowsInvalidArgumentException()
732+
{
733+
$set1 = new EnumSet('MabeEnumTest\TestAsset\EnumBasic');
734+
$set2 = new EnumSet('MabeEnumTest\TestAsset\Enum32');
735+
736+
$this->setExpectedException('InvalidArgumentException');
737+
$set1->intersect($set2);
738+
}
739+
740+
public function testDiff()
741+
{
742+
$set1 = new EnumSet('MabeEnumTest\TestAsset\EnumBasic');
743+
$set1->attach(EnumBasic::ONE);
744+
$set1->attach(EnumBasic::TWO);
745+
$set1->attach(EnumBasic::THREE);
746+
747+
$set2 = new EnumSet('MabeEnumTest\TestAsset\EnumBasic');
748+
$set2->attach(EnumBasic::TWO);
749+
$set2->attach(EnumBasic::THREE);
750+
$set2->attach(EnumBasic::FOUR);
751+
752+
$set3 = new EnumSet('MabeEnumTest\TestAsset\EnumBasic');
753+
$set3->attach(EnumBasic::THREE);
754+
$set3->attach(EnumBasic::FOUR);
755+
$set3->attach(EnumBasic::FIVE);
756+
757+
$rs = $set1->diff($set2, $set3);
758+
$this->assertSame(array(
759+
EnumBasic::ONE,
760+
), $rs->getValues());
761+
}
762+
763+
public function testDiffThrowsInvalidArgumentException()
764+
{
765+
$set1 = new EnumSet('MabeEnumTest\TestAsset\EnumBasic');
766+
$set2 = new EnumSet('MabeEnumTest\TestAsset\Enum32');
767+
768+
$this->setExpectedException('InvalidArgumentException');
769+
$set1->diff($set2);
770+
}
771+
772+
public function testSymDiff()
773+
{
774+
$set1 = new EnumSet('MabeEnumTest\TestAsset\EnumBasic');
775+
$set1->attach(EnumBasic::ONE);
776+
$set1->attach(EnumBasic::TWO);
777+
$set1->attach(EnumBasic::THREE);
778+
779+
$set2 = new EnumSet('MabeEnumTest\TestAsset\EnumBasic');
780+
$set2->attach(EnumBasic::TWO);
781+
$set2->attach(EnumBasic::THREE);
782+
$set2->attach(EnumBasic::FOUR);
783+
784+
$set3 = new EnumSet('MabeEnumTest\TestAsset\EnumBasic');
785+
$set3->attach(EnumBasic::THREE);
786+
$set3->attach(EnumBasic::FOUR);
787+
$set3->attach(EnumBasic::FIVE);
788+
789+
$rs = $set1->symDiff($set2, $set3);
790+
$this->assertSame(array(
791+
EnumBasic::ONE,
792+
EnumBasic::FOUR,
793+
EnumBasic::FIVE,
794+
), $rs->getValues());
795+
}
796+
797+
public function testSymDiffThrowsInvalidArgumentException()
798+
{
799+
$set1 = new EnumSet('MabeEnumTest\TestAsset\EnumBasic');
800+
$set2 = new EnumSet('MabeEnumTest\TestAsset\Enum32');
801+
802+
$this->setExpectedException('InvalidArgumentException');
803+
$set1->symDiff($set2);
804+
}
675805
}

0 commit comments

Comments
 (0)