Skip to content

Commit

Permalink
Merge tag 'v1.3.0'
Browse files Browse the repository at this point in the history
Version 1.3.0

# -----BEGIN PGP SIGNATURE-----
#
# iHUEABEIAB0WIQTO9r3W4mXrlJ9beRrI8be4WVvGzgUCYK42bgAKCRDI8be4WVvG
# zm7hAP9iIV+MgXgatm9YMrzOWlU9MT/LOdOfx5/3rJOmupJaMAD/XuWF6eV0jaau
# k+8wkLABq4GfqUriyinJxVgzCWVeOCo=
# =Bdnx
# -----END PGP SIGNATURE-----
# gpg: Signature made Wed May 26 13:52:14 2021 CEST
# gpg:                using DSA key CEF6BDD6E265EB949F5B791AC8F1B7B8595BC6CE
# gpg: conversion from 'utf-8' to 'US-ASCII' failed: Illegal byte sequence
# gpg: Good signature from "Jakub Bou\xc4\x8dek <pan@jakubboucek.cz>" [ultimate]
# gpg:                 aka "Jakub Bou\xc4\x8dek <jakub.boucek@redbit.cz>" [ultimate]
# gpg:                 aka "keybase.io/jakubboucek (Keybase) <jakubboucek@keybase.io>" [ultimate]
  • Loading branch information
jakubboucek committed May 26, 2021
2 parents a2976af + c8232c5 commit eed5b81
Show file tree
Hide file tree
Showing 12 changed files with 543 additions and 2 deletions.
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2021 Redbit s.r.o.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
131 changes: 131 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# Redbit Utils

Lightweight utilities for logging, IO, and Unix-like process signal

## Installation

Install via Composer:

```shell
composer install redbitcz/utils
```

## Requirements
Package requires PHP version 7.3 and above.

For handling Unix-like process signals requires the `pcntl` and `posix` PHP extensions. Without that support
related method call will be siletly ignored.

## Usage

### `Logger`

The `\Redbitcz\Utils\Log\Logger` class is implementation of PSR-3 logger interface and it decorates each
logger record with time and log severity name.

Example:
```
[2021-05-05 11:49:36] Logged message 1
[2021-05-05 11:49:38] Another logged message
```

Logger requires Writer `\Redbitcz\Utils\IO\IOutStream` instance. Package contains few several types
of Writer implementations which are different by the log target (console, general output, standard output, HTML output,
or file).

See [`Logger` example](examples/log/output-logger.php).

### `Progress`
The `\Redbitcz\Utils\Log\Progress` class is simple generator of progress status to reporting progress of operations.
In additive is added the time spent is each step and whole operation.

Example:
```shell
[2021-05-05 10:40:06] DEBUG: [ 0.000s/ 0.000] step 1/9: Logged step 1
[2021-05-05 10:40:06] DEBUG: [ 0.000s/ 0.000] step 2/9: Another logged message
[2021-05-05 10:40:06] DEBUG: [ 0.371s/ 0.371] step 3/9: Foo
[2021-05-05 10:40:10] DEBUG: [ 3.900s/ 4.271] step 4/9: Bar
[2021-05-05 10:40:10] DEBUG: [ 0.000s/ 4.271] step 5/9: Foo Bar
[2021-05-05 10:40:10] DEBUG: [ 0.000s/ 4.271] step 6/9: Foo Baz
[2021-05-05 10:40:10] DEBUG: [ 0.000s/ 4.271] step 7/9: Foo comes to the Bar
[2021-05-05 10:40:11] DEBUG: [ 0.212s/ 4.483] step 8/9: Hey Donald, get off that chandelier!
[2021-05-05 10:40:11] DEBUG: [ 0.001s/ 4.484] step 9/9: All Done
```
See [`Progress` example](examples/log/progress.php).

### `ProcessTerminationLock`

The `\Redbitcz\Utils\Process\ProcessTerminationLock` class is simple mechanism how to prevent (rspt. delay) unexpected
exit of PHP process during operation processing. It's recommended to workers to prevent break during processing a job
and similar usage in processes managed by a Process Control system (`systemd`, `supervisor`, etc.).

Example:

```php
while(true) {
$job = $worker->waitToJob();

ProcessTerminationLock::lock(); // Lock termination to prevent break job processing

//... long job processing

ProcessTerminationLock::unlock(); // Unlock
}
```
See [`ProcessTerminationLock` example](examples/process/termination-lock.php).

### `BitwiseVariator`
Classes in `\Redbitcz\Utils\Bitwise` namespace provides filtered bit variations generator over
[Bitwise values](https://en.wikipedia.org/wiki/Bitwise_operation).

That mean, when you have bits `1011`, variator generates all bits variations.

```php
$variations = BitwiseVariator::create(0b1011)->variate();
```

| Variation for bits `1011` |
|--------------------------:|
| `0000` |
| `0001` |
| `0010` |
| `0011` |
| `1000` |
| `1001` |
| `1010` |
| `1011` |

#### Filters

`BitwiseVariator` class provide filter to select variations with(out) some bits only.

```php
$variations = BitwiseVariator::create(0b1011)->must(0b0010)->variate();
```

| Variation for bits `1011` with bite `0010` |
|-------------------------------------------:|
| `0010` |
| `0011` |
| `1010` |
| `1011` |


```php
$variations = BitwiseVariator::create(0b1011)->mustNot(0b0010)->variate();
```

| Variation for bits `1011` without bite `0010` |
|----------------------------------------------:|
| `0000` |
| `0001` |
| `1000` |
| `1001` |

## License
The MIT License (MIT). Please see [License File](LICENSE) for more information.

## Contact
Redbit s.r.o. - @redbitcz - info@redbit.cz


4 changes: 4 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
{
"name": "Martin Dostál",
"email": "martin.dostal@redbit.cz"
},
{
"name": "Jakub Bouček",
"email": "jakub.boucek@redbit.cz"
}
],
"require": {
Expand Down
28 changes: 28 additions & 0 deletions examples/bitwise/bitwise-variator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);

use Redbitcz\Utils\Bitwise\BitwiseVariator;

require_once __DIR__ . '/../../vendor/autoload.php';

echo "Variations of 1011 ===================================\n";
$variations = BitwiseVariator::create(0b1011)->variate();
foreach ($variations as $i => $variation) {
echo sprintf("% 2s. variation: %04s (decimal: % 3s)\n", $i+1, decbin($variation), $variation);
}

echo "\nVariations of 1011 with bit 0010 =====================\n";
$variations = BitwiseVariator::create(0b1011)->must(0b0010)->variate();
foreach ($variations as $i => $variation) {
echo sprintf("% 2s. variation: %04s (decimal: % 3s)\n", $i+1, decbin($variation), $variation);
}

echo "\nVariations of 1011 without bit 0010 ==================\n";
$variations = BitwiseVariator::create(0b1011)->mustNot(0b0010)->variate();
foreach ($variations as $i => $variation) {
echo sprintf("% 2s. variation: %04s (decimal: % 3s)\n", $i+1, decbin($variation), $variation);
}



1 change: 0 additions & 1 deletion examples/pcntl/async-signal.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
<?php
/** @noinspection PhpComposerExtensionStubsInspection (because Windows) */

declare(strict_types=1);

Expand Down
3 changes: 2 additions & 1 deletion phpstan.neon
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
parameters:
excludes_analyse:
- 'tests/Pcntl/*' # because crashes PhpStan
- 'tests/Process/*' # because crashes PhpStan
- 'tests/Process/*' # because crashes PhpStan
- 'tests/Bitwise/*' # because test with too deep recurtion over data structures
49 changes: 49 additions & 0 deletions src/Bitwise/BitwiseFilter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

declare(strict_types=1);

namespace Redbitcz\Utils\Bitwise;

abstract class BitwiseFilter
{
/** @var int */
private $filter = 0;

/** @var int */
private $values = 0;

/**
* @param int $bite
* @return static
*/
public function must(int $bite): self
{
$this->filter |= $bite;
$this->values |= $bite;
return $this;
}

/**
* @param int $bite
* @return static
*/
public function mustNot(int $bite): self
{
$this->filter |= $bite;
$this->values &= ~$bite;
return $this;
}

public function getFilter(): int
{
return $this->filter;
}

/**
* @return int[]
*/
public function getValues(): array
{
return [$this->values];
}
}
61 changes: 61 additions & 0 deletions src/Bitwise/BitwiseVariator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

declare(strict_types=1);

namespace Redbitcz\Utils\Bitwise;

class BitwiseVariator
{
/** @var int */
private $bits;

public static function create(int $bits): BitwiseVariatorFilter
{
return (new self($bits))->filter();
}

public function __construct(int $bits)
{
$this->bits = $bits;
}

public function filter(): BitwiseVariatorFilter
{
return new BitwiseVariatorFilter($this);
}

/**
* @param int $filter
* @param int[] $values
* @return int[]
*/
public function variate(int $filter, array $values): array
{
$filter &= $this->bits;
$cleaner = static function ($value) use ($filter) {
return $value & $filter;
};
$values = array_map($cleaner, $values);
$qbits = $this->bits & ~$filter;

$variations = $values;
for ($weight = 1; $weight <= $qbits; $weight <<= 1) {
$bit = $qbits & $weight;
if ($bit) {
foreach ($variations as $variation) {
$variations[] = $variation | $bit;
}
}
}
return $variations;
}

/**
* @return int
* @internal
*/
public function getBits(): int
{
return $this->bits;
}
}
29 changes: 29 additions & 0 deletions src/Bitwise/BitwiseVariatorFilter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

declare(strict_types=1);

namespace Redbitcz\Utils\Bitwise;

class BitwiseVariatorFilter extends BitwiseFilter
{
/** @var BitwiseVariator */
protected $variator;

public function __construct(BitwiseVariator $variator)
{
$this->variator = $variator;
}

public function or(): BitwiseVariatorFilterLogicOr
{
return new BitwiseVariatorFilterLogicOr($this->variator, $this);
}

/**
* @return int[]
*/
public function variate(): array
{
return $this->variator->variate($this->getFilter(), $this->getValues());
}
}
34 changes: 34 additions & 0 deletions src/Bitwise/BitwiseVariatorFilterLogicOr.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

declare(strict_types=1);

namespace Redbitcz\Utils\Bitwise;

class BitwiseVariatorFilterLogicOr extends BitwiseVariatorFilter
{
/** @var BitwiseVariatorFilter */
private $previous;

public function __construct(BitwiseVariator $variator, BitwiseVariatorFilter $previous)
{
parent::__construct($variator);
$this->previous = $previous;
}

public function getFilter(): int
{
return parent::getFilter() | $this->previous->getFilter();
}

/**
* @return int[]
*/
public function getValues(): array
{
$variator = new BitwiseVariator($this->getFilter() & $this->variator->getBits());

$meVariations = $variator->variate(parent::getFilter(), parent::getValues());
$prevVariations = $variator->variate($this->previous->getFilter(), $this->previous->getValues());
return array_unique(array_merge($meVariations, $prevVariations));
}
}
Loading

0 comments on commit eed5b81

Please sign in to comment.