From dbd52c81e07da4440f3afc2e248c5b036f6bbec7 Mon Sep 17 00:00:00 2001 From: Andreas Gohr <andi@splitbrain.org> Date: Thu, 2 Jun 2016 20:32:50 +0200 Subject: [PATCH] minor optimization how cell counts are fixed in tables array splice operations are expensive. when many cells in a table row are missing, the operation should be executed only once instead for each missing cell. --- _test/tests/inc/parser/parser_table.test.php | 117 ++++++++++++++++--- inc/parser/handler.php | 14 ++- 2 files changed, 108 insertions(+), 23 deletions(-) diff --git a/_test/tests/inc/parser/parser_table.test.php b/_test/tests/inc/parser/parser_table.test.php index a9b4e284c..f05dd29aa 100644 --- a/_test/tests/inc/parser/parser_table.test.php +++ b/_test/tests/inc/parser/parser_table.test.php @@ -93,7 +93,7 @@ def'); abc | def'); - + $calls = array ( array('document_start',array()), array('p_open',array()), @@ -111,14 +111,14 @@ def'); $this->assertEquals($calls,array_map('stripbyteindex',$this->H->calls)); } - + function testTableHeaders() { $this->P->addMode('table',new Doku_Parser_Mode_Table()); $this->P->parse(' abc ^ X | Y ^ Z | def'); - + $calls = array ( array('document_start',array()), array('p_open',array()), @@ -291,14 +291,14 @@ def'); $this->assertEquals($calls,array_map('stripbyteindex',$this->H->calls)); } - + function testCellAlignment() { $this->P->addMode('table',new Doku_Parser_Mode_Table()); $this->P->parse(' abc | X | Y ^ Z | def'); - + $calls = array ( array('document_start',array()), array('p_open',array()), @@ -325,7 +325,7 @@ def'); $this->assertEquals($calls,array_map('stripbyteindex',$this->H->calls)); } - + function testCellSpan() { $this->P->addMode('table',new Doku_Parser_Mode_Table()); $this->P->parse(' @@ -334,7 +334,7 @@ abc | f ^ ^| |||| def'); - + $calls = array ( array('document_start',array()), array('p_open',array()), @@ -367,7 +367,7 @@ def'); ); $this->assertEquals($calls,array_map('stripbyteindex',$this->H->calls)); } - + function testCellRowSpan() { $this->P->addMode('table',new Doku_Parser_Mode_Table()); $this->P->parse(' @@ -376,7 +376,7 @@ abc |:::^ d | e| |b ^ ::: |:::f| def'); - + $calls = array ( array('document_start',array()), array('p_open',array()), @@ -473,7 +473,7 @@ def'); ); $this->assertEquals($calls,array_map('stripbyteindex',$this->H->calls)); } - + function testRowSpanTableHead() { $this->P->addMode('table',new Doku_Parser_Mode_Table()); $this->P->parse(' @@ -606,7 +606,7 @@ def'); abc | **X** | Y ^ Z | def'); - + $calls = array ( array('document_start',array()), array('p_open',array()), @@ -634,11 +634,11 @@ def'); array('p_close',array()), array('document_end',array()), ); - + $this->assertEquals($calls,array_map('stripbyteindex',$this->H->calls)); - + } - + function testTableEol() { $this->P->addMode('table',new Doku_Parser_Mode_Table()); $this->P->addMode('eol',new Doku_Parser_Mode_Eol()); @@ -683,7 +683,7 @@ def'); ); $this->assertEquals($calls,array_map('stripbyteindex',$this->H->calls)); } - + // This is really a failing test - formatting able to spread across cols // Problem is fixing it would mean a major rewrite of table handling function testTableStrong() { @@ -738,7 +738,7 @@ def'); ); $this->assertEquals($calls,array_map('stripbyteindex',$this->H->calls)); } - + // This is really a failing test - unformatted able to spread across cols // Problem is fixing it would mean a major rewrite of table handling function testTableUnformatted() { @@ -789,7 +789,7 @@ def'); ); $this->assertEquals($calls,array_map('stripbyteindex',$this->H->calls)); } - + function testTableLinebreak() { $this->P->addMode('table',new Doku_Parser_Mode_Table()); $this->P->addMode('linebreak',new Doku_Parser_Mode_Linebreak()); @@ -837,7 +837,7 @@ def'); $this->assertEquals($calls,array_map('stripbyteindex',$this->H->calls)); } - + // This is really a failing test - footnote able to spread across cols // Problem is fixing it would mean a major rewrite of table handling function testTableFootnote() { @@ -915,4 +915,85 @@ def'); $this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls); } + /** + * missing cells in one row get filled up... + */ + function testTable_CellFix() { + $syntax = "\n| r1c1 | r1c2 | r1c3 |\n| r2c1 |\n"; + $this->P->addMode('table',new Doku_Parser_Mode_Table()); + $this->P->parse($syntax); + $calls = array ( + array('document_start',array()), + array('table_open',array(3, 2, 2)), + + array('tablerow_open',array()), + array('tablecell_open',array(1,null,1)), + array('cdata',array(' r1c1 ')), + array('tablecell_close',array()), + array('tablecell_open',array(1,null,1)), + array('cdata',array(' r1c2 ')), + array('tablecell_close',array()), + array('tablecell_open',array(1,null,1)), + array('cdata',array(' r1c3 ')), + array('tablecell_close',array()), + array('tablerow_close',array()), + + array('tablerow_open',array()), + array('tablecell_open',array(1,null,1)), + array('cdata',array(' r2c1 ')), + array('tablecell_close',array()), + array('tablecell_open',array(1,null,1)), + array('cdata',array('')), + array('tablecell_close',array()), + array('tablecell_open',array(1,null,1)), + array('cdata',array('')), + array('tablecell_close',array()), + array('tablerow_close',array()), + + array('table_close',array(strlen($syntax))), + array('document_end',array()), + ); + $this->assertEquals($calls, array_map('stripbyteindex',$this->H->calls)); + } + + /** + * ... even if the longer row comes later + */ + function testTable_CellFix2() { + $syntax = "\n| r1c1 |\n| r2c1 | r2c2 | r2c3 |\n"; + $this->P->addMode('table',new Doku_Parser_Mode_Table()); + $this->P->parse($syntax); + $calls = array ( + array('document_start',array()), + array('table_open',array(3, 2, 2)), + + array('tablerow_open',array()), + array('tablecell_open',array(1,null,1)), + array('cdata',array(' r1c1 ')), + array('tablecell_close',array()), + array('tablecell_open',array(1,null,1)), + array('cdata',array('')), + array('tablecell_close',array()), + array('tablecell_open',array(1,null,1)), + array('cdata',array('')), + array('tablecell_close',array()), + array('tablerow_close',array()), + + array('tablerow_open',array()), + array('tablecell_open',array(1,null,1)), + array('cdata',array(' r2c1 ')), + array('tablecell_close',array()), + array('tablecell_open',array(1,null,1)), + array('cdata',array(' r2c2 ')), + array('tablecell_close',array()), + array('tablecell_open',array(1,null,1)), + array('cdata',array(' r2c3 ')), + array('tablecell_close',array()), + array('tablerow_close',array()), + + array('table_close',array(strlen($syntax))), + array('document_end',array()), + ); + $this->assertEquals($calls, array_map('stripbyteindex',$this->H->calls)); + } } diff --git a/inc/parser/handler.php b/inc/parser/handler.php index 815ac39c5..f477d36f8 100644 --- a/inc/parser/handler.php +++ b/inc/parser/handler.php @@ -1470,12 +1470,16 @@ class Doku_Handler_Table implements Doku_Handler_CallWriter_Interface { case 'tablerow_close': // Fix broken tables by adding missing cells + $moreCalls = array(); while (++$lastCell < $this->maxCols) { - array_splice($this->tableCalls, $key, 0, array( - array('tablecell_open', array(1, null, 1), $call[2]), - array('cdata', array(''), $call[2]), - array('tablecell_close', array(), $call[2]))); - $key += 3; + $moreCalls[] = array('tablecell_open', array(1, null, 1), $call[2]); + $moreCalls[] = array('cdata', array(''), $call[2]); + $moreCalls[] = array('tablecell_close', array(), $call[2]); + } + $moreCallsLength = count($moreCalls); + if($moreCallsLength) { + array_splice($this->tableCalls, $key, 0, $moreCalls); + $key += $moreCallsLength; } if($this->countTableHeadRows == $lastRow) { -- GitLab