Changeset 89 for trunk/dbc/dbc.php
- Timestamp:
- Feb 11, 2009, 7:49:33 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/dbc/dbc.php
r64 r89 1 1 <?php 2 2 3 class BinaryReader 4 { 5 private $handle; /// Handle na otevreny dbc soubor 6 7 /// Konstruktor 8 function __construct() 9 { 10 $this->handle = false; 11 } 12 13 /// Destruktor 14 function __destruct() 15 { 16 if ($this->handle) 17 fclose($this->handle); 18 } 19 20 public function loadFile($filename) 21 { 22 if ($this->handle) 23 fclose($this->handle); 24 25 $this->handle = @fopen($filename, "rb"); 26 if (!$this->handle) 27 die ("Soubor $filename neexistuje"); 28 } 29 30 /// Nacteni bytu 31 public function readByte() 32 { 33 return ord(fread($this->handle, 1)); 34 } 35 36 /// Nacteni unsigned int 37 public function readUint() 38 { 39 $val = unpack("V*", fread($this->handle, 4)); 40 return $val[1]; 41 } 42 43 /// Nacteni signed int 44 public function readInt() 45 { 46 $val = unpack("I*", fread($this->handle, 4)); 47 return $val[1]; 48 } 49 50 /// Nacteni float 51 public function readFloat() 52 { 53 $val = unpack("f*", fread($this->handle, 4)); 54 return $val[1]; 55 } 56 57 /// Nacteni znaku 58 public function readChar() 59 { 60 return fgetc($this->handle); 61 } 62 63 public function seekPos($pos, $type = SEEK_SET) 64 { 65 fseek($this->handle, $pos, $type); 66 } 67 } 3 include('stream.php'); 4 5 define('NOT_DBC_FILE', 'Není DBC soubor.'); 6 define('FIELD_COUNT_NOT_MATCH', 'Počet sloupců neodpovídá délce formátu.'); 7 define('RECORD_SIZE_NOT_MATCH', 'Velikost řádku neodpovídá zadanému formátu.'); 68 8 69 class DbcReader extends BinaryReader 70 { 71 private $offsets; /// Offsety jednotlivych poli 72 private $format; /// Format dbc souboru 73 74 private $recSize; /// Velikost jednoho zaznamu 75 private $recCount;/// Pocet zaznamu 76 private $strSize; /// Velikost string casti 77 private $fldCount;/// Pocet poli (v 1 zaznamu) 9 class DBCFile extends FileStream 10 { 11 private $HeaderSize = 20; 12 private $Offsets; 13 private $StringOffset; 14 private $StringList = array(); 15 private $StringListOffset = array(); 16 private $Format; 17 18 private $RecordSize; 19 private $RecordCount; 20 private $StringBlockSize; 21 private $FieldCount; 78 22 79 /// Nacteni dbc souboru 80 public function loadDbc($file, $format) 81 { 82 $this->loadFile($file); 23 public function OpenFile($FileName, $Format) 24 { 25 parent::OpenFile($FileName); 26 27 $this->Format = $Format; 28 if($this->ReadUint() != 0x43424457) die(NOT_DBC_FILE); 29 30 $this->RecordCount = $this->ReadUint(); 31 $this->FieldCount = $this->ReadUint(); 32 $this->RecordSize = $this->ReadUint(); 33 $this->StringBlockSize = $this->ReadUint(); 83 34 84 if ($this->readUint() != 0x43424457) 85 die ("NO DBC!"); 35 if(strlen($this->Format) != $this->FieldCount) 36 die(FIELD_COUNT_NOT_MATCH); 37 38 $this->GenerateOffsetTable($Format); 39 if($this->Offsets[count($this->Offsets) - 1] != $this->RecordSize) 40 die(RECORD_SIZE_NOT_MATCH.$this->Offsets[count($this->Offsets) - 1].' <> '.$this->RecordSize); 41 } 42 43 public function CreateFile($FileName, $Format) 44 { 45 parent::CreateFile($FileName); 46 47 $this->WriteUint(0x43424457); 86 48 87 $this->recCount = $this->readUint(); 88 $this->fldCount = $this->readUint(); 89 $this->recSize = $this->readUint(); 90 $this->strSize = $this->readUint(); 49 $this->StringList = array(); 50 $this->StringOffset = 1; 51 $this->Format = $Format; 52 $this->GenerateOffsetTable($Format); 53 $this->FieldCount = strlen($Format); 54 $this->RecordCount = 0; 55 $this->RecordSize = $this->Offsets[count($this->Offsets) - 1]; 56 $this->StringBlockSize = 0; 57 58 $this->WriteUint($this->RecordCount); 59 $this->WriteUint($this->FieldCount); 60 $this->WriteUint($this->RecordSize); 61 $this->WriteUint($this->StringBlockSize); 62 } 63 64 private function GenerateOffsetTable($Format) 65 { 66 $this->Offsets = array(); 67 $this->Offsets[0] = 0; 68 for($I = 0; $I < strlen($Format); $I++) 69 { 70 $this->Offsets[$I + 1] = $this->Offsets[$I]; 71 switch($Format[$I]) 72 { 73 case "b": 74 case "X": 75 $this->Offsets[$I + 1] += 1; 76 break; 77 case "x": 78 case "u": 79 case "i": 80 case "f": 81 case "s": 82 $this->Offsets[$I + 1] += 4; 83 break; 84 } 85 } 86 } 87 88 private function SeekPosi($Row, $Column) 89 { 90 $Position = $this->HeaderSize + $Row * $this->RecordSize + $this->Offsets[$Column]; 91 $this->Seek($Position); 92 } 93 94 public function GetByte($Row, $Column) 95 { 96 $this->SeekPosi($Row, $Column); 97 return($this->ReadByte()); 98 } 99 100 public function GetUint($Row, $Column) 101 { 102 $this->SeekPosi($Row, $Column); 103 return($this->ReadUint()); 104 } 105 106 public function GetInt($Row, $Column) 107 { 108 $this->SeekPosi($Row, $Column); 109 return($this->ReadInt()); 110 } 111 112 public function GetFloat($Row, $Column) 113 { 114 $this->SeekPosi($Row, $Column); 115 return($this->ReadFloat()); 116 } 117 118 public function SetByte($Row, $Column, $Value) 119 { 120 $this->SeekPosi($Row, $Column); 121 $this->WriteByte($Value); 122 } 123 124 public function SetUint($Row, $Column, $Value) 125 { 126 $this->SeekPosi($Row, $Column); 127 $this->WriteUint($Value); 128 } 129 130 public function SetInt($Row, $Column, $Value) 131 { 132 $this->SeekPosi($Row, $Column); 133 $this->WriteInt($Value); 134 } 135 136 public function SetFloat($Row, $Column, $Value) 137 { 138 $this->SeekPosi($Row, $Column); 139 $this->WriteFloat($Value); 140 } 141 142 public function GetString($Row, $Column) 143 { 144 $Offset = $this->GetUint($Row, $Column); 145 146 $Position = $this->HeaderSize + $this->RecordCount * $this->RecordSize + $Offset; 147 if($Position >= $this->GetSize()) return(''); 148 $this->Seek($Position); 91 149 92 //if (strlen($format) != $this->fldCount) 93 // die ("Field count error"); 94 95 $this->format = $format; 96 $this->generateOffsetTable($format); 97 } 98 99 /// Vytvoreni tabulky offsetu 100 private function generateOffsetTable($format) 101 { 102 //echo(strlen($format).' '.$format); 103 $this->offsets = array(); 104 $this->offsets[0] = 0; 105 for ($i = 1; $i < strlen($format); $i++) 106 { 107 $this->offsets[$i] = $this->offsets[$i-1]; 108 switch ($format[$i-1]) 109 { 110 case "b": case "X": $this->offsets[$i] += 1; break; 111 case "x": case "u": case "i": case "f": case "s": $this->offsets[$i] += 4; break; 112 } 113 } 114 115 $lastOff = $this->offsets[strlen($format) - 1] + ($format[strlen($format)-1] == "b" || $format[strlen($format)-1] == "X" ? 1 : 4); 116 if($lastOff != $this->recSize) 117 die ("Record size error! ".$lastOff.' <> '.$this->recSize); 118 } 119 120 ////////////////////////////////////////////////////////////////////////////// 121 122 /// Nastaveni pozice v souboru 123 private function seekPosi($row, $col) 124 { 125 $pos = 20 + $row*$this->recSize + $this->offsets[$col]; 126 //fseek($this->handle, $pos, SEEK_SET); 127 $this->seekPos($pos); 128 } 129 130 ////////////////////////////////////////////////////////////////////////////// 131 132 public function getByte($row, $col) 133 { 134 $this->seekPosi($row, $col); 135 return $this->readByte(); 136 } 137 138 public function getUint($row, $col) 139 { 140 $this->seekPosi($row, $col); 141 return $this->readUint(); 142 } 143 144 public function getInt($row, $col) 145 { 146 $this->seekPosi($row, $col); 147 return $this->readInt(); 148 } 149 150 public function getFloat($row, $col) 151 { 152 $this->seekPosi($row, $col); 153 return $this->readFloat(); 154 } 155 156 public function getString($row, $col) 157 { 158 $offset = $this->getUint($row, $col); 159 160 $pos = 20 + $this->recCount * $this->recSize + $offset; 161 $this->seekPos($pos); 162 163 $str = ""; 164 while (($char = $this->readChar()) != "\0") 165 $str .= $char; 166 167 return $str; 168 } 169 170 /// Vrati jeden cely radek jako pole 171 public function getLine($row) 172 { 173 $ret = array(); 174 for($i = 0; $i < $this->fldCount; $i++) 175 { 176 switch($this->format[$i]) 177 { 178 case "b": $ret[$i] = $this->getByte($row, $i); break; 179 case "u": $ret[$i] = $this->getUint($row, $i); break; 180 case "i": $ret[$i] = $this->getInt($row, $i); break; 181 case "f": $ret[$i] = $this->getFloat($row, $i); break; 182 case "s": $ret[$i] = $this->getString($row, $i); break; 183 case "x": case "X": default: break; 184 } 185 } 186 return $ret; 187 } 188 189 /// Vrati vybrane sloupecky z jednoho radku 190 public function getLineCols($row, $cols) 191 { 192 $ret = array(); 193 for($i = 0; $i < count($cols); $i++) 194 { 195 switch($this->format[$cols[$i]]) 196 { 197 case "b": $ret[$i] = $this->getByte($row, $cols[$i]); break; 198 case "u": $ret[$i] = $this->getUint($row, $cols[$i]); break; 199 case "i": $ret[$i] = $this->getInt($row, $cols[$i]); break; 200 case "f": $ret[$i] = $this->getFloat($row, $cols[$i]); break; 201 case "s": $ret[$i] = $this->getString($row, $cols[$i]); break; 202 case "x": case "X": default: break; 203 } 204 } 205 return $ret; 206 } 207 208 /// Pocet zaznamu 209 public function count() { return $this->recCount; } 210 /// Pocet poli 211 public function fieldCount() { return $this->fldCount; } 212 } 150 $String = ''; 151 while(($Char = $this->ReadChar()) != "\0") 152 { 153 $String .= $Char; 154 } 155 return($String); 156 } 157 158 public function SetString($Row, $Column, $Value) 159 { 160 if(in_array($Value, $this->StringList)) 161 { 162 $this->SetUint($Row, $Column, $this->StringListOffset[array_search($Value, $this->StringList)]); 163 } else 164 { 165 $this->SetUint($Row, $Column, $this->StringOffset); 166 $this->StringList[] = $Value; 167 $this->StringListOffset[] = $this->StringOffset; 168 $this->StringOffset += strlen($Value) + 1; 169 } 170 } 171 172 public function Commit() 173 { 174 $this->Seek(0); 175 $this->WriteUint(0x43424457); 176 $this->WriteUint($this->RecordCount); 177 $this->WriteUint($this->FieldCount); 178 $this->WriteUint($this->RecordSize); 179 $this->WriteUint($this->StringOffset); 180 $this->Seek($this->HeaderSize + $this->RecordCount * $this->RecordSize); 181 $this->WriteByte(0); 182 foreach($this->StringList as $Index => $Item) 183 { 184 $this->WriteString($Item); 185 } 186 } 187 188 public function GetLine($Row) 189 { 190 $Line = array(); 191 for($I = 0; $I < $this->FieldCount; $I++) 192 { 193 switch($this->Format[$I]) 194 { 195 case 'b': 196 $Line[$I] = $this->GetByte($Row, $I); 197 break; 198 case 'u': 199 $Line[$I] = $this->GetUint($Row, $I); 200 break; 201 case 'i': 202 $Line[$I] = $this->GetInt($Row, $I); 203 break; 204 case 'f': 205 $Line[$i] = $this->GetFloat($Row, $I); 206 break; 207 case 's': 208 $Line[$I] = $this->GetString($Row, $I); 209 break; 210 case 'x': 211 case 'X': 212 default: 213 break; 214 } 215 } 216 return($Line); 217 } 218 219 public function SetLine($Row, $Line) 220 { 221 for($I = 0; $I < $this->FieldCount; $I++) 222 { 223 switch($this->Format[$I]) 224 { 225 case 'b': 226 $this->SetByte($Row, $I, $Line[$I]); 227 break; 228 case 'u': 229 $this->SetUint($Row, $I, $Line[$I]); 230 break; 231 case 'i': 232 $this->SetInt($Row, $I, $Line[$I]); 233 break; 234 case 'f': 235 $this->SetFloat($Row, $I, $Line[$i]); 236 break; 237 case 's': 238 $this->SetString($Row, $I, $Line[$I]); 239 break; 240 case 'x': 241 case 'X': 242 default: 243 break; 244 } 245 } 246 return($Line); 247 } 248 249 public function GetLineCols($Row, $Columns) 250 { 251 $Line = array(); 252 for($I = 0; $I < count($Columns); $I++) 253 { 254 switch($this->Format[$Columns[$I]]) 255 { 256 case 'b': 257 $Line[$I] = $this->GetByte($Row, $Columns[$I]); 258 break; 259 case 'u': 260 $Line[$I] = $this->GetUint($Row, $Columns[$I]); 261 break; 262 case 'i': 263 $Line[$I] = $this->GetInt($Row, $Columns[$I]); 264 break; 265 case 'f': 266 $Line[$i] = $this->GetFloat($Row, $Columns[$I]); 267 break; 268 case 's': 269 $Line[$I] = $this->GetString($Row, $Columns[$I]); 270 break; 271 case 'x': 272 case 'X': 273 default: 274 break; 275 } 276 } 277 return($Line); 278 } 279 280 public function GetRecordCount() 281 { 282 return($this->RecordCount); 283 } 284 285 public function SetRecordCount($Value) 286 { 287 $this->RecordCount = $Value; 288 } 289 290 public function GetFieldCount() 291 { 292 return($this->FieldCount); 293 } 294 } 213 295 214 296 ?>
Note:
See TracChangeset
for help on using the changeset viewer.