blob: ba5242869b2b6679c24b685746b46000925ed8b4 [file] [log] [blame]
<?php
/**
* File containing the Permutation classes.
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package
* @version //autogen//
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
*/
/**
* A system for generating permutations of possible combinations.
*
* @package
* @version //autogen//
*/
abstract class ezcTemplatePermutation
{
public function __construct()
{
$this->index = 0;
}
abstract public function replace( $from , $to );
abstract public function generate();
abstract public function increase();
public function reset()
{
$this->index = 0;
}
static function generateString( $list )
{
$str = '';
for ( $i = 0; $i < count( $list ); ++$i )
{
$p = $list[$i];
if ( is_object( $p ) )
{
$str .= $p->generate();
}
else
{
$str .= $p;
}
}
return $str;
}
static function increaseList( $list )
{
for ( $i = count( $list ) - 1; $i >= 0; --$i )
{
$p = $list[$i];
if ( is_object( $p ) )
{
if ( $p->increase() )
return true;
$p->reset();
}
}
return false;
}
static function indentBlock( $text, $indentation )
{
$lines = preg_split( "#(\r\n|\r|\n)#", $text, -1, PREG_SPLIT_DELIM_CAPTURE );
for ( $i = 0; $i < count( $lines ); $i += 2 )
{
if ( $i == count( $lines ) - 1 &&
strlen( $lines[$i] ) == 0 )
continue;
$lines[$i] = $indentation . $lines[$i];
}
return implode( "", $lines );
}
static function column( $text )
{
$lines = preg_split( "#(\r\n|\r|\n)#", $text, -1, PREG_SPLIT_DELIM_CAPTURE );
for ( $i = 0; $i < count( $lines ); $i += 2 )
{
if ( $i == count( $lines ) - 1 )
break;
}
$c = strlen( $lines[$i] );
return $c;
}
static public function replaceList( &$list, $from, $to )
{
foreach ( $list as $i => $item )
{
if ( is_object( $item ) )
{
$item->replace( $from, $to );
}
else
{
$list[$i] = str_replace( $from, $to, $item );
}
}
}
}
class ezcTemplatePermutationList extends ezcTemplatePermutation
{
public function __construct( $list = null, $indentation = '' )
{
parent::__construct();
$this->list = $list;
$this->indentation = $indentation;
}
public function removeIndex( $index )
{
if ( $index < 0 || $index >= count( $this->list ) )
{
throw new Exception( "Index $index is out of range [0->" . count( $this->list ) . "]" );
}
unset( $this->list[$index] );
$this->list = array_values( $this->list );
}
public function replace( $from , $to )
{
self::replaceList( $this->list, $from, $to );
}
public function generate()
{
return self::indentBlock( self::generateString( $this->list ),
$this->indentation );
}
public function increase()
{
return self::increaseList( $this->list );
}
}
class ezcTemplatePermutationAlternative extends ezcTemplatePermutation
{
public function __construct( $list = null, $indentation = '' )
{
parent::__construct();
$this->list = $list;
$this->indentation = $indentation;
}
public function __clone()
{
foreach ( $this->list as $i => $v )
{
if ( is_object( $v ) )
{
$this->list[$i] = clone $v;
}
}
}
public function removeIndex( $index )
{
if ( $index < 0 || $index >= count( $this->list ) )
{
throw new Exception( "Index $index is out of range [0->" . count( $this->list ) . "]" );
}
unset( $this->list[$index] );
$this->list = array_values( $this->list );
}
public function replace( $from , $to )
{
self::replaceList( $this->list, $from, $to );
}
public function generate()
{
$p = $this->list[$this->index];
if ( is_object( $p ) )
{
return self::indentBlock( $p->generate(), $this->indentation );
}
else
{
return $p;
}
}
public function increase()
{
$p = $this->list[$this->index];
if ( is_object( $p ) )
{
if ( $p->increase() )
return true;
$p->reset();
}
$this->index++;
return $this->index < count( $this->list );
}
public function reset()
{
foreach ( $this->list as $p )
{
if ( is_object( $p ) )
{
$p->reset();
}
}
$this->index = 0;
}
}
/*class ezcTemplatePermutationOccurence extends ezcTemplatePermutation
{
public function __construct( $list, $min, $max )
{
parent::__construct();
$this->list = $list;
$this->min = $min;
$this->max = $max;
}
public function generate()
{
$times = $this->min + $this->index;
if ( $times === 0 )
return '';
$str = self::generateString( $this->list );
return str_repeat( $str, $times );
}
public function increase()
{
if ( self::increase( $this->list ) )
return true;
$this->index++;
return $this->index <= ( $this->max - $this->min );
}
}*/
class ezcTemplatePermutationNumber extends ezcTemplatePermutation
{
public function __construct( $min = false, $max = false )
{
parent::__construct();
$this->min = $min;
$this->max = $max;
}
public function replace( $from , $to )
{
}
public function generate()
{
return $this->min + $this->index;
}
public function increase()
{
$this->index++;
return $this->index <= ( $this->max - $this->min );
}
}
class ezcTemplatePermutationIndentChild extends ezcTemplatePermutation
{
public function __construct( ezcTemplatePermutation $child, $indentation )
{
parent::__construct();
$this->child = $child;
$this->indentation = $indentation;
}
public function replace( $from , $to )
{
$this->child->replace( $from, $to );
}
public function generate()
{
$p = $this->child;
if ( is_object( $p ) )
{
$text = $p->generate();
}
else
{
$text = $p;
}
return self::indentBlock( $text,
$this->indentation );
}
public function increase()
{
$p = $this->child;
if ( is_object( $p ) )
{
return $p->increase();
}
return false;
}
public function reset()
{
$p = $this->child;
if ( is_object( $p ) )
{
$p->reset();
}
}
}
class ezcTemplatePermutationAlternativeMaster extends ezcTemplatePermutation
{
public function __construct( array $slaves )
{
parent::__construct();
$this->slaves = $slaves;
$this->slaveIndex = count( $this->slaves ) - 1;
if ( count( $this->slaves ) == 0 )
{
throw new Exception( "Slave list cannot be empty" );
}
foreach ( $this->slaves as $i => $slave )
{
if ( !$slave instanceof ezcTemplatePermutationAlternativeSlave )
{
throw new Exception( "Slave entry {$i} is not an instance of ezcTemplatePermutationAlternativeSlave" );
}
}
}
public function removeIndex( $index )
{
if ( $index < 0 || $index >= count( $this->slaves ) )
{
throw new Exception( "Index $index is out of range [0->" . count( $this->slaves ) . "]" );
}
unset( $this->slaves[$index] );
$this->slaves = array_values( $this->slaves );
}
public function __clone()
{
foreach ( $this->slaves as $i => $v )
{
if ( is_object( $v ) )
{
$this->slaves[$i] = clone $v;
}
}
}
public function replace( $from , $to )
{
self::replaceList( $this->slaves, $from, $to );
}
public function generate()
{
// echo "master::generate(): si: {$this->slaveIndex}, sc: " . count( $this->slaves ) . "\n";
$p = $this->slaves[0];
if ( is_object( $p ) )
{
return $p->generate();
}
return $p;
}
public function increase()
{
// echo "master::increase(): si: {$this->slaveIndex}, sc: " . count( $this->slaves ) . "\n";
for ( $i = count( $this->slaves ) - 1; $i >= 0; --$i )
{
$p = $this->slaves[$i];
if ( is_object( $p ) )
{
if ( $p->increaseSlave() )
{
// echo "master::increase(): increaseSlave() is true\n";
return true;
}
// echo "master::increase(): increaseSlave() is false\n";
$p->resetSlave();
}
}
foreach ( $this->slaves as $slave )
{
$slave->index++;
}
$ret = $this->slaves[0]->index < count( $this->slaves[0]->list );
// echo "master::increase()#3: ret: '$ret', si: {$this->slaveIndex}, sc: " . count( $this->slaves ) . "\n";
return $ret;
}
public function reset()
{
foreach ( $this->slaves as $slave )
{
$slave->resetSlaves();
}
}
}
class ezcTemplatePermutationAlternativeSlave extends ezcTemplatePermutation
{
public function __construct( $list )
{
parent::__construct();
$this->list = $list;
$this->index = 0;
}
public function __clone()
{
foreach ( $this->list as $i => $v )
{
if ( is_object( $v ) )
{
$this->list[$i] = clone $v;
}
}
}
public function removeIndex( $index )
{
if ( $index < 0 || $index >= count( $this->list ) )
{
throw new Exception( "Index $index is out of range [0->" . count( $this->list ) . "]" );
}
unset( $this->list[$index] );
$this->list = array_values( $this->list );
}
public function replace( $from , $to )
{
self::replaceList( $this->list, $from, $to );
}
public function generate()
{
$p = $this->list[$this->index];
if ( is_object( $p ) )
{
return $p->generate();
}
return $p;
}
public function increaseSlave()
{
// echo "slave::increaseSlave(): i: {$this->index}\n";
$p = $this->list[$this->index];
if ( is_object( $p ) )
{
return $p->increase();
}
return false;
}
public function increase()
{
// Slaves do not control the increase(), this is up to the master.
// echo "slave::increase(): i: {$this->index}\n";
return false;
}
public function setIndex( $index )
{
// echo "slave::setIndex( $index )\n";
if ( $index >= count( $this->list ) )
{
throw new Exception( "New index {$index} is out of bounds (" . count( $this->list ) . ")" );
}
$this->index = $index;
}
public function resetSlave()
{
$p = $this->list[$this->index];
if ( is_object( $p ) )
{
return $p->reset();
}
}
public function resetSlaves()
{
foreach ( $this->list as $p )
{
if ( is_object( $p ) )
{
return $p->reset();
}
}
$this->index = 0;
}
public function reset()
{
// Slaves do not control the reset(), this is up to the master.
return false;
}
}
class ezcTemplatePermutationApp
{
public $outputToFile;
public function __construct( $file, $args = false, $dir = false )
{
$this->outputToFile = false;
if ( $dir === false )
{
$dir = dirname( __FILE__ ) . "/../regression_tests";
}
$this->fd = false;
$this->dir = $dir;
$this->file = $file;
if ( is_array( $args ) )
{
foreach ( $args as $arg )
{
if ( $arg == '--generate-file' )
$this->outputToFile = true;
}
}
}
public function store( $content, $file = false )
{
if ( $file === false )
$file = $this->dir . '/' . $this->file;
if ( $this->outputToFile )
{
if ( !file_exists( dirname( $file ) ) )
{
mkdir( dirname( $file ), 0777, true );
}
echo "Writing to ", $file, "\n";
file_put_contents( $file, $content );
return $file;
}
else
{
echo basename( $file ), "\n";
echo $content, "\n";
return false;
}
}
public function output( $content )
{
if ( $this->outputToFile )
{
if ( $this->fd === false )
{
$file = $this->dir . '/' . $this->file;
if ( !file_exists( dirname( $file ) ) )
{
mkdir( dirname( $file ), 0777, true );
}
$this->fd = fopen( $file, "w" );
}
fwrite( $this->fd, $content );
}
else
{
echo $content;
}
}
public function close()
{
if ( $this->outputToFile )
{
if ( $this->fd === false )
{
throw new Exception( "File has not yet been opened" );
}
echo "Writing to ", $this->dir . "/" . $this->file, "\n";
fclose( $this->fd );
$this->fd = false;
}
}
}
function app( $file, $args, $dir = false )
{
return new ezcTemplatePermutationApp( $file, $args, $dir );
}
function perm()
{
$args = func_get_args();
return new ezcTemplatePermutationList( $args );
}
function permI()
{
$args = func_get_args();
$indent = array_shift( $args );
return new ezcTemplatePermutationList( $args, $indent );
}
function alt()
{
$args = func_get_args();
return new ezcTemplatePermutationAlternative( $args );
}
function altI()
{
$args = func_get_args();
$indent = array_shift( $args );
return new ezcTemplatePermutationAlternative( $args, $indent );
}
function indent( $child, $indentation )
{
return new ezcTemplatePermutationIndentChild( $child, $indentation );
}
function num( $min = false, $max = false )
{
return new ezcTemplatePermutationNumber( $min, $max );
}
function altMaster()
{
$slaves = func_get_args();
return new ezcTemplatePermutationAlternativeMaster( $slaves );
}
function altSlave()
{
$list = func_get_args();
return new ezcTemplatePermutationAlternativeSlave( $list );
}
?>