name=$name;
$this->type=$type;
}
//Получить PDO тип
function getPDOType()
{
if($this->type==TCField::$BD_UINT1) return PDO::PARAM_BOOL;
if($this->type==TCField::$BD_INT4) return PDO::PARAM_INT;
if($this->type==TCField::$BD_INT8) return PDO::PARAM_INT;
if($this->type==TCField::$BD_FLOAT4) return PDO::PARAM_STR;
if($this->type==TCField::$BD_FLOAT8) return PDO::PARAM_STR;
if($this->type==TCField::$BD_UTF8_1) return PDO::PARAM_STR;
if($this->type==TCField::$BD_UTF8_2) return PDO::PARAM_STR;
if($this->type==TCField::$BD_UTF8_4) return PDO::PARAM_STR;
if($this->type==TCField::$BD_BLOB_4) return PDO::PARAM_LOB;
return PDO::PARAM_STR;
}
//Прочитать значение из файла в соответствии с типом
function ReadValue($fileHandle)
{
if($this->type==TCField::$BD_UINT1)
{ $this->value=fread($fileHandle, 1);
}else
if($this->type==TCField::$BD_UINT2)
{ $this->value=fread($fileHandle, 2);
}else
if($this->type==TCField::$BD_UINT4)
{ $this->value=fread($fileHandle, 4);
}else
if($this->type==TCField::$BD_INT1)
{ $this->value=fread($fileHandle, 1);
}else
if($this->type==TCField::$BD_INT2)
{ $this->value=fread($fileHandle, 2);
}else
if($this->type==TCField::$BD_INT4)
{ $this->value=fread($fileHandle, 4);
}else
if($this->type==TCField::$BD_INT8)
{ $this->value=fread($fileHandle, 8);
}else
if($this->type==TCField::$BD_FLOAT4)
{ $this->value=fread($fileHandle, 4);
}else
if($this->type==TCField::$BD_FLOAT8)
{ $this->value=fread($fileHandle, 8);
}else
if($this->type==TCField::$BD_UTF8_1)
{ $s=getBin('C',fread($fileHandle, 1));
if($s==0) $this->value='';
else $this->value=fread($fileHandle, $s);
}else
if($this->type==TCField::$BD_UTF8_2)
{ $s=getBin('S',fread($fileHandle, 2));
if($s==0) $this->value='';
else
{ //В цикле так как из зип потока читало порциями
$this->value='';
while($s>strlen($this->value))
$this->value.=fread($fileHandle, $s-strlen($this->value));
}
}else
if($this->type==TCField::$BD_UTF8_4)
{ $s=getBin('I',fread($fileHandle, 4));
if($s==0) $this->value='';
else
{ //В цикле так как из зип потока читало порциями
$this->value='';
while($s>strlen($this->value))
$this->value.=fread($fileHandle, $s-strlen($this->value));
}
}else
if($this->type==TCField::$BD_BLOB_4)
{ $s=getBin('I',fread($fileHandle, 4));
if($s==0) $this->value='';
else
{ //В цикле так как из зип потока читало порциями
$this->value='';
while($s>strlen($this->value))
$this->value.=fread($fileHandle, $s-strlen($this->value));
}
}
}
function pack($value)
{
if($value===NULL){ return NULL; }
if($this->type==TCField::$BD_UINT1)
{ return pack("C",$value);
}else
if($this->type==TCField::$BD_UINT2)
{ return pack("S",$value);
}else
if($this->type==TCField::$BD_UINT4)
{ return pack("I",$value);
}else
if($this->type==TCField::$BD_INT1)
{ return pack("c",$value);
}else
if($this->type==TCField::$BD_INT2)
{ return pack("s",$value);
}else
if($this->type==TCField::$BD_INT4)
{ return pack("i",$value);
}else
if($this->type==TCField::$BD_INT8)
{
/*$str='0000000000000000000000000000000000000000000000000000000000000000'.decbin($value); //TODO decbin c 64 битами не работает на 32 битном php только 32 unpack('H*', '01010101');
$str=substr($str,-64,64);
for($ii=0;$ii<8;$ii++)//побайтно записываем все 8 байт
{ $szRez=$szRez.pack("C",bindec(substr($str,-8,8)));
$str=substr($str,0,-8);
}*/
}else
if($this->type==TCField::$BD_FLOAT4)
{
$value=str_replace(',','.',$value); //Чтоб не зависело от настроек оракла
return pack("f",$value);
}else
if($this->type==TCField::$BD_FLOAT8)
{
$value=str_replace(',','.',$value); //Чтоб не зависело от настроек оракла
return pack("d",$value);
}else
if($this->type==TCField::$BD_UTF8_1)
{ //$str=iconv('WINDOWS-1251', 'UTF-8', $value);
return pack("C",strlen($value)).$value;
}else
if($this->type==TCField::$BD_UTF8_2)
{ //$str=iconv('WINDOWS-1251', 'UTF-8', $value);
return pack("S",strlen($value)).$value;
}else
if($this->type==TCField::$BD_UTF8_4)
{ //$str=iconv('WINDOWS-1251', 'UTF-8', $value);
return pack("I",strlen($value)).$value;
}else
if($this->type==TCField::$BD_BLOB_4)
{ return pack("I",strlen($value)).$value;
}
}
function setValue($value) //пакуем данные в соответствии с типом
{
$this->value=$this->pack($value);
}
//Распаковываем данные в соответствии с типом
function getValue()
{
if($this->value===NULL) return NULL;
if($this->type==TCField::$BD_UINT1)
{ return getBin ("C", $this->value);
}else
if($this->type==TCField::$BD_UINT2)
{ return getBin ("S", $this->value);
}else
if($this->type==TCField::$BD_UINT4)
{ return getBin ("I", $this->value);
}else
if($this->type==TCField::$BD_INT1)
{ return getBin ("c", $this->value);
}else
if($this->type==TCField::$BD_INT2)
{ return getBin ("s", $this->value);
}else
if($this->type==TCField::$BD_INT4)
{ return getBin ("i", $this->value);
}else
if($this->type==TCField::$BD_INT8)
{ //return getBin ("S", $this->value);
}else
if($this->type==TCField::$BD_FLOAT4)
{ return getBin ("f", $this->value);
}else
if($this->type==TCField::$BD_FLOAT8)
{ return getBin ("d", $this->value);
}else
if($this->type==TCField::$BD_UTF8_1 || $this->type==TCField::$BD_UTF8_2 || $this->type==TCField::$BD_UTF8_4)
{ return $this->value;
}else
if($this->type==TCField::$BD_BLOB_2 || $this->type==TCField::$BD_BLOB_4)
{ return $this->value;
}
return '';
}
}
class TCTable
{
public $id=0; //Идентификатор таблицы
public $name=''; //Название таблицы
public $fields = array(); //Массив полей
private $nc=0; //Байтов под NULL значения
private $m_NULL; //NULL значения
private $m_file;
/**
* Конструктор
* @param Строка $name Название таблицы
* @param Целое $id Идентификатор таблицы
*/
function TCTable($name,$id)
{ $this->name=$name;
$this->id=$id;
}
//Открыть таблицу по названию файла
function OpenTableF($file)
{
if(file_exists($file))
{
$this->OpenTableH(fopen($file,'r'));
}
}
//Открыть таблицу из HANDLE (файла)
function OpenTableH($handle)
{
$this->m_file=$handle;
if(getBin('S',fread($this->m_file, 2))!=65500) return false; //id файла
if(getBin('S',fread($this->m_file, 2))!=1) return false; //Версия файла
$this->id=getBin('I',fread($this->m_file, 4)); //ID таблицы или запроса (4 байта можно сделать 2)
if(getBin('C',fread($this->m_file, 1))!=0) return false; //Только плотные таблицы
$this->name=fread($this->m_file, getBin('C',fread($this->m_file, 1))); //Название таблицы
//Считываем столбцы
$count=getBin('C',fread($this->m_file, 1)); //Количество столбцов
for($i=0;$i<$count;$i++)
{
$field=new TCField (fread($this->m_file, getBin('C',fread($this->m_file, 1))),getBin('C',fread($this->m_file, 1)));
$this->addField($field);
//echo $field->name.'
';
}
return true;
}
//Открыть таблицу из потока
//OpenTable
//Прочитать следующую запись из таблицы
function ReadNextRecord()
{
if(feof($this->m_file)) return; //Неработает
$this->m_NULL='';
for($j=0;$j<$this->nc;$j++) //Побайтно
{
$v=fread($this->m_file, 1);
if(strlen($v)==0) return; //Проверка конца файла
$v=getBin('C',$v);
$v=decbin($v);
for($i=strlen($v);$i<8;$i++) $v='0'.$v;
$this->m_NULL.=$v;
}
$this->clearRows();
for($i=0;$ifields);$i++)
{
if($this->m_NULL[$i]=="1")
{
$this->fields[$i]->ReadValue($this->m_file);
}
}
return true;
}
//Добавить поле к таблице
function addField($field)
{ if($field!=NULL)
{ $this->fields[]=$field;
$this->nc=ceil(count($this->fields)/8.0); //Байтов под NULL
}
}
//Получить заголовок плотной таблицы в виде двоичной строки
function getHeader()
{
$szRez=''; //Данные из таблицы в двоичном формате
$szRez=$szRez.pack("S",65500); //id файла (2 байта)
$szRez=$szRez.pack("S",1); //Версия файла (2 байта)
$szRez=$szRez.pack("I",$this->id); //ID таблицы или запроса (4 байта)
$szRez=$szRez.pack("C",0); //Тип таблицы 0-"Плотная" 1-"Мягкая" (1 байт)
$szRez=$szRez.pack("C",strlen($this->name)).$this->name; //UTF8_1 строка
$szRez=$szRez.pack("C",count($this->fields)); //Колво столбцов (1 байт)
//Записываем id типов столбцов
for($i=0;$ifields);$i++)
{
$szRez.=pack("C",strlen($this->fields[$i]->name)).$this->fields[$i]->name;
$szRez.=pack("C",$this->fields[$i]->type);
}
return $szRez;
}
//Получить данные 1 записи в виде строки
function getCol()
{ $szRez='';
//Запишем NULL значения побайтно (1-есть данные 0-нету данных)
$str='';
for($i=0;$i<$this->nc*8;$i++)
{
if($i>=count($this->fields)) $str.='0'; else
if($this->fields[$i]->value===NULL) $str.='0'; else $str.='1';
if(strlen($str)==8)
{ $szRez=$szRez.pack("C",bindec($str));
$str='';
}
}
//Запишем сами данные в строку
for($i=0;$ifields);$i++)
{
$szRez.=$this->fields[$i]->value;
}
return $szRez;
}
//Row очистить запись
function clearRows()
{ for($i=0;$ifields);$i++)
{ $this->fields[$i]->value=null;
}
}
//Получить обьект столбца по имени
function getRowByName($name)
{ for($i=0;$ifields);$i++)
{ if($this->fields[$i]->name==$name) return $this->fields[$i];
}
}
//Получить объект столбца по номеру
function getRowByNum($num)
{ return $this->fields[$num];
}
}
?>