<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Yaml;

use Symfony\Component\Yaml\Exception\ParseException;

/**
 * Parser parses YAML strings to convert them to PHP arrays.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Parser
{
    const TAG_PATTERN = '((?P<tag>![\w!.\/:-]+) +)?';
    const BLOCK_SCALAR_HEADER_PATTERN = '(?P<separator>\||>)(?P<modifiers>\+|\-|\d+|\+\d+|\-\d+|\d+\+|\d+\-)?(?P<comments> +#.*)?';

    private $offset = 0;
    private $totalNumberOfLines;
    private $lines = array();
    private $currentLineNb = -1;
    private $currentLine = '';
    private $refs = array();
    private $skippedLineNumbers = array();
    private $locallySkippedLineNumbers = array();

    /**
     * Constructor.
     *
     * @param int      $offset             The offset of YAML document (used for line numbers in error messages)
     * @param int|null $totalNumberOfLines The overall number of lines being parsed
     * @param int[]    $skippedLineNumbers Number of comment lines that have been skipped by the parser
     */
    public function __construct($offset = 0, $totalNumberOfLines = null, array $skippedLineNumbers = array())
    {
        $this->offset = $offset;
        $this->totalNumberOfLines = $totalNumberOfLines;
        $this->skippedLineNumbers = $skippedLineNumbers;
    }

    /**
     * Parses a YAML string to a PHP value.
     *
     * @param string $value A YAML string
     * @param int    $flags A bit field of PARSE_* constants to customize the YAML parser behavior
     *
     * @return mixed A PHP value
     *
     * @throws ParseException If the YAML is not valid
     */
    public function parse($value, $flags = 0)
    {
        if (is_bool($flags)) {
            @trigger_error('Passing a boolean flag to toggle exception handling is deprecated since version 3.1 and will be removed in 4.0. Use the Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE flag instead.', E_USER_DEPRECATED);

            if ($flags) {
                $flags = Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE;
            } else {
                $flags = 0;
            }
        }

        if (func_num_args() >= 3) {
            @trigger_error('Passing a boolean flag to toggle object support is deprecated since version 3.1 and will be removed in 4.0. Use the Yaml::PARSE_OBJECT flag instead.', E_USER_DEPRECATED);

            if (func_get_arg(2)) {
                $flags |= Yaml::PARSE_OBJECT;
            }
        }

        if (func_num_args() >= 4) {
            @trigger_error('Passing a boolean flag to toggle object for map support is deprecated since version 3.1 and will be removed in 4.0. Use the Yaml::PARSE_OBJECT_FOR_MAP flag instead.', E_USER_DEPRECATED);

            if (func_get_arg(3)) {
                $flags |= Yaml::PARSE_OBJECT_FOR_MAP;
            }
        }

        if (false === preg_match('//u', $value)) {
            throw new ParseException('The YAML value does not appear to be valid UTF-8.');
        }

        $this->refs = array();

        $mbEncoding = null;
        $e = null;
        $data = null;

        if (2 /* MB_OVERLOAD_STRING */ & (int) ini_get('mbstring.func_overload')) {
            $mbEncoding = mb_internal_encoding();
            mb_internal_encoding('UTF-8');
        }

        try {
            $data = $this->doParse($value, $flags);
        } catch (\Exception $e) {
        } catch (\Throwable $e) {
        }

        if (null !== $mbEncoding) {
            mb_internal_encoding($mbEncoding);
        }

        $this->lines = array();
        $this->currentLine = '';
        $this->refs = array();
        $this->skippedLineNumbers = array();
        $this->locallySkippedLineNumbers = array();

        if (null !== $e) {
            throw $e;
        }

        return $data;
    }

    private function doParse($value, $flags)
    {
        $this->currentLineNb = -1;
        $this->currentLine = '';
        $value = $this->cleanup($value);
        $this->lines = explode("\n", $value);
        $this->locallySkippedLineNumbers = array();

        if (null === $this->totalNumberOfLines) {
            $this->totalNumberOfLines = count($this->lines);
        }

        $data = array();
        $context = null;
        $allowOverwrite = false;

        while ($this->moveToNextLine()) {
            if ($this->isCurrentLineEmpty()) {
                continue;
            }

            // tab?
            if ("\t" === $this->currentLine[0]) {
                throw new ParseException('A YAML file cannot contain tabs as indentation.', $this->getRealCurrentLineNb() + 1, $this->currentLine);
            }

            $isRef = $mergeNode = false;
            if (self::preg_match('#^\-((?P<leadspaces>\s+)(?P<value>.+))?$#u', rtrim($this->currentLine), $values)) {
                if ($context && 'mapping' == $context) {
                    throw new ParseException('You cannot define a sequence item when in a mapping', $this->getRealCurrentLineNb() + 1, $this->currentLine);
                }
                $context = 'sequence';

                if (isset($values['value']) && self::preg_match('#^&(?P<ref>[^ ]+) *(?P<value>.*)#u', $values['value'], $matches)) {
                    $isRef = $matches['ref'];
                    $values['value'] = $matches['value'];
                }

                // array
                if (!isset($values['value']) || '' == trim($values['value'], ' ') || 0 === strpos(ltrim($values['value'], ' '), '#')) {
                    $data[] = $this->parseBlock($this->getRealCurrentLineNb() + 1, $this->getNextEmbedBlock(null, true), $flags);
                } else {
                    if (isset($values['leadspaces'])
                        && self::preg_match('#^(?P<key>'.Inline::REGEX_QUOTED_STRING.'|[^ \'"\{\[].*?) *\:(\s+(?P<value>.+))?$#u', rtrim($values['value']), $matches)
                    ) {
                        // this is a compact notation element, add to next block and parse
                        $block = $values['value'];
                        if ($this->isNextLineIndented()) {
                            $block .= "\n".$this->getNextEmbedBlock($this->getCurrentLineIndentation() + strlen($values['leadspaces']) + 1);
                        }

                        $data[] = $this->parseBlock($this->getRealCurrentLineNb(), $block, $flags);
                    } else {
                        $data[] = $this->parseValue($values['value'], $flags, $context);
                    }
                }
                if ($isRef) {
                    $this->refs[$isRef] = end($data);
                }
            } elseif (
                self::preg_match('#^(?P<key>'.Inline::REGEX_QUOTED_STRING.'|[^ \'"\[\{].*?) *\:(\s+(?P<value>.+))?$#u', rtrim($this->currentLine), $values)
                && (false === strpos($values['key'], ' #') || in_array($values['key'][0], array('"', "'")))
            ) {
                if ($context && 'sequence' == $context) {
                    throw new ParseException('You cannot define a mapping item when in a sequence', $this->currentLineNb + 1, $this->currentLine);
                }
                $context = 'mapping';

                // force correct settings
                Inline::parse(null, $flags, $this->refs);
                try {
                    Inline::$parsedLineNumber = $this->getRealCurrentLineNb();
                    $key = Inline::parseScalar($values['key']);
                } catch (ParseException $e) {
                    $e->setParsedLine($this->getRealCurrentLineNb() + 1);
                    $e->setSnippet($this->currentLine);

                    throw $e;
                }

                // Convert float keys to strings, to avoid being converted to integers by PHP
                if (is_float($key)) {
                    $key = (string) $key;
                }

                if ('<<' === $key) {
                    $mergeNode = true;
                    $allowOverwrite = true;
                    if (isset($values['value']) && 0 === strpos($values['value'], '*')) {
                        $refName = substr($values['value'], 1);
                        if (!array_key_exists($refName, $this->refs)) {
                            throw new ParseException(sprintf('Reference "%s" does not exist.', $refName), $this->getRealCurrentLineNb() + 1, $this->currentLine);
                        }

                        $refValue = $this->refs[$refName];

                        if (!is_array($refValue)) {
                            throw new ParseException('YAML merge keys used with a scalar value instead of an array.', $this->getRealCurrentLineNb() + 1, $this->currentLine);
                        }

                        $data += $refValue; // array union
                    } else {
                        if (isset($values['value']) && $values['value'] !== '') {
                            $value = $values['value'];
                        } else {
                            $value = $this->getNextEmbedBlock();
                        }
                        $parsed = $this->parseBlock($this->getRealCurrentLineNb() + 1, $value, $flags);

                        if (!is_array($parsed)) {
                            throw new ParseException('YAML merge keys used with a scalar value instead of an array.', $this->getRealCurrentLineNb() + 1, $this->currentLine);
                        }

                        if (isset($parsed[0])) {
                            // If the value associated with the merge key is a sequence, then this sequence is expected to contain mapping nodes
                            // and each of these nodes is merged in turn according to its order in the sequence. Keys in mapping nodes earlier
                            // in the sequence override keys specified in later mapping nodes.
                            foreach ($parsed as $parsedItem) {
                                if (!is_array($parsedItem)) {
                                    throw new ParseException('Merge items must be arrays.', $this->getRealCurrentLineNb() + 1, $parsedItem);
                                }

                                $data += $parsedItem; // array union
                            }
                        } else {
                            // If the value associated with the key is a single mapping node, each of its key/value pairs is inserted into the
                            // current mapping, unless the key already exists in it.
                            $data += $parsed; // array union
                        }
                    }
                } elseif (isset($values['value']) && self::preg_match('#^&(?P<ref>[^ ]+) *(?P<value>.*)#u', $values['value'], $matches)) {
                    $isRef = $matches['ref'];
                    $values['value'] = $matches['value'];
                }

                if ($mergeNode) {
                    // Merge keys
                } elseif (!isset($values['value']) || '' == trim($values['value'], ' ') || 0 === strpos(ltrim($values['value'], ' '), '#')) {
                    // hash
                    // if next line is less indented or equal, then it means that the current value is null
                    if (!$this->isNextLineIndented() && !$this->isNextLineUnIndentedCollection()) {
                        // Spec: Keys MUST be unique; first one wins.
                        // But overwriting is allowed when a merge node is used in current block.
                        if ($allowOverwrite || !isset($data[$key])) {
                            $data[$key] = null;
                        } else {
                            @trigger_error(sprintf('Duplicate key "%s" detected on line %d whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key, $this->getRealCurrentLineNb() + 1), E_USER_DEPRECATED);
                        }
                    } else {
                        // remember the parsed line number here in case we need it to provide some contexts in error messages below
                        $realCurrentLineNbKey = $this->getRealCurrentLineNb();
                        $value = $this->parseBlock($this->getRealCurrentLineNb() + 1, $this->getNextEmbedBlock(), $flags);
                        // Spec: Keys MUST be unique; first one wins.
                        // But overwriting is allowed when a merge node is used in current block.
                        if ($allowOverwrite || !isset($data[$key])) {
                            $data[$key] = $value;
                        } else {
                            @trigger_error(sprintf('Duplicate key "%s" detected on line %d whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key, $realCurrentLineNbKey + 1), E_USER_DEPRECATED);
                        }
                    }
                } else {
                    $value = $this->parseValue($values['value'], $flags, $context);
                    // Spec: Keys MUST be unique; first one wins.
                    // But overwriting is allowed when a merge node is used in current block.
                    if ($allowOverwrite || !isset($data[$key])) {
                        $data[$key] = $value;
                    } else {
                        @trigger_error(sprintf('Duplicate key "%s" detected on line %d whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key, $this->getRealCurrentLineNb() + 1), E_USER_DEPRECATED);
                    }
                }
                if ($isRef) {
                    $this->refs[$isRef] = $data[$key];
                }
            } else {
                // multiple documents are not supported
                if ('---' === $this->currentLine) {
                    throw new ParseException('Multiple documents are not supported.', $this->currentLineNb + 1, $this->currentLine);
                }

                // 1-liner optionally followed by newline(s)
                if (is_string($value) && $this->lines[0] === trim($value)) {
                    try {
                        Inline::$parsedLineNumber = $this->getRealCurrentLineNb();
                        $value = Inline::parse($this->lines[0], $flags, $this->refs);
                    } catch (ParseException $e) {
                        $e->setParsedLine($this->getRealCurrentLineNb() + 1);
                        $e->setSnippet($this->currentLine);

                        throw $e;
                    }

                    return $value;
                }

                throw new ParseException('Unable to parse.', $this->getRealCurrentLineNb() + 1, $this->currentLine);
            }
        }

        if (Yaml::PARSE_OBJECT_FOR_MAP & $flags && !is_object($data) && 'mapping' === $context) {
            $object = new \stdClass();

            foreach ($data as $key => $value) {
                $object->$key = $value;
            }

            $data = $object;
        }

        return empty($data) ? null : $data;
    }

    private function parseBlock($offset, $yaml, $flags)
    {
        $skippedLineNumbers = $this->skippedLineNumbers;

        foreach ($this->locallySkippedLineNumbers as $lineNumber) {
            if ($lineNumber < $offset) {
                continue;
            }

            $skippedLineNumbers[] = $lineNumber;
        }

        $parser = new self($offset, $this->totalNumberOfLines, $skippedLineNumbers);
        $parser->refs = &$this->refs;

        return $parser->doParse($yaml, $flags);
    }

    /**
     * Returns the current line number (takes the offset into account).
     *
     * @return int The current line number
     */
    private function getRealCurrentLineNb()
    {
        $realCurrentLineNumber = $this->currentLineNb + $this->offset;

        foreach ($this->skippedLineNumbers as $skippedLineNumber) {
            if ($skippedLineNumber > $realCurrentLineNumber) {
                break;
            }

            ++$realCurrentLineNumber;
        }

        return $realCurrentLineNumber;
    }

    /**
     * Returns the current line indentation.
     *
     * @return int The current line indentation
     */
    private function getCurrentLineIndentation()
    {
        return strlen($this->currentLine) - strlen(ltrim($this->currentLine, ' '));
    }

    /**
     * Returns the next embed block of YAML.
     *
     * @param int  $indentation The indent level at which the block is to be read, or null for default
     * @param bool $inSequence  True if the enclosing data structure is a sequence
     *
     * @return string A YAML string
     *
     * @throws ParseException When indentation problem are detected
     */
    private function getNextEmbedBlock($indentation = null, $inSequence = false)
    {
        $oldLineIndentation = $this->getCurrentLineIndentation();
        $blockScalarIndentations = array();

        if ($this->isBlockScalarHeader()) {
            $blockScalarIndentations[] = $this->getCurrentLineIndentation();
        }

        if (!$this->moveToNextLine()) {
            return;
        }

        if (null === $indentation) {
            $newIndent = $this->getCurrentLineIndentation();

            $unindentedEmbedBlock = $this->isStringUnIndentedCollectionItem();

            if (!$this->isCurrentLineEmpty() && 0 === $newIndent && !$unindentedEmbedBlock) {
                throw new ParseException('Indentation problem.', $this->getRealCurrentLineNb() + 1, $this->currentLine);
            }
        } else {
            $newIndent = $indentation;
        }

        $data = array();
        if ($this->getCurrentLineIndentation() >= $newIndent) {
            $data[] = substr($this->currentLine, $newIndent);
        } else {
            $this->moveToPreviousLine();

            return;
        }

        if ($inSequence && $oldLineIndentation === $newIndent && isset($data[0][0]) && '-' === $data[0][0]) {
            // the previous line contained a dash but no item content, this line is a sequence item with the same indentation
            // and therefore no nested list or mapping
            $this->moveToPreviousLine();

            return;
        }

        $isItUnindentedCollection = $this->isStringUnIndentedCollectionItem();

        if (empty($blockScalarIndentations) && $this->isBlockScalarHeader()) {
            $blockScalarIndentations[] = $this->getCurrentLineIndentation();
        }

        $previousLineIndentation = $this->getCurrentLineIndentation();

        while ($this->moveToNextLine()) {
            $indent = $this->getCurrentLineIndentation();

            // terminate all block scalars that are more indented than the current line
            if (!empty($blockScalarIndentations) && $indent < $previousLineIndentation && trim($this->currentLine) !== '') {
                foreach ($blockScalarIndentations as $key => $blockScalarIndentation) {
                    if ($blockScalarIndentation >= $this->getCurrentLineIndentation()) {
                        unset($blockScalarIndentations[$key]);
                    }
                }
            }

            if (empty($blockScalarIndentations) && !$this->isCurrentLineComment() && $this->isBlockScalarHeader()) {
                $blockScalarIndentations[] = $this->getCurrentLineIndentation();
            }

            $previousLineIndentation = $indent;

            if ($isItUnindentedCollection && !$this->isCurrentLineEmpty() && !$this->isStringUnIndentedCollectionItem() && $newIndent === $indent) {
                $this->moveToPreviousLine();
                break;
            }

            if ($this->isCurrentLineBlank()) {
                $data[] = substr($this->currentLine, $newIndent);
                continue;
            }

            // we ignore "comment" lines only when we are not inside a scalar block
            if (empty($blockScalarIndentations) && $this->isCurrentLineComment()) {
                // remember ignored comment lines (they are used later in nested
                // parser calls to determine real line numbers)
                //
                // CAUTION: beware to not populate the global property here as it
                // will otherwise influence the getRealCurrentLineNb() call here
                // for consecutive comment lines and subsequent embedded blocks
                $this->locallySkippedLineNumbers[] = $this->getRealCurrentLineNb();

                continue;
            }

            if ($indent >= $newIndent) {
                $data[] = substr($this->currentLine, $newIndent);
            } elseif (0 == $indent) {
                $this->moveToPreviousLine();

                break;
            } else {
                throw new ParseException('Indentation problem.', $this->getRealCurrentLineNb() + 1, $this->currentLine);
            }
        }

        return implode("\n", $data);
    }

    /**
     * Moves the parser to the next line.
     *
     * @return bool
     */
    private function moveToNextLine()
    {
        if ($this->currentLineNb >= count($this->lines) - 1) {
            return false;
        }

        $this->currentLine = $this->lines[++$this->currentLineNb];

        return true;
    }

    /**
     * Moves the parser to the previous line.
     *
     * @return bool
     */
    private function moveToPreviousLine()
    {
        if ($this->currentLineNb < 1) {
            return false;
        }

        $this->currentLine = $this->lines[--$this->currentLineNb];

        return true;
    }

    /**
     * Parses a YAML value.
     *
     * @param string $value   A YAML value
     * @param int    $flags   A bit field of PARSE_* constants to customize the YAML parser behavior
     * @param string $context The parser context (either sequence or mapping)
     *
     * @return mixed A PHP value
     *
     * @throws ParseException When reference does not exist
     */
    private function parseValue($value, $flags, $context)
    {
        if (0 === strpos($value, '*')) {
            if (false !== $pos = strpos($value, '#')) {
                $value = substr($value, 1, $pos - 2);
            } else {
                $value = substr($value, 1);
            }

            if (!array_key_exists($value, $this->refs)) {
                throw new ParseException(sprintf('Reference "%s" does not exist.', $value), $this->currentLineNb + 1, $this->currentLine);
            }

            return $this->refs[$value];
        }

        if (self::preg_match('/^'.self::TAG_PATTERN.self::BLOCK_SCALAR_HEADER_PATTERN.'$/', $value, $matches)) {
            $modifiers = isset($matches['modifiers']) ? $matches['modifiers'] : '';

            $data = $this->parseBlockScalar($matches['separator'], preg_replace('#\d+#', '', $modifiers), (int) abs($modifiers));

            if (isset($matches['tag']) && '!!binary' === $matches['tag']) {
                return Inline::evaluateBinaryScalar($data);
            }

            return $data;
        }

        try {
            $quotation = '' !== $value && ('"' === $value[0] || "'" === $value[0]) ? $value[0] : null;

            // do not take following lines into account when the current line is a quoted single line value
            if (null !== $quotation && preg_match('/^'.$quotation.'.*'.$quotation.'(\s*#.*)?$/', $value)) {
                return Inline::parse($value, $flags, $this->refs);
            }

            while ($this->moveToNextLine()) {
                // unquoted strings end before the first unindented line
                if (null === $quotation && $this->getCurrentLineIndentation() === 0) {
                    $this->moveToPreviousLine();

                    break;
                }

                $value .= ' '.trim($this->currentLine);

                // quoted string values end with a line that is terminated with the quotation character
                if ('' !== $this->currentLine && substr($this->currentLine, -1) === $quotation) {
                    break;
                }
            }

            Inline::$parsedLineNumber = $this->getRealCurrentLineNb();
            $parsedValue = Inline::parse($value, $flags, $this->refs);

            if ('mapping' === $context && is_string($parsedValue) && '"' !== $value[0] && "'" !== $value[0] && '[' !== $value[0] && '{' !== $value[0] && '!' !== $value[0] && false !== strpos($parsedValue, ': ')) {
                throw new ParseException('A colon cannot be used in an unquoted mapping value.');
            }

            return $parsedValue;
        } catch (ParseException $e) {
            $e->setParsedLine($this->getRealCurrentLineNb() + 1);
            $e->setSnippet($this->currentLine);

            throw $e;
        }
    }

    /**
     * Parses a block scalar.
     *
     * @param string $style       The style indicator that was used to begin this block scalar (| or >)
     * @param string $chomping    The chomping indicator that was used to begin this block scalar (+ or -)
     * @param int    $indentation The indentation indicator that was used to begin this block scalar
     *
     * @return string The text value
     */
    private function parseBlockScalar($style, $chomping = '', $indentation = 0)
    {
        $notEOF = $this->moveToNextLine();
        if (!$notEOF) {
            return '';
        }

        $isCurrentLineBlank = $this->isCurrentLineBlank();
        $blockLines = array();

        // leading blank lines are consumed before determining indentation
        while ($notEOF && $isCurrentLineBlank) {
            // newline only if not EOF
            if ($notEOF = $this->moveToNextLine()) {
                $blockLines[] = '';
                $isCurrentLineBlank = $this->isCurrentLineBlank();
            }
        }

        // determine indentation if not specified
        if (0 === $indentation) {
            if (self::preg_match('/^ +/', $this->currentLine, $matches)) {
                $indentation = strlen($matches[0]);
            }
        }

        if ($indentation > 0) {
            $pattern = sprintf('/^ {%d}(.*)$/', $indentation);

            while (
                $notEOF && (
                    $isCurrentLineBlank ||
                    self::preg_match($pattern, $this->currentLine, $matches)
                )
            ) {
                if ($isCurrentLineBlank && strlen($this->currentLine) > $indentation) {
                    $blockLines[] = substr($this->currentLine, $indentation);
                } elseif ($isCurrentLineBlank) {
                    $blockLines[] = '';
                } else {
                    $blockLines[] = $matches[1];
                }

                // newline only if not EOF
                if ($notEOF = $this->moveToNextLine()) {
                    $isCurrentLineBlank = $this->isCurrentLineBlank();
                }
            }
        } elseif ($notEOF) {
            $blockLines[] = '';
        }

        if ($notEOF) {
            $blockLines[] = '';
            $this->moveToPreviousLine();
        } elseif (!$notEOF && !$this->isCurrentLineLastLineInDocument()) {
            $blockLines[] = '';
        }

        // folded style
        if ('>' === $style) {
            $text = '';
            $previousLineIndented = false;
            $previousLineBlank = false;

            for ($i = 0, $blockLinesCount = count($blockLines); $i < $blockLinesCount; ++$i) {
                if ('' === $blockLines[$i]) {
                    $text .= "\n";
                    $previousLineIndented = false;
                    $previousLineBlank = true;
                } elseif (' ' === $blockLines[$i][0]) {
                    $text .= "\n".$blockLines[$i];
                    $previousLineIndented = true;
                    $previousLineBlank = false;
                } elseif ($previousLineIndented) {
                    $text .= "\n".$blockLines[$i];
                    $previousLineIndented = false;
                    $previousLineBlank = false;
                } elseif ($previousLineBlank || 0 === $i) {
                    $text .= $blockLines[$i];
                    $previousLineIndented = false;
                    $previousLineBlank = false;
                } else {
                    $text .= ' '.$blockLines[$i];
                    $previousLineIndented = false;
                    $previousLineBlank = false;
                }
            }
        } else {
            $text = implode("\n", $blockLines);
        }

        // deal with trailing newlines
        if ('' === $chomping) {
            $text = preg_replace('/\n+$/', "\n", $text);
        } elseif ('-' === $chomping) {
            $text = preg_replace('/\n+$/', '', $text);
        }

        return $text;
    }

    /**
     * Returns true if the next line is indented.
     *
     * @return bool Returns true if the next line is indented, false otherwise
     */
    private function isNextLineIndented()
    {
        $currentIndentation = $this->getCurrentLineIndentation();
        $EOF = !$this->moveToNextLine();

        while (!$EOF && $this->isCurrentLineEmpty()) {
            $EOF = !$this->moveToNextLine();
        }

        if ($EOF) {
            return false;
        }

        $ret = $this->getCurrentLineIndentation() > $currentIndentation;

        $this->moveToPreviousLine();

        return $ret;
    }

    /**
     * Returns true if the current line is blank or if it is a comment line.
     *
     * @return bool Returns true if the current line is empty or if it is a comment line, false otherwise
     */
    private function isCurrentLineEmpty()
    {
        return $this->isCurrentLineBlank() || $this->isCurrentLineComment();
    }

    /**
     * Returns true if the current line is blank.
     *
     * @return bool Returns true if the current line is blank, false otherwise
     */
    private function isCurrentLineBlank()
    {
        return '' == trim($this->currentLine, ' ');
    }

    /**
     * Returns true if the current line is a comment line.
     *
     * @return bool Returns true if the current line is a comment line, false otherwise
     */
    private function isCurrentLineComment()
    {
        //checking explicitly the first char of the trim is faster than loops or strpos
        $ltrimmedLine = ltrim($this->currentLine, ' ');

        return '' !== $ltrimmedLine && $ltrimmedLine[0] === '#';
    }

    private function isCurrentLineLastLineInDocument()
    {
        return ($this->offset + $this->currentLineNb) >= ($this->totalNumberOfLines - 1);
    }

    /**
     * Cleanups a YAML string to be parsed.
     *
     * @param string $value The input YAML string
     *
     * @return string A cleaned up YAML string
     */
    private function cleanup($value)
    {
        $value = str_replace(array("\r\n", "\r"), "\n", $value);

        // strip YAML header
        $count = 0;
        $value = preg_replace('#^\%YAML[: ][\d\.]+.*\n#u', '', $value, -1, $count);
        $this->offset += $count;

        // remove leading comments
        $trimmedValue = preg_replace('#^(\#.*?\n)+#s', '', $value, -1, $count);
        if ($count == 1) {
            // items have been removed, update the offset
            $this->offset += substr_count($value, "\n") - substr_count($trimmedValue, "\n");
            $value = $trimmedValue;
        }

        // remove start of the document marker (---)
        $trimmedValue = preg_replace('#^\-\-\-.*?\n#s', '', $value, -1, $count);
        if ($count == 1) {
            // items have been removed, update the offset
            $this->offset += substr_count($value, "\n") - substr_count($trimmedValue, "\n");
            $value = $trimmedValue;

            // remove end of the document marker (...)
            $value = preg_replace('#\.\.\.\s*$#', '', $value);
        }

        return $value;
    }

    /**
     * Returns true if the next line starts unindented collection.
     *
     * @return bool Returns true if the next line starts unindented collection, false otherwise
     */
    private function isNextLineUnIndentedCollection()
    {
        $currentIndentation = $this->getCurrentLineIndentation();
        $notEOF = $this->moveToNextLine();

        while ($notEOF && $this->isCurrentLineEmpty()) {
            $notEOF = $this->moveToNextLine();
        }

        if (false === $notEOF) {
            return false;
        }

        $ret = $this->getCurrentLineIndentation() === $currentIndentation && $this->isStringUnIndentedCollectionItem();

        $this->moveToPreviousLine();

        return $ret;
    }

    /**
     * Returns true if the string is un-indented collection item.
     *
     * @return bool Returns true if the string is un-indented collection item, false otherwise
     */
    private function isStringUnIndentedCollectionItem()
    {
        return '-' === rtrim($this->currentLine) || 0 === strpos($this->currentLine, '- ');
    }

    /**
     * Tests whether or not the current line is the header of a block scalar.
     *
     * @return bool
     */
    private function isBlockScalarHeader()
    {
        return (bool) self::preg_match('~'.self::BLOCK_SCALAR_HEADER_PATTERN.'$~', $this->currentLine);
    }

    /**
     * A local wrapper for `preg_match` which will throw a ParseException if there
     * is an internal error in the PCRE engine.
     *
     * This avoids us needing to check for "false" every time PCRE is used
     * in the YAML engine
     *
     * @throws ParseException on a PCRE internal error
     *
     * @see preg_last_error()
     *
     * @internal
     */
    public static function preg_match($pattern, $subject, &$matches = null, $flags = 0, $offset = 0)
    {
        if (false === $ret = preg_match($pattern, $subject, $matches, $flags, $offset)) {
            switch (preg_last_error()) {
                case PREG_INTERNAL_ERROR:
                    $error = 'Internal PCRE error.';
                    break;
                case PREG_BACKTRACK_LIMIT_ERROR:
                    $error = 'pcre.backtrack_limit reached.';
                    break;
                case PREG_RECURSION_LIMIT_ERROR:
                    $error = 'pcre.recursion_limit reached.';
                    break;
                case PREG_BAD_UTF8_ERROR:
                    $error = 'Malformed UTF-8 data.';
                    break;
                case PREG_BAD_UTF8_OFFSET_ERROR:
                    $error = 'Offset doesn\'t correspond to the begin of a valid UTF-8 code point.';
                    break;
                default:
                    $error = 'Error.';
            }

            throw new ParseException($error);
        }

        return $ret;
    }
}

{'repo_name': 'cashmusic/platform', 'stars': '1005', 'repo_language': 'PHP', 'file_name': 'SeedBase.php', 'mime_type': 'text/x-php', 'hash': -8541484149587016595, 'source_dataset': 'data'}


/*
 * Copyright 2009 Jerome Glisse.
 * All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sub license, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
 * USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * The above copyright notice and this permission notice (including the
 * next paragraph) shall be included in all copies or substantial portions
 * of the Software.
 *
 */
/*
 * Authors:
 *    Jerome Glisse <glisse@freedesktop.org>
 *    Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
 *    Dave Airlie
 */
#include <linux/list.h>
#include <linux/slab.h>
#include <drm/drmP.h>
#include "radeon_drm.h"
#include "radeon.h"
#include "radeon_trace.h"

int radeon_ttm_init(struct radeon_device *rdev);
void radeon_ttm_fini(struct radeon_device *rdev);
static void radeon_bo_clear_surface_reg(struct radeon_bo *bo);

/*
 * To exclude mutual BO access we rely on bo_reserve exclusion, as all
 * function are calling it.
 */

void radeon_bo_clear_va(struct radeon_bo *bo)
{
	struct radeon_bo_va *bo_va, *tmp;

	list_for_each_entry_safe(bo_va, tmp, &bo->va, bo_list) {
		/* remove from all vm address space */
		mutex_lock(&bo_va->vm->mutex);
		list_del(&bo_va->vm_list);
		mutex_unlock(&bo_va->vm->mutex);
		list_del(&bo_va->bo_list);
		kfree(bo_va);
	}
}

static void radeon_ttm_bo_destroy(struct ttm_buffer_object *tbo)
{
	struct radeon_bo *bo;

	bo = container_of(tbo, struct radeon_bo, tbo);
	mutex_lock(&bo->rdev->gem.mutex);
	list_del_init(&bo->list);
	mutex_unlock(&bo->rdev->gem.mutex);
	radeon_bo_clear_surface_reg(bo);
	radeon_bo_clear_va(bo);
	drm_gem_object_release(&bo->gem_base);
	kfree(bo);
}

bool radeon_ttm_bo_is_radeon_bo(struct ttm_buffer_object *bo)
{
	if (bo->destroy == &radeon_ttm_bo_destroy)
		return true;
	return false;
}

void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain)
{
	u32 c = 0;

	rbo->placement.fpfn = 0;
	rbo->placement.lpfn = 0;
	rbo->placement.placement = rbo->placements;
	rbo->placement.busy_placement = rbo->placements;
	if (domain & RADEON_GEM_DOMAIN_VRAM)
		rbo->placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED |
					TTM_PL_FLAG_VRAM;
	if (domain & RADEON_GEM_DOMAIN_GTT)
		rbo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_TT;
	if (domain & RADEON_GEM_DOMAIN_CPU)
		rbo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
	if (!c)
		rbo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
	rbo->placement.num_placement = c;
	rbo->placement.num_busy_placement = c;
}

int radeon_bo_create(struct radeon_device *rdev,
		     unsigned long size, int byte_align, bool kernel, u32 domain,
		     struct radeon_bo **bo_ptr)
{
	struct radeon_bo *bo;
	enum ttm_bo_type type;
	unsigned long page_align = roundup(byte_align, PAGE_SIZE) >> PAGE_SHIFT;
	unsigned long max_size = 0;
	size_t acc_size;
	int r;

	size = ALIGN(size, PAGE_SIZE);

	if (unlikely(rdev->mman.bdev.dev_mapping == NULL)) {
		rdev->mman.bdev.dev_mapping = rdev->ddev->dev_mapping;
	}
	if (kernel) {
		type = ttm_bo_type_kernel;
	} else {
		type = ttm_bo_type_device;
	}
	*bo_ptr = NULL;

	/* maximun bo size is the minimun btw visible vram and gtt size */
	max_size = min(rdev->mc.visible_vram_size, rdev->mc.gtt_size);
	if ((page_align << PAGE_SHIFT) >= max_size) {
		printk(KERN_WARNING "%s:%d alloc size %ldM bigger than %ldMb limit\n",
			__func__, __LINE__, page_align  >> (20 - PAGE_SHIFT), max_size >> 20);
		return -ENOMEM;
	}

	acc_size = ttm_bo_dma_acc_size(&rdev->mman.bdev, size,
				       sizeof(struct radeon_bo));

retry:
	bo = kzalloc(sizeof(struct radeon_bo), GFP_KERNEL);
	if (bo == NULL)
		return -ENOMEM;
	r = drm_gem_object_init(rdev->ddev, &bo->gem_base, size);
	if (unlikely(r)) {
		kfree(bo);
		return r;
	}
	bo->rdev = rdev;
	bo->gem_base.driver_private = NULL;
	bo->surface_reg = -1;
	INIT_LIST_HEAD(&bo->list);
	INIT_LIST_HEAD(&bo->va);
	radeon_ttm_placement_from_domain(bo, domain);
	/* Kernel allocation are uninterruptible */
	mutex_lock(&rdev->vram_mutex);
	r = ttm_bo_init(&rdev->mman.bdev, &bo->tbo, size, type,
			&bo->placement, page_align, 0, !kernel, NULL,
			acc_size, &radeon_ttm_bo_destroy);
	mutex_unlock(&rdev->vram_mutex);
	if (unlikely(r != 0)) {
		if (r != -ERESTARTSYS) {
			if (domain == RADEON_GEM_DOMAIN_VRAM) {
				domain |= RADEON_GEM_DOMAIN_GTT;
				goto retry;
			}
			dev_err(rdev->dev,
				"object_init failed for (%lu, 0x%08X)\n",
				size, domain);
		}
		return r;
	}
	*bo_ptr = bo;

	trace_radeon_bo_create(bo);

	return 0;
}

int radeon_bo_kmap(struct radeon_bo *bo, void **ptr)
{
	bool is_iomem;
	int r;

	if (bo->kptr) {
		if (ptr) {
			*ptr = bo->kptr;
		}
		return 0;
	}
	r = ttm_bo_kmap(&bo->tbo, 0, bo->tbo.num_pages, &bo->kmap);
	if (r) {
		return r;
	}
	bo->kptr = ttm_kmap_obj_virtual(&bo->kmap, &is_iomem);
	if (ptr) {
		*ptr = bo->kptr;
	}
	radeon_bo_check_tiling(bo, 0, 0);
	return 0;
}

void radeon_bo_kunmap(struct radeon_bo *bo)
{
	if (bo->kptr == NULL)
		return;
	bo->kptr = NULL;
	radeon_bo_check_tiling(bo, 0, 0);
	ttm_bo_kunmap(&bo->kmap);
}

void radeon_bo_unref(struct radeon_bo **bo)
{
	struct ttm_buffer_object *tbo;
	struct radeon_device *rdev;

	if ((*bo) == NULL)
		return;
	rdev = (*bo)->rdev;
	tbo = &((*bo)->tbo);
	mutex_lock(&rdev->vram_mutex);
	ttm_bo_unref(&tbo);
	mutex_unlock(&rdev->vram_mutex);
	if (tbo == NULL)
		*bo = NULL;
}

int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr)
{
	int r, i;

	if (bo->pin_count) {
		bo->pin_count++;
		if (gpu_addr)
			*gpu_addr = radeon_bo_gpu_offset(bo);
		return 0;
	}
	radeon_ttm_placement_from_domain(bo, domain);
	if (domain == RADEON_GEM_DOMAIN_VRAM) {
		/* force to pin into visible video ram */
		bo->placement.lpfn = bo->rdev->mc.visible_vram_size >> PAGE_SHIFT;
	}
	for (i = 0; i < bo->placement.num_placement; i++)
		bo->placements[i] |= TTM_PL_FLAG_NO_EVICT;
	r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false, false);
	if (likely(r == 0)) {
		bo->pin_count = 1;
		if (gpu_addr != NULL)
			*gpu_addr = radeon_bo_gpu_offset(bo);
	}
	if (unlikely(r != 0))
		dev_err(bo->rdev->dev, "%p pin failed\n", bo);
	return r;
}

int radeon_bo_unpin(struct radeon_bo *bo)
{
	int r, i;

	if (!bo->pin_count) {
		dev_warn(bo->rdev->dev, "%p unpin not necessary\n", bo);
		return 0;
	}
	bo->pin_count--;
	if (bo->pin_count)
		return 0;
	for (i = 0; i < bo->placement.num_placement; i++)
		bo->placements[i] &= ~TTM_PL_FLAG_NO_EVICT;
	r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false, false);
	if (unlikely(r != 0))
		dev_err(bo->rdev->dev, "%p validate failed for unpin\n", bo);
	return r;
}

int radeon_bo_evict_vram(struct radeon_device *rdev)
{
	/* late 2.6.33 fix IGP hibernate - we need pm ops to do this correct */
	if (0 && (rdev->flags & RADEON_IS_IGP)) {
		if (rdev->mc.igp_sideport_enabled == false)
			/* Useless to evict on IGP chips */
			return 0;
	}
	return ttm_bo_evict_mm(&rdev->mman.bdev, TTM_PL_VRAM);
}

void radeon_bo_force_delete(struct radeon_device *rdev)
{
	struct radeon_bo *bo, *n;

	if (list_empty(&rdev->gem.objects)) {
		return;
	}
	dev_err(rdev->dev, "Userspace still has active objects !\n");
	list_for_each_entry_safe(bo, n, &rdev->gem.objects, list) {
		mutex_lock(&rdev->ddev->struct_mutex);
		dev_err(rdev->dev, "%p %p %lu %lu force free\n",
			&bo->gem_base, bo, (unsigned long)bo->gem_base.size,
			*((unsigned long *)&bo->gem_base.refcount));
		mutex_lock(&bo->rdev->gem.mutex);
		list_del_init(&bo->list);
		mutex_unlock(&bo->rdev->gem.mutex);
		/* this should unref the ttm bo */
		drm_gem_object_unreference(&bo->gem_base);
		mutex_unlock(&rdev->ddev->struct_mutex);
	}
}

int radeon_bo_init(struct radeon_device *rdev)
{
	/* Add an MTRR for the VRAM */
	rdev->mc.vram_mtrr = mtrr_add(rdev->mc.aper_base, rdev->mc.aper_size,
			MTRR_TYPE_WRCOMB, 1);
	DRM_INFO("Detected VRAM RAM=%lluM, BAR=%lluM\n",
		rdev->mc.mc_vram_size >> 20,
		(unsigned long long)rdev->mc.aper_size >> 20);
	DRM_INFO("RAM width %dbits %cDR\n",
			rdev->mc.vram_width, rdev->mc.vram_is_ddr ? 'D' : 'S');
	return radeon_ttm_init(rdev);
}

void radeon_bo_fini(struct radeon_device *rdev)
{
	radeon_ttm_fini(rdev);
}

void radeon_bo_list_add_object(struct radeon_bo_list *lobj,
				struct list_head *head)
{
	if (lobj->wdomain) {
		list_add(&lobj->tv.head, head);
	} else {
		list_add_tail(&lobj->tv.head, head);
	}
}

int radeon_bo_list_validate(struct list_head *head)
{
	struct radeon_bo_list *lobj;
	struct radeon_bo *bo;
	u32 domain;
	int r;

	r = ttm_eu_reserve_buffers(head);
	if (unlikely(r != 0)) {
		return r;
	}
	list_for_each_entry(lobj, head, tv.head) {
		bo = lobj->bo;
		if (!bo->pin_count) {
			domain = lobj->wdomain ? lobj->wdomain : lobj->rdomain;

		retry:
			radeon_ttm_placement_from_domain(bo, domain);
			r = ttm_bo_validate(&bo->tbo, &bo->placement,
						true, false, false);
			if (unlikely(r)) {
				if (r != -ERESTARTSYS && domain == RADEON_GEM_DOMAIN_VRAM) {
					domain |= RADEON_GEM_DOMAIN_GTT;
					goto retry;
				}
				return r;
			}
		}
		lobj->gpu_offset = radeon_bo_gpu_offset(bo);
		lobj->tiling_flags = bo->tiling_flags;
	}
	return 0;
}

int radeon_bo_fbdev_mmap(struct radeon_bo *bo,
			     struct vm_area_struct *vma)
{
	return ttm_fbdev_mmap(vma, &bo->tbo);
}

int radeon_bo_get_surface_reg(struct radeon_bo *bo)
{
	struct radeon_device *rdev = bo->rdev;
	struct radeon_surface_reg *reg;
	struct radeon_bo *old_object;
	int steal;
	int i;

	BUG_ON(!atomic_read(&bo->tbo.reserved));

	if (!bo->tiling_flags)
		return 0;

	if (bo->surface_reg >= 0) {
		reg = &rdev->surface_regs[bo->surface_reg];
		i = bo->surface_reg;
		goto out;
	}

	steal = -1;
	for (i = 0; i < RADEON_GEM_MAX_SURFACES; i++) {

		reg = &rdev->surface_regs[i];
		if (!reg->bo)
			break;

		old_object = reg->bo;
		if (old_object->pin_count == 0)
			steal = i;
	}

	/* if we are all out */
	if (i == RADEON_GEM_MAX_SURFACES) {
		if (steal == -1)
			return -ENOMEM;
		/* find someone with a surface reg and nuke their BO */
		reg = &rdev->surface_regs[steal];
		old_object = reg->bo;
		/* blow away the mapping */
		DRM_DEBUG("stealing surface reg %d from %p\n", steal, old_object);
		ttm_bo_unmap_virtual(&old_object->tbo);
		old_object->surface_reg = -1;
		i = steal;
	}

	bo->surface_reg = i;
	reg->bo = bo;

out:
	radeon_set_surface_reg(rdev, i, bo->tiling_flags, bo->pitch,
			       bo->tbo.mem.start << PAGE_SHIFT,
			       bo->tbo.num_pages << PAGE_SHIFT);
	return 0;
}

static void radeon_bo_clear_surface_reg(struct radeon_bo *bo)
{
	struct radeon_device *rdev = bo->rdev;
	struct radeon_surface_reg *reg;

	if (bo->surface_reg == -1)
		return;

	reg = &rdev->surface_regs[bo->surface_reg];
	radeon_clear_surface_reg(rdev, bo->surface_reg);

	reg->bo = NULL;
	bo->surface_reg = -1;
}

int radeon_bo_set_tiling_flags(struct radeon_bo *bo,
				uint32_t tiling_flags, uint32_t pitch)
{
	int r;

	r = radeon_bo_reserve(bo, false);
	if (unlikely(r != 0))
		return r;
	bo->tiling_flags = tiling_flags;
	bo->pitch = pitch;
	radeon_bo_unreserve(bo);
	return 0;
}

void radeon_bo_get_tiling_flags(struct radeon_bo *bo,
				uint32_t *tiling_flags,
				uint32_t *pitch)
{
	BUG_ON(!atomic_read(&bo->tbo.reserved));
	if (tiling_flags)
		*tiling_flags = bo->tiling_flags;
	if (pitch)
		*pitch = bo->pitch;
}

int radeon_bo_check_tiling(struct radeon_bo *bo, bool has_moved,
				bool force_drop)
{
	BUG_ON(!atomic_read(&bo->tbo.reserved));

	if (!(bo->tiling_flags & RADEON_TILING_SURFACE))
		return 0;

	if (force_drop) {
		radeon_bo_clear_surface_reg(bo);
		return 0;
	}

	if (bo->tbo.mem.mem_type != TTM_PL_VRAM) {
		if (!has_moved)
			return 0;

		if (bo->surface_reg >= 0)
			radeon_bo_clear_surface_reg(bo);
		return 0;
	}

	if ((bo->surface_reg >= 0) && !has_moved)
		return 0;

	return radeon_bo_get_surface_reg(bo);
}

void radeon_bo_move_notify(struct ttm_buffer_object *bo,
			   struct ttm_mem_reg *mem)
{
	struct radeon_bo *rbo;
	if (!radeon_ttm_bo_is_radeon_bo(bo))
		return;
	rbo = container_of(bo, struct radeon_bo, tbo);
	radeon_bo_check_tiling(rbo, 0, 1);
	radeon_vm_bo_invalidate(rbo->rdev, rbo);
}

int radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo)
{
	struct radeon_device *rdev;
	struct radeon_bo *rbo;
	unsigned long offset, size;
	int r;

	if (!radeon_ttm_bo_is_radeon_bo(bo))
		return 0;
	rbo = container_of(bo, struct radeon_bo, tbo);
	radeon_bo_check_tiling(rbo, 0, 0);
	rdev = rbo->rdev;
	if (bo->mem.mem_type == TTM_PL_VRAM) {
		size = bo->mem.num_pages << PAGE_SHIFT;
		offset = bo->mem.start << PAGE_SHIFT;
		if ((offset + size) > rdev->mc.visible_vram_size) {
			/* hurrah the memory is not visible ! */
			radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_VRAM);
			rbo->placement.lpfn = rdev->mc.visible_vram_size >> PAGE_SHIFT;
			r = ttm_bo_validate(bo, &rbo->placement, false, true, false);
			if (unlikely(r != 0))
				return r;
			offset = bo->mem.start << PAGE_SHIFT;
			/* this should not happen */
			if ((offset + size) > rdev->mc.visible_vram_size)
				return -EINVAL;
		}
	}
	return 0;
}

int radeon_bo_wait(struct radeon_bo *bo, u32 *mem_type, bool no_wait)
{
	int r;

	r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, 0);
	if (unlikely(r != 0))
		return r;
	spin_lock(&bo->tbo.bdev->fence_lock);
	if (mem_type)
		*mem_type = bo->tbo.mem.mem_type;
	if (bo->tbo.sync_obj)
		r = ttm_bo_wait(&bo->tbo, true, true, no_wait);
	spin_unlock(&bo->tbo.bdev->fence_lock);
	ttm_bo_unreserve(&bo->tbo);
	return r;
}

/**
 * radeon_bo_reserve - reserve bo
 * @bo:		bo structure
 * @no_wait:		don't sleep while trying to reserve (return -EBUSY)
 *
 * Returns:
 * -EBUSY: buffer is busy and @no_wait is true
 * -ERESTARTSYS: A wait for the buffer to become unreserved was interrupted by
 * a signal. Release all buffer reservations and return to user-space.
 */
int radeon_bo_reserve(struct radeon_bo *bo, bool no_wait)
{
	int r;

	r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, 0);
	if (unlikely(r != 0)) {
		if (r != -ERESTARTSYS)
			dev_err(bo->rdev->dev, "%p reserve failed\n", bo);
		return r;
	}
	return 0;
}

/* object have to be reserved */
struct radeon_bo_va *radeon_bo_va(struct radeon_bo *rbo, struct radeon_vm *vm)
{
	struct radeon_bo_va *bo_va;

	list_for_each_entry(bo_va, &rbo->va, bo_list) {
		if (bo_va->vm == vm) {
			return bo_va;
		}
	}
	return NULL;
}

{'repo_name': 'shinpei0208/gdev', 'stars': '162', 'repo_language': 'C', 'file_name': 'CMakeLists.txt', 'mime_type': 'text/plain', 'hash': -2177450548924289947, 'source_dataset': 'data'}


// Copyright (C) 2005-2020 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library.  This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING3.  If not see
// <http://www.gnu.org/licenses/>.

// 25.2.4 replace_copy_if

// { dg-do compile }

#include <algorithm>
#include <testsuite_iterators.h>

using __gnu_test::input_iterator_wrapper;
using __gnu_test::output_iterator_wrapper;

struct X { };

struct Y { };

struct Z
{
  Z&
  operator=(const X&)
  { return *this; }

  Z&
  operator=(const Y&)
  { return *this; }
};

bool
predicate(const X&)
{ return true; }

output_iterator_wrapper<Z>
test1(input_iterator_wrapper<X>& begin,
      input_iterator_wrapper<X>& end,
      output_iterator_wrapper<Z>& output,
      const Y& new_val)
{
  return std::replace_copy_if(begin, end, output, predicate,
			      new_val);
}

{'repo_name': 'gcc-mirror/gcc', 'stars': '3986', 'repo_language': 'C', 'file_name': 'epiphany.opt', 'mime_type': 'text/plain', 'hash': 8311734424936644947, 'source_dataset': 'data'}


/**
 * Copyright © 2002 Instituto Superior Técnico
 *
 * This file is part of FenixEdu Academic.
 *
 * FenixEdu Academic is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * FenixEdu Academic is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with FenixEdu Academic.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.fenixedu.academic.util.report;

import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import java.util.Objects;

import org.fenixedu.academic.util.report.ReportPrinter.ReportDescription;
import org.fenixedu.academic.util.report.ReportPrinter.ReportResult;

public class ReportsUtils {

    private static ReportPrinter printer = (reports) -> {
        throw new UnsupportedOperationException("Cannot print reports: " + Arrays.toString(reports));
    };

    public static void setPrinter(ReportPrinter printer) {
        ReportsUtils.printer = Objects.requireNonNull(printer);
    }

    public static ReportResult generateReport(final String key, final Map<String, Object> parameters,
            final Collection<?> dataSource) {
        try {
            return printer.printReport(key, parameters, dataSource);
        } catch (Exception e) {
            throw new RuntimeException("Exception while generating report '" + key + "'", e);
        }
    }

    public static ReportResult generateReport(final ReportDescription... reports) {
        try {
            return printer.printReports(reports);
        } catch (Exception e) {
            throw new RuntimeException("Exception while generating reports '" + Arrays.toString(reports) + "'", e);
        }
    }
}

{'repo_name': 'FenixEdu/fenixedu-academic', 'stars': '154', 'repo_language': 'Java', 'file_name': 'ImportMessaging.java', 'mime_type': 'text/x-java', 'hash': 4772630883848453292, 'source_dataset': 'data'}


@import url("class.css");

body { font-family:Arial, sans-serif; background:#F3F3F3; overflow:hidden; }
input { padding:0; margin:0; }
a { outline:none; }

/* Buttons */
a.btt, a.arr { display:block; background:url(../images/btt-buttons.png) no-repeat 0 0; text-indent:-9999px; line-height:0; }

a.arr-add { width:13px; height:13px; background-position:-38px -562px; }
a.arr-add:hover { background-position:-38px -580px; }
a.arr-remove { width:13px; height:13px; background-position:-72px -562px; }
a.arr-remove:hover { background-position:-72px -580px; }
a.arr-duplicate { width:13px; height:13px; background-position:-177px -562px; }
a.arr-duplicate:hover { background-position:-177px -580px; }

a.btt-design { width:52px; height:22px; background-position:-249px -917px; }
a.btt-design:hover { background-position:-249px -1000px; }
a.btt-design.active { background-position:-249px -960px; }
a.btt-present { width:58px; height:22px; background-position:-306px -917px; }
a.btt-present:hover { background-position:-306px -1000px; }
a.btt-present.active { background-position:-306px -960px; }

a.btt-login { width:43px; height:22px; background-position:-17px -917px; }
a.btt-login:hover { background-position:-17px -1000px; }
a.btt-login.active { background-position:-17px -960px; }
a.btt-save { width:40px; height:22px; background-position:-108px -917px; }
a.btt-save:hover { background-position:-108px -1000px; }
a.btt-save.active { background-position:-17px -960px; }
a.btt-load { width:40px; height:22px; background-position:-160px -917px; }
a.btt-load:hover { background-position:-160px -1000px; }
a.btt-load.active { background-position:-17px -960px; }

a.btt-edit-master { width:90px; height:26px; background-position:-343px -1226px; }
a.btt-edit-master:hover { background-position:-343px -1269px; }
a.btt-edit-instance { width:90px; height:26px; background-position:-451px -1226px; }
a.btt-edit-instance:hover { background-position:-451px -1269px; }

a.btt-ok { width:35px; height:26px; background-position:-495px -211px;  }
a.btt-ok:hover { background-position:-495px -182px; }
a.btt-paste { width:48px; height:26px; background-position:-201px -415px; }
a.btt-paste:hover { background-position:-201px -385px; }

a.btt-edit-all { width:57px; height:26px; background-position:-544px -212px; }
a.btt-edit-all:hover { background-position:-544px -182px; }
a.btt-edit-all.active { background-position:-544px -152px; }

a.btt-new-master-object { width:128px; height:26px; background-position:-495px -1039px; }
a.btt-new-master-object:hover { background-position:-495px -1103px; }
a.btt-new-master-object.active { background-position:-495px -980px; }
a.btt-instance-of-master { width:90px; height:40px; background-position:-635px -979px; }
a.btt-instance-of-master:hover { background-position:-635px -1102px; }
a.btt-instance-of-master.active { background-position:-635px -1038px; }

a.btt-save-locally { width:90px; height:26px; background-position:-397px -212px; }
a.btt-save-locally:hover { background-position:-397px -182px; }
a.btt-load-file { width:66px; height:26px; background-position:-325px -212px; position: relative; }
a.btt-load-file:hover { background-position:-325px -182px; }

a.btt-selection { width:28px; height:28px; background-position:-57px -1267px; }
a.btt-selection:hover { background-position:-160px -1267px; }
a.btt-selection.active { background-position:-109px -1267px; }
a.btt-object { width:28px; height:28px; background-position:-57px -1301px; }
a.btt-object:hover { background-position:-160px -1301px; }
a.btt-object.active { background-position:-109px -1301px; }
a.btt-text { width:28px; height:28px; background-position:-57px -1335px; }
a.btt-text:hover { background-position:-160px -1335px; }
a.btt-text.active { background-position:-109px -1335px; }
a.btt-form { width:28px; height:28px; background-position:-57px -1369px; }
a.btt-form:hover { background-position:-160px -1369px; }
a.btt-form.active { background-position:-109px -1369px; }
a.btt-exp-threads { width:28px; height:28px; background-position:-57px -1403px; }
a.btt-exp-threads:hover { background-position:-160px -1403px; }
a.btt-exp-threads.active { background-position:-109px -1403px; }

a.btt-delete { margin:5px 3px 0 0; width:17px; height:17px; background-position:-713px -156px; }
a.btt-delete:hover { background-position:-713px -187px; }
a.btt-add { width:26px; height:26px; background-position:-611px -212px; }
a.btt-add:hover { background-position:-611px -182px; }
a.btt-see-all { width:58px; height:26px; background-position:-736px -213px; }
a.btt-see-all:hover { background-position:-736px -182px; }
a.btt-close { width:52px; height:26px; background-position:-649px -212px; }
a.btt-close:hover { background-position:-649px -182px; }

a.btt-frm-input-field { width:80px; height:60px; background-position:-10px -1490px; }
a.btt-frm-input-field:hover { background-position:-10px -1552px; }
a.btt-frm-checkbox { width:80px; height:60px; width:70px; background-position:-92px -1490px; }
a.btt-frm-checkbox:hover { background-position:-92px -1552px; }
a.btt-frm-radio-button { width:80px; height:60px; background-position:-164px -1490px; }
a.btt-frm-radio-button:hover { background-position:-164px -1552px; }
a.btt-frm-textarea { width:80px; height:60px; background-position:-246px -1490px; }
a.btt-frm-textarea:hover { background-position:-246px -1552px; }
a.btt-frm-pulldown {width:80px; height:60px;  background-position:-328px -1490px; }
a.btt-frm-pulldown:hover { background-position:-328px -1552px; }
a.btt-frm-button { width:80px; height:60px; background-position:-410px -1490px; }
a.btt-frm-button:hover { background-position:-410px -1552px; }

a.btt-inbetween { width:8px; height:4px; background-position:-352px -1417px; }
a.btt-inbetween:hover { background-position:-272px -1417px; }

a.btt-thread { width:28px; height:28px; background-position:-242px -1405px; }
a.btt-thread:hover { background-position:-282px -1405px; }
a.btt-thread.active { background-position:-322px -1405px; }

a.btt-add-thread { width:28px; height:28px; background-position:-362px -1405px; }
a.btt-add-thread:hover { background-position:-362px -1440px; }

a.btt-snapshot { width:28px; height:28px; background-position:-491px -1363px; }
a.btt-snapshot:hover { background-position:-533px -1363px; }
a.btt-action { width:28px; height:28px; background-position:-491px -1397px; }
a.btt-action:hover { background-position:-533px -1397px; }

a.btt-states { width:36px; height:36px; background-position:-591px -50px; }
a.btt-states.active { background-position:-511px -50px; }
a.btt-states:hover { background-position:-551px -50px; }

.w-hold { display:block; width:116px; height:45px; background:url(../images/btt-buttons.png) no-repeat 0 0; text-indent:-9999px; line-height:0;  }
.w-hold.holding-z { background-position:-677px -530px !important; }
.w-hold.holding-x { width:110px; height:78px; background-position:-563px -566px !important; }
.w-hold.hold-c { float:right; position:fixed; bottom:-5px; right:-5px; width:112px; height:37px; background-position:-122px -476px; }

.bg-over { background:url(../images/btt-buttons.png); background-position:-26px -365px; }

/* WRAPPER */
#wrapper { float:left; width:100%; margin-bottom:2px; }
#header { display:block; height:37px; background:#F3F3F3 url(../images/btt-buttons.png) no-repeat 0 0; }
#toolbox { background:#F3F3F3; float:left; width:38px; }
#workspace { float:left; display:block; margin-top:1px; }
#rightpanel { background:#F3F3F3; float:right; width:140px; font-size:9px; position:relative; }
#footer { clear:both; background:#F3F3F3; color:#DFDFDF; padding:0; width:100%; height:37px; font-size:10px; }

/* Header */
#header #wrap, #header #project #fProjName, #header #project #fThreadName, #header #project input#fEditing { float:left; }
#header #logo { float:left; width:38px; height:37px; }
	/* Change View: Design / Present */
	#header #change-view { float:left; width:150px; padding:7px 0 0 50px; }
	#header #change-view a { float:left; margin:0 5px; }

	/* Project: Name - Login - Save and Load */
	#header #project { float:left; padding:5px 0 0 45px; font-size:18px; color:#999999; font-family:Verdana; font-weight:bold; }
		#header #hSave { padding:7px 0 0 0; position:absolute; right:0; top:0; }
		#header #hSave a { float:left; margin:0 3px; }
		#header #hSave > div, #hSave > a { float:left; }
		#header #hSave a#fBLogout { float:right; margin-top:1px; }
		.hButton { padding:0 5px 0 0; border:0; }
			#header #hLoggedOut { }
			#header #hLoggedIn { text-align:right; padding:0 10px 0 0; width:260px; height:15px; display:none; }

		/* On hover over anchor buttons */
		/* SaveLoad Manager Stuff */
		#fSaveLoad { position:absolute; top:0px; right:0px; width:205px; z-index:100001; display:none; }
		#fSLSave, #fSLLoad, #fSLLogin { display:none; }
		.fSLCore { background: #4c4c4c; padding: 20px 0px 5px 10px; border-left:5px solid #4c4c4c; border-bottom:7px solid #4c4c4c; border-radius-bottomleft:4px; -webkit-border-radius-bottomleft:4px; -moz-border-radius-bottomleft:4px; }

		/* fSLLogin: Login Module */
		#fSLLogin {}
			#fSLLogin .d-menu { position:absolute; top:7px; right:0; }
			#fSLLogin .d-menu a { opacity:0.2; }
			#fSLLogin .d-inside {}
			#fSLLogin .d-inside h3 { margin:0; font-family:Verdana, serif; font-size:18px; font-weight:bold; color:#999; }
			#fSLLogin .d-inside small { margin:0 0 10px 0; font-family:Verdana, serif; font-size:11px; font-weight:normal; color:#CCC; }
			#fSLLogin .d-inside .d-wrap { margin:3px 0 5px 0; }
			#fSLLogin .d-inside .d-wrap input { width:95px; }
			#fSLLogin .d-inside a.btt-ok { margin-top:5px; }

		/* fSLSave: Save Module */
		#fSLSave { }
			#fSLSave .d-menu { position:absolute; top:7px; right:0; }
			#fSLSave .d-menu a { float:left; margin:0 6px 0 0; opacity:0.2; }
			#fSLSave .d-menu a.btt-load { margin-right:0; }
			#fSLSave .d-inside {}
			#fSLSave .d-inside h3 { margin:0; font-family:Verdana, serif; font-size:18px; font-weight:bold; color:#999; }
			#fSLSave .d-inside small { margin:0 0 10px 0; font-family:Verdana, serif; font-size:11px; font-weight:normal; color:#CCC; }
			#fSLSave .d-inside .d-wrap { margin:10px 0; }
			#fSLSave .d-inside .d-wrap a.btt-ok { float:right; margin:-3px 0 0 0; }
			#fSLSave .d-inside .d-wrap span.s-url { font-size:9px; color:#999; }
			#fSLSave .d-inside .d-wrap input.ipt-name { width:95px; }
			#fSLSave .d-inside .d-wrap #fTaken { display:none; position:absolute; right:49px; width:71px; padding:10px; color:#222; background:#EEE; border:1px solid #FFF; }
			#fSLSave .d-inside a.btt-save-locally { display:block; margin:3px 0 0 -2px; }

		/* fSLLoad: Load Module */
		#fSLLoad {}
			#fSLLoad .d-menu { position:absolute; top:7px; right:0; }
			#fSLLoad .d-menu a { float:left; margin:0 6px 0 0; opacity:0.2; }
			#fSLLoad .d-menu a.btt-load { margin-right:0; }
			#fSLLoad .d-inside {}
			#fSLLoad .d-inside h3 { margin:0; font-family:Verdana, serif; font-size:18px; font-weight:bold; color:#999; }
			#fSLLoad .d-inside small { margin:0 0 10px 0; font-family:Verdana, serif; font-size:11px; font-weight:normal; color:#CCC; }
			#fSLLoad .d-inside ul { margin:15px 0; }
			#fSLLoad .d-inside ul li { color:#999; font-size:9px; padding:3px 0; border-bottom:1px solid #666; }
			#fSLLoad .d-inside ul li a { color:#999; }
			#fSLLoad .d-inside a.btt-load-file { display:block; margin:3px 0 0 -2px; }

/* Left: Toolbox's anchors */
#toolbox a { margin:0 0 5px 5px; }

/* Workspace */
#fNotify {	background:#4C4C4C; border:4px solid #4C4C4C; border-radius:6px;	-webkit-border-bottom-right:6px;	-moz-border-radius-bottomright:6px; position:absolute; height:30px; left:38px; z-index:100002; padding:10px 10px 0 10px; margin:1px 0 0 0; color:#FFFFFF; font-size:18px; font-family:Verdana; display:none; opacity:0; }
.fWorkspace { border:1px solid #dFdFdF; overflow:hidden; position:absolute; background:#FFF; }
	/* Experience Threads */
	#fExpThreadBar { position:absolute; z-index:100001;	height:48px; margin:1px 0 0 1px; display:none; background:#B2B2B2; }
		#fExpTBArrow { width:10px; height:7px; background:url(../images/btt-buttons.png) -290px -1395px !important; position:absolute; top:-47px; left:26px; }

		#fExpTBThread { float:left; padding:10px 0 0 15px; }
		#fExpTBThread * { float:left; }
		#fExpTBThread a.btt-inbetween { margin:12px 5px 0 5px; }

		#fExpTBControls { float:right; padding:10px; }
		#fExpTBControls a { float:left; margin:0 0 0 5px; }
		#fExpTBControls a.btt-delete { margin:5px 0 5px 0; }

		#fExpTBOver { width:58px; top:48px; display:none; position:absolute; text-align:center; }
		#fExpTBOver div { width:48px; margin:0 auto; background:#B4B4B4; }
		#fExpTBOver div a { margin:0 auto; padding:3px 0 3px 0; }

		/* Add Thread */
			#fExpAdd { display:none; width:390px; position:absolute; top:100px; margin-left:30%; }
			.fExpAddCore { width:360px; background:#4C4C4C; padding:10px 15px 10px 15px; margin:0; font-size:1px; position:relative; border:5px solid #4C4C4C; border-radius:5px; -moz-border-radius:5px; -webkit-border-radius:5px; }

		/* See all */
			#fExpOverview { display:none; background:url('../images/bg-exp-thread-overview.png') repeat-y; position:absolute; z-index:10000; margin:1px 0 0 1px; }

/* Right - Pages - Panel */
.panelTitle { padding:4px; font-family:Verdana; font-size:10px; font-weight:bold; color:#ffffff; background:#888; margin-bottom:1px; }
.fPanelItemsList { overflow:hidden; clear:left; position:relative; cursor:auto; }
.panelItemsListCollapse { position:relative; height:-40px; }
.panelItemSelected { background: #333333 !important; color:#FFF !important; }
.fPanelItemsList div:hover, #fRightClickMenu div:hover{ background:#E5E5E5; }
	/* Right - Pages - Panel Navigation: Up and Down */
	.panel-navigation { display:block; }
		.panel-navigation a { display:block; width:138px; height:6px; background:url(../images/btt-buttons.png) no-repeat 0 0; text-indent:-9999px; line-height:0; }
			.panel-navigation a.panelArrowUp { background-position:-332px -1085px; }
			.panel-navigation a.panelArrowUp:hover { background-position:-332px -1048px; }
			.panel-navigation a.panelArrowDown { background-position:-332px -1102px; }
			.panel-navigation a.panelArrowDown:hover { background-position:-332px -1065px; }

	/* Right - Pages - Panel Icons: Add, Remove, Duplicate */
	.panelIcons {	background:#F4F4F4; width:100%; bottom:0; right:0; position:absolute; }
		.panelIcons a { float:left; display:block; margin:0px 2px 1px 2px; width:13px; height:13px;  }

/* Editing: Ideas */
	.fFCore { background:#4C4C4C; height:60px; display:inline; float:left; border:5px solid #4C4C4C; border-radius-topleft:5px; border-radius-topright:5px; -moz-border-radius-topleft:5px; -moz-border-radius-topright:5px; -webkit-border-radius-topleft:5px; -webkit-border-radius-topright:5px; }
	/* All Instance */
		.fFInstCore {	height:60px; background:#CCC; width:190px; padding-left:10px; border:5px solid #CCC; border-radius-topleft:5px; border-radius-topright:5px; -moz-border-radius-topleft:5px; -moz-border-radius-topright:5px; -webkit-border-radius-topleft:5px; -webkit-border-radius-topright:5px; }

/* Form Manager */
#fFormManager {}
#fFormManager .fFMCore { padding:10px 0 10px 0; }
	#fFormManager .fFMCore a { float:left; margin:0 5px 0 0; }

/* Edit States */
#fFStates { width:590px; border:5px solid #4C4C4C; border-radius-topleft:5px; border-radius-topright:5px; -moz-border-radius-topleft:5px; -moz-border-radius-topright:5px; -webkit-border-radius-topleft:5px; -webkit-border-radius-topright:5px; }
	/* Edit States: Edit Master + Press V */
		#fFStates #fSMIToggle { position:absolute; margin-top:8px; left:750px; }

/* Paste as */
#fPManager { position:absolute; width:270px; top:100px; left:100px; display:none; }
	#fPManager .fCBCorePaste { background:#4C4C4C; padding:20px 0 20px 0; text-align:center; background:#4c4c4c; border:4px solid #4c4c4c; border-radius:4px; -moz-border-radius:4px; }
	#fPManager .fCBCorePaste .w-buttons { width:223px; margin:0 auto; }
		#fPManager a.btt-new-master-object { float:left; }
		#fPManager a.btt-instance-of-master { float:right;  }
		#fPManager a.btt-paste { margin:0 auto; }

/* SET ACTION */
#fExpAct { width:390px; position:absolute; top:100px; margin-left:30%; display:none; cursor:move; }
	#fExpAct .fInput { width:100%; }

/* fStateManager - STATES: Holding Z */
#fStateManager { position:absolute; height:80px; top:50px; left:100px; display:none; }
	#fStateManager .fSMCore { padding:5px; }
	#fStateManager .fSMCore table { margin:0; padding:0; border: 0px;}
	#fStateManager .fSMCore table p { font-size:12px; color:#EEE; }
	#fStateManager .fSMCore table small { font-size:11px; color:#8C95C8; margin:0 0 0 10px; }
	#fStateManager .fSMCore table a#editAll { margin:10px 0 15px 13px; position: relative; }
	#fStateManager .fSMCore table #fSMStateName { white-space:nowrap; vertical-align:top; padding: 2px 0 0 2px; }
	#fStateManager .fSMCore table .fSMArrows { width:31px; margin:0 auto; padding: 0 0 15px 5px; }
	#fStateManager .fSMCore table .fSMArrows a { float:left; }
	#fStateManager .fSMCore table .fSMArrows a.arr-add { margin:0 5px 0 0; }
	#fStateManager .fSMCore table .fSMStates { padding-top: 8px; }
	#fStateManager .fSMCore table .fSMStates a { padding-bottom: 5px; }

/* fIdeaManager - Ideas STATES - Holding X */
#fIdeaManager { position:absolute; top:100px; left:100px; display:none; }
	#fIdeaManager #fIMCore { width:100px; background:#4C4C4C; padding:10px; margin:0; font-size:12px; border:4px solid #4C4C4C; border-radius:4px; -moz-border-radius:4px; position: relative; }
	#fIdeaManager #fIMCore .fIMHeader { position:absolute; top:10px; right:-5px; width:65px; }
	#fIdeaManager #fIMCore .fIMIdea { padding:5px 0 0 0; margin:0; position:relative; }
	#fIdeaManager #fIMCore .fIMArrows { margin:10px 0 0 1px; padding:0; }
	#fIdeaManager #fIMCore .fIMArrows a { float:left; }
	#fIdeaManager #fIMCore .fIMArrows a.arr-add { margin:0 5px 0 0; }

.fSMCore, .fFMCore { background:#4C4C4C; float:left; padding:5px 5px 0 0; margin:0; font-size:1px; border:6px solid #4C4C4C; border-radius:6px; -webkit-border-radius:6px; -moz-border-radius:6px; }
.fWorkspaceExpanded {	margin:0 102px 0 0 !important; }

/* Text */
.fTThick, .fTThickDrk { font:bold 32px Verdana; color:#4C4C4C; }  /* h3, .h3 = h-thick, h-thick-dark */
.fTThick2 { font:bold 18px Verdana; color:#999; } /* h4, .h4 = h-thick-18 */
.fT18 { font:18px Verdana; color:#999; } /* h5, h-18 */
.fT12 { font:12px Verdana; color:#FFF; } /* h6, h-12 */
.fT11 { font:11px Verdana; color:#CCC; } /* h7, h-11 */
.fTsmall { font:bold 10px verdana; color:#FFF; } /* h8, h-10 */
.fT9 { font:normal 9px Verdana; color:#CCC; } /* h9, h-9 */
.fTI { font-style:italic; } /* h-italic */
.fTB { font-weight:bold; } /* h-bold */
.fTDim { color:#999; } /* h-999 */
.fTThickDrk { color:#333; } /* h-333 */
.fTBlue { color:#8C92C5 !important; } /* h-blue */
.fTOrange { color: #FF6600 !important; } /* h-orange */

.fLink { text-decoration:none; }
.fLink:hover { color:#ffffff; text-decoration:underline; }

/* form elements */
.fInput { border:1px solid #000000; background-color:#cccccc; padding:3px; color:#2f2f2f; }
.fOptional { background-color:#737373; }
.fOptional:focus { background-color:#cccccc; }

#fNotifyRound { position:absolute; top:0px; right:-7px; }
/* EditMaster Overlay */
#fEditMasterOverlay { background:url('../images/bg_editMaster.png'); position:absolute; z-index:10001; width:100%; height:100%; }
/* List */
.fList { margin:3px 0 0 0; padding:0px; list-style:none; border-top:1px solid #666666; }
.fList li { font:9px verdana; padding:3px 0 3px 0; color:#999999; border-bottom:1px solid #666666; }
.fList li a { color:inherit; text-decoration:none; }
.fList li:hover { background-color: #333333; color:#ffffff; cursor:pointer; }
/* Panels */
.panel { width:138px; background-color:#f3f3f3; border:1px solid #DFDFDF; margin-bottom:3px; position:absolute; right:0px; height:100%; z-index:10001; }
#fRightClickMenu { width:200px; background-color:#ffffff; border:1px solid #666666; margin-bottom:3px; position:absolute; z-index:10003; right:0px; }
#fRightClickMenu div a { font-family:verdana; font-size:9px; color:#616DB4; text-decoration:none; }
.panelItem, #fRightClickMenu div { padding:2px; padding-left:4px; background-color:#F4F4F4; font-family:verdana; font-size:9px; color:#666666; cursor:pointer; }
/* Workspace and items inside of it */
.fObject { border:1px solid #dfdfdf; background:#FFF; position:absolute; text-align:center; }

.fForm { position:absolute !important; cursor:default; opacity:1; }

.p1 {}
.p2 { background:#dfdfdf; }
.p3 { background:#5f5f5f; }
.p4 { background:#1f1f1f; }

.fText { background:#FFF url('../images/bg_txt01.png') 0px 1px repeat; position:absolute; font-size:12px; text-align:left; wrap-option:softwrap; white-space:pre-wrap !important; }
.fTextHasTxt { outline:0px solid #ffffff; border:1px solid transparent; background:url('') !important; color:#909090; }
.fStateLabel { top:0px; right:0px; margin-right:-19px; margin-top: -1px; height:10px; width:12px; padding:0 2px 0 2px; background-color:#CFCFCF; color:#ffffff; font-size:8px; position:absolute; text-transform:capitalize; font-weight:bold; font-family:verdana; letter-spacing:-1px; }
.fLabelHolder { top:50%; display:inline; position:relative; }
.fLabel  { top:-6px; display:inline; font-size:10px; color:#9f9f9f; position:relative; }
.fLBracket { color:#6f6f6f; }
div.fLabel:hover { color:#333333; }
.fHighlight { position:absolute; top:0px; left:0px; outline:1px solid #000000; outline-offset:1px; text-align:left; width:100%; height:100%; }
.parent { background-image:url('../images/bg_parent.gif'); background-position:top right; background-repeat:no-repeat; }
.selected.fObject,.selectedWorkspace, .selectedTxt {	position: absolute; border-color:#0f0f0f; }
.selected.fForm { outline:1px solid #2f2f2f; opacity:1; }
.selectedInst {
	/*border-color: #D95700;
	background-image: url('../images/bg_selectedInst.gif');*/
}
.selectedTxt { border: 1px solid; }
.toBeCut {	opacity: 0.3; }
.selectedTxt { border:1px solid; }
/*inside items */
div.selected.fInsideMaster, .selected div.fInsideMaster { border-color:#626FB5; }
div.selected.fInsideInstance, .selected div.fInsideInstance { border-color:#FF6600; }
div.selectedTxt.fInsideMasterText, .selected div.fInsideMasterText { background:url('../images/bg_txtM01.png') 0px 1px repeat; color:#626FB5; }
div.selectedTxt.fInsideInstanceText, .selected div.fInsideInstanceText { background:url('../images/bg_txtI01.png') 0px 1px repeat; color:#FF6600; }
.fForm.selected.fInsideMaster, .selected .fForm.fInsideMaster { outline:1px solid #626FB5; opacity:1; }
.fForm.selected.fInsideInstance, .selected .fForm.fInsideInstance  { outline:1px solid #FF6600; opacity:1; }
input[type="text"].fForm, textarea.fForm { border:1px inset #cfcfcf; }
input[type="button"].fForm, input[type="text"].fForm, select.fForm { width:100px; }
/*cursor handling*/
.cursorMove { cursor:move !important; }
div.resizable { cursor:auto; }
.cursorCrosshair { cursor:crosshair; }
.pasteFillInst { background-color:#D95700; width:100%; height:100%; position:absolute; float:left; opacity:1; z-index:100000; }
/**** Footer Items - separate states *****/
#fFooterOI, #fFooterText, #fFooterForm, #fFooterWorkspace { padding-left:45px; position:absolute; display:none; z-index:10003; }
#fFooterWorkspace { display:block; }
/**** Footer Items - generic classes *****/
.fFItem,.fFInstItem {	float:left; bottom:0px; height:95px; padding-left:10px; }
.fFInstItem {	left:873px; bottom:-25px; position:absolute; }
.fFTop { height:35px; bottom:3px; position:relative; }
#fFInstItems { padding:5px 0 5px 0; }
#fFInstItems a img {	opacity:0.5; border:0px; }
#fFInstItems a { padding:0 2px 2px 0; }
#fFooterOI { height:105px !important; }
#fFAs { width:150px; text-align:center; }
#fFAs * { padding: 18px 1px 0 1px; }
#fWHXYHolder { padding:5px 0 0 5px; }
#fInstCore, #fStates { height:100%; display:inline; float:left; padding:0 3px 0 3px; }
#fInstCore .fIcons, #fStates .fIcons {	padding:4px 0px 0px 0px; }
#fObjName, #fStateName { text-decoration:none; }
.fWSTitle { display:inline; float:left; padding-top:16px; }
#fSSize,#fSPos,#fSContents,#fSEvents,#fSTone,#fMIToggleText { display:inline; float: left; padding-right:15px; }
#fMIToggleText { width:45px; }
#fSTone { padding-right:0px; }
#fSSize { margin-left:20px; padding-right:20px; }
.fSCheck { display:inline; float:left; padding:0 0 0 0; margin:4px 0 0 4px; background:url('../images/checkbox_on.png') no-repeat top left; width:18px;  height:16px; cursor:pointer; }
.fEditingObj div div.fSTitle { padding:3px 0 0 3px !important; }
.fEditingObj div div.fSTitle, .fSTitle { display:inline; float:left; padding:3px 0 0 0px; color:#8C95C8; height:17px; cursor:pointer; }
.fSInputLetter {	clear:left; margin:2px 0 2px -13px; display:inline; float:left; }
.fSInput { display:inline; float:left; margin-left:-1px; }
.fSText { clear:left; margin-left:4px; }
.fEditingObj div div.fSInput input, .fSInput input { font-size:10px; height:15px; background-color:#626FB5; font-family:arial; border:1px solid #3F4985; color:#ffffff;  padding:1px; margin-left:4px; }

/* off/unchecked state */
.fSOff div input { font-size:10px; height:15px; background-color:#FF6600; font-family:arial; border:1px solid #CA5100; color:#ffffff; padding:1px; margin-left:4px; }
.fSOff .fSTitle { color:#FF6600; }
.fSOff .fSCheck { background: url('../images/checkbox_off.png') no-repeat top left; }
.fFooterLink { color:#ffffff; }
.fEditable { border:1px solid #cccccc; background-color:#ffffff; padding:1px; padding-left:2px; font-size:9px; font-family:verdana; }
.fEditableLabel { width:65%; border:1px solid #CFCFCF; display:inline; font-family:inherit; font-size:inherit; }
.fEditableText { width:100%; height:100%; border:0px; margin:0px; background-color:#ffffff; position:absolute; font-family:inherit; font-size:inherit; }
.fCenter { text-align:center; height:14px; padding-top:2px; }
#fCBManager,#fPManager,#fEventManager,#fStateManager,#fIdeaManager,#fFormManager,#fExpAdd,#fExpAct { z-index:100000; }
#fEventManager { width: 238px; background-color: #ffffff; border:1px solid #666666; margin-bottom:3px; float:right; top:100px; left:100px; position:absolute; background:#333333; color:#dfdfdf; padding:5px; }
.fActCursor { cursor:url('../images/a_arrowFaded.png'), default; }
.fActNone { opacity:0.5; }
#fActMouseClear,#fActKeyClear { display:none; }
#fExpArrow { position:absolute; z-index:100002; background:url('../images/a_arrow.png'); width:38px; height:38px; display:none; cursor:move; }
.fArrowL { background: url('../images/a_arrow_L.png') !important; }
.fArrowR { background: url('../images/a_arrow_R.png') !important; }
.fArrowDL { background: url('../images/a_arrow_DL.png') !important; }
#fExpKey { position:absolute; background:url('../images/a_key.png') no-repeat right top; padding:2px 50px 0 0; z-index:100002; height:38px; top:95px; right:160px; min-width:100px; color:#CD0000; font-weight:bold; font-size:24px; text-align:right; display:none; }
/* State Manager*/
#fFormManager { position:absolute; height:80px; top:100px; left:100px; display:none; }
.fSMTitle1 { text-align:right; vertical-align:bottom; float:left; margin:2px 4px 0 0; width:95px; height:80px; position:relative; }
.fSMState { float:left; padding:0 3px 0 0; margin:0px; width:36px; text-align:center; vertical-align:top; position:relative; }
.fSMState input,.fIMIdea input { position:absolute; left:11px; bottom:-17px; margin:0px; padding:0px; width:14px; height:14px; }
.fIMIdea input { left:45px; top:15px; }
.fSMArrows { padding:3px 3px 0 3px; width:20px; }
.fSMStarting { display:block; position:absolute; bottom:13px; right:0px; color:#8C95C8; }
/* Clipboard State */
#fCBManager { position:absolute; width:270px; top:100px; left:100px; display:none; }
#fCBManager .fCBCore { padding:0px 10px 10px 10px; background:#4c4c4c; border:4px solid #4c4c4c; border-radius:4px; -moz-border-radius:4px; }
.fCBContents { display:none; }
#CBEmpty { padding:20px; }
#fCBInto { width:100%; height:33px; background:url('../images/into.png') no-repeat; vertical-align:middle; padding:10px 0 0 70px; text-align:left; font-weight: bold; color:#cccccc; }
.fThreadOverviewItem { position:absolute; text-decoration:none; cursor:move; }
.fExpHoverText { padding:3px 0 0 6px; }
#fTempJData { width:650px; height:550px; background-color:#ffffff; border:1px solid #666666; margin-bottom:3px; float:right; top:20px; left:400px; position:absolute; color:#000000; padding:5px; }
#fTempJData textarea { width:100%; height:100%; }

.hiddenSubmit {
	display: none;
}

/* ----------------------------------------------------------------- // ------------------------------------------------------------------------ */

{'repo_name': 'linowski/fluidia', 'stars': '125', 'repo_language': 'JavaScript', 'file_name': 'project01.json', 'mime_type': 'text/plain', 'hash': 3251487100552507507, 'source_dataset': 'data'}


/*
 * Copyright (C) Igor Sysoev
 * Copyright (C) Nginx, Inc.
 */

/*
ngx_radix_tree_t基数树与ngx_rbtree_t红黑树一样都是二叉查找树，ngx_rbtree_t红黑树具备的优点，ngx_radix_tree t基数树同样也有，
但ngx_radix_treej基数树的应用范围要比ngx_rbtree_t红黑树小，因为ngx_radix_treej要求元素必须以整型数据作为关键字，所以大大减少
了它的应用场景。然而，由于ngx_radix_tree_t墓数树在插入、删除元素时不需要做旋转操作，因此它的插入、删除效率一般要比ngx_rbtree_t
红黑树高。选择使用哪种二叉查找树取决于实际的应用场景。不过，ngx_radix_tree_t基数树的用法要比ngx_rbtree_t红黑树简单许多。
*/
#include <ngx_config.h>
#include <ngx_core.h>

static ngx_radix_node_t *ngx_radix_alloc(ngx_radix_tree_t *tree);

/*
将预分配节点简单地设置为-1，这样pool内存池中就会只使用1个页面来尽可能地分配基数树节点
*/
ngx_radix_tree_t *
ngx_radix_tree_create(ngx_pool_t *pool, ngx_int_t preallocate)
{
    uint32_t           key, mask, inc;
    ngx_radix_tree_t  *tree;

    tree = ngx_palloc(pool, sizeof(ngx_radix_tree_t));
    if (tree == NULL) {
        return NULL;
    }

    tree->pool = pool;
    tree->free = NULL;
    tree->start = NULL;
    tree->size = 0;

    tree->root = ngx_radix_alloc(tree);
    if (tree->root == NULL) {
        return NULL;
    }

    tree->root->right = NULL;
    tree->root->left = NULL;
    tree->root->parent = NULL;
    tree->root->value = NGX_RADIX_NO_VALUE;

    if (preallocate == 0) {
        return tree;
    }

    /*
     * Preallocation of first nodes : 0, 1, 00, 01, 10, 11, 000, 001, etc.
     * increases TLB hits even if for first lookup iterations.
     * On 32-bit platforms the 7 preallocated bits takes continuous 4K,
     * 8 - 8K, 9 - 16K, etc.  On 64-bit platforms the 6 preallocated bits
     * takes continuous 4K, 7 - 8K, 8 - 16K, etc.  There is no sense to
     * to preallocate more than one page, because further preallocation
     * distributes the only bit per page.  Instead, a random insertion
     * may distribute several bits per page.
     *
     * Thus, by default we preallocate maximum
     *     6 bits on amd64 (64-bit platform and 4K pages)
     *     7 bits on i386 (32-bit platform and 4K pages)
     *     7 bits on sparc64 in 64-bit mode (8K pages)
     *     8 bits on sparc64 in 32-bit mode (8K pages)
     */

    if (preallocate == -1) {
        switch (ngx_pagesize / sizeof(ngx_radix_node_t)) {

        /* amd64 */
        case 128:
            preallocate = 6;
            break;

        /* i386, sparc64 */
        case 256:
            preallocate = 7;
            break;

        /* sparc64 in 32-bit mode */
        default:
            preallocate = 8;
        }
    }

    mask = 0;
    inc = 0x80000000;

    while (preallocate--) {

        key = 0;
        mask >>= 1;
        mask |= 0x80000000;

        do {
            if (ngx_radix32tree_insert(tree, key, mask, NGX_RADIX_NO_VALUE)
                != NGX_OK)
            {
                return NULL;
            }

            key += inc;

        } while (key);

        inc >>= 1;
    }

    return tree;
}

ngx_int_t
ngx_radix32tree_insert(ngx_radix_tree_t *tree, uint32_t key, uint32_t mask,
    uintptr_t value)
{
    uint32_t           bit;
    ngx_radix_node_t  *node, *next;

    bit = 0x80000000;

    node = tree->root;
    next = tree->root;

    while (bit & mask) {
        if (key & bit) {
            next = node->right;

        } else {
            next = node->left;
        }

        if (next == NULL) {
            break;
        }

        bit >>= 1;
        node = next;
    }

    if (next) {
        if (node->value != NGX_RADIX_NO_VALUE) {
            return NGX_BUSY;
        }

        node->value = value;
        return NGX_OK;
    }

    while (bit & mask) {
        next = ngx_radix_alloc(tree);
        if (next == NULL) {
            return NGX_ERROR;
        }

        next->right = NULL;
        next->left = NULL;
        next->parent = node;
        next->value = NGX_RADIX_NO_VALUE;

        if (key & bit) {
            node->right = next;

        } else {
            node->left = next;
        }

        bit >>= 1;
        node = next;
    }

    node->value = value;

    return NGX_OK;
}

ngx_int_t
ngx_radix32tree_delete(ngx_radix_tree_t *tree, uint32_t key, uint32_t mask)
{
    uint32_t           bit;
    ngx_radix_node_t  *node;

    bit = 0x80000000;
    node = tree->root;

    while (node && (bit & mask)) {
        if (key & bit) {
            node = node->right;

        } else {
            node = node->left;
        }

        bit >>= 1;
    }

    if (node == NULL) {
        return NGX_ERROR;
    }

    if (node->right || node->left) {
        if (node->value != NGX_RADIX_NO_VALUE) {
            node->value = NGX_RADIX_NO_VALUE;
            return NGX_OK;
        }

        return NGX_ERROR;
    }

    for ( ;; ) {
        if (node->parent->right == node) {
            node->parent->right = NULL;

        } else {
            node->parent->left = NULL;
        }

        node->right = tree->free;
        tree->free = node;

        node = node->parent;

        if (node->right || node->left) {
            break;
        }

        if (node->value != NGX_RADIX_NO_VALUE) {
            break;
        }

        if (node->parent == NULL) {
            break;
        }
    }

    return NGX_OK;
}

uintptr_t
ngx_radix32tree_find(ngx_radix_tree_t *tree, uint32_t key)
{
    uint32_t           bit;
    uintptr_t          value;
    ngx_radix_node_t  *node;

    bit = 0x80000000;
    value = NGX_RADIX_NO_VALUE;
    node = tree->root;

    while (node) {
        if (node->value != NGX_RADIX_NO_VALUE) {
            value = node->value;
        }

        if (key & bit) {
            node = node->right;

        } else {
            node = node->left;
        }

        bit >>= 1;
    }

    return value;
}

#if (NGX_HAVE_INET6)

ngx_int_t
ngx_radix128tree_insert(ngx_radix_tree_t *tree, u_char *key, u_char *mask,
    uintptr_t value)
{
    u_char             bit;
    ngx_uint_t         i;
    ngx_radix_node_t  *node, *next;

    i = 0;
    bit = 0x80;

    node = tree->root;
    next = tree->root;

    while (bit & mask[i]) {
        if (key[i] & bit) {
            next = node->right;

        } else {
            next = node->left;
        }

        if (next == NULL) {
            break;
        }

        bit >>= 1;
        node = next;

        if (bit == 0) {
            if (++i == 16) {
                break;
            }

            bit = 0x80;
        }
    }

    if (next) {
        if (node->value != NGX_RADIX_NO_VALUE) {
            return NGX_BUSY;
        }

        node->value = value;
        return NGX_OK;
    }

    while (bit & mask[i]) {
        next = ngx_radix_alloc(tree);
        if (next == NULL) {
            return NGX_ERROR;
        }

        next->right = NULL;
        next->left = NULL;
        next->parent = node;
        next->value = NGX_RADIX_NO_VALUE;

        if (key[i] & bit) {
            node->right = next;

        } else {
            node->left = next;
        }

        bit >>= 1;
        node = next;

        if (bit == 0) {
            if (++i == 16) {
                break;
            }

            bit = 0x80;
        }
    }

    node->value = value;

    return NGX_OK;
}

ngx_int_t
ngx_radix128tree_delete(ngx_radix_tree_t *tree, u_char *key, u_char *mask)
{
    u_char             bit;
    ngx_uint_t         i;
    ngx_radix_node_t  *node;

    i = 0;
    bit = 0x80;
    node = tree->root;

    while (node && (bit & mask[i])) {
        if (key[i] & bit) {
            node = node->right;

        } else {
            node = node->left;
        }

        bit >>= 1;

        if (bit == 0) {
            if (++i == 16) {
                break;
            }

            bit = 0x80;
        }
    }

    if (node == NULL) {
        return NGX_ERROR;
    }

    if (node->right || node->left) {
        if (node->value != NGX_RADIX_NO_VALUE) {
            node->value = NGX_RADIX_NO_VALUE;
            return NGX_OK;
        }

        return NGX_ERROR;
    }

    for ( ;; ) {
        if (node->parent->right == node) {
            node->parent->right = NULL;

        } else {
            node->parent->left = NULL;
        }

        node->right = tree->free;
        tree->free = node;

        node = node->parent;

        if (node->right || node->left) {
            break;
        }

        if (node->value != NGX_RADIX_NO_VALUE) {
            break;
        }

        if (node->parent == NULL) {
            break;
        }
    }

    return NGX_OK;
}

uintptr_t
ngx_radix128tree_find(ngx_radix_tree_t *tree, u_char *key)
{
    u_char             bit;
    uintptr_t          value;
    ngx_uint_t         i;
    ngx_radix_node_t  *node;

    i = 0;
    bit = 0x80;
    value = NGX_RADIX_NO_VALUE;
    node = tree->root;

    while (node) {
        if (node->value != NGX_RADIX_NO_VALUE) {
            value = node->value;
        }

        if (key[i] & bit) {
            node = node->right;

        } else {
            node = node->left;
        }

        bit >>= 1;

        if (bit == 0) {
            i++;
            bit = 0x80;
        }
    }

    return value;
}

#endif

static ngx_radix_node_t *
ngx_radix_alloc(ngx_radix_tree_t *tree)
{
    ngx_radix_node_t  *p;

    if (tree->free) {
        p = tree->free;
        tree->free = tree->free->right;
        return p;
    }

    if (tree->size < sizeof(ngx_radix_node_t)) {
        tree->start = ngx_pmemalign(tree->pool, ngx_pagesize, ngx_pagesize);
        if (tree->start == NULL) {
            return NULL;
        }

        tree->size = ngx_pagesize;
    }

    p = (ngx_radix_node_t *) tree->start;
    tree->start += sizeof(ngx_radix_node_t);
    tree->size -= sizeof(ngx_radix_node_t);

    return p;
}

{'repo_name': 'y123456yz/reading-code-of-nginx-1.9.2', 'stars': '2382', 'repo_language': 'C', 'file_name': 'koi-win', 'mime_type': 'text/plain', 'hash': -1470252824763278143, 'source_dataset': 'data'}