Skip to content

Commit 7a9c1e4

Browse files
author
Ivan Dudarev
committed
String float support
1 parent 1c81d75 commit 7a9c1e4

File tree

2 files changed

+75
-61
lines changed

2 files changed

+75
-61
lines changed

src/Wizard.php

Lines changed: 57 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,11 @@ class Wizard
8989
),
9090
'networks' => array(
9191
'format' => '',
92-
'len' => 4,
93-
'items' => 0,
92+
's' => 4,
93+
'n' => 0,
9494
'fields' => array(),
9595
),
96+
'maxItemLen' => 0,
9697
);
9798

9899
/**
@@ -608,7 +609,8 @@ protected function cleanTmpDb()
608609
foreach ($this->networks as $network) {
609610
foreach ($network['map'] as $register) {
610611
$innerSql = 'SELECT `_pk` FROM `'.$register.'` GROUP BY `_pk`';
611-
$sql = 'DELETE FROM `_ips` WHERE WHERE `parameter` = "'.$register.'" AND `value` NOT IN ('.$innerSql.');';
612+
$sql = 'DELETE FROM `_ips` WHERE WHERE `parameter` = "'.$register.'" AND `value` NOT IN ('
613+
.$innerSql.');';
612614
$this->pdo->exec($sql);
613615
}
614616
}
@@ -642,12 +644,14 @@ protected function definePackFormat() {
642644
}
643645
break;
644646
default:
645-
$fieldClassName = __NAMESPACE__.'\\Field\\'.mb_convert_case($data['type'], \MB_CASE_TITLE).'Field';
647+
$fieldClassName = __NAMESPACE__.'\\Field\\'
648+
.mb_convert_case($data['type'], \MB_CASE_TITLE).'Field';
646649
/**
647650
* @var FieldAbstract $validator
648651
*/
649652
$validator = new $fieldClassName($field, $data);
650-
$sql = 'SELECT MAX(`' . $field . '`) AS `max`, MIN(`' . $field . '`) AS `min` FROM `' . $table . '`;';
653+
$sql = 'SELECT MAX(`' . $field . '`) AS `max`, MIN(`' . $field . '`) AS `min` FROM `'
654+
. $table . '`;';
651655
$res = $this->pdo->query($sql);
652656
$row = $res->fetch();
653657
$validator->update($row['min']);
@@ -662,8 +666,8 @@ protected function definePackFormat() {
662666
$bin = Pack::pack($pack, $empty);
663667

664668
$this->meta['registers'][$table]['format'] = $pack;
665-
$this->meta['registers'][$table]['len'] = strlen($bin);
666-
$this->meta['registers'][$table]['items'] = 0;
669+
$this->meta['registers'][$table]['s'] = strlen($bin);
670+
$this->meta['registers'][$table]['n'] = 0;
667671
$this->meta['registers'][$table]['fields'] = $empty;
668672
}
669673
}
@@ -680,7 +684,7 @@ protected function compileRegister($register)
680684
$empty = $this->meta['registers'][$register]['fields'];
681685
$bin = Pack::pack($format, $empty);
682686
fwrite($file, $bin);
683-
$offset = 0;
687+
$offset = strlen($bin);
684688
$select = array(
685689
'*' => '`'.$register.'`.*',
686690
);
@@ -708,13 +712,19 @@ protected function compileRegister($register)
708712
if (!empty($cellValue)) $check = 1;
709713
}
710714
$bin = Pack::pack($format, $row);
715+
$binLen = strlen($bin);
711716
if ($check) {
712-
$offset ++;
717+
if ($binLen > $this->meta['maxItemLen']) {
718+
$this->meta['maxItemLen'] = $binLen;
719+
}
720+
$offset += $binLen;
713721
fwrite($file,$bin);
714722
}
715-
716-
$this->pdo->exec('UPDATE `'.$register.'` SET `_offset` =\''.($check?$offset:0).'\' WHERE `_pk` = \''.$rowId.'\';');
717-
$this->pdo->exec('UPDATE `_ips` SET `offset` =\''.($check?$offset:0).'\' WHERE `parameter` = \''.$register.'\' AND `value`=\''.$rowId.'\';');
723+
$sql = 'UPDATE `'.$register.'` SET `_offset` =\''.($check?$offset:0).'\' WHERE `_pk` = \''.$rowId.'\';';
724+
$this->pdo->exec($sql);
725+
$sql = 'UPDATE `_ips` SET `offset` =\''.($check?$offset:0).'\' WHERE `parameter` = \''
726+
.$register.'\' AND `value`=\''.$rowId.'\';';
727+
$this->pdo->exec($sql);
718728

719729
$transactionIterator += 2;
720730
if ($transactionIterator > 100000) {
@@ -723,7 +733,7 @@ protected function compileRegister($register)
723733
$transactionIterator = 0;
724734
}
725735
}
726-
$this->meta['registers'][$register]['items'] = $offset;
736+
$this->meta['registers'][$register]['n'] = $offset;
727737
$this->pdo->commit();
728738
fclose($file);
729739
}
@@ -747,15 +757,19 @@ protected function compileNetwork()
747757
$format = array();
748758
foreach ($fields as $register=>$null) {
749759
$values[$register] = array();
750-
$format[$register] = Pack::getOptimalFormat(0, $this->meta['registers'][$register]['items'], $register);
760+
$format[$register] = Pack::getOptimalFormat(
761+
0,
762+
$this->meta['registers'][$register]['n'],
763+
$register
764+
);
751765
}
752766

753767

754768
$this->meta['networks']['format'] = implode('/', $format);
755769

756770
$pack = $this->meta['networks']['format'];
757771
$binaryPrevData = Pack::pack($pack, $fields);
758-
$this->meta['networks']['len'] += strlen($binaryPrevData);
772+
$this->meta['networks']['s'] += strlen($binaryPrevData);
759773
$offset = 0;
760774
$this->meta['index'][0] = 0;
761775
$file = fopen($this->prefix.'.networks.dat','w');
@@ -796,7 +810,7 @@ protected function compileNetwork()
796810
fwrite($file, pack('N', $ip) . $binaryData);
797811
}
798812
}
799-
$this->meta['networks']['items'] = $offset;
813+
$this->meta['networks']['n'] = $offset;
800814
for($i=1;$i<=255;$i++) {
801815
if (!isset($this->meta['index'][$i])) $this->meta['index'][$i] = $this->meta['index'][$i-1];
802816
}
@@ -817,27 +831,34 @@ protected function compileHeader()
817831
*/
818832
$header = pack('C', self::FORMAT_VERSION);
819833

834+
/*
835+
* Maximal length of register item
836+
*/
837+
$header .= pack('I', $this->meta['maxItemLen']);
838+
820839
/*
821840
* Registers count.
822841
*/
823842
$header .= pack('C', count($this->meta['registers']));
824843

825-
826844
$rnmLen = 1;
827845
$pckLen = strlen($this->meta['networks']['format']);
828-
$lenMax = $this->meta['networks']['len'];
829-
$itmMax = $this->meta['networks']['items'];
846+
$numMax = $this->meta['networks']['n'];
847+
$registerOffset = filesize($this->prefix.'.networks.dat');;
830848
foreach ($this->meta['registers'] as $registerName => $register) {
849+
$this->meta['registers'][$registerName]['s'] = $registerOffset;
850+
$file = $this->prefix.'.reg.'.$registerName.'.dat';
851+
$registerOffset += filesize($file);
831852
if (strlen($registerName) > $rnmLen) $rnmLen = strlen($registerName);
832853
if (strlen($register['format']) > $pckLen) $pckLen = strlen($register['format']);
833-
if ($register['len'] > $lenMax) $lenMax = $register['len'];
834-
if ($register['items'] > $itmMax) $itmMax = $register['items'];
854+
if ($register['n'] > $numMax) $numMax = $register['n'];
835855
}
836856
$rnm = 'A'.$rnmLen.'name';
837857
$pck = 'A'.$pckLen.'format';
838-
$len = Pack::getOptimalFormat(0, $lenMax, 'len');
839-
$itm = Pack::getOptimalFormat(0, $itmMax, 'items');
840-
$format = $rnm.'/'.$pck.'/'.$len.'/'.$itm;
858+
$sizeMax = ($this->meta['networks']['s'] > $registerOffset)?$this->meta['networks']['s']:$registerOffset;
859+
$size = Pack::getOptimalFormat(0, $sizeMax, 's');
860+
$itm = Pack::getOptimalFormat(0, $numMax, 'n');
861+
$format = $rnm.'/'.$pck.'/'.$size.'/'.$itm;
841862

842863
/*
843864
* Size of registers definition unpack format.
@@ -850,8 +871,8 @@ protected function compileHeader()
850871
$empty = array(
851872
'name' => '',
852873
'format' => '',
853-
'len' => 0,
854-
'items' => 0,
874+
's' => 0,
875+
'n' => 0,
855876
);
856877
$header .= pack('S',strlen(Pack::pack($format, $empty)));
857878

@@ -902,8 +923,8 @@ protected function compileHeader()
902923
array(
903924
'name' => $registerName,
904925
'format' => $register['format'],
905-
'len' => $register['len'],
906-
'items' => $register['items']
926+
's' => $register['s'],
927+
'n' => $register['n']
907928
)
908929
);
909930
}
@@ -916,8 +937,8 @@ protected function compileHeader()
916937
array(
917938
'name' => 'n',
918939
'format' => $this->meta['networks']['format'],
919-
'len' => $this->meta['networks']['len'],
920-
'items' => $this->meta['networks']['items']
940+
's' => $this->meta['networks']['s'],
941+
'n' => $this->meta['networks']['n']
921942
)
922943
);
923944

@@ -978,12 +999,13 @@ protected function makeFile($fileName)
978999
fclose($stream);
9791000
if (is_writable($file)) unlink($file);
9801001
}
981-
982-
$time = empty($this->time)?time():$this->time;
983-
fwrite($database,pack('I1A128',$time,$this->author));
984-
fwrite($database,pack('A*',$this->license));
1002+
$data = array(
1003+
'time' => empty($this->time)?time():$this->time,
1004+
'author' => $this->author,
1005+
'license' => $this->license,
1006+
);
1007+
fwrite($database,pack::pack('Itime/~author/A*license', $data));
9851008
fclose($database);
986-
9871009
rename($tmp, $fileName);
9881010
}
9891011
}

tests/Functional/DatabaseTest.php

Lines changed: 18 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,11 @@ public function testSimple()
6060
$this->assertSame(1, $db['header']['RGC']);
6161
$this->assertSame(0, $db['header']['RLC']);
6262
$this->assertSame('A10name', $db['meta']['registers']['interval']['format']);
63-
$this->assertSame(10, $db['meta']['registers']['interval']['len']);
64-
$this->assertSame(4, $db['meta']['registers']['interval']['items']);
63+
$this->assertSame(20, $db['meta']['registers']['interval']['s']);
64+
$this->assertSame(50, $db['meta']['registers']['interval']['n']);
6565
$this->assertSame('Cinterval', $db['meta']['networks']['format']);
66-
$this->assertSame(5, $db['meta']['networks']['len']);
67-
$this->assertSame(4, $db['meta']['networks']['items']);
66+
$this->assertSame(5, $db['meta']['networks']['s']);
67+
$this->assertSame(4, $db['meta']['networks']['n']);
6868
$this->assertSame(0, $db['index'][0]);
6969
$this->assertSame(0, $db['index'][63]);
7070
$this->assertSame(1, $db['index'][64]);
@@ -142,20 +142,18 @@ public function testRelation()
142142
$db = $this->parseFile($dbFile);
143143

144144
$this->assertSame('ISD', $db['header']['control']);
145-
$this->assertSame('A2code/A10name', $db['meta']['registers']['country']['format']);
146-
$this->assertSame(12, $db['meta']['registers']['country']['len']);
147-
$this->assertSame(3, $db['meta']['registers']['country']['items']);
148-
$this->assertSame('A15name/CcountryId/r4latitude:8049909/R4longitude', $db['meta']['registers']['city']['format']);
149-
$this->assertSame(22, $db['meta']['registers']['city']['len']);
150-
$this->assertSame(5, $db['meta']['registers']['city']['items']);
145+
$this->assertSame('A2code/~name', $db['meta']['registers']['country']['format']);
146+
$this->assertSame(35, $db['meta']['registers']['country']['s']);
147+
$this->assertSame(38, $db['meta']['registers']['country']['n']);
148+
$this->assertSame('~name/CcountryId/r4latitude:8049909/R4longitude', $db['meta']['registers']['city']['format']);
149+
$this->assertSame(73, $db['meta']['registers']['city']['s']);
150+
$this->assertSame(87, $db['meta']['registers']['city']['n']);
151151
$this->assertSame('Ccity', $db['meta']['networks']['format']);
152-
$this->assertSame(5, $db['meta']['networks']['len']);
153-
$this->assertSame(7, $db['meta']['networks']['items']);
152+
$this->assertSame(5, $db['meta']['networks']['s']);
153+
$this->assertSame(7, $db['meta']['networks']['n']);
154154
$this->assertSame('city', $db['relations'][0]['p']);
155155
$this->assertSame('countryId', $db['relations'][0]['f']);
156156
$this->assertSame('country', $db['relations'][0]['c']);
157-
$this->assertArrayHasKey($db['registers']['city'][2]['countryId'], $db['registers']['country']);
158-
$this->assertSame('kz', $db['registers']['country'][$db['registers']['city'][2]['countryId']]['code']);
159157
$this->assertSame($time, $db['time']);
160158
$this->assertSame($author, $db['author']);
161159
$this->assertSame($license, $db['license']);
@@ -244,7 +242,6 @@ protected function parseFile($dbFile)
244242
'RLD' => 0,
245243
'RLUF' => '',
246244
'RGMUF' => '',
247-
248245
),
249246
'meta' => array(),
250247
'index' => array(),
@@ -261,9 +258,9 @@ protected function parseFile($dbFile)
261258
$result['header']['control'] = $meta['control'];
262259
$header = fread($db, $result['header']['size']);
263260
$offset = 0;
264-
$meta = Pack::unpack('Cversion/CRGC/SRGF/SRGD/CRLC/CRLF/SRLD', substr($header,$offset,10));
261+
$meta = Pack::unpack('Cversion/ImaxItemLen/CRGC/SRGF/SRGD/CRLC/CRLF/SRLD', substr($header,$offset,14));
265262
$result['header'] = array_replace($result['header'], $meta);
266-
$offset += 10;
263+
$offset += 14;
267264
$unpack = 'A'.$meta['RLF'].'RLUF/A'.$meta['RGF'].'RGMUF';
268265
$size = $meta['RLF']+$meta['RGF'];
269266
$meta = Pack::unpack($unpack, substr($header, $offset, $size));
@@ -295,25 +292,20 @@ protected function parseFile($dbFile)
295292
$offset += $result['header']['RGD'];
296293
$result['index'] = array_values(unpack('I*',substr($header, $offset)));
297294

298-
for ($i=0;$i<$result['meta']['networks']['items'];$i++) {
295+
for ($i=0;$i<$result['meta']['networks']['n'];$i++) {
299296
$data = Pack::unpack(
300297
'N_ip/'.$result['meta']['networks']['format'],
301-
fread($db, $result['meta']['networks']['len'])
298+
fread($db, $result['meta']['networks']['s'])
302299
);
303300
$data['_ip'] = long2ip($data['_ip']);
304301
$result['networks'][] = $data;
305302
}
306303

307304
foreach ($result['meta']['registers'] as $register=>$data) {
308-
for ($id=0;$id<=$data['items'];$id++) {
309-
$result['registers'][$register][$id] = Pack::unpack(
310-
$data['format'],
311-
fread($db, $data['len'])
312-
);
313-
}
305+
$registerData[$register] = fread($db, $data['n']);
314306
}
315307

316-
$meta = Pack::unpack('Itime/A128author/A*license', fread($db, filesize($dbFile)));
308+
$meta = Pack::unpack('Itime/~author/A*license', fread($db, filesize($dbFile)));
317309
$result = array_replace($result, $meta);
318310
fclose($db);
319311
return $result;

0 commit comments

Comments
 (0)