Last active
January 1, 2019 18:34
-
-
Save helloanoop/c94e214290a63e0a479b67a1fbbffda6 to your computer and use it in GitHub Desktop.
Revisions
-
helloanoop revised this gist
Jan 1, 2019 . No changes.There are no files selected for viewing
-
helloanoop created this gist
Jan 1, 2019 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,139 @@ <?php class Database { /** * Storage * @var array */ protected $database = array(); /** * Transactions * @var array */ protected $transactions = array(); /** * Value usage counter * @var array */ protected $valueUsage = array(); /** * Set value * @param $name * @param bool $value */ protected function setValue($name,$value=false) { if(isset($this->database[$name])) { $this->valueUsage[$this->database[$name]] -= 1; unset($this->database[$name]); } if ($value) { $this->database[$name] = $value; // IDEA: if values are mostly large, we can keep their hashes as $valueUsage key $this->valueUsage[$value] = isset($this->valueUsage[$value]) ? $this->valueUsage[$value] + 1 : 1; } } /** * Keep records about value change * @param $name */ protected function addTransactionChange($name) { if ($this->transactions) { $lastTransaction = end($this->transactions); if (!isset($lastTransaction[$name])) { $this->transactions[key($this->transactions)][$name] = $this->get($name); } } } /** * Open a transactional block */ public function begin() { array_push($this->transactions, array()); } /** * Rollback all of the commands from the most recent transaction block * * @throws Exception */ public function rollback() { if ($this->transactions) { $lastTransaction = end($this->transactions); foreach($lastTransaction as $name => $value) { $this->setValue($name,$value); } unset($this->transactions[key($this->transactions)]); } else { throw new Exception("INVALID ROLLBACK"); } } /** * Permanently store all of the operations from any presently open transactional blocks */ public function commit() { $this->transactions = array(); } /** * Return the value stored under the variable $name * @param $name * @return string */ public function get($name) { return isset($this->database[$name]) ? $this->database[$name] : 'null'; } /** * Set variable * @param $name * @param $value */ public function set($name,$value) { $this->addTransactionChange($name); $this->setValue($name,$value); } /** * Unset variable * @param $name */ public function delete($name) { $this->addTransactionChange($name); $this->setValue($name); } /** * Returns the number of variables equal to $value * @param $value * @return int */ public function numEqualTo($value) { return isset($this->valueUsage[$value]) ? $this->valueUsage[$value] : 0; } } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,55 @@ <?php require_once('database.php'); $database = new Database(); if(!defined('STDIN')) define('STDIN', fopen('php://stdin', 'r')); if(!defined('STDOUT')) define('STDOUT', fopen('php://stdout', 'w')); if(!defined('STDERR')) define('STDERR', fopen('php://stderr', 'w')); fwrite(STDOUT, "\nHey! Program will terminate on command 'END'\n\n"); $data = array(); do { $command = trim(fgets(STDIN)); $data[] = explode(' ', $command); } while ($command != 'END'); fwrite(STDOUT, "-- OUTPUT --\n"); try { foreach ($data as $cmd) { switch ($cmd[0]) { case 'BEGIN': $database->begin(); break; case 'ROLLBACK': $database->rollback(); break; case 'COMMIT': $database->commit(); break; case 'GET': echo $database->get($cmd[1])."\n"; break; case 'SET': $database->set($cmd[1],@$cmd[2]); break; case 'UNSET': $database->delete($cmd[1]); break; case 'NUMEQUALTO': echo $database->numEqualTo($cmd[1])."\n"; break; case 'END': exit(0); break; default: fwrite(STDOUT, "There is no command $cmd[0]!\n"); exit(0); break; } } } catch(Exception $e) { fwrite(STDOUT, $e->getMessage()); }