Ferreteria/v0.6/clade/IO/Aspect/Connx/Buffer

From Woozle Writes Code
< Ferreteria‎ | v0.6‎ | clade‎ | IO‎ | Aspect‎ | Connx
Jump to navigation Jump to search
clade: IO\Aspect\Connx\Buffer
Clade Family
Connx Buffer
Clade Aliases
Alias Clade
Base* IO\Aspect\Connx
Subpages

About

  • Purpose: buffer system base class
    • For now, I'm implementing this as minimally as possible.
    • The idea is that podling classes can:
      • add other functionality which gets exceuted on Put/Get (e.g. update reporting).
      • implement more efficient buffering, maybe.
      • Might we want to be able to limit the number of bytes fetched by RemoveBytes()? Maybe later.

History

  • 2024-11-24 started
  • 2025-03-13 at first I removed HasBytes(), but (long story short) I really just need to clearly define what all these pieces are for before I can straighten anything out.
    • Functionality needed (with entity names as I work them out):
      • AvailBuffByteCount(): number of bytes available to read out from buffer (data buffered)
      • AvailSrceByteCount(): number of bytes available to read into buffer (data source), if available
      • IsMore() flag to indicate that the source is not permanently empty
        • (either there's more to read, or we expect there will be -- i.e. not EoF)
        • (for writing purposes, this could instead indicate that there's room to write)
      • SpentByteCount() (UI): number of bytes processed so far
      • RemoveBytes() (Action): fetch bytes from buffer (fill buffer if empty)
  • 2025-03-28 moved from [WFe]IO ⇒ [WFe]IO\Connx and re-parented to xConnx
  • 2025-12-16 changed storage of spent-bytes-counter from $nSpent to $qnSpent; removed IncSpentBytes(int $n) and added QNSpent().

Code

interface iBuffer extends BaseIface {
    // COUNTERS
    function AvailByteCount() : int;   // bytes currently remaining (buffered + source)
    function SpentByteCount() : int;  // bytes already processed/transferred (read or written)
    // ACCESS
    function RewindAll() : void;        // reset to beginning of input or output file
    function AppendBytes(string $s);    // write bytes into buffer
    function &CurrentBytes() : string;  // get reference to currently available bytes
    function DiscardBytes(int $nBytes); // remove $nBytes bytes from the buffer
    function RemoveBytes() : string;    // read bytes out of buffer
    function RestoreBytes(string $s);   // put bytes back into buffer (this is a bit of a kluge, I guess...)
    function IsMore() : bool;           // there is more to read (or room to write to, I guess?)
}
abstract class caBuffer extends BaseClass implements iBuffer {

    // ++ CONFIG ++ //

    protected function InspectorClass() : string { return ViewClass::class; }

    // -- CONFIG -- //
    // ++ ACCESS ++ //

    protected $sBuff;
    protected function AvailBuffByteCount() : int {    // bytes available to read from buffer
        return strlen($this->sBuff);
    }
    protected function AvailSrceByteCount() : int { echo self::PromptForMethod(); }   // bytes currently remaining to read from source

    // RETURNS: {bytes in buffer} + {size of file} - {bytes already read from file}
    public function AvailByteCount() : int { return $this->AvailBuffByteCount() + $this->AvailSrceByteCount() - $this->SpentByteCount(); }

    // ++ ACCESS: tracking ++ //

    private $qnSpent = NULL;
    public function QNSpent() : QIntIface { return $this->qnSpent ?? ($this->qnSpent = QIntClass::AsNew()); }
    public function SpentByteCount() : int { return $this->QNSpent()->GetItNz(); }

    // ++ ACCESS: info ++ //

    public function IsMore() : bool { return $this->AvailByteCount() > 0; } // assumes static file

    // ++ ACCESS: R/W ++ //

    public function RewindAll() : void { $this->nSpent = 0; $this->sBuff = ''; }

    // TODO: rename to something better
    public function AppendBytes(string $s) {
        $this->ErrorIfShut('write to');
        #if (!$this->IsOpen()) {
        #    $id = $this->ObjectID();
        #    self::ThrowHissy("Writing to buffer (id$id) before it has been opened.");
        #}

        $this->sBuff .= $s;
        #self::GotToHere();
    }
    protected function AddBytesForFetch(string $s) { $this->sBuff .= $s; }

    public function &CurrentBytes() : string { return $this->sBuff; }
    public function DiscardBytes(int $nBytes) {
        $this->sBuff = substr($this->sBuff,$nBytes);  // remove $nBytes from the buffer
        $this->QNSpent()->AddIt($nBytes);                       // increment the "spent bytes" counter
    }

    // TODO: rename to something better
    public function RemoveBytes() : string {
        $this->ErrorIfShut('read from');
        $sOut = $this->sBuff;
        $nLen = strlen($sOut);
        $this->nSpent += $nLen;
        $this->sBuff = '';
        return $sOut;
    }
    public function RestoreBytes(string $s) {
        $this->nSpent -= strlen($s);
        $this->sBuff = $s.$this->sBuff; // restore $s to beginning of buffer
    }
    protected function ErrorIfShut(string $sAction) {
        if (!$this->IsOpen()) {
            $id = $this->ObjectID();
            self::ThrowHissy("Trying to $sAction closed buffer (id$id).");
        }
    }

    // -- ACCESS -- //
    // ++ UI OUTPUT ++ //

    public function DescribeInline() : string { return $this->StatusLine(); }

    // DEBUGGING, mainly
    public function StatusLine() : string {
        $sID = $this->ObjectID();
        $nBuff = $this->AvailBuffByteCount();
        $nSrce = $this->AvailSrceByteCount();
        $nSpent = $this->SpentByteCount();
        $sAlive = $this->IsOpen() ? 'OPEN' : 'SHUT';
        return "id$sID [$sAlive]: buff=$nBuff srce=$nSrce spent=$nSpent";
    }

    // -- UI OUTPUT -- //
}