text:
<?php
/**
 * Created by PhpStorm.
 * User: Exodus
 * Date: 28.05.2016
 * Time: 16:05
 */

namespace Exodus4D\Pathfinder\Lib;

use Exodus4D\Pathfinder\Lib\Db\Pool;
use Exodus4D\Pathfinder\Lib\Api\CcpClient;
use Exodus4D\Pathfinder\Lib\Api\GitHubClient;
use Exodus4D\Pathfinder\Lib\Api\SsoClient;
use Exodus4D\Pathfinder\Lib\Api\EveScoutClient;
use Exodus4D\Pathfinder\Lib\Socket\AbstractSocket;
use Exodus4D\Pathfinder\Lib\Socket\SocketInterface;
use Exodus4D\Pathfinder\Lib\Socket\TcpSocket;

class Config extends \Prefab {

    /**
     * prefix for custom Pathfinder env vars
     */
    const PREFIX_KEY                                = 'PF';

    /**
     * delimiter for custom Pathfinder env vars
     */
    const ARRAY_DELIMITER                           = '-';

    /**
     * Hive key for all Pathfinder config vars (*.ini files)
     */
    const HIVE_KEY_PATHFINDER                       = 'PATHFINDER';

    /**
     * Hive key for all environment config vars (*.ini files)
     */
    const HIVE_KEY_ENVIRONMENT                      = 'ENVIRONMENT';

    /**
     * Hive key for custom plugins (js map modules)
     */
    const HIVE_KEY_PLUGIN                           = 'PLUGIN';

    /**
     * Hive key for Socket validation check
     */
    const CACHE_KEY_SOCKET_VALID                    = 'CACHED_SOCKET_VALID';

    /**
     * Cache time for Socket validation check
     */
    const CACHE_TTL_SOCKET_VALID                    = 60;

    // ================================================================================================================
    // Redis
    // ================================================================================================================

    /**
     * Redis connect timeout (seconds)
     */
    const REDIS_OPT_TIMEOUT                         = 2;

    /**
     * Redis read timeout (seconds)
     */
    const REDIS_OPT_READ_TIMEOUT                    = 10;

    /**
     * redis retry interval (milliseconds)
     */
    const REDIS_OPT_RETRY_INTERVAL                  = 200;

    // ================================================================================================================
    // EVE downtime
    // ================================================================================================================

    /**
     * SSO downtime length (estimation), minutes
     */
    const DOWNTIME_LENGTH                           = 8;

    /**
     * SSO downtime buffer length extends downtime length, minutes
     */
    const DOWNTIME_BUFFER                           = 1;

    // ================================================================================================================
    // ESI API id´s
    // ================================================================================================================

    /**
     * ESI categoryId or 'Structure's
     */
    const ESI_CATEGORY_STRUCTURE_ID                 = 65;

    /**
     * ESI categoryId or 'Ship's
     */
    const ESI_CATEGORY_SHIP_ID                      = 6;

    /**
     * ESI groupId or 'Wormhole's
     */
    const ESI_GROUP_WORMHOLE_ID                     = 988;

    /**
     * ESI dogmaAttributeId for 'scanWormholeStrength's
     */
    const ESI_DOGMA_ATTRIBUTE_SCANWHSTRENGTH_ID     = 1908;

    /**
     * error message for missing Composer dependency class
     */
    const ERROR_CLASS_NOT_EXISTS_COMPOSER           = 'Class "%s" not found. → Check installed Composer packages';

    /**
     * error message for missing Composer dependency method
     */
    const ERROR_METHOD_NOT_EXISTS_COMPOSER          = 'Method "%s()" not found in class "%s". → Check installed Composer packages';

    /**
     * environment config keys that should be parsed as array
     * -> use "," as delimiter in config files/data
     */
    const ARRAY_KEYS                                = ['CCP_ESI_SCOPES', 'CCP_ESI_SCOPES_ADMIN'];

    /**
     * custom HTTP status codes
     */
    const
        HTTP_422 = 'Unprocessable Entity';

    /**
     * all environment data
     * @var array
     */
    private $serverConfigData                       = [];

    /**
     * Config constructor.
     * @param \Base $f3
     */
    public function __construct(\Base $f3){
        // set server data
        // -> CGI params (Nginx)
        // -> .htaccess (Apache)
        $this->setServerData();
        // set environment data
        $this->setAllEnvironmentData($f3);
        // set hive configuration variables
        // -> overwrites default configuration
        $this->setHiveVariables($f3);

        // set global getter for \DateTimeZone
        $f3->set('getTimeZone', function() use ($f3) : \DateTimeZone {
            return new \DateTimeZone( $f3->get('TZ') );
        });

        // set global getter for new \DateTime
        $f3->set('getDateTime', function(string $time = 'now', ?\DateTimeZone $timeZone = null) use ($f3) : \DateTime {
            $timeZone = $timeZone ? : $f3->get('getTimeZone')();
           return new \DateTime($time, $timeZone);
        });

        // database connection pool -----------------------------------------------------------------------------------
        $f3->set(Pool::POOL_NAME, Pool::instance(
            function(string $alias) use ($f3) : array {
                // get DB config by alias for new connections
                return self::getDatabaseConfig($f3, $alias);
            },
            function(string $schema) use ($f3) : array {
                // get DB requirement vars from requirements.ini
                return self::getRequiredDbVars($f3, $schema);
            }
        ));

        // lazy init Web Api clients ----------------------------------------------------------------------------------
        $f3->set(SsoClient::CLIENT_NAME, SsoClient::instance());
        $f3->set(CcpClient::CLIENT_NAME, CcpClient::instance());
        $f3->set(GitHubClient::CLIENT_NAME, GitHubClient::instance());
        $f3->set(EveScoutClient::CLIENT_NAME, EveScoutClient::instance());

        // Socket connectors ------------------------------------------------------------------------------------------
        $f3->set(TcpSocket::SOCKET_NAME, function(array $options = ['timeout' => 1]) : SocketInterface {
            return AbstractSocket::factory(TcpSocket::class, self::getSocketUri(), $options);
        });
    }

    /**
     * get environment configuration data
     * @param \Base $f3
     * @return array|null
     */
    protected function getAllEnvironmentData(\Base $f3){
        if(!$f3->exists(self::HIVE_KEY_ENVIRONMENT, $environmentData)){
            $environmentData =  $this->setAllEnvironmentData($f3);
        }

        return $environmentData;
    }

    /**
     * set/overwrite some global framework variables original set in config.ini
     * -> can be  overwritten in environments.ini OR ENV-Vars
     * -> see: https://github.com/exodus4d/pathfinder/issues/175
     * that depend on environment settings
     * @param \Base $f3
     */
    protected function setHiveVariables(\Base $f3){
        // hive keys that can be overwritten
        $hiveKeys = ['BASE', 'URL', 'DEBUG', 'CACHE'];

        foreach($hiveKeys as $key){
            if( !is_null( $var = self::getEnvironmentData($key)) ){
                $f3->set($key,$var);
            }
        }
    }

    /**
     * set all environment configuration data
     * @param \Base $f3
     * @return array|mixed|null
     */
    protected function setAllEnvironmentData(\Base $f3){
        $environmentData = null;

        if( !empty($this->serverConfigData['ENV']) ){
            // get environment config from $_SERVER data
            $environmentData = (array)$this->serverConfigData['ENV'];

            // some environment variables should be parsed as array
            array_walk($environmentData, function(&$item, $key){
                $item = (in_array($key, self::ARRAY_KEYS)) ? explode(',', $item) : $item;
            });

            $environmentData['ENVIRONMENT_CONFIG'] = 'PHP: environment variables';
        }else{
            // get environment data from *.ini file config
            $customConfDir = $f3->get('CONF');

            // check "custom" ini dir, of not found check default ini dir
            foreach($customConfDir as $type => $path){
                $envConfFile = $path . 'environment.ini';
                $f3->config($envConfFile, true);

                if(
                    $f3->exists(self::HIVE_KEY_ENVIRONMENT) &&
                    ($environment = $f3->get(self::HIVE_KEY_ENVIRONMENT . '.SERVER')) &&
                    ($environmentData = $f3->get(self::HIVE_KEY_ENVIRONMENT . '.' . $environment))
                ){
                    $environmentData['ENVIRONMENT_CONFIG'] = 'Config: ' . $envConfFile;
                    break;
                }
            }
        }

        if( !is_null($environmentData) ){
            ksort($environmentData);
            $f3->set(self::HIVE_KEY_ENVIRONMENT, $environmentData);
        }

        return $environmentData;
    }

    /**
     * get/extract all server data passed to PHP
     * this can be done by either:
     * OS Environment variables:
     *  -> add to /etc/environment
     * OR:
     * Nginx (server config):
     * -> FastCGI syntax
     *      fastcgi_param PF-ENV-DEBUG 3;
     */
    protected function setServerData(){
        $data = [];
        foreach($_SERVER as $key => $value){
            if(strpos($key, self::PREFIX_KEY . self::ARRAY_DELIMITER) === 0){
                $path = explode( self::ARRAY_DELIMITER, $key);
                // remove prefix
                array_shift($path);

                $tmp = &$data;
                foreach($path as $segment){
                    $tmp[$segment] = (array)$tmp[$segment];
                    $tmp = &$tmp[$segment];
                }

                // type cast values
                // (e.g. '1.2' => (float); '4' => (int),...)
                $tmp = is_numeric($value) ? $value + 0 : $value;
            }
        }

        $this->serverConfigData = $data;
    }

    /**
     * get a environment variable by hive key
     * @param $key
     * @return string|null
     */
    static function getEnvironmentData($key){
        $hiveKey = self::HIVE_KEY_ENVIRONMENT . '.' . $key;
        \Base::instance()->exists($hiveKey, $data);
        return $data;
    }

    /**
     * get database config values
     * @param \Base $f3
     * @param string $alias
     * @return array
     */
    static function getDatabaseConfig(\Base $f3, string $alias) : array {
        $alias = strtoupper($alias);

        $config = [
            'ALIAS'     => $alias,
            'SCHEME'    => 'mysql',
            'HOST'      => 'localhost',
            'PORT'      => 3306,
            'SOCKET'    => null,
            'NAME'      => self::getEnvironmentData('DB_' . $alias . '_NAME'),
            'USER'      => self::getEnvironmentData('DB_' . $alias . '_USER'),
            'PASS'      => self::getEnvironmentData('DB_' . $alias . '_PASS')
        ];

        $pdoReg = '/^(?<SCHEME>[[:alpha:]]+):((host=(?<HOST>[a-zA-Z0-9-_\.]*))|(unix_socket=(?<SOCKET>[a-zA-Z0-9\/]*\.sock)))((;dbname=(?<NAME>\w*))|(;port=(?<PORT>\d*))){0,2}/';
        if(preg_match($pdoReg, self::getEnvironmentData('DB_' . $alias . '_DNS'), $matches)){
            // remove unnamed matches
            $matches = array_intersect_key($matches, $config);
            // remove empty matches
            $matches = array_filter($matches);
            // merge matches with default config
            $config = array_merge($config, $matches);
        }

        // connect options --------------------------------------------------------------------------------------------
        $options = [
            \PDO::ATTR_ERRMODE          => \PDO::ERRMODE_EXCEPTION,
            \PDO::ATTR_TIMEOUT          => $f3->get('REQUIREMENTS.MYSQL.PDO_TIMEOUT')
        ];

        if($config['SCHEME'] == 'mysql'){
            $options[\PDO::MYSQL_ATTR_COMPRESS]     = true;
            $options[\PDO::MYSQL_ATTR_INIT_COMMAND] = implode(',', [
                "SET NAMES " . self::getRequiredDbVars($f3, $config['SCHEME'])['CHARACTER_SET_CONNECTION'] . " COLLATE " . self::getRequiredDbVars($f3, $config['SCHEME'])['COLLATION_CONNECTION'],
                "@@session.time_zone = '+00:00'",
                "@@session.default_storage_engine = " . self::getRequiredDbVars($f3, $config['SCHEME'])['DEFAULT_STORAGE_ENGINE']
            ]);
        }

        if(self::getPathfinderData('experiments.persistent_db_connections')){
            $options[\PDO::ATTR_PERSISTENT] = true;
        }

        $config['OPTIONS'] = $options;

        return $config;
    }

    /**
     * get required MySQL variables from requirements.ini
     * @param \Base $f3
     * @param string $schema
     * @return array
     */
    static function getRequiredDbVars(\Base $f3, string $schema) : array {
        return $f3->exists('REQUIREMENTS[' . strtoupper($schema) . '][VARS]', $vars) ? $vars : [];
    }

    /**
     * get SMTP config values
     * @return \stdClass
     */
    static function getSMTPConfig() : \stdClass{
        $config             = new \stdClass();
        $config->host       = self::getEnvironmentData('SMTP_HOST');
        $config->port       = self::getEnvironmentData('SMTP_PORT');
        $config->scheme     = self::getEnvironmentData('SMTP_SCHEME');
        $config->username   = self::getEnvironmentData('SMTP_USER');
        $config->password   = self::getEnvironmentData('SMTP_PASS');
        $config->from       = [
            self::getEnvironmentData('SMTP_FROM') => self::getPathfinderData('name')
        ];
        return $config;
    }

    /**
     * validates an SMTP config
     * @param \stdClass $config
     * @return bool
     */
    static function isValidSMTPConfig(\stdClass $config) : bool {
        // validate email from either an configured array or plain string
        $validateMailConfig = function($mailConf = null) : bool {
            $email = null;
            if(is_array($mailConf)){
                reset($mailConf);
                $email = key($mailConf);
            }elseif(is_string($mailConf)){
                $email = $mailConf;
            }
            return \Audit::instance()->email($email);
        };

        return (
            !empty($config->host) &&
            !empty($config->username) &&
            $validateMailConfig($config->from) &&
            $validateMailConfig($config->to)
        );
    }

    /**
     * get email for notifications by hive key
     * @param $key
     * @return mixed
     */
    static function getNotificationMail($key){
        return self::getPathfinderData('notification' . ($key ? '.' . $key : ''));
    }

    /**
     * get map default config values for map types (private/corp/ally)
     * -> read from pathfinder.ini
     * @param string $mapType
     * @return mixed
     */
    static function getMapsDefaultConfig($mapType = ''){
        if( $mapConfig = self::getPathfinderData('map' . ($mapType ? '.' . $mapType : '')) ){
            $mapConfig = Util::arrayChangeKeyCaseRecursive($mapConfig);
        }

        return $mapConfig;
    }

    /**
     * get Plugin config from `plugin.ini`
     * @param string|null $key
     * @param bool $checkEnabled
     * @return array|null
     */
    static function getPluginConfig(?string $key, bool $checkEnabled = true) : ?array {
        $isEnabled = $checkEnabled ?
            filter_var(\Base::instance()->get(
                self::HIVE_KEY_PLUGIN . '.' . strtoupper($key) . '_ENABLED'),
                FILTER_VALIDATE_BOOLEAN
            ) :
            true;

        $data = null;
        if($isEnabled){
            $hiveKey = self::HIVE_KEY_PLUGIN . '.' . strtoupper($key);
            $data = (array)\Base::instance()->get($hiveKey);
        }
        return $data;
    }

    /**
     * use this function to "validate" the socket connection.
     * The result will be CACHED for a few seconds!
     * This function is intended to pre-check a Socket connection if it MIGHT exists.
     * No data will be send to the Socket, this function just validates if a socket is available
     * -> see pingDomain()
     * @param string $uri
     * @return bool
     */
    static function validSocketConnect(string $uri) : bool{
        $valid = false;
        $f3 = \Base::instance();

        if( !$f3->exists(self::CACHE_KEY_SOCKET_VALID, $valid) ){
            if( $socketUrl = self::getSocketUri() ){
                // get socket URI parts -> not elegant...
                $domain = parse_url( $socketUrl, PHP_URL_SCHEME) . '://' . parse_url( $socketUrl, PHP_URL_HOST);
                $port = parse_url( $socketUrl, PHP_URL_PORT);
                // check connection -> get ms
                $status = self::pingDomain($domain, $port);
                if($status >= 0){
                    // connection OK
                    $valid = true;
                }else{
                    // connection error/timeout
                    $valid = false;
                }
            }else{
                // requirements check failed or URL not valid
                $valid = false;
            }

            $f3->set(self::CACHE_KEY_SOCKET_VALID, $valid, self::CACHE_TTL_SOCKET_VALID);
        }

        return $valid;
    }

    /**
     * get response time for a host in ms or -1 on error/timeout
     * @param string $domain
     * @param int $port
     * @param int $timeout
     * @return int
     */
    static function pingDomain(string $domain, int $port, $timeout = 1) : int {
        $startTime = microtime(true);
        $file      = @fsockopen ($domain, $port, $errno, $errstr, $timeout);
        $stopTime  = microtime(true);

        if (!$file){
            // Site is down
            $status = -1;
        }else {
            fclose($file);
            $status = ($stopTime - $startTime) * 1000;
            $status = floor($status);
        }
        return $status;
    }

    /**
     * get URI for TCP socket
     * @return bool|string
     */
    static function getSocketUri(){
        $uri = false;

        if(
            ( $ip = self::getEnvironmentData('SOCKET_HOST') ) &&
            ( $port = self::getEnvironmentData('SOCKET_PORT') )
        ){
            $uri = 'tcp://' . $ip . ':' . $port;
        }
        return $uri;
    }

    /**
     * @param string $key
     * @return null|mixed
     */
    static function getPathfinderData($key = ''){
        $hiveKey = self::HIVE_KEY_PATHFINDER . ($key ? '.' . strtoupper($key) : '');
        if( !\Base::instance()->exists($hiveKey, $data) ){
            $data = null;
        }
        return $data;
    }

    /**
     * get HTTP status by HTTP return code
     * -> either from F3 or from self::Config constants
     * @param int $code
     * @return string
     */
    static function getHttpStatusByCode(int $code) : string {
        if(empty($status = @constant('Base::HTTP_' .  $code))){
            $status = @constant('self::HTTP_' .  $code);
        }
        return $status;
    }

    /**
     * parse [D]ata [S]ource [N]ame string from *.ini into $conf parts
     * -> $dsn = redis=localhost:6379:2
     *    $conf = ['type' => 'redis', 'host' => 'localhost', 'port' => 6379, 'db' => 2]
     * -> some $conf values might be NULL if not found in $dsn!
     * -> some missing values become defaults
     * @param string $dsn
     * @param array|null $conf
     * @return bool
     */
    static function parseDSN(string $dsn, ?array &$conf = []) : bool {
        // reset reference
        if($matches = (bool)preg_match('/^(\w+)\h*=\h*(.+)/', strtolower(trim($dsn)), $parts)){
            $conf['type'] = $parts[1];
            if($conf['type'] == 'redis'){
                [$conf['host'], $conf['port'], $conf['db'], $conf['auth']] = explode(':', $parts[2]) + [1 => 6379, 2 => null, 3 => null];
            }elseif($conf['type'] == 'folder'){
                $conf['folder'] = $parts[2];
            }
            // int cast numeric values
            $conf = array_map(function($val){
                return is_numeric($val) ? intval($val) : $val;
            }, $conf);
        }
        return $matches;
    }

    /**
     * check if a given DateTime() is within downTime range: downtime + 10m
     * -> can be used for prevent logging errors during downTime
     * @param \DateTime|null $dateCheck
     * @return bool
     */
    static function inDownTimeRange(\DateTime $dateCheck = null) : bool {
        $inRange = false;
        // default daily downtime 00:00am
        $downTimeParts = [0, 0];
        if( !empty($downTime = (string)self::getEnvironmentData('CCP_SSO_DOWNTIME')) ){
            $parts = array_map('intval', explode(':', $downTime));
            if(count($parts) === 2){
                // well formatted DOWNTIME found in config files
                $downTimeParts = $parts;
            }
        }

        try{
            // downTime Range is 10m
            $downtimeLength = self::DOWNTIME_LENGTH + (2 * self::DOWNTIME_BUFFER);
            $timezone = \Base::instance()->get('getTimeZone')();

            // if not set -> use current time
            $dateCheck = is_null($dateCheck) ? new \DateTime('now', $timezone) : $dateCheck;
            $dateDowntimeStart = new \DateTime('now', $timezone);
            $dateDowntimeStart->setTime($downTimeParts[0],$downTimeParts[1]);
            $dateDowntimeStart->sub(new \DateInterval('PT' . self::DOWNTIME_BUFFER . 'M'));

            $dateDowntimeEnd = clone $dateDowntimeStart;
            $dateDowntimeEnd->add(new \DateInterval('PT' . $downtimeLength . 'M'));

            $dateRange = new DateRange($dateDowntimeStart, $dateDowntimeEnd);
            $inRange = $dateRange->inRange($dateCheck);
        }catch(\Exception $e){
            $f3 = \Base::instance();
            $f3->error(500, $e->getMessage(), $e->getTrace());
        }

        return $inRange;
    }

    /**
     * format timeInterval in seconds into human readable string
     * @param int $seconds
     * @return string
     * @throws \Exception
     */
    static function formatTimeInterval(int $seconds = 0) : string {
        $dtF = new \DateTime('@0');
        $dtT = new \DateTime("@" . $seconds);
        $diff = $dtF->diff($dtT);

        $format = ($d = $diff->format('%d')) ? $d . 'd ' : '';
        $format .= ($h = $diff->format('%h')) ? $h . 'h ' : '';
        $format .= ($i = $diff->format('%i')) ? $i . 'm ' : '';
        $format .= ($s = $diff->format('%s')) ? $s . 's' : '';
        return $format;
    }

    /**
     * @param $fromExists
     * @param int $ttlMax
     * @return int
     */
    static function ttlLeft($fromExists, int $ttlMax) : int {
        $ttlMax = max($ttlMax, 0);
        if($fromExists){
            // == true || array
            if(is_array($fromExists)){
                return max(min((int)ceil(round(array_sum($fromExists) - microtime(true), 4)), $ttlMax), 0);
            }else{
                return 0;
            }
        }else{
            // == false
            return $ttlMax;
        }
    }

    /**
     * @param string|null $class
     * @return string
     */
    static function withNamespace(?string $class) : string {
        $path = [\Base::instance()->get('NAMESPACE')];
        if($class){
            $path[] = $class;
        }
        return implode('\\', $path);
    }
}

redpajama_set_name: RedPajamaGithub


text:
<?php

class CSSUnityOptionParser {
    public $input;
    public $type;
    public $output_dir;
    public $output_name;
    public $separate;
    public $mhtml_uri;
    public $root;
    public $substitute;
    public $recursive;

    /**
     * Creates a new instance of this class.
     *
     * @param array $options string array of options
     * @param bool $recursive if input contains directories, recurses through all subdirectories
     */
    function __construct($options) {
        if (empty($options)) {
            $this->_error_write("Options argument is required.", 1);
        }

        if (!is_array($options)) {
            $this->_error_write("Options argument must be a string array of options.", 2);
        }

        // parse options into variables
        $this->input = $this->_getopt_or_default($options, array('input', 'i'), null);
        $this->type = $this->_getopt_or_default($options, array('type', 't'), 'all');
        $this->separate = isset($options['separate']) || isset($options['s']);

        if ($this->_is_cli()) {
            $this->output_dir = $this->_getopt_or_default($options, array('output', 'o'), getcwd());
            $this->output_dir = str_replace('//', '/', $this->output_dir . '/');
            $inputs = explode(',', $this->input);
            $inputpath = pathinfo($inputs[0]);
            $this->output_name = $this->_getopt_or_default($options, array('output-name', 'n'), $inputpath['filename']);
            $this->mhtml_uri = $this->_getopt_or_default($options, array('mhtml-uri', 'm'), false);
            if ($this->mhtml_uri) {
                // add trailing slash
                $this->mhtml_uri .= '/';

                // remove duplicates
                $this->mhtml_uri = preg_replace('/\/{2}$/', '/', $this->mhtml_uri);
            } else {
                if ($this->type === 'all' || $this->type === 'mhtml') {
                    $this->_error_write("Absolute URI for MHTML is required if type is 'all' or 'mhtml'.");
                    $this->_error_write("Try 'unify.php' for more information.", 3);
                }
            }
        }

        $this->root = $this->_getopt_or_default($options, array('root', 'r'), '');
        $this->substitute = $this->_getopt_or_default($options, array('substitute', 'S'), '');
        $this->recursive = isset($options['recursive']) || isset($options['R']);
    }

    private function _getopt_or_default($options, $keys, $default) {
        $value = $default;
        foreach ($keys as $key) {
            if (isset($options[$key])) {
                return $options[$key];
            }
        }
        return $value;
    }

    private function _is_cli() {
        return (php_sapi_name() == 'cli' && empty($_SERVER['REMOTE_ADDR']));
    }

    private function _error_write($message, $status=false) {
        if ($this->_is_cli()) {
            fwrite(STDERR, "$message\n");
        } else {
            echo "$message\n";
        }

        if (is_int($status)) {
            exit($status);
        }
    }
}
?>


text:
<?php
namespace Blog\Form;
use Blog\Model\Post;
use Zend\Form\Fieldset;
use Zend\Stdlib\Hydrator\ClassMethods;

class PostFieldset  extends FieldSet
{
	public function __construct($name= null ,$options =array()){
		parent::__construct($name ,$options);
		$this->setHydrator(new ClassMethods(false));
		$this->setObject(new Post());
		$this->add(array(
					'type'=>'hidden',
					'name'=>'id'
					));

		$this->add(array(
					'type'=>'text',
					'name'=>'text',
					'options'=>array(
						'label'=>'Blog text'
						)
					));

		$this->add(
				array(
					'type'=>'text',
					'name'=>'title',
					'options'=>array(
						'label'=>'Blog Title'
						),
					));
	}

}


text:
package fqdn

import (
	"encoding/json"
	"net"
	"regexp"
	"sort"
	"time"
	"unsafe"

	"github.com/cilium/cilium/pkg/fqdn/matchpattern"
	"github.com/cilium/cilium/pkg/fqdn/re"
	"github.com/cilium/cilium/pkg/ip"
	"github.com/cilium/cilium/pkg/lock"
	"github.com/cilium/cilium/pkg/option"
)

// cacheEntry objects hold data passed in via DNSCache.Update, nominally
// equating to a DNS lookup. They are internal to DNSCache and should not be
// returned.
// cacheEntry objects are immutable once created; the address of an instance is
// a unique identifier.
// Note: the JSON names are intended to correlate to field names from
// api/v1/models.DNSLookup to allow dumping the json from
// `cilium fqdn cache list` to a file that can be unmarshalled via
// `--tofqdns-per-cache`
type cacheEntry struct {
	// Name is a DNS name, it my be not fully qualified (e.g. myservice.namespace)
	Name string `json:"fqdn,omitempty"`

	// LookupTime is when the data begins being valid
	LookupTime time.Time `json:"lookup-time,omitempty"`

	// ExpirationTime is a calcutated time when the DNS data stops being valid.
	// It is simply LookupTime + TTL
	ExpirationTime time.Time `json:"expiration-time,omitempty"`

	// TTL represents the number of seconds past LookupTime that this data is
	// valid.
	TTL int `json:"ttl,omitempty"`

	// IPs are the IPs associated with Name for this cacheEntry.
	IPs []net.IP `json:"ips,omitempty"`
}

// isExpiredBy returns true if entry is no longer valid at pointInTime
func (entry *cacheEntry) isExpiredBy(pointInTime time.Time) bool {
	return pointInTime.After(entry.ExpirationTime)
}

// ipEntries maps a unique IP to the cacheEntry that provides it in .IPs.
// Multiple IPs may point to the same cacheEntry, or they may all be different.
// Crucially, an IP may be present in a cacheEntry but the IP in ipEntries
// points to another cacheEntry. This is because the second cacheEntry has a
// later expiration for this specific IP, and may not include the other IPs
// provided by the first entry.
// The DNS name in the entries is not checked, but is assumed to be the same
// for all entries.
// Note: They are guarded by the DNSCache mutex.
type ipEntries map[string]*cacheEntry

// nameEntries maps a DNS name to the cache entry that inserted it into the
// cache. It used in reverse DNS lookups. It is similar to ipEntries, above,
// but the key is a DNS name.
type nameEntries map[string]*cacheEntry

// getIPs returns a sorted list of non-expired unique IPs.
// This needs a read-lock
func (s ipEntries) getIPs(now time.Time) []net.IP {
	ips := make([]net.IP, 0, len(s)) // worst case size
	for ip, entry := range s {
		if entry != nil && !entry.isExpiredBy(now) {
			ips = append(ips, net.ParseIP(ip))
		}
	}

	return ip.KeepUniqueIPs(ips) // sorts IPs
}

// DNSCache manages DNS data that will expire after a certain TTL. Information
// is tracked per-IP address, retaining the latest-expiring DNS data for each
// address.
// For most real-world DNS data, the entry per name remains small because newer
// lookups replace older ones. Large TTLs may cause entries to grow if many
// unique IPs are returned in separate lookups.
// It is critical to run .GC periodically. This cleans up expired entries and
// steps forward the time used to determine that entries are expired. This
// means that the Lookup functions may return expired entries until GC is
// called.
// Redundant entries are removed on insert.
type DNSCache struct {
	lock.RWMutex

	// forward DNS lookups name -> IPEntries
	// IPEntries maps IP -> entry that provides it. An entry may provide multiple IPs.
	forward map[string]ipEntries

	// IP->dnsNames lookup
	// This map is subordinate to forward, above. An IP inserted into forward, or
	// expired in forward, should also be added/removed in reverse.
	reverse map[string]nameEntries

	// LastCleanup is the latest time for which entries have been expired. It is
	// used as "now" when doing lookups and advanced by calls to .GC
	// When an entry is added with an expiration time before lastCleanup, it is
	// set to that value.
	lastCleanup time.Time

	// cleanup maps the TTL expiration times (in seconds since the epoch) to
	// DNS names that expire in that second. On every new insertion where the
	// new data is actually inserted into the cache (i.e. it expires later than
	// an existing entry) cleanup will be updated. CleanupExpiredEntries cleans
	// up these entries on demand.
	// Note: Lookup functions will not return expired entries, and this is used
	// to proactively enforce expirations.
	// Note: It is important to periodically call CleanupExpiredEntries
	// otherwise this map will grow forever.
	cleanup map[int64][]string

	// overLimit is a set of DNS names that were over the per-host configured
	// limit when they received an update. The excess IPs will be removed when
	// cleanupOverLimitEntries is called, but will continue to be returned by
	// Lookup until then.
	// Note: It is important to periodically call GC otherwise this map will
	// grow forever (it is very bounded, however).
	overLimit map[string]bool

	// perHostLimit is the number of maximum number of IP per host.
	perHostLimit int

	// minTTL is the minimun TTL value that a cache entry can have, if the TTL
	// sent in the Update is lower, the TTL will be owerwritten to this value.
	// Due is only read-only is not protected by the mutex.
	minTTL int
}

// NewDNSCache returns an initialized DNSCache
func NewDNSCache(minTTL int) *DNSCache {
	c := &DNSCache{
		forward: make(map[string]ipEntries),
		reverse: make(map[string]nameEntries),
		// lastCleanup is populated on the first insert
		cleanup:      map[int64][]string{},
		overLimit:    map[string]bool{},
		perHostLimit: 0,
		minTTL:       minTTL,
	}
	return c
}

// NewDNSCache returns an initialized DNSCache and set the max host limit to
// the given argument
func NewDNSCacheWithLimit(minTTL int, limit int) *DNSCache {
	c := NewDNSCache(minTTL)
	c.perHostLimit = limit
	return c
}

func (c *DNSCache) DisableCleanupTrack() {
	c.Lock()
	defer c.Unlock()
	c.cleanup = nil
}

// Update inserts a new entry into the cache.
// After insertion cache entries for name are expired and redundant entries
// evicted. This is O(number of new IPs) for eviction, and O(number of IPs for
// name) for expiration.
// lookupTime is the time the DNS information began being valid. It should be
// in the past.
// name is used as is and may be an unqualified name (e.g. myservice.namespace).
// ips may be an IPv4 or IPv6 IP. Duplicates will be removed.
// ttl is the DNS TTL for ips and is a seconds value.
func (c *DNSCache) Update(lookupTime time.Time, name string, ips []net.IP, ttl int) bool {
	if c.minTTL > ttl {
		ttl = c.minTTL
	}

	entry := &cacheEntry{
		Name:           name,
		LookupTime:     lookupTime,
		ExpirationTime: lookupTime.Add(time.Duration(ttl) * time.Second),
		TTL:            ttl,
		IPs:            ips,
	}

	c.Lock()
	defer c.Unlock()
	return c.updateWithEntry(entry)
}

// updateWithEntry implements the insertion of a cacheEntry. It is used by
// DNSCache.Update and DNSCache.UpdateWithEntry.
// This needs a write lock
func (c *DNSCache) updateWithEntry(entry *cacheEntry) bool {
	changed := false
	entries, exists := c.forward[entry.Name]
	if !exists {
		changed = true
		entries = make(map[string]*cacheEntry)
		c.forward[entry.Name] = entries
	}

	if c.updateWithEntryIPs(entries, entry) {
		changed = true
	}

	if c.perHostLimit > 0 && len(entries) > c.perHostLimit {
		c.overLimit[entry.Name] = true
	}
	return changed
}

// AddNameToCleanup adds the IP with the given TTL to the the cleanup map to
// delete the entry from the policy when it expires.
// Need to be called with a write lock
func (c *DNSCache) addNameToCleanup(entry *cacheEntry) {
	if c.cleanup == nil {
		return
	}
	if c.lastCleanup.IsZero() || entry.ExpirationTime.Before(c.lastCleanup) {
		c.lastCleanup = entry.ExpirationTime
	}
	expiration := entry.ExpirationTime.Unix()
	expiredEntries, exists := c.cleanup[expiration]
	if !exists {
		expiredEntries = []string{}
	}
	c.cleanup[expiration] = append(expiredEntries, entry.Name)
}

// cleanupExpiredEntries cleans all the expired entries since lastCleanup up to
// expires, but not including it. lastCleanup is set to expires and later
// cleanups begin from that time.
// It returns the list of names that have expired data and a map of removed DNS
// cache entries, keyed by IP.
func (c *DNSCache) cleanupExpiredEntries(expires time.Time) (affectedNames []string, removed map[string][]*cacheEntry) {
	if c.lastCleanup.IsZero() {
		return nil, nil
	}

	var toCleanNames []string
	for c.lastCleanup.Before(expires) {
		key := c.lastCleanup.Unix()
		if entries, exists := c.cleanup[key]; exists {
			toCleanNames = append(toCleanNames, entries...)
			delete(c.cleanup, key)
		}
		c.lastCleanup = c.lastCleanup.Add(time.Second).Truncate(time.Second)
	}

	removed = make(map[string][]*cacheEntry)
	for _, name := range KeepUniqueNames(toCleanNames) {
		if entries, exists := c.forward[name]; exists {
			affectedNames = append(affectedNames, name)
			for ip, entry := range c.removeExpired(entries, c.lastCleanup, time.Time{}) {
				removed[ip] = append(removed[ip], entry)
			}
		}
	}

	return affectedNames, removed
}

// cleanupOverLimitEntries returns the names that has reached the max number of
// IP per host. Internally the function sort the entries by the expiration
// time.
func (c *DNSCache) cleanupOverLimitEntries() (affectedNames []string, removed map[string][]*cacheEntry) {
	type IPEntry struct {
		ip    string
		entry *cacheEntry
	}
	removed = make(map[string][]*cacheEntry)

	// For global cache the limit maybe is not used at all.
	if c.perHostLimit == 0 {
		return affectedNames, nil
	}

	for dnsName := range c.overLimit {
		entries, ok := c.forward[dnsName]
		if !ok {
			continue
		}
		overlimit := len(entries) - c.perHostLimit
		if overlimit <= 0 {
			continue
		}
		sortedEntries := make([]IPEntry, 0, len(entries))
		for ip, entry := range entries {
			sortedEntries = append(sortedEntries, IPEntry{ip, entry})
		}

		sort.Slice(sortedEntries, func(i, j int) bool {
			return sortedEntries[i].entry.ExpirationTime.Before(sortedEntries[j].entry.ExpirationTime)
		})

		for i := 0; i < overlimit; i++ {
			key := sortedEntries[i]
			delete(entries, key.ip)
			c.remove(key.ip, key.entry)
			removed[key.ip] = append(removed[key.ip], key.entry)
		}
		affectedNames = append(affectedNames, dnsName)
	}
	c.overLimit = map[string]bool{}
	return affectedNames, removed
}

// GC cleans TTL expired entries up to now, and overlimit entries, returning
// both sets.
// If zombies is passed in, expired IPs are inserted into it. GC and
// other management of zombies is left to the caller.
// Note: zombies use the original lookup's ExpirationTime for DeletePendingAt,
// not the now parameter. This allows better ordering in zombie GC.
func (c *DNSCache) GC(now time.Time, zombies *DNSZombieMappings) (affectedNames []string) {
	c.Lock()
	expiredNames, expiredEntries := c.cleanupExpiredEntries(now)
	overLimitNames, overLimitEntries := c.cleanupOverLimitEntries()
	c.Unlock()

	if zombies != nil {
		// Iterate over 2 maps
		for _, m := range []map[string][]*cacheEntry{
			expiredEntries,
			overLimitEntries,
		} {
			for ipStr, entries := range m {
				for _, entry := range entries {
					zombies.Upsert(entry.ExpirationTime, ipStr, entry.Name)
				}
			}
		}
	}

	return KeepUniqueNames(append(expiredNames, overLimitNames...))
}

// UpdateFromCache is a utility function that allows updating a DNSCache
// instance with all the internal entries of another. Latest-Expiration still
// applies, thus the merged outcome is consistent with adding the entries
// individually.
// When namesToUpdate has non-zero length only those names are updated from
// update, otherwise all DNS names in update are used.
func (c *DNSCache) UpdateFromCache(update *DNSCache, namesToUpdate []string) {
	if update == nil {
		return
	}

	c.Lock()
	defer c.Unlock()
	c.updateFromCache(update, namesToUpdate)
}

func (c *DNSCache) updateFromCache(update *DNSCache, namesToUpdate []string) {
	update.RLock()
	defer update.RUnlock()

	if len(namesToUpdate) == 0 {
		for name := range update.forward {
			namesToUpdate = append(namesToUpdate, name)
		}
	}
	for _, name := range namesToUpdate {
		newEntries, exists := update.forward[name]
		if !exists {
			continue
		}
		for _, newEntry := range newEntries {
			c.updateWithEntry(newEntry)
		}
	}
}

// ReplaceFromCacheByNames operates as an atomic combination of ForceExpire and
// multiple UpdateFromCache invocations. The result is to collect all entries
// for DNS names in namesToUpdate from each DNSCache in updates, replacing the
// current entries for each of those names.
func (c *DNSCache) ReplaceFromCacheByNames(namesToUpdate []string, updates ...*DNSCache) {
	c.Lock()
	defer c.Unlock()

	// Remove any DNS name in namesToUpdate with a lookup before "now". This
	// effectively deletes all lookups because we're holding the lock.
	c.forceExpireByNames(time.Now(), namesToUpdate)

	for _, update := range updates {
		c.updateFromCache(update, namesToUpdate)
	}
}

// Lookup returns a set of unique IPs that are currently unexpired for name, if
// any exist. An empty list indicates no valid records exist. The IPs are
// returned sorted.
func (c *DNSCache) Lookup(name string) (ips []net.IP) {
	c.RLock()
	defer c.RUnlock()

	return c.lookupByTime(c.lastCleanup, name)
}

// lookupByTime takes a timestamp for expiration comparisons, and is only
// intended for testing.
func (c *DNSCache) lookupByTime(now time.Time, name string) (ips []net.IP) {
	entries, found := c.forward[name]
	if !found {
		return nil
	}

	return entries.getIPs(now)
}

// LookupByRegexp returns all non-expired cache entries that match re as a map
// of name -> IPs
func (c *DNSCache) LookupByRegexp(re *regexp.Regexp) (matches map[string][]net.IP) {
	return c.lookupByRegexpByTime(c.lastCleanup, re)
}

// lookupByRegexpByTime takes a timestamp for expiration comparisons, and is
// only intended for testing.
func (c *DNSCache) lookupByRegexpByTime(now time.Time, re *regexp.Regexp) (matches map[string][]net.IP) {
	matches = make(map[string][]net.IP)

	c.RLock()
	defer c.RUnlock()

	for name, entry := range c.forward {
		if re.MatchString(name) {
			if ips := entry.getIPs(now); len(ips) > 0 {
				matches[name] = append(matches[name], ips...)
			}
		}
	}

	return matches
}

// LookupIP returns all DNS names in entries that include that IP. The cache
// maintains the latest-expiring entry per-name per-IP. This means that multiple
// names referrring to the same IP will expire from the cache at different times,
// and only 1 entry for each name-IP pair is internally retained.
func (c *DNSCache) LookupIP(ip net.IP) (names []string) {
	c.RLock()
	defer c.RUnlock()

	return c.lookupIPByTime(c.lastCleanup, ip)
}

// lookupIPByTime takes a timestamp for expiration comparisons, and is
// only intended for testing.
func (c *DNSCache) lookupIPByTime(now time.Time, ip net.IP) (names []string) {
	ipKey := ip.String()
	cacheEntries, found := c.reverse[ipKey]
	if !found {
		return nil
	}

	for name, entry := range cacheEntries {
		if entry != nil && !entry.isExpiredBy(now) {
			names = append(names, name)
		}
	}

	sort.Strings(names)
	return names
}

// updateWithEntryIPs adds a mapping for every IP found in `entry` to `ipEntries`
// (which maps IP -> cacheEntry). It will replace existing IP->old mappings in
// `entries` if the current entry expires sooner (or has already expired).
// This needs a write lock
func (c *DNSCache) updateWithEntryIPs(entries ipEntries, entry *cacheEntry) bool {
	added := false
	for _, ip := range entry.IPs {
		ipStr := ip.String()
		old, exists := entries[ipStr]
		if old == nil || !exists || old.isExpiredBy(entry.ExpirationTime) {
			entries[ipStr] = entry
			c.upsertReverse(ipStr, entry)
			c.addNameToCleanup(entry)
			added = true
		}
	}
	return added

}

// removeExpired removes expired (or nil) cacheEntry pointers from entries, an
// ipEntries instance for a specific name. It returns a boolean if any entry is
// removed.
// now is the "current time" and entries with ExpirationTime before then are
// removed.
// expireLookupsBefore is an optional parameter. It causes any entry with a
// LookupTime before it to be expired. It is intended for use with cache
// clearing functions like ForceExpire, and does not maintain the cache's
// guarantees.
// This needs a write lock
func (c *DNSCache) removeExpired(entries ipEntries, now time.Time, expireLookupsBefore time.Time) (removed ipEntries) {
	removed = make(ipEntries)
	for ip, entry := range entries {
		if entry == nil || entry.isExpiredBy(now) || entry.LookupTime.Before(expireLookupsBefore) {
			delete(entries, ip)
			c.remove(ip, entry)
			removed[ip] = entry
		}
	}

	return removed
}

// upsertReverse updates the reverse DNS cache for ip with entry, if it expires
// later than the already-stored entry.
// It is assumed that entry includes ip.
// This needs a write lock
func (c *DNSCache) upsertReverse(ip string, entry *cacheEntry) {
	entries, exists := c.reverse[ip]
	if entries == nil || !exists {
		entries = make(map[string]*cacheEntry)
		c.reverse[ip] = entries
	}
	entries[entry.Name] = entry
}

// remove removes the reference between ip and the name stored in entry from
// the DNS cache (both in forward and reverse maps). This assumes the write
// lock is taken.
func (c *DNSCache) remove(ip string, entry *cacheEntry) {
	c.removeForward(ip, entry)
	c.removeReverse(ip, entry)
}

// removeForward removes the reference between ip and the name stored in entry.
// When no more references from ip to any name exist, the map entry is deleted
// outright.
// It is assumed that entry includes ip.
// This needs a write lock.
func (c *DNSCache) removeForward(ip string, entry *cacheEntry) {
	entries, exists := c.forward[entry.Name]
	if entries == nil || !exists {
		return
	}
	delete(entries, ip)
	if len(entries) == 0 {
		delete(c.forward, entry.Name)
	}
}

// removeReverse is the equivalent of removeForward() but for the reverse map.
func (c *DNSCache) removeReverse(ip string, entry *cacheEntry) {
	entries, exists := c.reverse[ip]
	if entries == nil || !exists {
		return
	}
	delete(entries, entry.Name)
	if len(entries) == 0 {
		delete(c.reverse, ip)
	}
}

// ForceExpire is used to clear entries from the cache before their TTL is
// over. This operation does not keep previous guarantees that, for each IP,
// the most recent lookup to provide that IP is used.
// Note that all parameters must match, if provided. `time.Time{}` is the
// match-all time parameter.
// For example:
//   ForceExpire(time.Time{}, 'cilium.io') expires all entries for cilium.io.
//   ForceExpire(time.Now(), 'cilium.io') expires all entries for cilium.io
//   that expired before the current time.
// expireLookupsBefore requires a lookup to have a LookupTime before it in
// order to remove it.
// nameMatch will remove any DNS names that match.
func (c *DNSCache) ForceExpire(expireLookupsBefore time.Time, nameMatch *regexp.Regexp) (namesAffected []string) {
	c.Lock()
	defer c.Unlock()

	for name, entries := range c.forward {
		// If nameMatch was passed in, we must match it. Otherwise, "match all".
		if nameMatch != nil && !nameMatch.MatchString(name) {
			continue
		}
		// We pass expireLookupsBefore as the `now` parameter but it is redundant
		// because LookupTime must be before ExpirationTime.
		// The second expireLookupsBefore actually matches lookup times, and will
		// delete the entries completely.
		for _, entry := range c.removeExpired(entries, expireLookupsBefore, expireLookupsBefore) {
			namesAffected = append(namesAffected, entry.Name)
		}
	}

	return KeepUniqueNames(namesAffected)
}

func (c *DNSCache) forceExpireByNames(expireLookupsBefore time.Time, names []string) (namesAffected []string) {
	for _, name := range names {
		entries, exists := c.forward[name]
		if !exists {
			continue
		}

		// We pass expireLookupsBefore as the `now` parameter but it is redundant
		// because LookupTime must be before ExpirationTime.
		// The second expireLookupsBefore actually matches lookup times, and will
		// delete the entries completely.
		for _, entry := range c.removeExpired(entries, expireLookupsBefore, expireLookupsBefore) {
			namesAffected = append(namesAffected, entry.Name)
		}
	}

	return namesAffected
}

// Dump returns unexpired cache entries in the cache. They are deduplicated,
// but not usefully sorted. These objects should not be modified.
func (c *DNSCache) Dump() (lookups []*cacheEntry) {
	c.RLock()
	defer c.RUnlock()

	// Collect all the still-valid entries
	lookups = make([]*cacheEntry, 0, len(c.forward))
	for _, entries := range c.forward {
		for _, entry := range entries {
			lookups = append(lookups, entry)
		}
	}

	// Dedup the entries. They are created once and are immutable so the address
	// is a unique identifier.
	// We iterate through the list, keeping unique pointers. This is correct
	// because the list is sorted and, if two consecutive entries are the same,
	// it is safe to overwrite the second duplicate.
	sort.Slice(lookups, func(i, j int) bool {
		return uintptr(unsafe.Pointer(lookups[i])) < uintptr(unsafe.Pointer(lookups[j]))
	})

	deduped := lookups[:0] // len==0 but cap==cap(lookups)
	for readIdx, lookup := range lookups {
		if readIdx == 0 || deduped[len(deduped)-1] != lookups[readIdx] {
			deduped = append(deduped, lookup)
		}
	}

	return deduped
}

// Count returns two values, the count of still-valid FQDNs inside the DNS
// cache and the count of the still-valid entries (IPs) in the DNS cache.
//
// The FQDN count returns the length of the DNS cache size.
//
// The IP count is not deduplicated, see Dump(). In other words, this value
// represents an accurate tally of IPs associated with an FQDN in the DNS
// cache.
func (c *DNSCache) Count() (uint64, uint64) {
	c.RLock()
	defer c.RUnlock()

	var ips uint64
	for _, entries := range c.forward {
		ips += uint64(len(entries))
	}
	return uint64(len(c.forward)), ips
}

// MarshalJSON serialises the set of DNS lookup cacheEntries needed to
// reconstruct this cache instance.
// Note: Expiration times are honored and the reconstructed cache instance is
// expected to return the same values as the original at that point in time.
func (c *DNSCache) MarshalJSON() ([]byte, error) {
	lookups := c.Dump()

	// serialise into a JSON object array
	return json.Marshal(lookups)
}

// UnmarshalJSON rebuilds a DNSCache from serialized JSON.
// Note: This is destructive to any currect data. Use UpdateFromCache for bulk
// updates.
func (c *DNSCache) UnmarshalJSON(raw []byte) error {
	lookups := make([]*cacheEntry, 0)
	if err := json.Unmarshal(raw, &lookups); err != nil {
		return err
	}

	c.Lock()
	defer c.Unlock()

	c.forward = make(map[string]ipEntries)
	c.reverse = make(map[string]nameEntries)

	for _, newLookup := range lookups {
		c.updateWithEntry(newLookup)
	}

	return nil
}

// DNSZombieMapping is an IP that has expired or been evicted from a DNS cache.
// It records the DNS name and IP, along with other bookkeeping timestamps that
// help determine when it can be finally deleted. Zombies are dead when
// they are not marked alive by CT GC.
// Special handling exists when the count of zombies is large. Overlimit
// zombies are deleted in GC with the following preferences (this is cumulative
// and in order of precedence):
// - Zombies with zero AliveAt are evicted before those with a non-zero value
//   (i.e. known connections marked by CT GC are evicted last)
// - Zombies with an earlier DeletePendingAtTime are evicted first.
//   Note: Upsert sets DeletePendingAt on every update, thus making GC prefer
//   to evict IPs with less DNS churn on them.
// - Zombies with the lowest count of DNS names in them are evicted first
type DNSZombieMapping struct {
	// Names is the list of names that had DNS lookups with this IP. These may
	// derive from unrelated DNS lookups. The list is maintained de-duplicated.
	Names []string `json:"names,omitempty"`

	// IP is an address that is pending for delete but may be in-use by a
	// connection.
	IP net.IP `json:"ip,omitempty"`

	// AliveAt is the last time this IP was marked alive via
	// DNSZombieMappings.MarkAlive.
	// When AliveAt is later than DNSZombieMappings.lastCTGCUpdate the zombie is
	// considered alive.
	AliveAt time.Time `json:"alive-at,omitempty"`

	// DeletePendingAt is the time at which this IP was most-recently scheduled
	// for deletion. This can be updated if an IP expires from the DNS caches
	// multiple times.
	// When DNSZombieMappings.lastCTGCUpdate is earlier than DeletePendingAt a
	// zombie is alive.
	DeletePendingAt time.Time `json:"delete-pending-at,omitempty"`
}

// DeepCopy returns a copy of zombie that does not share any internal pointers
// or fields
func (zombie *DNSZombieMapping) DeepCopy() *DNSZombieMapping {
	return &DNSZombieMapping{
		Names:           append([]string{}, zombie.Names...),
		IP:              zombie.IP,
		DeletePendingAt: zombie.DeletePendingAt,
		AliveAt:         zombie.AliveAt,
	}
}

// DNSZombieMappings collects DNS Name->IP mappings that may be inactive and
// evicted, and so may be deleted. They are periodically marked alive by the CT
// GC goroutine. When .GC is called, alive and dead zombies are returned,
// allowing us to skip deleting an IP from the global DNS cache to avoid
// breaking connections that outlast the DNS TTL.
type DNSZombieMappings struct {
	lock.Mutex
	deletes        map[string]*DNSZombieMapping // map[ip]toDelete
	lastCTGCUpdate time.Time
	max            int // max allowed zombies

	// perHostLimit is the number of maximum number of IP per host.
	perHostLimit int
}

// NewDNSZombieMappings constructs a DNSZombieMappings that is read to use
func NewDNSZombieMappings(max, perHostLimit int) *DNSZombieMappings {
	return &DNSZombieMappings{
		deletes:      make(map[string]*DNSZombieMapping),
		max:          max,
		perHostLimit: perHostLimit,
	}
}

// Upsert enqueues the ip -> qname as a possible deletion
// updatedExisting is true when an earlier enqueue existed and was updated
// If an existing entry is updated, the later expiryTime is applied to the existing entry.
func (zombies *DNSZombieMappings) Upsert(expiryTime time.Time, ipStr string, qname ...string) (updatedExisting bool) {
	zombies.Lock()
	defer zombies.Unlock()

	zombie, updatedExisting := zombies.deletes[ipStr]
	if !updatedExisting {
		zombie = &DNSZombieMapping{
			Names:           KeepUniqueNames(qname),
			IP:              net.ParseIP(ipStr),
			DeletePendingAt: expiryTime,
		}
		zombies.deletes[ipStr] = zombie
	} else {
		zombie.Names = KeepUniqueNames(append(zombie.Names, qname...))
		// Keep the latest expiry time
		if expiryTime.After(zombie.DeletePendingAt) {
			zombie.DeletePendingAt = expiryTime
		}
	}
	return updatedExisting
}

// isConnectionAlive returns true if 'zombie' is considered alive.
// Zombie is considered dead if both of these conditions apply:
// 1. CT GC has run after the DNS Expiry time and grace period (lastCTGCUpdate > DeletePendingAt + GracePeriod), and
// 2. The CG GC run did not mark the Zombie alive (lastCTGCUpdate > AliveAt)
// otherwise the Zombie is alive.
func (zombies *DNSZombieMappings) isConnectionAlive(zombie *DNSZombieMapping) bool {
	return !(zombies.lastCTGCUpdate.After(zombie.DeletePendingAt) && zombies.lastCTGCUpdate.After(zombie.AliveAt))
}

// getAliveNames returns all the names that are alive
//   a name is alive if at least one of the IPs that resolve to it is alive
func (zombies *DNSZombieMappings) getAliveNames() map[string][]*DNSZombieMapping {
	aliveNames := make(map[string][]*DNSZombieMapping)

	for _, z := range zombies.deletes {
		if zombies.isConnectionAlive(z) {
			for _, name := range z.Names {
				if _, ok := aliveNames[name]; !ok {
					aliveNames[name] = make([]*DNSZombieMapping, 0, 5)
				}
				aliveNames[name] = append(aliveNames[name], z)
			}
		}
	}

	return aliveNames
}

// isZombieAlive returns true if zombie is alive
//
// A zombie is alive if its connection is alive or if one of its names is
// alive. The function takes an argument that contains the aliveNames (can be
// obtained via getAliveNames())
func (zombies *DNSZombieMappings) isZombieAlive(zombie *DNSZombieMapping, aliveNames map[string][]*DNSZombieMapping) (alive, overLimit bool) {
	if zombies.isConnectionAlive(zombie) {
		alive = true
		if zombies.perHostLimit == 0 {
			return alive, overLimit
		}
	}

	for _, name := range zombie.Names {
		if z, ok := aliveNames[name]; ok {
			alive = true
			if zombies.perHostLimit == 0 {
				return alive, overLimit
			} else if len(z) > zombies.perHostLimit {
				overLimit = true
				return alive, overLimit
			}
		}
	}

	return alive, overLimit
}

// sortZombieMappingSlice sorts the provided slice by whether the connection is
// marked alive or not, the oldest created connections, and tie-break by the
// number of DNS names for that IP.
//
// Important zombies shuffle to the end of the slice.
func sortZombieMappingSlice(alive []*DNSZombieMapping) {
	sort.Slice(alive, func(i, j int) bool {
		return alive[i].AliveAt.Before(alive[j].AliveAt) ||
			alive[i].DeletePendingAt.Before(alive[j].DeletePendingAt) ||
			len(alive[i].Names) < len(alive[j].Names)
	})
}

// GC returns alive and dead DNSZombieMapping entries. This removes dead
// zombies interally, and repeated calls will return different data.
// Zombies are alive if they have been marked alive (with MarkAlive). When
// SetCTGCTime is called and an zombie not marked alive, it becomes dead.
// Calling Upsert on a dead zombie will make it alive again.
// Alive zombies are limited by zombies.max. 0 means no zombies are allowed,
// disabling the behavior. It is expected to be a large value and is in place
// to avoid runaway zombie growth when CT GC is at a large interval.
func (zombies *DNSZombieMappings) GC() (alive, dead []*DNSZombieMapping) {
	zombies.Lock()
	defer zombies.Unlock()

	aliveNames := zombies.getAliveNames()

	// Collect zombies we can delete
	for _, zombie := range zombies.deletes {
		zombieAlive, overLimit := zombies.isZombieAlive(zombie, aliveNames)
		if overLimit {
			// No-op: This zombie is part of a name in 'aliveNames'
			// that needs to impose a per-host IP limit. Decide
			// whether to add to alive or dead in the next loop.
		} else if zombieAlive {
			alive = append(alive, zombie.DeepCopy())
		} else {
			// Emit the actual object here since we will no longer update it
			dead = append(dead, zombie)
		}
	}

	if zombies.perHostLimit > 0 {
		warnActiveDNSEntries := false
		deadIdx := len(dead)

		// Find names which have too many IPs associated mark them dead.
		//
		// Multiple names can refer to the same IP, so if we expire the
		// zombie by IP then we need to ensure that it doesn't get
		// added to both 'alive' and 'dead'.
		//
		// 1) Assemble all of the 'dead', starting from 'deadIdx'.
		//    Assemble alive candidates in 'possibleAlive'.
		// 2) Ensure that 'possibleAlive' doesn't contain any of the
		//    entries in 'dead[deadIdx:]'.
		// 3) Add the remaining 'possibleAlive' to 'alive'.
		possibleAlive := make(map[*DNSZombieMapping]struct{})
		for _, aliveIPsForName := range aliveNames {
			if len(aliveIPsForName) <= zombies.perHostLimit {
				// Already handled in the loop above.
				continue
			}
			overLimit := len(aliveIPsForName) - zombies.perHostLimit
			sortZombieMappingSlice(aliveIPsForName)
			dead = append(dead, aliveIPsForName[:overLimit]...)
			for _, z := range aliveIPsForName[overLimit:] {
				possibleAlive[z] = struct{}{}
			}
			if dead[len(dead)-1].AliveAt.IsZero() {
				warnActiveDNSEntries = true
			}
		}
		if warnActiveDNSEntries {
			log.Warningf("Evicting expired DNS cache entries that may be in-use due to per-host limits. This may cause recently created connections to be disconnected. Raise %s to mitigate this.", option.ToFQDNsMaxIPsPerHost)
		}

		for _, dead := range dead[deadIdx:] {
			if _, ok := possibleAlive[dead]; ok {
				delete(possibleAlive, dead)
			}
		}

		for zombie := range possibleAlive {
			alive = append(alive, zombie.DeepCopy())
		}
	}

	// Limit alive zombies to max. This is messy, and will break some existing
	// connections. We sort by whether the connection is marked alive or not, the
	// oldest created connections, and tie-break by the number of DNS names for
	// that IP.
	overLimit := len(alive) - zombies.max
	if overLimit > 0 {
		sortZombieMappingSlice(alive)
		dead = append(dead, alive[:overLimit]...)
		alive = alive[overLimit:]
		if dead[len(dead)-1].AliveAt.IsZero() {
			log.Warning("Evicting expired DNS cache entries that may be in-use. This may cause recently created connections to be disconnected. Raise --tofqdns-max-deferred-connection-deletes to mitigate this.")
		}
	}

	// Delete the zombies we collected above from the internal map
	for _, zombie := range dead {
		delete(zombies.deletes, zombie.IP.String())
	}

	return alive, dead
}

// MarkAlive makes an zombie alive and not dead. When now is later than the
// time set with SetCTGCTime the zombie remains alive.
func (zombies *DNSZombieMappings) MarkAlive(now time.Time, ip net.IP) {
	zombies.Lock()
	defer zombies.Unlock()

	if zombie, exists := zombies.deletes[ip.String()]; exists {
		zombie.AliveAt = now
	}
}

// SetCTGCTime marks the start of the most recent CT GC. This must be set after
// all MarkAlive calls complete to avoid a race between the DNS garbage
// collector and the CT GC. This would occur when a DNS zombie that has not
// been visited by the CT GC run is seen by a concurrent DNS garbage collector
// run, and then deleted.
// When 'ctGCStart' is later than an alive timestamp, set with MarkAlive, the zombie is
// no longer alive. Thus, this call acts as a gating function for what data is
// returned by GC.
func (zombies *DNSZombieMappings) SetCTGCTime(ctGCStart time.Time) {
	zombies.Lock()
	zombies.lastCTGCUpdate = ctGCStart
	zombies.Unlock()
}

// ForceExpire is used to clear zombies irrespective of their alive status.
// Only zombies with DeletePendingAt times before expireLookupBefore are
// considered for deletion. Each name in an zombie is matched against
// nameMatcher (nil is match all) and when an zombie no longer has any valid
// names will it be removed outright.
// Note that all parameters must match, if provided. `time.Time{}` is the
// match-all time parameter.
// expireLookupsBefore requires an zombie to have been enqueued before the
// specified time in order to remove it.
// For example:
//   ForceExpire(time.Time{}, 'cilium.io') expires all entries for cilium.io.
//   ForceExpire(time.Now(), 'cilium.io') expires all entries for cilium.io
//   that expired before the current time.
// nameMatch will remove that specific DNS name from zombies that include it,
// deleting it when no DNS names remain.
func (zombies *DNSZombieMappings) ForceExpire(expireLookupsBefore time.Time, nameMatch *regexp.Regexp, cidr *net.IPNet) (namesAffected []string) {
	zombies.Lock()
	defer zombies.Unlock()
	return zombies.forceExpireLocked(expireLookupsBefore, nameMatch, cidr)

}

func (zombies *DNSZombieMappings) forceExpireLocked(expireLookupsBefore time.Time, nameMatch *regexp.Regexp, cidr *net.IPNet) (namesAffected []string) {
	var toDelete []*DNSZombieMapping

	for _, zombie := range zombies.deletes {
		// Do not expire zombies that were enqueued after expireLookupsBefore, but
		// only if the value is non-zero
		if !expireLookupsBefore.IsZero() && zombie.DeletePendingAt.After(expireLookupsBefore) {
			continue
		}

		// If cidr is provided, skip zombies with IPs outside the range
		if cidr != nil && !cidr.Contains(zombie.IP) {
			continue
		}

		// A zombie has multiple names, collect the ones that should remain (i.e.
		// do not match nameMatch)
		var newNames []string
		for _, name := range zombie.Names {
			if nameMatch != nil && !nameMatch.MatchString(name) {
				newNames = append(newNames, name)
			} else {
				namesAffected = append(namesAffected, name)
			}
		}
		zombie.Names = newNames

		// Delete the zombie outright if no names remain
		if len(zombie.Names) == 0 {
			toDelete = append(toDelete, zombie)
		}
	}

	// Delete the zombies that are now empty
	for _, zombie := range toDelete {
		delete(zombies.deletes, zombie.IP.String())
	}

	return namesAffected
}

// ForceExpireByNameIP wraps ForceExpire to simplify clearing all IPs from a
// new DNS lookup.
// The error return is for errors compiling the internal regexp. This should
// never happen.
func (zombies *DNSZombieMappings) ForceExpireByNameIP(expireLookupsBefore time.Time, name string, ips ...net.IP) error {
	reStr := matchpattern.ToRegexp(name)
	re, err := re.CompileRegex(reStr)
	if err != nil {
		return err
	}

	zombies.Lock()
	defer zombies.Unlock()
	for _, ip := range ips {
		cidr := net.IPNet{Mask: net.CIDRMask(len(ip)*8, len(ip)*8)}
		cidr.IP = ip.Mask(cidr.Mask)
		zombies.forceExpireLocked(expireLookupsBefore, re, &cidr)
	}
	return nil
}

// CIDRMatcherFunc is a function passed to (*DNSZombieMappings).DumpAlive,
// called on each zombie to determine whether it should be returned.
type CIDRMatcherFunc func(ip net.IP) bool

// DumpAlive returns copies of still-alive zombies matching cidrMatcher.
func (zombies *DNSZombieMappings) DumpAlive(cidrMatcher CIDRMatcherFunc) (alive []*DNSZombieMapping) {
	zombies.Lock()
	defer zombies.Unlock()

	aliveNames := zombies.getAliveNames()
	for _, zombie := range zombies.deletes {
		if alive, _ := zombies.isZombieAlive(zombie, aliveNames); !alive {
			continue
		}
		// only proceed if zombie is alive and the IP matches the CIDR selector
		if cidrMatcher != nil && !cidrMatcher(zombie.IP) {
			continue
		}

		alive = append(alive, zombie.DeepCopy())
	}

	return alive
}

// MarshalJSON encodes DNSZombieMappings into JSON. Only the DNSZombieMapping
// entries are encoded.
func (zombies *DNSZombieMappings) MarshalJSON() ([]byte, error) {
	zombies.Lock()
	defer zombies.Unlock()

	// This hackery avoids exposing DNSZombieMappings.deletes as a public field.
	// The JSON package cannot serialize private fields so we have to make a
	// proxy type here.
	aux := struct {
		Deletes map[string]*DNSZombieMapping `json:"deletes,omitempty"`
	}{
		Deletes: zombies.deletes,
	}

	return json.Marshal(aux)
}

// UnmarshalJSON rebuilds a DNSZombieMappings from serialized JSON. It resets
// the AliveAt timestamps, requiring a CT GC cycle to occur before any zombies
// are deleted (by not being marked alive).
// Note: This is destructive to any currect data
func (zombies *DNSZombieMappings) UnmarshalJSON(raw []byte) error {
	zombies.Lock()
	defer zombies.Unlock()

	// This hackery avoids exposing DNSZombieMappings.deletes as a public field.
	// The JSON package cannot deserialize private fields so we have to make a
	// proxy type here.
	aux := struct {
		Deletes map[string]*DNSZombieMapping `json:"deletes,omitempty"`
	}{
		Deletes: zombies.deletes,
	}
	if err := json.Unmarshal(raw, &aux); err != nil {
		return err
	}
	zombies.deletes = aux.Deletes

	// Reset the alive time to ensure no deletes happen until we run CT GC again
	for _, zombie := range zombies.deletes {
		zombie.AliveAt = time.Time{}
	}
	return nil
}


text:
<!DOCTYPE html>
<html ng-app="helloWorldApp">
<head>
	<meta charset="utf-8">
	<title>Hello World</title>
</head>
<body>
	<ng-view></ng-view>
	<script type="text/javascript" src="/lib/jquery/dist/jquery.min.js"></script>
	<script type="text/javascript" src="/lib/bootstrap/dist/js/bootstrap.min.js"></script>
	<script type="text/javascript" src="/lib/angular/angular.min.js"></script>
	<script type="text/javascript" src="/lib/angular-route/angular-route.min.js"></script>
	<link rel="stylesheet" type="text/css" href="/lib/bootstrap/dist/css/bootstrap.css">
	<link rel="stylesheet" type="text/css" href="/styles/style.css">
	<link rel="stylesheet" href="/lib/animate.css/animate.min.css">
	<script type="text/javascript" src="/lib/angular-ui-bootstrap/src/modal/modal.js"></script>
	<script src="/primus/primus.js"></script>
	<script type="text/javascript" src="app/bundle.js"></script>
	<script>
</script>
</body>
</html>


text:
using UnityEngine;
using UnityEngine.UI;
using System.Collections;

public class MoneyUI : MonoBehaviour
{
    public Text MoneyText;
    // Update is called once per frame
    void Update()
    {
        MoneyText.text = "$ " + PlayerStats.Money.ToString();
    }
}


text:
package com.sun.tools.internal.ws.wscompile;

import com.sun.istack.internal.tools.ParallelWorldClassLoader;
import com.sun.tools.internal.ws.resources.JavacompilerMessages;

import java.io.File;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URISyntaxException;

/**
 * A helper class to invoke javac.
 *
 * @author WS Development Team
 */
class JavaCompilerHelper{
    static File getJarFile(Class clazz) {
        URL url = null;
        try {
            url = ParallelWorldClassLoader.toJarUrl(clazz.getResource('/'+clazz.getName().replace('.','/')+".class"));
            return new File(url.toURI());
        } catch (ClassNotFoundException e) {
            // if we can't figure out where JAXB/JAX-WS API are, we couldn't have been executing this code.
            throw new Error(e);
        } catch (MalformedURLException e) {
            // if we can't figure out where JAXB/JAX-WS API are, we couldn't have been executing this code.
            throw new Error(e);
        } catch (URISyntaxException e) {
            // url.toURI() is picky and doesn't like ' ' in URL, so this is the fallback
            return new File(url.getPath());
        }
    }

    static boolean compile(String[] args, OutputStream out, ErrorReceiver receiver){
        ClassLoader cl = Thread.currentThread().getContextClassLoader();
        try {
            /* try to use the new compiler */
            Class comSunToolsJavacMainClass =
                    cl.loadClass("com.sun.tools.javac.Main");
            try {
                Method compileMethod =
                        comSunToolsJavacMainClass.getMethod(
                                "compile",
                                compileMethodSignature);
                    Object result =
                            compileMethod.invoke(
                                    null, args, new PrintWriter(out));
                    return result instanceof Integer && (Integer) result == 0;
            } catch (NoSuchMethodException e2) {
                receiver.error(JavacompilerMessages.JAVACOMPILER_NOSUCHMETHOD_ERROR("getMethod(\"compile\", Class[])"), e2);
            } catch (IllegalAccessException e) {
                receiver.error(e);
            } catch (InvocationTargetException e) {
                receiver.error(e);
            }
        } catch (ClassNotFoundException e) {
            receiver.error(JavacompilerMessages.JAVACOMPILER_CLASSPATH_ERROR("com.sun.tools.javac.Main"), e);
        } catch (SecurityException e) {
            receiver.error(e);
        }
        return false;
    }

    private static final Class[] compileMethodSignature = {String[].class, PrintWriter.class};
}


text:
<?php

namespace Cecil\Exception;

class RuntimeException extends \RuntimeException implements ExceptionInterface
{
    private $pageFile;
    private $pageLine;
    private $pageCol;

    public function __construct(string $message, string $pageFile = null, int $pageLine = null, int $pageCol = null, \Throwable $previous = null)
    {
        $this->pageFile = $pageFile;
        $this->pageLine = $pageLine;
        $this->pageCol = $pageCol;

        parent::__construct($message, 0, $previous);
    }

    public function getPageFile()
    {
        return $this->pageFile;
    }

    public function getPageLine()
    {
        return $this->pageLine;
    }

    public function getPageCol()
    {
        return $this->pageCol;
    }
}


text:
/**********************************************************************
 * Author:      Leo Liberti                                            *
 * Name:        expression.h                                           *
 * Source:      GNU C++                                                *
 * Purpose:     symbolic expression (base classes and functionality)   *
 * History:     010517 0.0 work started                                *
 * License:    (C) Leo Liberti, all rights reserved. Code published under the
               Common Public License.
***********************************************************************/

#ifndef __EV3EXPRESSIONH__
#define __EV3EXPRESSIONH__

#include <iostream>
#include <vector>
#include <map>

#include "common.h"
#include "tree.h"
#include "exceptions.h"
#include "operand.h"

namespace Ev3
{

class BasicExpression;

typedef Pointer<BasicExpression> Expression;

class BasicExpression : public Operand, public Tree<BasicExpression>
{

private:

public:

  // constructors

  // create empty
  BasicExpression();

  // create a constant leaf
  explicit BasicExpression(const double t);

  // create a constant (integer-valued) leaf
  explicit BasicExpression(const Int t);

  // create an (empty) operator or a variable leaf
  BasicExpression(const Int t,
                  const bool isvar);

  // create a variable leaf and set coefficient
  BasicExpression(const double c,
                  const Int t,
                  const std::string & vn);

  // user-defined copy constructor with two options (to make a copy)
  BasicExpression(const Expression & t,
                  const bool iscopy);

  // copy constructor
  BasicExpression(const BasicExpression & t);

  // destructor
  ~BasicExpression();

  // BasicExpression class methods:
  void Debug () const;

  // prints to a string
  std::string ToString() const;

  // output is a tree
  std::string PrintTree(const int blanks,
                        const int tabs) const;

  // sets an expression to zero (deleting all existing subnodes)
  void Zero();

  // sets an expression to one (deleting all existing subnodes)
  void One();

  // is expression this == expression t?
  // (note that this half-replicates Tree::operator==,
  //  but I couldn't think of any other convenient way to fit in
  //  the operand data in == and still use the Tree's ==)
  bool IsEqualTo(const Expression & t) const;
  bool operator == (const BasicExpression & t) const;

  // other comparison operators
  bool IsEqualTo(const double t) const;

  // this returns true if args are equal up to top node coefficient
  bool IsEqualToNoCoeff(const Expression & t) const;

  // this returns true if args have equal operator structures and
  // maintain variable/constant assignment to leaf nodes
  // (a schema is an expression modulo leaves)
  bool IsEqualBySchema(const Expression & t) const;

  // this returns true if args have equal operator label
  bool IsEqualByOperator(const int theoplabel) const;

  // this returns the number of variables in the expression
  int NumberOfVariables() const;
  int NumberOfVariables(int & maxvi) const;

  // whether expression depends on variable
  bool DependsOnVariable(const Int vi) const;

  // whether expression depends on variable linearly
  // (0=depends nonlinearly, 1=depends linearly, 2=doesn't depend at all)
  int DependsLinearlyOnVariable(const Int vi) const;

  // in a product, multiply all coeffs. of the operands, set result
  // as coeff of whole product, reset all operand coffs at 1; if
  // resulting global coeff is zero, delete all nodes and set
  // this to zero constant.
  // don't do anything on other operators
  void ConsolidateProductCoeffs();

  // in a sum or product, if coeff of sum operand is not 1, distribute it
  // to the operands and set whole coeff to 1
  void DistributeCoeffOverSum();
  void DistributeCoeffOverProduct();

  // enforce constant dependencies (added for MORON - see ../PROGNOTES)
  // this only acts on the proper leaf nodes
  void EnforceDependency();

  // substitute a variable with a constant
  void VariableToConstant(const int varindex,
                          const double c);

  // replace variable indexed v1 with variable indexed v2 (with varname vn)
  void ReplaceVariable(const int v1,
                       const int v2,
                       const std::string & vn);
  void ReplaceVariable(const int v1,
                       const int v2,
                       const std::string & vn,
                       const double c2);

  // replace with a variable the deepest node conforming to schema and
  // return replaced term or zero expression if no replacement occurs
  Expression ReplaceBySchema(const int vi,
                             const std::string & vn,
                             const Expression & schema);
  // works on subnodes not on current node
  Expression ReplaceBySchemaRecursive(const int vi,
                                      const std::string & vn,
                                      const Expression & schema);

  // replace with a variable the deepest node with given operator label
  // return replaced term or zero expression if no replacement occurs
  Expression ReplaceByOperator(const int vi,
                               const std::string & vn,
                               const int oplabel);
  // works on subnodes not on current node
  Expression ReplaceByOperatorRecursive(const int vi,
                                        const std::string & vn,
                                        const int oplabel);

  // replace all occurrences of subexpression needle with replace
  // return number of replacements
  int ReplaceSubexpression(const Expression & needle,
                           const Expression & replace);

  // replace this with given expression (SIGSEGV risk, see implementation)
  void ReplaceWithExpression(const Expression & replace);

  // reset all names of variables having IDs between lid, uid to vn
  void ResetVarNames(const std::string & vn,
                     int lid,
                     int uid);

  // distribute products over sums - returns true if changed
  // (re-call until false)
  bool DistributeProductsOverSums();

  // find variable indices in an expression
  void GetVarIndices(std::vector<int> & vidx);

  // return list of varIDs involved in a certain schema
  // e.g. f(x1*x2+x1*x3+x4*log(x5), x*y) = {1,2,3}
  void GetVarIndicesInSchema(std::vector<int> & vidx,
                             const Expression & schema);

  // find the variable name corresponding to variable index vi
  std::string FindVariableName(int vi);

  // is this expression linear?
  bool IsLinear() const;

  // is this expression a quadratic product of variables?
  // If yes, return the product type: PRODUCT, POWER or VAR
  bool IsQuadratic(int & prodtype) const;
  bool IsQuadratic() const;

  // return info about the linear part (assumes Simplify() has already been
  // called on this) - return false if expression has no linear part
  // by "linear part" we mean lin(x) in expr(x,y) = lin(x) + nonlin(y)
  // lincoeff[i] is the i-th nonzero coeff, linvi[i] is the corresponding
  // i-th varindex (starts from 1), c is the constant term to be added
  bool GetLinearInfo(std::vector<double> & lincoeff,
                     std::vector<int> & linvi,
                     std::vector<std::string> & linvn,
                     double & c);

  // return info about the pure linear part (assumes Simplify() has
  // already been called on this) - much as above call but the "pure
  // linear part" is e.g. x+y in x+y+y^2
  bool GetPureLinearInfo(std::vector<double> & lincoeff,
                         std::vector<int>& linvi,
                         std::vector<std::string> & linvn,
                         double & c);

  // get the linear part - x in x+y+y^2
  Expression GetLinearPart();

  // get the pure linar part - x+y in x+y+y^2
  Expression GetPureLinearPart();

  // get the nonlinear part - nonlin(y) in expr(x,y) = lin(x) + nonlin(y)
  Expression GetNonlinearPart();

  // get the purely nonlinear part - eg. y^2 in x+y+y^2
  Expression GetPureNonlinearPart();

  // return the additive constant of the expression
  double GetConstantPart();

  // return the additive constant of the expression and remove it from the
  // expression itself
  double RemoveAdditiveConstant();
};

std::ostream & operator<< (std::ostream & out, const BasicExpression & expr);
std::ostream & operator<< (std::ostream & out, const Expression & expr);

// All these functions contain tricks to simplify the operands. This
// means that both the operands may be changed, and indeed that the
// return value is often one of the changed operands.  To make sure
// you are not changing the operands, use the CopyOf function or the
// Copy() method in Pointer class; or use the equivalent operators below
// in order not to touch the argument expressions.

// add a link of b to a, return link to created expression
Expression SumLink(Expression a,
                   Expression b);
// add a link of b to a with coeff -1, return link of a
Expression DifferenceLink(Expression a,
                          Expression b);
// multiply a by a link of b, return link of a
Expression ProductLink(Expression a,
                       Expression b);
// divide a by a link of b, return link of a
Expression FractionLink(Expression a,
                        Expression b);
// raise a to power b, return link of a
Expression PowerLink(Expression a,
                     Expression b);
// change sign to coeff of a, return link of a
Expression MinusLink(Expression a);
// other unary functions (of a):
Expression SinLink(Expression a);
Expression CosLink(Expression a);
Expression TanLink(Expression a);
Expression AsinLink(Expression a);
Expression AcosLink(Expression a);
Expression AtanLink(Expression a);
Expression SinhLink(Expression a);
Expression CoshLink(Expression a);
Expression TanhLink(Expression a);
Expression AsinhLink(Expression a);
Expression AcoshLink(Expression a);
Expression AtanhLink(Expression a);
Expression Log2Link(Expression a);
Expression Log10Link(Expression a);
Expression LogLink(Expression a);
Expression LnLink(Expression a);
Expression LngammaLink(Expression a);
Expression GammaLink(Expression a);
Expression ExpLink(Expression a);
Expression ErfLink(Expression a);
Expression ErfcLink(Expression a);
Expression SqrtLink(Expression a);
Expression CbrtLink(Expression a);
Expression BesselJ0Link(Expression a);
Expression BesselJ1Link(Expression a);
Expression BesselY0Link(Expression a);
Expression BesselY1Link(Expression a);
Expression SignLink(Expression a);
Expression RintLink(Expression a);
Expression AbsLink(Expression a);
Expression CotLink(Expression a);
Expression CothLink(Expression a);

// these are equivalent to the above but they don't change the arguments
Expression operator + (Expression a,
                       Expression b);
Expression operator - (Expression a,
                       Expression b);
Expression operator * (Expression a,
                       Expression b);
Expression operator / (Expression a,
                       Expression b);
Expression operator ^ (Expression a,
                       Expression b);
Expression operator - (Expression a);
Expression Sin(Expression a);
Expression Cos(Expression a);
Expression Tan(Expression a);
Expression Asin(Expression a);
Expression Acos(Expression a);
Expression Atan(Expression a);
Expression Sinh(Expression a);
Expression Cosh(Expression a);
Expression Tanh(Expression a);
Expression Asinh(Expression a);
Expression Acosh(Expression a);
Expression Atanh(Expression a);
Expression Log2(Expression a);
Expression Log10(Expression a);
Expression Log(Expression a);
Expression Ln(Expression a);
Expression Lngamma(Expression a);
Expression Gamma(Expression a);
Expression Exp(Expression a);
Expression Erf(Expression a);
Expression Erfc(Expression a);
Expression Sqrt(Expression a);
Expression Cbrt(Expression a);
Expression BesselJ0(Expression a);
Expression BesselJ1(Expression a);
Expression BesselY0(Expression a);
Expression BesselY1(Expression a);
Expression Sign(Expression a);
Expression Rint(Expression a);
Expression Abs(Expression a);
Expression Cot(Expression a);
Expression Coth(Expression a);

// symbolic differentiation of a w.r.t. variable with index vi,
// return the created expression (a is not changed)
Expression Diff(const Expression & a,
                Int vi);
Expression DiffNoSimplify(const Expression & ac,
                          Int vi);

// SIMPLIFICATIONS - all simplifications return true if they were
// effective or false if they weren't

// sin^2+cos^2 = 1 simplification
bool TrigSimp(Expression a);

// generic simplification with modification of the expression
bool Simplify(Expression* a);
bool SimplifyRecursive(Expression* a);
bool SimplifyConstant(Expression* a);
bool DifferenceToSum(Expression* a);
bool CompactLinearPart(Expression* a);
bool CompactLinearPartRecursive(Expression* a);
bool CompactProducts(Expression* a);
bool ReorderNodes(Expression* a);

// destroys the whole tree and all nodes, be careful
void RecursiveDestroy(Expression* a);

// generic simplification on a copy of the expression
Expression SimplifyCopy(Expression* a, bool& ischanged);

} /* namespace Ev3 */

#endif /* __EV3EXPRESSIONH__ */


text:
<?php
namespace empire\framework\gid;

use \Exception;

/**
 * Thrown when a GID cannot be created or parsed.
 *
 * @author Tobias Hornberger [tobias.hornberger@falsemirror.de]
 */
class GIDException extends Exception {
}


text:
package semeval2014.task9;

import static org.apache.uima.fit.factory.AnalysisEngineFactory.createEngineDescription;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.uima.analysis_engine.AnalysisEngineDescription;
import org.apache.uima.resource.ResourceInitializationException;

import semeval2014.task9.extractor.EmoticonFeatureExtractor;
import semeval2014.task9.io.TaskBSemevalTwitterCorpusReader;
import weka.classifiers.bayes.NaiveBayes;
import weka.classifiers.functions.SMO;
import de.tudarmstadt.ukp.dkpro.core.tokit.BreakIteratorSegmenter;
import de.tudarmstadt.ukp.dkpro.lab.Lab;
import de.tudarmstadt.ukp.dkpro.lab.task.Dimension;
import de.tudarmstadt.ukp.dkpro.lab.task.ParameterSpace;
import de.tudarmstadt.ukp.dkpro.lab.task.impl.BatchTask.ExecutionPolicy;
import de.tudarmstadt.ukp.dkpro.tc.core.Constants;
import de.tudarmstadt.ukp.dkpro.tc.features.length.NrOfTokensFeatureExtractor;
import de.tudarmstadt.ukp.dkpro.tc.features.ngram.NGramFeatureExtractor;
import de.tudarmstadt.ukp.dkpro.tc.weka.report.BatchCrossValidationReport;
import de.tudarmstadt.ukp.dkpro.tc.weka.report.BatchOutcomeIDReport;
import de.tudarmstadt.ukp.dkpro.tc.weka.report.BatchTrainTestReport;
import de.tudarmstadt.ukp.dkpro.tc.weka.report.ClassificationReport;
import de.tudarmstadt.ukp.dkpro.tc.weka.task.BatchTaskCrossValidation;
import de.tudarmstadt.ukp.dkpro.tc.weka.task.BatchTaskTrainTest;
import de.tudarmstadt.ukp.dkpro.tc.weka.writer.WekaDataWriter;

public class SubtaskB_TC
    implements Constants
{
    public static final String LANGUAGE_CODE = "en";

    public static int NUM_FOLDS = 3;

    public static final String corpusFilePathTrain = "src/main/resources/twitter/tweeti-b.dist.tweets";
    public static final String corpusFilePathTest = "src/main/resources/twitter/tweeti-b.test.tweets";

    public static void main(String[] args)
        throws Exception
    {
        ParameterSpace pSpace = getParameterSpace();

        SubtaskB_TC experiment = new SubtaskB_TC();
        experiment.runCrossValidation(pSpace);

        // enable when test data is available
//        experiment.runTrainTest(pSpace);
    }

    public static ParameterSpace getParameterSpace()
    {
        // configure training and test data reader dimension
        Map<String, Object> dimReaders = new HashMap<String, Object>();
        dimReaders.put(DIM_READER_TRAIN, TaskBSemevalTwitterCorpusReader.class);
        dimReaders.put(DIM_READER_TRAIN_PARAMS, Arrays.asList(new Object[] {
                TaskBSemevalTwitterCorpusReader.PARAM_SOURCE_LOCATION, corpusFilePathTrain,
                TaskBSemevalTwitterCorpusReader.PARAM_LANGUAGE, LANGUAGE_CODE }
        ));
        dimReaders.put(DIM_READER_TEST, TaskBSemevalTwitterCorpusReader.class);
        dimReaders.put(DIM_READER_TEST_PARAMS, Arrays.asList(new Object[] {
                TaskBSemevalTwitterCorpusReader.PARAM_SOURCE_LOCATION, corpusFilePathTest,
                TaskBSemevalTwitterCorpusReader.PARAM_LANGUAGE, LANGUAGE_CODE}
        ));

        // lets try SMO and NaiveBayes classifiers from Weka
        @SuppressWarnings("unchecked")
        Dimension<List<String>> dimClassificationArgs = Dimension.create(
                DIM_CLASSIFICATION_ARGS,
                Arrays.asList(new String[] { SMO.class.getName() }),
                Arrays.asList(new String[] { NaiveBayes.class.getName() })
        );

        // in this example, we only use two feature extractors
        // - length in tokens
        // - frequent n-grams
        // - emoticon counts
        // a real experiment would use many more
        //
        // you can use pre-defined ones from
        // http://code.google.com/p/dkpro-tc/
        // or write your own extractors
        @SuppressWarnings("unchecked")
        Dimension<List<String>> dimFeatureSets = Dimension.create(
                DIM_FEATURE_SET,
                Arrays.asList(new String[] {
                        NrOfTokensFeatureExtractor.class.getName()

                }),
                Arrays.asList(new String[] {
                        NrOfTokensFeatureExtractor.class.getName(),
                        NGramFeatureExtractor.class.getName()
                }),
                Arrays.asList(new String[] {
                        NrOfTokensFeatureExtractor.class.getName(),
                        NGramFeatureExtractor.class.getName(),
                        EmoticonFeatureExtractor.class.getName()
                })
        );

        // configuring feature extractors
        //
        // each group represents one run with the corresponding parameters
        @SuppressWarnings("unchecked")
        Dimension<List<Object>> dimPipelineParameters = Dimension.create(
                DIM_PIPELINE_PARAMS,
                Arrays.asList(new Object[] {
                        NGramFeatureExtractor.PARAM_NGRAM_USE_TOP_K, "50",
                        NGramFeatureExtractor.PARAM_NGRAM_MIN_N, 1,
                        NGramFeatureExtractor.PARAM_NGRAM_MAX_N, 3
                }),
                Arrays.asList(new Object[] {
                        NGramFeatureExtractor.PARAM_NGRAM_USE_TOP_K, "100",
                        NGramFeatureExtractor.PARAM_NGRAM_MIN_N, 1,
                        NGramFeatureExtractor.PARAM_NGRAM_MAX_N, 3
                })
        );

        @SuppressWarnings("unchecked")
        ParameterSpace pSpace = new ParameterSpace(
                Dimension.createBundle("readers", dimReaders),
                Dimension.create(DIM_DATA_WRITER, WekaDataWriter.class.getName()),
                Dimension.create(DIM_MULTI_LABEL, false),
                dimPipelineParameters,
                dimFeatureSets,
                dimClassificationArgs
        );

        return pSpace;
    }

    // ##### CV #####
    protected void runCrossValidation(ParameterSpace pSpace)
        throws Exception
    {

        BatchTaskCrossValidation batch = new BatchTaskCrossValidation("SemEval2014_Task9_Subtask_B_CV",
                getPreprocessing(), NUM_FOLDS);
        batch.setInnerReport(ClassificationReport.class);
        batch.setParameterSpace(pSpace);
        batch.setExecutionPolicy(ExecutionPolicy.RUN_AGAIN);
        batch.addReport(BatchCrossValidationReport.class);

        // Run
        Lab.getInstance().run(batch);
    }

    // ##### TRAIN-TEST #####
    protected void runTrainTest(ParameterSpace pSpace)
        throws Exception
    {

        BatchTaskTrainTest batch = new BatchTaskTrainTest("SemEval2014_Task9_Subtask_B_TrainTest",
                getPreprocessing());
        batch.setInnerReport(ClassificationReport.class);
        batch.setParameterSpace(pSpace);
        batch.setExecutionPolicy(ExecutionPolicy.RUN_AGAIN);
        batch.addReport(BatchTrainTestReport.class);
        batch.addReport(BatchOutcomeIDReport.class);

        // Run
        Lab.getInstance().run(batch);
    }

    protected AnalysisEngineDescription getPreprocessing()
        throws ResourceInitializationException
    {
        return createEngineDescription(
            createEngineDescription(BreakIteratorSegmenter.class)
        );
    }
}


text:
/**
* @file  CSObjCont.h
* @brief Generic container, meant to efficiently hold objects (not thread safe).
*/

#ifndef _INC_CSOBJCONT_H
#define _INC_CSOBJCONT_H

#include "CSObjContRec.h"
#include <vector>
#include <utility> // for std::move

/* Reverse container wrapper */

template <typename T>
class cont_reversed
{
    T _iterable;

public:
    explicit cont_reversed(T&& iterable) noexcept : _iterable{ std::move(iterable) } {}

    inline auto begin() const noexcept  { return std::rbegin(_iterable); }
    inline auto end() const noexcept    { return std::rend(_iterable);   }
};

template <typename T>
class cont_reverse_iterate
{
    T & _iterable;

public:
    explicit cont_reverse_iterate(T &iterable) noexcept : _iterable{ iterable } {}

    inline auto begin() const noexcept  { return std::rbegin(_iterable); }
    inline auto end() const noexcept    { return std::rend(_iterable); }
};

/* CSObjCont */

#define BASECONT std::vector<CSObjContRec*>
class CSObjCont
{
protected:
    BASECONT _Contents;
    bool _fIsClearing;

public:
    friend class CSObjContRec;
    static const char * m_sClassName;

    /** @name Constructors, Destructor, Asign operator:
    */
    ///@{
    /**
    * @brief Sets head, tail and count.
    */
    CSObjCont();
    virtual ~CSObjCont();

private:
    /**
    * @brief No copies allowed.
    */
    CSObjCont(const CSObjCont& copy);
    /**
    * @brief No copies allowed.
    */
    CSObjCont& operator=(const CSObjCont& other);
    ///@}

    /** @name Iterators:
    */
    ///@{

public:
    using iterator               = BASECONT::iterator;
    using const_iterator         = BASECONT::const_iterator;
    using reverse_iterator       = BASECONT::reverse_iterator;
    using const_reverse_iterator = BASECONT::const_reverse_iterator;

    inline iterator begin() noexcept                        { return _Contents.begin();  }
    inline iterator end()   noexcept                        { return _Contents.end();    }
    inline const_iterator begin()  const noexcept           { return _Contents.begin();  }
    inline const_iterator end()    const noexcept           { return _Contents.end();    }
    inline const_iterator cbegin() const noexcept           { return _Contents.cbegin(); }
    inline const_iterator cend()   const noexcept           { return _Contents.cend();   }

    inline reverse_iterator rbegin() noexcept               { return _Contents.rbegin(); }
    inline reverse_iterator rend()   noexcept               { return _Contents.rend();   }
    inline const_reverse_iterator rbegin()  const noexcept  { return _Contents.rbegin(); }
    inline const_reverse_iterator rend()    const noexcept  { return _Contents.rend();   }

    /**
    * @brief Returns a copy of the CSObjCont base container, which is safe to iterate on even if one of its elements is ::Delete'd.
    *   When an element is deleted from the CSObjCont with CObjBase::Delete or its virtuals, the element is removed from the CSObjCont, thus invalidating
    *   its existing iterators, but the removed element is only scheduled for deletion on the next tick, so the object does still exist by the time we are
    *   iterating on this container.
    *   So, if we iterate (on the same tick and without using "delete" on the elements) on another copy container, which holds the same pointers to CSObjListRec
    *   but without being modified during the iteration, we are safe and prevent the invalidation of the existing iterators, loop indexes and such.
    * @return A copy of the base container.
    */
    inline BASECONT GetIterationSafeCont() const noexcept;

    /**
    * @brief Returns a reverse-iterated copy of the CSObjCont base container, which is safe to iterate on even if one of its elements is ::Delete'd.
    *   See GetIterationSafeContReverse() for more info.
    *   As a general rule of thumb, whenever possible it's better to iterate through the elements in reverse order, in the case of the raw CSObjCont and of the
    *   BASECONT copy returned by GetIterationSafeCont. This happens because if an element gets deleted, it will be erased in any case from the CSObjCont, and
    *   removing the last element is more efficient than removing the first element (since we are using std::vector as BASECONT).
    * @return A copy of the base container, which will be iterated in reverse order.
    */
    inline cont_reversed<BASECONT> GetIterationSafeContReverse() const noexcept;

    ///@}

    /** @name Capacity:
    */
    ///@{

    /**
    * @brief Check if CSObjCont if empty.
    * @return true if CSObjCont is empty, false otherwise.
    */
    inline bool IsContainerEmpty() const noexcept;

    /**
    * @brief Get the record count of the list.
    * @return The record count of the list.
    */
    inline size_t GetContentCount() const noexcept;
    ///@}

    /** @name Element Access:
    */
    ///@{

    /**
    * @brief Get the nth element of the list.
    * @param index of the element to get.
    * @return nth element if lenght is greater or equal to index, nullptr otherwise.
    */
    inline CSObjContRec* GetContentIndex(size_t index) const noexcept;

    /**
    * @brief Get the first record of the CSObjCont.
    * @return The first record of the CSObjCont if list is not empty, nullptr otherwise.
    */
    inline CSObjContRec* GetContainerHead() const noexcept;

    /**
    * @brief Get the last record of the CSObjCont.
    * @return The last record of the CSObjCont if list is not empty, nullptr otherwise.
    */
    inline CSObjContRec* GetContainerTail() const noexcept;

    /** @name Modifiers:
    */
    ///@{

    /**
    * @brief Remove all records of the CSObjCont.
    */
    void ClearContainer();

    /**
    * @brief Insert a record at head.
    * @param pNewRec record to insert.
    */
    //void InsertContentHead(CSObjContRec* pNewRec);

    /**
    * @brief Insert a record at tail.
    * @param pNewRec record to insert.
    */
    void InsertContentTail(CSObjContRec* pNewRec);

protected:
    /**
    * @brief Trigger that fires when a record if removed.
    *
    * Override this to get called when an item is removed from this list.
    * Never called directly. Called CSObjContRec::RemoveSelf()
    * @see CSObjContRec::RemoveSelf().
    *
    * @param pObRec removed record.
    */
    virtual void OnRemoveObj( CSObjContRec* pObjRec );
    ///@}
};

/* Inlined methods are defined here */

BASECONT CSObjCont::GetIterationSafeCont() const noexcept
{
    return _Contents;   // Return a copy of the base container
}

cont_reversed<BASECONT> CSObjCont::GetIterationSafeContReverse() const noexcept
{
    return cont_reversed<BASECONT>(BASECONT(_Contents)); // Return a reverse-iterable copy of the base container
}

bool CSObjCont::IsContainerEmpty() const noexcept
{
    return _Contents.empty();
}

size_t CSObjCont::GetContentCount() const noexcept
{
    return _Contents.size();
}

CSObjContRec* CSObjCont::GetContentIndex(size_t i) const noexcept
{
    return _Contents[i];
}

CSObjContRec* CSObjCont::GetContainerHead() const noexcept
{
    return _Contents.front();
}

CSObjContRec* CSObjCont::GetContainerTail() const noexcept
{
    return _Contents.back();
}

#undef BASECONT

#endif //_INC_CSOBJCONT_H