Adding Buffer::append()
Another simple helper method.
Hi - cheers for the pull request!
The Buffer class is currently immutable, as it's pretty much Parsers job to prepare a buffer like that. Is there a use case that Parser can't already fulfill?
Also, i'm not sure how this interacts with getBinary() (https://github.com/Bit-Wasp/buffertools-php/blob/master/src/Buffertools/Buffer.php#L142) - Let me think about this some more and get back to you.
PS: I think there's a performance improvement to be gained from the code, especially if calling it a lot (if $other instanceof self, do private property access), which I roughly benchmarked in the below snippet. I need to think more about getBinary (or not to direct property access for the string to allow getBinary to do it's job)
<?php
interface BufI {
public function getDat(): string;
public function getSize(): int;
public function append(BufI $other): BufI;
}
trait FuncMethod {
public function append(BufI $other): BufI {
return new ObjFunc($this->getDat() . $other->getDat(), $this->getSize() + $other->getSize());
}
}
trait PropMethod {
public function append(BufI $other): BufI {
// assumes $other is actually self too.
return new ObjProp($this->val . $other->val, $this->size+$other->size);
}
}
trait FavorSelfMethod {
public function append(BufI $other): BufI {
if ($other instanceof self) {
return new ObjOptimistic($this->val . $other->val, $this->size + $other->size);
}
return new ObjOptimistic($this->getDat() . $other->getDat(), $this->getSize() + $other->getSize());
}
}
abstract class Obj implements BufI {
protected $val;
protected $size;
public function __construct(string $val, int $size) {
$this->val = $val;
$this->size = $size;
}
public function getSize(): int {
return $this->size;
}
public function getDat(): string {
return $this->val;
}
}
class ObjFunc extends Obj {
use FuncMethod;
}
class ObjProp extends Obj {
use PropMethod;
}
class ObjOptimistic extends Obj {
use FavorSelfMethod;
}
function test(int $runs, BufI $a, BufI $b) {
$t = 0;
for ($i = 0; $i < $runs; $i++) {
$s = microtime(true);
$a->append($b);
$diff = microtime(true) - $s;
$t += $diff;
}
return $t;
}
for ($j = 1; $j < 32; $j++) {
$runs = 2 << $j;
echo "runs: {$runs}\n";
$t1 = test($runs, new ObjFunc("A", 1), new ObjFunc("BB", 2));
$t2 = test($runs, new ObjProp("A", 1), new ObjProp("BB", 2));
$t3 = test($runs, new ObjOptimistic("A", 1), new ObjOptimistic("BB", 2));
echo "ObjFunc " . $t1 . PHP_EOL;
echo "ObjProp " . $t2 . PHP_EOL;
echo "ObjOptimistic " . $t3 . PHP_EOL;
echo "------------------------\n";
}
Parser could sure do this. you could always use:
$a = $a->concat($b); // Buffertools::concat($a, $b)
That exist in PR #89
So this method is just "nice to have". About getBinary() i think it's fine, if i have 2 buffers with let say 16 byte length. appending one to the other would set the length to 32 (and pad each 16 byte block if needed). whould be the same as $a = Buffertools::concat($a, $b)?