Cache.php
<?php
namespace Tlf\LexerTrait;
/**
* Handles caching of asts & grammar lists
*/
trait Cache {
/**
* Static cache so different instances of Lexer don't use all the memory, since cacheMap files are fairly large.
*/
static protected $_cacheMap;
/**
* Copy of .cache/map.json
*/
protected $cacheMap = null;
public function getCachedAst($filePath){
if ($this->useCache===false)return false;
$cacheDir = dirname(__DIR__, 2).'/.cache/';
if (!is_file($cacheDir.'/map.json'))return false;
$this->cacheMap = &static::$_cacheMap[$cacheDir.'/map.json'];
if ($this->cacheMap == null){
// $mem = memory_get_usage();
// $max = ini_get('memory_limit');
// $filesize = filesize($cacheDir.'/map.json');
// ob_end_clean();
//
// echo "\n\n";
// var_dump("Mem: $mem ");
// var_dump("Max: $max");
// var_dump("File: $filesize");
// echo "\n\n";
//
// string(12) "Mem: 645656 "
// string(9) "Max: 128M"
//string(12) "File: 139698"
// exit;
$content = file_get_contents($cacheDir.'/map.json');
$this->cacheMap = json_decode($content,true);
}
if (!isset($this->cacheMap['files'][$filePath]))return false;
$file = $this->cacheMap['files'][$filePath];
if (sha1_file($filePath)!=$file['sha1'])return false;
$grammarList = $this->getGrammarListForCache();
if ($grammarList != $file['grammarList']) return false;
$astTree = include($file['cachedAstPath']);
if (!is_array($astTree))return false;
$ast = new \Tlf\Lexer\Ast('file');
$ast->setTree($astTree);
return $ast;
}
public function cacheFileAst($filePath, $ast){
if ($this->useCache===false)return;
$tree = $ast->getTree();
$cacheDir = dirname(__DIR__, 2).'/.cache/';
if (!is_dir($cacheDir))mkdir($cacheDir);
if (!is_dir($cacheDir.'/fileast/'))mkdir($cacheDir.'/fileast/');
if (!is_file($cacheDir.'/map.json'))file_put_contents($cacheDir.'/map.json',json_encode([]));
$map = $this->cacheMap ?? json_decode(file_get_contents($cacheDir.'/map.json'),true);
if (isset($map['files'][$filePath]['cachedAstPath'])){
if (is_file($cachedPath = $map['files'][$filePath]['cachedAstPath'])){
unlink($cachedPath);
}
}
$map['files'][$filePath]['sha1'] = sha1_file($filePath);
$map['files'][$filePath]['grammarList'] = $this->getGrammarListForCache();
if (!is_dir($cacheDir.'/fileast'))mkdir($cacheDir.'/fileast');
$cachedAstPath = $cacheDir.'/fileast/'.uniqid().'.php';
$map['files'][$filePath]['cachedAstPath'] = $cachedAstPath;
file_put_contents($cachedAstPath,
'<?php return '
. var_export($tree,true)
.';'
);
$this->cacheMap = $map;
file_put_contents($cacheDir.'/map.json', json_encode($map, JSON_PRETTY_PRINT));
}
public function getGrammarListForCache(){
if ($this->grammarListForCache!=null)return $this->grammarListForCache;
$grammarList = [];
foreach ($this->grammars as $g){
$grammarList[get_class($g)] = filemtime((new \ReflectionClass($g))->getFileName());
}
ksort($grammarList);
$this->grammarListForCache = $grammarList;
return $grammarList;
}
}