<commit_before>/*
    Copyright 2011 Joe Hermaszewski. All rights reserved.

    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions are met:

    1. Redistributions of source code must retain the above copyright notice,
    this list of conditions and the following disclaimer.

    2. Redistributions in binary form must reproduce the above copyright notice,
    this list of conditions and the following disclaimer in the documentation
    and/or other materials provided with the distribution.

    THIS SOFTWARE IS PROVIDED BY JOE HERMASZEWSKI "AS IS" AND ANY EXPRESS OR
    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
    EVENT SHALL JOE HERMASZEWSKI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

    The views and conclusions contained in the software and documentation are
    those of the authors and should not be interpreted as representing official
    policies, either expressed or implied, of Joe Hermaszewski.
*/

#include "terminal_types.hpp"

#include <algorithm>
#include <cassert>
#include <functional>
#include <map>
#include <string>

namespace JoeLang
{
namespace Compiler
{

//------------------------------------------------------------------------------
// Tables of terminals
//------------------------------------------------------------------------------

//
// Ignored Sequence
//
const std::map<TerminalType, FunctionalTerminal> g_ignoredTerminals =
{
    { TerminalType::WHITESPACE,    { ReadWhitespace,   "whitespace"    } },
    { TerminalType::LINE_COMMENT,  { ReadLineComment,  "line comment"  } },
    { TerminalType::BLOCK_COMMENT, { ReadBlockComment, "block comment" } }
};

//
// Punctuation
//
const std::map<TerminalType, LiteralTerminal> g_punctuationTerminals =
{
    { TerminalType::OPEN_BRACE,           { "{"  } },
    { TerminalType::CLOSE_BRACE,          { "}"  } },
    { TerminalType::OPEN_ROUND,           { "("  } },
    { TerminalType::CLOSE_ROUND,          { ")"  } },
    { TerminalType::OPEN_ANGLED,          { "<"  } },
    { TerminalType::CLOSE_ANGLED,         { ">"  } },
    { TerminalType::OPEN_SQUARE,          { "["  } },
    { TerminalType::CLOSE_SQUARE,         { "]"  } },

    { TerminalType::EQUALITY,             { "==" } },
    { TerminalType::NOT_EQUALITY,         { "!=" } },
    { TerminalType::LESS_THAN_EQUALS,     { "<=" } },
    { TerminalType::GREATER_THAN_EQUALS,  { ">=" } },
    { TerminalType::LESS_THAN,            { "<"  } },
    { TerminalType::GREATER_THAN,         { ">"  } },

    { TerminalType::EQUALS,               { "="  } },
    { TerminalType::PLUS_EQUALS,          { "+=" } },
    { TerminalType::MINUS_EQUALS,         { "-=" } },
    { TerminalType::MULTIPLY_EQUALS,      { "*=" } },
    { TerminalType::DIVIDE_EQUALS,        { "/=" } },
    { TerminalType::MODULO_EQUALS,        { "%=" } },
    { TerminalType::AND_EQUALS,           { "&=" } },
    { TerminalType::INCLUSIVE_OR_EQUALS,  { "|=" } },
    { TerminalType::EXCLUSIVE_OR_EQUALS,  { "^=" } },
    { TerminalType::LEFT_SHIFT_EQUALS,    { "<<="} },
    { TerminalType::RIGHT_SHIFT_EQUALS,   { ">>="} },

    { TerminalType::LOGICAL_AND,          { "&&" } },
    { TerminalType::LOGICAL_OR,           { "||" } },
    { TerminalType::LOGICAL_NOT,          { "!"  } },

    { TerminalType::INCREMENT,            { "++" } },
    { TerminalType::DECREMENT,            { "--" } },
    { TerminalType::PLUS,                 { "+"  } },
    { TerminalType::MINUS,                { "-"  } },
    { TerminalType::MULTIPLY,             { "*"  } },
    { TerminalType::DIVIDE,               { "/"  } },
    { TerminalType::MODULO,               { "%"  } },
    { TerminalType::AND,                  { "&"  } },
    { TerminalType::INCLUSIVE_OR,         { "|"  } },
    { TerminalType::EXCLUSIVE_OR,         { "^"  } },
    { TerminalType::BITWISE_NOT,          { "~"  } },
    { TerminalType::LEFT_SHIFT,           { "<<" } },
    { TerminalType::RIGHT_SHIFT,          { ">>" } },

    { TerminalType::SEMICOLON,            { ";"  } },
    { TerminalType::COMMA,                { ","  } },
    { TerminalType::PERIOD,               { "."  } },
    { TerminalType::COLON,                { ":"  } },
    { TerminalType::QUERY,                { "?"  } }
};

//
// Literals
//
const std::map<TerminalType, FunctionalTerminal> g_literalTerminals =
{
    { TerminalType::INTEGER_LITERAL,   { ReadIntegerLiteral,   "integer literal"   } },
    { TerminalType::FLOATING_LITERAL,  { ReadFloatingLiteral,  "floating literal"  } },
    { TerminalType::CHARACTER_LITERAL, { ReadCharacterLiteral, "character literal" } },
    { TerminalType::STRING_LITERAL,    { ReadStringLiteral,    "string literal"    } },
    { TerminalType::IDENTIFIER,        { ReadIdentifier,       "identifier"        } },
};

//
// Keywords
//
const std::map<TerminalType, LiteralTerminal> g_keywordTerminals =
{
    { TerminalType::TECHNIQUE,    { "technique",  "" } },
    { TerminalType::PASS,         { "pass",       "" } },

    { TerminalType::TYPE_INT,     { "int",        "" } },

    { TerminalType::TRUE,         { "true",       "" } },
    { TerminalType::FALSE,        { "false",      "" } }
};

const std::string& GetTerminalString( TerminalType terminal_type )
{
    std::map<TerminalType, LiteralTerminal>::const_iterator literal_iterator;
    std::map<TerminalType, FunctionalTerminal>::const_iterator functional_iterator;

    functional_iterator = g_ignoredTerminals.find( terminal_type );
    if( functional_iterator != g_ignoredTerminals.end() )
        return functional_iterator->second.readable_string;

    literal_iterator = g_punctuationTerminals.find( terminal_type );
    if( literal_iterator != g_punctuationTerminals.end() )
        return literal_iterator->second.readable_string.empty()
                  ? literal_iterator->second.matched_string
                  : literal_iterator->second.readable_string;

    functional_iterator = g_literalTerminals.find( terminal_type );
    if( functional_iterator != g_literalTerminals.end() )
        return functional_iterator->second.readable_string;

    literal_iterator = g_keywordTerminals.find( terminal_type );
    if( literal_iterator != g_keywordTerminals.end() )
        return literal_iterator->second.readable_string.empty()
                  ? literal_iterator->second.matched_string
                  : literal_iterator->second.readable_string;

    const static std::string s = "Unnamed Terminal";
    const static std::string e = "EOF";

    if ( terminal_type == TerminalType::END_OF_INPUT )
        return e;
    return s;
}

//------------------------------------------------------------------------------
// LiteralTerminal
//------------------------------------------------------------------------------

std::size_t LiteralTerminal::Read( std::string::const_iterator begin,
                                   std::string::const_iterator end ) const
{
    assert( end >= begin && "begin is past end" );
    if( std::size_t(end - begin) < matched_string.size() ||
        !std::equal( matched_string.begin(), matched_string.end(), begin ) )
        return 0;

    return matched_string.size();
}

//------------------------------------------------------------------------------
// FunctionalTerminal
//------------------------------------------------------------------------------

std::size_t FunctionalTerminal::Read( std::string::const_iterator begin,
                                      std::string::const_iterator end ) const
{
    assert( end >= begin && "begin is past end" );
    return function( begin, end );
}

//------------------------------------------------------------------------------
// Reading Functions
//------------------------------------------------------------------------------

std::size_t ReadWhitespace( std::string::const_iterator begin,
                            std::string::const_iterator end )
{
    std::string::const_iterator p = begin;
    while( p < end )
    {
        char c = *p;
        if( c != ' '  &&
            c != '\n' &&
            c != '\r' &&
            c != '\t' &&
            c != '\v' )
            break;
        ++p;
    }

    return p - begin;
}

std::size_t ReadLineComment( std::string::const_iterator begin,
                             std::string::const_iterator end )
{
    std::string::const_iterator p = begin;
    if( end - begin < 2 )
        return 0;

    if( *p++ == '/' &&
        *p++ == '/' )
    {
        while( p < end )
        {
            char c = *p;
            if( c == '\n' )
                break;
            ++p;
        }
        return p - begin;
    }

    return 0;
}

std::size_t ReadBlockComment( std::string::const_iterator begin,
                              std::string::const_iterator end )
{
    std::string::const_iterator p = begin;
    if( end - begin < 4 )
        return 0;

    if( *p++ == '/' &&
        *p++ == '*' )
    {
        ++p;
        while( p < end )
        {
            char c = *p;
            if( c == '/' &&
                *(p-1) == '*' )
                return p - begin + 1;

            ++p;
        }
        return 0;
    }

    return 0;
}

std::size_t ReadIdentifier( std::string::const_iterator begin,
                            std::string::const_iterator end )
{
    std::string::const_iterator p = begin;
    if( !IsNonDigit( *p) )
        return 0;

    ++p;
    while( IsDigitOrNonDigit( *p ) )
        ++p;

    for( const auto& terminal_reader : g_keywordTerminals )
        if( std::size_t( p - begin ) == terminal_reader.second.matched_string.size() &&
            std::equal( begin, p, terminal_reader.second.matched_string.begin() ) )
            return 0;

    return p - begin;
}

std::size_t ReadDigitSequence( std::string::const_iterator begin,
                               std::string::const_iterator end )
{
    std::string::const_iterator p = begin;
    char c = *p;
    while( ( c >= '0' ) && ( c <= '9' ) && ( p < end ) )
    {
        ++p;
        c = *p;
    }
    return p - begin;
}

std::size_t ReadHexDigitSequence( std::string::const_iterator begin,
                                  std::string::const_iterator end )
{
    std::string::const_iterator p = begin;
    char c = *p;
    while( IsHexDigit( c ) && p < end )
    {
        ++p;
        c = *p;
    }
    return p - begin;
}

std::size_t ReadOctalDigitSequence( std::string::const_iterator begin,
                                    std::string::const_iterator end )
{
    std::string::const_iterator p = begin;
    char c = *p;
    while( ( c >= '0' ) && ( c <= '7' ) && p < end )
    {
        ++p;
        c = *p;
    }
    return p - begin;
}

std::size_t ReadIntegerLiteral( std::string::const_iterator begin,
                                std::string::const_iterator end )
{
    std::string::const_iterator p = begin;
    if( *p == '0' )
    {
        ++p;
        if( p >= end )
            return 1;

        if( *p == 'x' ||
            *p == 'X' )
        {
            ++p;
            int n = ReadHexDigitSequence( p, end );
            if( !n )
                return 0;
            p += n;
            if( *p == 'e' ||
                *p == 'E' )
                return 0;
            return p - begin;
        }

        p += ReadOctalDigitSequence( p, end );
    }
    else
    {
        p += ReadDigitSequence( begin, end );
    }

    // Check that we haven't just read the first part of a float
    if( *p == '.' ||
        *p == 'e' ||
        *p == 'E' )
        return 0;

    // Read the integer suffix
    // TODO return any chars here for better diagnostics
    if( *p == 'u' )
        ++p;

    if( *p == 'i' )
        ++p;
    else if( *p == 'l' )
        ++p;
    else if( *p == 's' )
        ++p;
    else if( *p == 't' )
        ++p;

    return p - begin;
}

std::size_t ReadExponent( std::string::const_iterator begin,
                          std::string::const_iterator end )
{
    if( end - begin < 2 )
        return 0;

    std::string::const_iterator p = begin;
    char c = *p;
    if( ( c != 'e' ) && ( c != 'E' ) )
        return 0;

    ++p;
    c = *p;

    if( ( c == '+' ) || ( c == '-' ) )
        ++p;

    int s = ReadDigitSequence( p, end );
    if( s == 0 )
        return 0;

    p += s;
    return p - begin;
}

std::size_t ReadFloatingLiteral( std::string::const_iterator begin,
                                 std::string::const_iterator end )
{
    std::string::const_iterator p = begin;
    int s = ReadDigitSequence( p, end );
    if( !s )
    {
        if( *p != '.' )
            return 0;

        ++p;
        s = ReadDigitSequence( p, end );
        if( !s )
            return 0;

        p += s;

        p += ReadExponent( p, end );
    }
    else
    {
        p += s;
        if( p >= end )
            return 0;

        if( *p != '.' )
        {
            s = ReadExponent( p, end );
            if( !s )
                return 0;
        }
        else
        {
            ++p;
            p += ReadDigitSequence( p, end );
            p += ReadExponent( p, end );
        }
    }

    if( p >= end )
        return p - begin;

    char c = *p;
    if( c == 'f' )
        ++p;

    return p - begin;
}

std::size_t ReadCharOrEscapedChar( std::string::const_iterator begin,
                                   std::string::const_iterator end )
{
    if( end - begin < 2 )
        return 0;

    std::string::const_iterator p = begin;
    if( *p == '\\' )
        ++p;

    ++p;
    return p - begin;
}

std::size_t ReadCharacterLiteral( std::string::const_iterator begin,
                                  std::string::const_iterator end )
{
    std::string::const_iterator p = begin;
    if( *p != '\'' )
        return 0;

    p += ReadCharOrEscapedChar( p, end );

    if( *p != '\'' )
        return 0;

    return p - begin;
}

std::size_t ReadStringLiteral( std::string::const_iterator begin,
                               std::string::const_iterator end )
{
    std::string::const_iterator p = begin;
    if( *p != '\"' )
        return 0;

    ++p;

    while( *p != '\"' &&
           p < end )
        p += ReadCharOrEscapedChar( p, end );

    if( p == end )
        return 0;

    ++p;

    return p - begin;
}

bool IsHexDigit( char c )
{
    return ( c >= '0' && c <= '9' ) ||
           ( c >= 'a' && c <= 'f' ) ||
           ( c >= 'A' && c <= 'F' );
}

bool IsNonDigit( char c )
{
    return ( c >= 'a' && c <= 'z' ) ||
           ( c >= 'A' && c <= 'Z' ) ||
           ( c == '_' );
}

bool IsDigitOrNonDigit( char c )
{
    return IsNonDigit( c ) ||
           ( c >= '0' && c <= '9' );
}

} // namespace Compiler
} // namespace JoeLang
<commit_msg>[~] comments<commit_after>/*
    Copyright 2011 Joe Hermaszewski. All rights reserved.

    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions are met:

    1. Redistributions of source code must retain the above copyright notice,
    this list of conditions and the following disclaimer.

    2. Redistributions in binary form must reproduce the above copyright notice,
    this list of conditions and the following disclaimer in the documentation
    and/or other materials provided with the distribution.

    THIS SOFTWARE IS PROVIDED BY JOE HERMASZEWSKI "AS IS" AND ANY EXPRESS OR
    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
    EVENT SHALL JOE HERMASZEWSKI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

    The views and conclusions contained in the software and documentation are
    those of the authors and should not be interpreted as representing official
    policies, either expressed or implied, of Joe Hermaszewski.
*/

#include "terminal_types.hpp"

#include <algorithm>
#include <cassert>
#include <functional>
#include <map>
#include <string>

namespace JoeLang
{
namespace Compiler
{

//------------------------------------------------------------------------------
// Tables of terminals
//------------------------------------------------------------------------------

//
// Ignored Sequence
//
const std::map<TerminalType, FunctionalTerminal> g_ignoredTerminals =
{
    { TerminalType::WHITESPACE,    { ReadWhitespace,   "whitespace"    } },
    { TerminalType::LINE_COMMENT,  { ReadLineComment,  "line comment"  } },
    { TerminalType::BLOCK_COMMENT, { ReadBlockComment, "block comment" } }
};

//
// Punctuation
//
const std::map<TerminalType, LiteralTerminal> g_punctuationTerminals =
{
    { TerminalType::OPEN_BRACE,           { "{"  } },
    { TerminalType::CLOSE_BRACE,          { "}"  } },
    { TerminalType::OPEN_ROUND,           { "("  } },
    { TerminalType::CLOSE_ROUND,          { ")"  } },
    { TerminalType::OPEN_ANGLED,          { "<"  } },
    { TerminalType::CLOSE_ANGLED,         { ">"  } },
    { TerminalType::OPEN_SQUARE,          { "["  } },
    { TerminalType::CLOSE_SQUARE,         { "]"  } },

    { TerminalType::EQUALITY,             { "==" } },
    { TerminalType::NOT_EQUALITY,         { "!=" } },
    { TerminalType::LESS_THAN_EQUALS,     { "<=" } },
    { TerminalType::GREATER_THAN_EQUALS,  { ">=" } },
    { TerminalType::LESS_THAN,            { "<"  } },
    { TerminalType::GREATER_THAN,         { ">"  } },

    { TerminalType::EQUALS,               { "="  } },
    { TerminalType::PLUS_EQUALS,          { "+=" } },
    { TerminalType::MINUS_EQUALS,         { "-=" } },
    { TerminalType::MULTIPLY_EQUALS,      { "*=" } },
    { TerminalType::DIVIDE_EQUALS,        { "/=" } },
    { TerminalType::MODULO_EQUALS,        { "%=" } },
    { TerminalType::AND_EQUALS,           { "&=" } },
    { TerminalType::INCLUSIVE_OR_EQUALS,  { "|=" } },
    { TerminalType::EXCLUSIVE_OR_EQUALS,  { "^=" } },
    { TerminalType::LEFT_SHIFT_EQUALS,    { "<<="} },
    { TerminalType::RIGHT_SHIFT_EQUALS,   { ">>="} },

    { TerminalType::LOGICAL_AND,          { "&&" } },
    { TerminalType::LOGICAL_OR,           { "||" } },
    { TerminalType::LOGICAL_NOT,          { "!"  } },

    { TerminalType::INCREMENT,            { "++" } },
    { TerminalType::DECREMENT,            { "--" } },
    { TerminalType::PLUS,                 { "+"  } },
    { TerminalType::MINUS,                { "-"  } },
    { TerminalType::MULTIPLY,             { "*"  } },
    { TerminalType::DIVIDE,               { "/"  } },
    { TerminalType::MODULO,               { "%"  } },
    { TerminalType::AND,                  { "&"  } },
    { TerminalType::INCLUSIVE_OR,         { "|"  } },
    { TerminalType::EXCLUSIVE_OR,         { "^"  } },
    { TerminalType::BITWISE_NOT,          { "~"  } },
    { TerminalType::LEFT_SHIFT,           { "<<" } },
    { TerminalType::RIGHT_SHIFT,          { ">>" } },

    { TerminalType::SEMICOLON,            { ";"  } },
    { TerminalType::COMMA,                { ","  } },
    { TerminalType::PERIOD,               { "."  } },
    { TerminalType::COLON,                { ":"  } },
    { TerminalType::QUERY,                { "?"  } }
};

//
// Literals
//
const std::map<TerminalType, FunctionalTerminal> g_literalTerminals =
{
    { TerminalType::INTEGER_LITERAL,   { ReadIntegerLiteral,   "integer literal"   } },
    { TerminalType::FLOATING_LITERAL,  { ReadFloatingLiteral,  "floating literal"  } },
    { TerminalType::CHARACTER_LITERAL, { ReadCharacterLiteral, "character literal" } },
    { TerminalType::STRING_LITERAL,    { ReadStringLiteral,    "string literal"    } },
    { TerminalType::IDENTIFIER,        { ReadIdentifier,       "identifier"        } },
};

//
// Keywords
//
const std::map<TerminalType, LiteralTerminal> g_keywordTerminals =
{
    { TerminalType::TECHNIQUE,    { "technique",  "" } },
    { TerminalType::PASS,         { "pass",       "" } },

    //
    // Types
    //
    { TerminalType::TYPE_INT,     { "int",        "" } },

    //
    // Constants
    //
    { TerminalType::TRUE,         { "true",       "" } },
    { TerminalType::FALSE,        { "false",      "" } }
};

const std::string& GetTerminalString( TerminalType terminal_type )
{
    std::map<TerminalType, LiteralTerminal>::const_iterator literal_iterator;
    std::map<TerminalType, FunctionalTerminal>::const_iterator functional_iterator;

    functional_iterator = g_ignoredTerminals.find( terminal_type );
    if( functional_iterator != g_ignoredTerminals.end() )
        return functional_iterator->second.readable_string;

    literal_iterator = g_punctuationTerminals.find( terminal_type );
    if( literal_iterator != g_punctuationTerminals.end() )
        return literal_iterator->second.readable_string.empty()
                  ? literal_iterator->second.matched_string
                  : literal_iterator->second.readable_string;

    functional_iterator = g_literalTerminals.find( terminal_type );
    if( functional_iterator != g_literalTerminals.end() )
        return functional_iterator->second.readable_string;

    literal_iterator = g_keywordTerminals.find( terminal_type );
    if( literal_iterator != g_keywordTerminals.end() )
        return literal_iterator->second.readable_string.empty()
                  ? literal_iterator->second.matched_string
                  : literal_iterator->second.readable_string;

    const static std::string s = "Unnamed Terminal";
    const static std::string e = "EOF";

    if ( terminal_type == TerminalType::END_OF_INPUT )
        return e;
    return s;
}

//------------------------------------------------------------------------------
// LiteralTerminal
//------------------------------------------------------------------------------

std::size_t LiteralTerminal::Read( std::string::const_iterator begin,
                                   std::string::const_iterator end ) const
{
    assert( end >= begin && "begin is past end" );
    if( std::size_t(end - begin) < matched_string.size() ||
        !std::equal( matched_string.begin(), matched_string.end(), begin ) )
        return 0;

    return matched_string.size();
}

//------------------------------------------------------------------------------
// FunctionalTerminal
//------------------------------------------------------------------------------

std::size_t FunctionalTerminal::Read( std::string::const_iterator begin,
                                      std::string::const_iterator end ) const
{
    assert( end >= begin && "begin is past end" );
    return function( begin, end );
}

//------------------------------------------------------------------------------
// Reading Functions
//------------------------------------------------------------------------------

std::size_t ReadWhitespace( std::string::const_iterator begin,
                            std::string::const_iterator end )
{
    std::string::const_iterator p = begin;
    while( p < end )
    {
        char c = *p;
        if( c != ' '  &&
            c != '\n' &&
            c != '\r' &&
            c != '\t' &&
            c != '\v' )
            break;
        ++p;
    }

    return p - begin;
}

std::size_t ReadLineComment( std::string::const_iterator begin,
                             std::string::const_iterator end )
{
    std::string::const_iterator p = begin;
    if( end - begin < 2 )
        return 0;

    if( *p++ == '/' &&
        *p++ == '/' )
    {
        while( p < end )
        {
            char c = *p;
            if( c == '\n' )
                break;
            ++p;
        }
        return p - begin;
    }

    return 0;
}

std::size_t ReadBlockComment( std::string::const_iterator begin,
                              std::string::const_iterator end )
{
    std::string::const_iterator p = begin;
    if( end - begin < 4 )
        return 0;

    if( *p++ == '/' &&
        *p++ == '*' )
    {
        ++p;
        while( p < end )
        {
            char c = *p;
            if( c == '/' &&
                *(p-1) == '*' )
                return p - begin + 1;

            ++p;
        }
        return 0;
    }

    return 0;
}

std::size_t ReadIdentifier( std::string::const_iterator begin,
                            std::string::const_iterator end )
{
    std::string::const_iterator p = begin;
    if( !IsNonDigit( *p) )
        return 0;

    ++p;
    while( IsDigitOrNonDigit( *p ) )
        ++p;

    for( const auto& terminal_reader : g_keywordTerminals )
        if( std::size_t( p - begin ) == terminal_reader.second.matched_string.size() &&
            std::equal( begin, p, terminal_reader.second.matched_string.begin() ) )
            return 0;

    return p - begin;
}

std::size_t ReadDigitSequence( std::string::const_iterator begin,
                               std::string::const_iterator end )
{
    std::string::const_iterator p = begin;
    char c = *p;
    while( ( c >= '0' ) && ( c <= '9' ) && ( p < end ) )
    {
        ++p;
        c = *p;
    }
    return p - begin;
}

std::size_t ReadHexDigitSequence( std::string::const_iterator begin,
                                  std::string::const_iterator end )
{
    std::string::const_iterator p = begin;
    char c = *p;
    while( IsHexDigit( c ) && p < end )
    {
        ++p;
        c = *p;
    }
    return p - begin;
}

std::size_t ReadOctalDigitSequence( std::string::const_iterator begin,
                                    std::string::const_iterator end )
{
    std::string::const_iterator p = begin;
    char c = *p;
    while( ( c >= '0' ) && ( c <= '7' ) && p < end )
    {
        ++p;
        c = *p;
    }
    return p - begin;
}

std::size_t ReadIntegerLiteral( std::string::const_iterator begin,
                                std::string::const_iterator end )
{
    std::string::const_iterator p = begin;
    if( *p == '0' )
    {
        ++p;
        if( p >= end )
            return 1;

        if( *p == 'x' ||
            *p == 'X' )
        {
            ++p;
            int n = ReadHexDigitSequence( p, end );
            if( !n )
                return 0;
            p += n;
            if( *p == 'e' ||
                *p == 'E' )
                return 0;
            return p - begin;
        }

        p += ReadOctalDigitSequence( p, end );
    }
    else
    {
        p += ReadDigitSequence( begin, end );
    }

    // Check that we haven't just read the first part of a float
    if( *p == '.' ||
        *p == 'e' ||
        *p == 'E' )
        return 0;

    // Read the integer suffix
    // TODO return any chars here for better diagnostics
    if( *p == 'u' )
        ++p;

    if( *p == 'i' )
        ++p;
    else if( *p == 'l' )
        ++p;
    else if( *p == 's' )
        ++p;
    else if( *p == 't' )
        ++p;

    return p - begin;
}

std::size_t ReadExponent( std::string::const_iterator begin,
                          std::string::const_iterator end )
{
    if( end - begin < 2 )
        return 0;

    std::string::const_iterator p = begin;
    char c = *p;
    if( ( c != 'e' ) && ( c != 'E' ) )
        return 0;

    ++p;
    c = *p;

    if( ( c == '+' ) || ( c == '-' ) )
        ++p;

    int s = ReadDigitSequence( p, end );
    if( s == 0 )
        return 0;

    p += s;
    return p - begin;
}

std::size_t ReadFloatingLiteral( std::string::const_iterator begin,
                                 std::string::const_iterator end )
{
    std::string::const_iterator p = begin;
    int s = ReadDigitSequence( p, end );
    if( !s )
    {
        if( *p != '.' )
            return 0;

        ++p;
        s = ReadDigitSequence( p, end );
        if( !s )
            return 0;

        p += s;

        p += ReadExponent( p, end );
    }
    else
    {
        p += s;
        if( p >= end )
            return 0;

        if( *p != '.' )
        {
            s = ReadExponent( p, end );
            if( !s )
                return 0;
        }
        else
        {
            ++p;
            p += ReadDigitSequence( p, end );
            p += ReadExponent( p, end );
        }
    }

    if( p >= end )
        return p - begin;

    char c = *p;
    if( c == 'f' )
        ++p;

    return p - begin;
}

std::size_t ReadCharOrEscapedChar( std::string::const_iterator begin,
                                   std::string::const_iterator end )
{
    if( end - begin < 2 )
        return 0;

    std::string::const_iterator p = begin;
    if( *p == '\\' )
        ++p;

    ++p;
    return p - begin;
}

std::size_t ReadCharacterLiteral( std::string::const_iterator begin,
                                  std::string::const_iterator end )
{
    std::string::const_iterator p = begin;
    if( *p != '\'' )
        return 0;

    p += ReadCharOrEscapedChar( p, end );

    if( *p != '\'' )
        return 0;

    return p - begin;
}

std::size_t ReadStringLiteral( std::string::const_iterator begin,
                               std::string::const_iterator end )
{
    std::string::const_iterator p = begin;
    if( *p != '\"' )
        return 0;

    ++p;

    while( *p != '\"' &&
           p < end )
        p += ReadCharOrEscapedChar( p, end );

    if( p == end )
        return 0;

    ++p;

    return p - begin;
}

bool IsHexDigit( char c )
{
    return ( c >= '0' && c <= '9' ) ||
           ( c >= 'a' && c <= 'f' ) ||
           ( c >= 'A' && c <= 'F' );
}

bool IsNonDigit( char c )
{
    return ( c >= 'a' && c <= 'z' ) ||
           ( c >= 'A' && c <= 'Z' ) ||
           ( c == '_' );
}

bool IsDigitOrNonDigit( char c )
{
    return IsNonDigit( c ) ||
           ( c >= '0' && c <= '9' );
}

} // namespace Compiler
} // namespace JoeLang
<|endoftext|>


<commit_before>/*
 * Copyright 2011-2013 Blender Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License
 */

#include <stdlib.h>

#include "background.h"
#include "camera.h"
#include "curves.h"
#include "device.h"
#include "film.h"
#include "integrator.h"
#include "light.h"
#include "mesh.h"
#include "object.h"
#include "osl.h"
#include "particles.h"
#include "scene.h"
#include "shader.h"
#include "svm.h"
#include "tables.h"

#include "util_foreach.h"
#include "util_progress.h"

CCL_NAMESPACE_BEGIN

Scene::Scene(const SceneParams& params_, const DeviceInfo& device_info_)
: params(params_)
{
	device = NULL;
	memset(&dscene.data, 0, sizeof(dscene.data));

	camera = new Camera();
	lookup_tables = new LookupTables();
	film = new Film();
	background = new Background();
	light_manager = new LightManager();
	mesh_manager = new MeshManager();
	object_manager = new ObjectManager();
	integrator = new Integrator();
	image_manager = new ImageManager();
	particle_system_manager = new ParticleSystemManager();
	curve_system_manager = new CurveSystemManager();

	/* OSL only works on the CPU */
	if(device_info_.type == DEVICE_CPU)
		shader_manager = ShaderManager::create(this, params.shadingsystem);
	else
		shader_manager = ShaderManager::create(this, SceneParams::SVM);

	if (device_info_.type == DEVICE_CPU)
		image_manager->set_extended_image_limits();
}

Scene::~Scene()
{
	free_memory(true);
}

void Scene::free_memory(bool final)
{
	foreach(Shader *s, shaders)
		delete s;
	foreach(Mesh *m, meshes)
		delete m;
	foreach(Object *o, objects)
		delete o;
	foreach(Light *l, lights)
		delete l;
	foreach(ParticleSystem *p, particle_systems)
		delete p;

	shaders.clear();
	meshes.clear();
	objects.clear();
	lights.clear();
	particle_systems.clear();

	if(device) {
		camera->device_free(device, &dscene);
		film->device_free(device, &dscene, this);
		background->device_free(device, &dscene);
		integrator->device_free(device, &dscene);

		object_manager->device_free(device, &dscene);
		mesh_manager->device_free(device, &dscene);
		shader_manager->device_free(device, &dscene, this);
		light_manager->device_free(device, &dscene);

		particle_system_manager->device_free(device, &dscene);
		curve_system_manager->device_free(device, &dscene);

		if(!params.persistent_data || final)
			image_manager->device_free(device, &dscene);

		lookup_tables->device_free(device, &dscene);
	}

	if(final) {
		delete lookup_tables;
		delete camera;
		delete film;
		delete background;
		delete integrator;
		delete object_manager;
		delete mesh_manager;
		delete shader_manager;
		delete light_manager;
		delete particle_system_manager;
		delete curve_system_manager;
		delete image_manager;
	}
}

void Scene::device_update(Device *device_, Progress& progress)
{
	if(!device)
		device = device_;

	/* The order of updates is important, because there's dependencies between
	 * the different managers, using data computed by previous managers.
	 *
	 * - Image manager uploads images used by shaders.
	 * - Camera may be used for adapative subdivison.
	 * - Displacement shader must have all shader data available.
	 * - Light manager needs final mesh data to compute emission CDF.
	 */

	image_manager->set_pack_images(device->info.pack_images);

	progress.set_status("Updating Shaders");
	shader_manager->device_update(device, &dscene, this, progress);

	if(progress.get_cancel()) return;

	progress.set_status("Updating Images");
	image_manager->device_update(device, &dscene, progress);

	if(progress.get_cancel()) return;

	progress.set_status("Updating Background");
	background->device_update(device, &dscene, this);

	if(progress.get_cancel()) return;

	progress.set_status("Updating Camera");
	camera->device_update(device, &dscene, this);

	if(progress.get_cancel()) return;

	progress.set_status("Updating Objects");
	object_manager->device_update(device, &dscene, this, progress);

	if(progress.get_cancel()) return;

	progress.set_status("Updating Hair Systems");
	curve_system_manager->device_update(device, &dscene, this, progress);

	if(progress.get_cancel()) return;

	progress.set_status("Updating Meshes");
	mesh_manager->device_update(device, &dscene, this, progress);

	if(progress.get_cancel()) return;

	progress.set_status("Updating Lights");
	light_manager->device_update(device, &dscene, this, progress);

	if(progress.get_cancel()) return;

	progress.set_status("Updating Particle Systems");
	particle_system_manager->device_update(device, &dscene, this, progress);

	if(progress.get_cancel()) return;

	progress.set_status("Updating Film");
	film->device_update(device, &dscene, this);

	if(progress.get_cancel()) return;

	progress.set_status("Updating Integrator");
	integrator->device_update(device, &dscene, this);

	if(progress.get_cancel()) return;

	progress.set_status("Updating Lookup Tables");
	lookup_tables->device_update(device, &dscene);

	if(progress.get_cancel()) return;

	progress.set_status("Updating Device", "Writing constant memory");
	device->const_copy_to("__data", &dscene.data, sizeof(dscene.data));
}

Scene::MotionType Scene::need_motion(bool advanced_shading)
{
	if(integrator->motion_blur)
		return (advanced_shading)? MOTION_BLUR: MOTION_NONE;
	else if(Pass::contains(film->passes, PASS_MOTION))
		return MOTION_PASS;
	else
		return MOTION_NONE;
}

bool Scene::need_global_attribute(AttributeStandard std)
{
	if(std == ATTR_STD_UV)
		return Pass::contains(film->passes, PASS_UV);
	if(std == ATTR_STD_MOTION_PRE || std == ATTR_STD_MOTION_POST)
		return need_motion() == MOTION_PASS;

	return false;
}

void Scene::need_global_attributes(AttributeRequestSet& attributes)
{
	for(int std = ATTR_STD_NONE; std < ATTR_STD_NUM; std++)
		if(need_global_attribute((AttributeStandard)std))
			attributes.add((AttributeStandard)std);
}

bool Scene::need_update()
{
	return (need_reset() || film->need_update);
}

bool Scene::need_reset()
{
	return (background->need_update
		|| image_manager->need_update
		|| camera->need_update
		|| object_manager->need_update
		|| mesh_manager->need_update
		|| light_manager->need_update
		|| lookup_tables->need_update
		|| integrator->need_update
		|| shader_manager->need_update
		|| particle_system_manager->need_update
		|| curve_system_manager->need_update);
}

void Scene::reset()
{
	shader_manager->reset(this);
	shader_manager->add_default(this);

	/* ensure all objects are updated */
	camera->tag_update();
	film->tag_update(this);
	background->tag_update(this);
	integrator->tag_update(this);
}

void Scene::device_free()
{
	free_memory(false);
}

CCL_NAMESPACE_END

<commit_msg>Fix T38526: crash using blackbody node on background with multiple importance sampling.<commit_after>/*
 * Copyright 2011-2013 Blender Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License
 */

#include <stdlib.h>

#include "background.h"
#include "camera.h"
#include "curves.h"
#include "device.h"
#include "film.h"
#include "integrator.h"
#include "light.h"
#include "mesh.h"
#include "object.h"
#include "osl.h"
#include "particles.h"
#include "scene.h"
#include "shader.h"
#include "svm.h"
#include "tables.h"

#include "util_foreach.h"
#include "util_progress.h"

CCL_NAMESPACE_BEGIN

Scene::Scene(const SceneParams& params_, const DeviceInfo& device_info_)
: params(params_)
{
	device = NULL;
	memset(&dscene.data, 0, sizeof(dscene.data));

	camera = new Camera();
	lookup_tables = new LookupTables();
	film = new Film();
	background = new Background();
	light_manager = new LightManager();
	mesh_manager = new MeshManager();
	object_manager = new ObjectManager();
	integrator = new Integrator();
	image_manager = new ImageManager();
	particle_system_manager = new ParticleSystemManager();
	curve_system_manager = new CurveSystemManager();

	/* OSL only works on the CPU */
	if(device_info_.type == DEVICE_CPU)
		shader_manager = ShaderManager::create(this, params.shadingsystem);
	else
		shader_manager = ShaderManager::create(this, SceneParams::SVM);

	if (device_info_.type == DEVICE_CPU)
		image_manager->set_extended_image_limits();
}

Scene::~Scene()
{
	free_memory(true);
}

void Scene::free_memory(bool final)
{
	foreach(Shader *s, shaders)
		delete s;
	foreach(Mesh *m, meshes)
		delete m;
	foreach(Object *o, objects)
		delete o;
	foreach(Light *l, lights)
		delete l;
	foreach(ParticleSystem *p, particle_systems)
		delete p;

	shaders.clear();
	meshes.clear();
	objects.clear();
	lights.clear();
	particle_systems.clear();

	if(device) {
		camera->device_free(device, &dscene);
		film->device_free(device, &dscene, this);
		background->device_free(device, &dscene);
		integrator->device_free(device, &dscene);

		object_manager->device_free(device, &dscene);
		mesh_manager->device_free(device, &dscene);
		shader_manager->device_free(device, &dscene, this);
		light_manager->device_free(device, &dscene);

		particle_system_manager->device_free(device, &dscene);
		curve_system_manager->device_free(device, &dscene);

		if(!params.persistent_data || final)
			image_manager->device_free(device, &dscene);

		lookup_tables->device_free(device, &dscene);
	}

	if(final) {
		delete lookup_tables;
		delete camera;
		delete film;
		delete background;
		delete integrator;
		delete object_manager;
		delete mesh_manager;
		delete shader_manager;
		delete light_manager;
		delete particle_system_manager;
		delete curve_system_manager;
		delete image_manager;
	}
}

void Scene::device_update(Device *device_, Progress& progress)
{
	if(!device)
		device = device_;

	/* The order of updates is important, because there's dependencies between
	 * the different managers, using data computed by previous managers.
	 *
	 * - Image manager uploads images used by shaders.
	 * - Camera may be used for adapative subdivison.
	 * - Displacement shader must have all shader data available.
	 * - Light manager needs lookup tables and final mesh data to compute emission CDF.
	 */

	image_manager->set_pack_images(device->info.pack_images);

	progress.set_status("Updating Shaders");
	shader_manager->device_update(device, &dscene, this, progress);

	if(progress.get_cancel()) return;

	progress.set_status("Updating Images");
	image_manager->device_update(device, &dscene, progress);

	if(progress.get_cancel()) return;

	progress.set_status("Updating Background");
	background->device_update(device, &dscene, this);

	if(progress.get_cancel()) return;

	progress.set_status("Updating Camera");
	camera->device_update(device, &dscene, this);

	if(progress.get_cancel()) return;

	progress.set_status("Updating Objects");
	object_manager->device_update(device, &dscene, this, progress);

	if(progress.get_cancel()) return;

	progress.set_status("Updating Hair Systems");
	curve_system_manager->device_update(device, &dscene, this, progress);

	if(progress.get_cancel()) return;

	progress.set_status("Updating Film");
	film->device_update(device, &dscene, this);

	if(progress.get_cancel()) return;

	progress.set_status("Updating Lookup Tables");
	lookup_tables->device_update(device, &dscene);

	if(progress.get_cancel()) return;

	progress.set_status("Updating Meshes");
	mesh_manager->device_update(device, &dscene, this, progress);

	if(progress.get_cancel()) return;

	progress.set_status("Updating Lights");
	light_manager->device_update(device, &dscene, this, progress);

	if(progress.get_cancel()) return;

	progress.set_status("Updating Particle Systems");
	particle_system_manager->device_update(device, &dscene, this, progress);

	if(progress.get_cancel()) return;

	progress.set_status("Updating Integrator");
	integrator->device_update(device, &dscene, this);

	if(progress.get_cancel()) return;

	progress.set_status("Updating Device", "Writing constant memory");
	device->const_copy_to("__data", &dscene.data, sizeof(dscene.data));
}

Scene::MotionType Scene::need_motion(bool advanced_shading)
{
	if(integrator->motion_blur)
		return (advanced_shading)? MOTION_BLUR: MOTION_NONE;
	else if(Pass::contains(film->passes, PASS_MOTION))
		return MOTION_PASS;
	else
		return MOTION_NONE;
}

bool Scene::need_global_attribute(AttributeStandard std)
{
	if(std == ATTR_STD_UV)
		return Pass::contains(film->passes, PASS_UV);
	if(std == ATTR_STD_MOTION_PRE || std == ATTR_STD_MOTION_POST)
		return need_motion() == MOTION_PASS;

	return false;
}

void Scene::need_global_attributes(AttributeRequestSet& attributes)
{
	for(int std = ATTR_STD_NONE; std < ATTR_STD_NUM; std++)
		if(need_global_attribute((AttributeStandard)std))
			attributes.add((AttributeStandard)std);
}

bool Scene::need_update()
{
	return (need_reset() || film->need_update);
}

bool Scene::need_reset()
{
	return (background->need_update
		|| image_manager->need_update
		|| camera->need_update
		|| object_manager->need_update
		|| mesh_manager->need_update
		|| light_manager->need_update
		|| lookup_tables->need_update
		|| integrator->need_update
		|| shader_manager->need_update
		|| particle_system_manager->need_update
		|| curve_system_manager->need_update);
}

void Scene::reset()
{
	shader_manager->reset(this);
	shader_manager->add_default(this);

	/* ensure all objects are updated */
	camera->tag_update();
	film->tag_update(this);
	background->tag_update(this);
	integrator->tag_update(this);
}

void Scene::device_free()
{
	free_memory(false);
}

CCL_NAMESPACE_END

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: StorageFileAccess.cxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 02:42:54 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_connectivity.hxx"

#if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H
#include <config.h>
#endif

#ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
#include <com/sun/star/container/XNameAccess.hpp>
#endif
#ifndef _COM_SUN_STAR_EMBED_XSTORAGE_HPP_
#include <com/sun/star/embed/XStorage.hpp>
#endif
#include "hsqldb/StorageFileAccess.h"
#include "hsqldb/HStorageMap.hxx"

#include <rtl/logfile.hxx>

using namespace ::com::sun::star::container;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::embed;
using namespace ::com::sun::star::io;
using namespace ::com::sun::star::lang;
using namespace ::connectivity::hsqldb;

#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
/*****************************************************************************/
/* exception macros */

#define ThrowException(env, type, msg) { \
    env->ThrowNew(env->FindClass(type), msg); }

/*
 * Class:     com_sun_star_sdbcx_comp_hsqldb_StorageFileAccess
 * Method:    isStreamElement
 * Signature: (Ljava/lang/String;Ljava/lang/String;)Z
 */
JNIEXPORT jboolean JNICALL Java_com_sun_star_sdbcx_comp_hsqldb_StorageFileAccess_isStreamElement
  (JNIEnv * env, jobject /*obj_this*/,jstring key, jstring name)
{
    TStorages::mapped_type aStoragePair = StorageContainer::getRegisteredStorage(StorageContainer::jstring2ustring(env,key));
    if ( aStoragePair.first.first.is() )
    {
        try
        {
            ::rtl::OUString sName = StorageContainer::jstring2ustring(env,name);
            try
            {
                ::rtl::OUString sOldName = StorageContainer::removeOldURLPrefix(sName);
                if ( aStoragePair.first.first->isStreamElement(sOldName) )
                {
                    try
                    {
                        aStoragePair.first.first->renameElement(sOldName,StorageContainer::removeURLPrefix(sName,aStoragePair.first.second));
                    }
                    catch(Exception&)
                    {
                    }
                }
            }
            catch(NoSuchElementException&)
            {
            }
            return aStoragePair.first.first->isStreamElement(StorageContainer::removeURLPrefix(sName,aStoragePair.first.second));
        }
        catch(NoSuchElementException&)
        {
        }
        catch(Exception& e)
        {
            OSL_ENSURE(0,"Exception catched! : Java_com_sun_star_sdbcx_comp_hsqldb_StorageFileAccess_isStreamElement");
            if (JNI_FALSE != env->ExceptionCheck())
                env->ExceptionClear();
            ::rtl::OString cstr( ::rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_JAVA_UTF8 ) );
            OSL_TRACE( __FILE__": forwarding Exception: %s", cstr.getStr() );
        }
    }
    return JNI_FALSE;
}
// -----------------------------------------------------------------------------

/*
 * Class:     com_sun_star_sdbcx_comp_hsqldb_StorageFileAccess
 * Method:    removeElement
 * Signature: (Ljava/lang/String;Ljava/lang/String;)V
 */
JNIEXPORT void JNICALL Java_com_sun_star_sdbcx_comp_hsqldb_StorageFileAccess_removeElement
  (JNIEnv * env, jobject /*obj_this*/,jstring key, jstring name)
{
#ifdef HSQLDB_DBG
    {
        ::rtl::OUString sKey = StorageContainer::jstring2ustring(env,key);
        ::rtl::OUString sName = StorageContainer::jstring2ustring(env,name);
    }
#endif
    TStorages::mapped_type aStoragePair = StorageContainer::getRegisteredStorage(StorageContainer::jstring2ustring(env,key));
    if ( aStoragePair.first.first.is() )
    {
        try
        {
            aStoragePair.first.first->removeElement(StorageContainer::removeURLPrefix(StorageContainer::jstring2ustring(env,name),aStoragePair.first.second));
        }
        catch(NoSuchElementException&)
        {
            if (JNI_FALSE != env->ExceptionCheck())
                env->ExceptionClear();
        }
        catch(Exception& e)
        {
            OSL_ENSURE(0,"Exception catched! : Java_com_sun_star_sdbcx_comp_hsqldb_StorageFileAccess_removeElement");
            StorageContainer::throwJavaException(e,env);
        }
    }
}
// -----------------------------------------------------------------------------

/*
 * Class:     com_sun_star_sdbcx_comp_hsqldb_StorageFileAccess
 * Method:    renameElement
 * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
 */
JNIEXPORT void JNICALL Java_com_sun_star_sdbcx_comp_hsqldb_StorageFileAccess_renameElement
  (JNIEnv * env, jobject /*obj_this*/,jstring key, jstring oldname, jstring newname)
{
#ifdef HSQLDB_DBG
    {
        ::rtl::OUString sKey = StorageContainer::jstring2ustring(env,key);
        ::rtl::OUString sNewName = StorageContainer::jstring2ustring(env,newname);
        ::rtl::OUString sOldName = StorageContainer::jstring2ustring(env,oldname);
    }
#endif
    TStorages::mapped_type aStoragePair = StorageContainer::getRegisteredStorage(StorageContainer::jstring2ustring(env,key));
    if ( aStoragePair.first.first.is() )
    {
        try
        {
            aStoragePair.first.first->renameElement(
                StorageContainer::removeURLPrefix(StorageContainer::jstring2ustring(env,oldname),aStoragePair.first.second),
                StorageContainer::removeURLPrefix(StorageContainer::jstring2ustring(env,newname),aStoragePair.first.second)
            );
#ifdef HSQLDB_DBG
            {
                ::rtl::OUString sNewName = StorageContainer::removeURLPrefix(StorageContainer::jstring2ustring(env,newname),aStoragePair.first.second);
                OSL_ENSURE(aStoragePair.first.first->isStreamElement(sNewName),"Stream could not be renamed");
            }
#endif
        }
        catch(NoSuchElementException&)
        {
        }
        catch(Exception& e)
        {
            OSL_ENSURE(0,"Exception catched! : Java_com_sun_star_sdbcx_comp_hsqldb_StorageFileAccess_renameElement");
            StorageContainer::throwJavaException(e,env);
        }
    }
}
// -----------------------------------------------------------------------------
<commit_msg>INTEGRATION: CWS changefileheader (1.9.216); FILE MERGED 2008/04/01 10:53:03 thb 1.9.216.2: #i85898# Stripping all external header guards 2008/03/28 15:23:39 rt 1.9.216.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: StorageFileAccess.cxx,v $
 * $Revision: 1.10 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_connectivity.hxx"

#if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H
#include <config.h>
#endif
#include <com/sun/star/container/XNameAccess.hpp>
#include <com/sun/star/embed/XStorage.hpp>
#include "hsqldb/StorageFileAccess.h"
#include "hsqldb/HStorageMap.hxx"

#include <rtl/logfile.hxx>

using namespace ::com::sun::star::container;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::embed;
using namespace ::com::sun::star::io;
using namespace ::com::sun::star::lang;
using namespace ::connectivity::hsqldb;

#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
/*****************************************************************************/
/* exception macros */

#define ThrowException(env, type, msg) { \
    env->ThrowNew(env->FindClass(type), msg); }

/*
 * Class:     com_sun_star_sdbcx_comp_hsqldb_StorageFileAccess
 * Method:    isStreamElement
 * Signature: (Ljava/lang/String;Ljava/lang/String;)Z
 */
JNIEXPORT jboolean JNICALL Java_com_sun_star_sdbcx_comp_hsqldb_StorageFileAccess_isStreamElement
  (JNIEnv * env, jobject /*obj_this*/,jstring key, jstring name)
{
    TStorages::mapped_type aStoragePair = StorageContainer::getRegisteredStorage(StorageContainer::jstring2ustring(env,key));
    if ( aStoragePair.first.first.is() )
    {
        try
        {
            ::rtl::OUString sName = StorageContainer::jstring2ustring(env,name);
            try
            {
                ::rtl::OUString sOldName = StorageContainer::removeOldURLPrefix(sName);
                if ( aStoragePair.first.first->isStreamElement(sOldName) )
                {
                    try
                    {
                        aStoragePair.first.first->renameElement(sOldName,StorageContainer::removeURLPrefix(sName,aStoragePair.first.second));
                    }
                    catch(Exception&)
                    {
                    }
                }
            }
            catch(NoSuchElementException&)
            {
            }
            return aStoragePair.first.first->isStreamElement(StorageContainer::removeURLPrefix(sName,aStoragePair.first.second));
        }
        catch(NoSuchElementException&)
        {
        }
        catch(Exception& e)
        {
            OSL_ENSURE(0,"Exception catched! : Java_com_sun_star_sdbcx_comp_hsqldb_StorageFileAccess_isStreamElement");
            if (JNI_FALSE != env->ExceptionCheck())
                env->ExceptionClear();
            ::rtl::OString cstr( ::rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_JAVA_UTF8 ) );
            OSL_TRACE( __FILE__": forwarding Exception: %s", cstr.getStr() );
        }
    }
    return JNI_FALSE;
}
// -----------------------------------------------------------------------------

/*
 * Class:     com_sun_star_sdbcx_comp_hsqldb_StorageFileAccess
 * Method:    removeElement
 * Signature: (Ljava/lang/String;Ljava/lang/String;)V
 */
JNIEXPORT void JNICALL Java_com_sun_star_sdbcx_comp_hsqldb_StorageFileAccess_removeElement
  (JNIEnv * env, jobject /*obj_this*/,jstring key, jstring name)
{
#ifdef HSQLDB_DBG
    {
        ::rtl::OUString sKey = StorageContainer::jstring2ustring(env,key);
        ::rtl::OUString sName = StorageContainer::jstring2ustring(env,name);
    }
#endif
    TStorages::mapped_type aStoragePair = StorageContainer::getRegisteredStorage(StorageContainer::jstring2ustring(env,key));
    if ( aStoragePair.first.first.is() )
    {
        try
        {
            aStoragePair.first.first->removeElement(StorageContainer::removeURLPrefix(StorageContainer::jstring2ustring(env,name),aStoragePair.first.second));
        }
        catch(NoSuchElementException&)
        {
            if (JNI_FALSE != env->ExceptionCheck())
                env->ExceptionClear();
        }
        catch(Exception& e)
        {
            OSL_ENSURE(0,"Exception catched! : Java_com_sun_star_sdbcx_comp_hsqldb_StorageFileAccess_removeElement");
            StorageContainer::throwJavaException(e,env);
        }
    }
}
// -----------------------------------------------------------------------------

/*
 * Class:     com_sun_star_sdbcx_comp_hsqldb_StorageFileAccess
 * Method:    renameElement
 * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
 */
JNIEXPORT void JNICALL Java_com_sun_star_sdbcx_comp_hsqldb_StorageFileAccess_renameElement
  (JNIEnv * env, jobject /*obj_this*/,jstring key, jstring oldname, jstring newname)
{
#ifdef HSQLDB_DBG
    {
        ::rtl::OUString sKey = StorageContainer::jstring2ustring(env,key);
        ::rtl::OUString sNewName = StorageContainer::jstring2ustring(env,newname);
        ::rtl::OUString sOldName = StorageContainer::jstring2ustring(env,oldname);
    }
#endif
    TStorages::mapped_type aStoragePair = StorageContainer::getRegisteredStorage(StorageContainer::jstring2ustring(env,key));
    if ( aStoragePair.first.first.is() )
    {
        try
        {
            aStoragePair.first.first->renameElement(
                StorageContainer::removeURLPrefix(StorageContainer::jstring2ustring(env,oldname),aStoragePair.first.second),
                StorageContainer::removeURLPrefix(StorageContainer::jstring2ustring(env,newname),aStoragePair.first.second)
            );
#ifdef HSQLDB_DBG
            {
                ::rtl::OUString sNewName = StorageContainer::removeURLPrefix(StorageContainer::jstring2ustring(env,newname),aStoragePair.first.second);
                OSL_ENSURE(aStoragePair.first.first->isStreamElement(sNewName),"Stream could not be renamed");
            }
#endif
        }
        catch(NoSuchElementException&)
        {
        }
        catch(Exception& e)
        {
            OSL_ENSURE(0,"Exception catched! : Java_com_sun_star_sdbcx_comp_hsqldb_StorageFileAccess_renameElement");
            StorageContainer::throwJavaException(e,env);
        }
    }
}
// -----------------------------------------------------------------------------
<|endoftext|>


<commit_before>/*
 * Category.cpp
 *
 * Copyright 2000, LifeLine Networks BV (www.lifeline.nl). All rights reserved.
 * Copyright 2000, Bastiaan Bakker. All rights reserved.
 *
 * See the COPYING file for the terms of usage and distribution.
 */

#include <log4cpp/Portability.hh>

#ifdef LOG4CPP_HAVE_UNISTD_H
#    include <unistd.h>
#endif

#include <log4cpp/OstringStream.hh>
#include <log4cpp/Category.hh>
#include <log4cpp/HierarchyMaintainer.hh>
#include <log4cpp/NDC.hh>

namespace log4cpp {

    Category& Category::getRoot() {
        return getInstance("");
    }

    void Category::setRootPriority(Priority::Value priority) {
        getRoot().setPriority(priority);
    }

    Priority::Value Category::getRootPriority() throw() {
        return getRoot().getPriority();
    }

    Category& Category::getInstance(const std::string& name) {
        return HierarchyMaintainer::getDefaultMaintainer().getInstance(name);
    }

    Category* Category::exists(const std::string& name) {
        return HierarchyMaintainer::getDefaultMaintainer().getExistingInstance(name);
    }

    std::vector<Category*>* Category::getCurrentCategories() {
        return HierarchyMaintainer::getDefaultMaintainer().
            getCurrentCategories();
    }

    void Category::shutdown() {
        HierarchyMaintainer::getDefaultMaintainer().shutdown();
    }

    Category::Category(const std::string& name, Category* parent, Priority::Value priority) :
        _name(name),
        _parent(parent),
        _priority(priority),
        _isAdditive(true) {
    }

    Category::~Category() {
        removeAllAppenders();
    }

    const std::string& Category::getName() const throw() {
        return _name;
    }

    Priority::Value Category::getPriority() const throw() {
        return _priority;
    }

    void Category::setPriority(Priority::Value priority)
    throw(std::invalid_argument) {
        if ((priority < Priority::NOTSET) || (getParent() != NULL)) {
            _priority = priority;
        } else {
            /* caller tried to set NOTSET priority to root Category.
               Bad caller!
            */
            throw std::invalid_argument("cannot set priority NOTSET on Root Category");
        }
    }

    Priority::Value Category::getChainedPriority() const throw() {
        // REQUIRE(rootCategory->getPriority() != Priority::NOTSET)

        const Category* c = this;
        while(c->getPriority() >= Priority::NOTSET) {
            c = c->getParent();
        }

        return c->getPriority();
    }

    void Category::addAppender(Appender* appender)
    throw(std::invalid_argument) {
        if (appender) {
            threading::ScopedLock lock(_appenderSetMutex);
            {
                AppenderSet::iterator i = _appender.find(appender);
                if (_appender.end() == i) {
                    // not found
                    _appender.insert(appender);
                    _ownsAppender[appender] = true;
                }
            }
        } else {
            throw std::invalid_argument("NULL appender");
        }
    }

    void Category::addAppender(Appender& appender) {
        threading::ScopedLock lock(_appenderSetMutex);
        {
            AppenderSet::iterator i = _appender.find(&appender);
            if (_appender.end() == i) {
                _appender.insert(&appender);
                _ownsAppender[&appender] = false;
            }
        }
    }

    Appender* Category::getAppender() const {
        threading::ScopedLock lock(_appenderSetMutex);
        {
            AppenderSet::const_iterator i = _appender.begin();
            return (_appender.end() == i) ? NULL : *i;
        }
    }

    Appender* Category::getAppender(const std::string& name) const {
        threading::ScopedLock lock(_appenderSetMutex);
        {
            AppenderSet::const_iterator i = _appender.begin();
            if (_appender.end() != i) {
                // found
                return((*i)->getAppender(name));
            }
            else {
                return(NULL);
            }
        }
    }

    AppenderSet Category::getAllAppenders() const {
        return _appender;
    }

    void Category::removeAllAppenders() {
        threading::ScopedLock lock(_appenderSetMutex);
        {
            for (AppenderSet::iterator i = _appender.begin();
                 i != _appender.end(); i++) {
                // found
                OwnsAppenderMap::iterator i2;
                if (ownsAppender(*i, i2)) {
                    delete (*i);
                }
            }

            _ownsAppender.clear();
            _appender.clear();
        }
    }

    void Category::removeAppender(Appender* appender) {
        threading::ScopedLock lock(_appenderSetMutex);
        {
            AppenderSet::iterator i = _appender.find(appender);
            if (_appender.end() != i) {
                OwnsAppenderMap::iterator i2;
                if (ownsAppender(*i, i2)) {
                    _ownsAppender.erase(i2);
                    delete (*i);
                }
                _appender.erase(i);
            } else {
                // appender not found
            }
        }
    }

    bool Category::ownsAppender(Appender* appender) const throw() {
        bool owned = false;

        threading::ScopedLock lock(_appenderSetMutex);
        {
            if (NULL != appender) {
                OwnsAppenderMap::const_iterator i =
                    _ownsAppender.find(appender);
                if (_ownsAppender.end() != i) {
                    owned = (*i).second;
                }
            }
        }

        return owned;
    }

    /* assume lock is held */
    bool Category::ownsAppender(Appender* appender,
                                Category::OwnsAppenderMap::iterator& i2) throw() {
        bool owned = false;

        if (NULL != appender) {
            OwnsAppenderMap::iterator i = _ownsAppender.find(appender);
            if (_ownsAppender.end() != i) {
                owned = (*i).second;
                if (owned) {
                    i2 = i;
                }
            }
        }

        return owned;
    }

    void Category::callAppenders(const LoggingEvent& event) throw() {
        threading::ScopedLock lock(_appenderSetMutex);
        {
            if (!_appender.empty()) {
                for(AppenderSet::const_iterator i = _appender.begin();
                    i != _appender.end(); i++) {
                    (*i)->doAppend(event);
                }
            }
        }
        if (getAdditivity() && (getParent() != NULL)) {
            getParent()->callAppenders(event);
        }
    }

    void Category::setAdditivity(bool additivity) {
        _isAdditive = additivity;
    }

    bool Category::getAdditivity() const throw() {
        return _isAdditive;
    }

    Category* Category::getParent() throw() {
        return _parent;
    }

    const Category* Category::getParent() const throw() {
        return _parent;
    }

    void Category::_logUnconditionally(Priority::Value priority,
                                       const char* format,
                                       va_list arguments) throw() {
        OstringStream messageBuffer;

        messageBuffer.vform(format, arguments);
        _logUnconditionally2(priority, messageBuffer.str());
    }

    void Category::_logUnconditionally2(Priority::Value priority,
                                        const std::string& message) throw() {
        LoggingEvent event(getName(), message, NDC::get(), priority);
        callAppenders(event);
    }

    bool Category::isPriorityEnabled(Priority::Value priority) const throw() {
        return(getChainedPriority() >= priority);
    }

    void Category::log(Priority::Value priority,
                       const char* stringFormat, ...) throw() {
        if (isPriorityEnabled(priority)) {
            va_list va;
            va_start(va, stringFormat);
            _logUnconditionally(priority, stringFormat, va);
            va_end(va);
        }
    }

    void Category::log(Priority::Value priority,
                       const std::string& message) throw() {
        if (isPriorityEnabled(priority))
            _logUnconditionally2(priority, message);
    }

    void Category::logva(Priority::Value priority,
                         const char* stringFormat,
                         va_list va) throw() {
        if (isPriorityEnabled(priority)) {
            _logUnconditionally(priority, stringFormat, va);
        }
    }

    void Category::debug(const char* stringFormat, ...) throw() {
        if (isPriorityEnabled(Priority::DEBUG)) {
            va_list va;
            va_start(va,stringFormat);
            _logUnconditionally(Priority::DEBUG, stringFormat, va);
            va_end(va);
        }
    }

    void Category::debug(const std::string& message) throw() {
        if (isPriorityEnabled(Priority::DEBUG))
            _logUnconditionally2(Priority::DEBUG, message);
    }

    void Category::info(const char* stringFormat, ...) throw() {
        if (isPriorityEnabled(Priority::INFO)) {
            va_list va;
            va_start(va,stringFormat);
            _logUnconditionally(Priority::INFO, stringFormat, va);
            va_end(va);
        }
    }

    void Category::info(const std::string& message) throw() {
        if (isPriorityEnabled(Priority::INFO))
            _logUnconditionally2(Priority::INFO, message);
    }

    void Category::notice(const char* stringFormat, ...) throw() {
        if (isPriorityEnabled(Priority::NOTICE)) {
            va_list va;
            va_start(va,stringFormat);
            _logUnconditionally(Priority::NOTICE, stringFormat, va);
            va_end(va);
        }
    }

    void Category::notice(const std::string& message) throw() {
        if (isPriorityEnabled(Priority::NOTICE))
            _logUnconditionally2(Priority::NOTICE, message);
    }

    void Category::warn(const char* stringFormat, ...) throw() {
        if (isPriorityEnabled(Priority::WARN)) {
            va_list va;
            va_start(va,stringFormat);
            _logUnconditionally(Priority::WARN, stringFormat, va);
            va_end(va);
        }
    }

    void Category::warn(const std::string& message) throw() {
        if (isPriorityEnabled(Priority::WARN))
            _logUnconditionally2(Priority::WARN, message);
    }

    void Category::error(const char* stringFormat, ...) throw() {
               if (isPriorityEnabled(Priority::ERROR)) {
            va_list va;
            va_start(va,stringFormat);
                       _logUnconditionally(Priority::ERROR, stringFormat, va);
            va_end(va);
        }
    }

    void Category::error(const std::string& message) throw() {
               if (isPriorityEnabled(Priority::ERROR))
            _logUnconditionally2(Priority::ERROR, message);
    }

    void Category::crit(const char* stringFormat, ...) throw() {
        if (isPriorityEnabled(Priority::CRIT)) {
            va_list va;
            va_start(va,stringFormat);
            _logUnconditionally(Priority::CRIT, stringFormat, va);
            va_end(va);
        }
    }

    void Category::crit(const std::string& message) throw() {
        if (isPriorityEnabled(Priority::CRIT))
            _logUnconditionally2(Priority::CRIT, message);
    }

    void Category::alert(const char* stringFormat, ...) throw() {
        if (isPriorityEnabled(Priority::ALERT)) {
            va_list va;
            va_start(va,stringFormat);
            _logUnconditionally(Priority::ALERT, stringFormat, va);
            va_end(va);
        }
    }

    void Category::alert(const std::string& message) throw() {
        if (isPriorityEnabled(Priority::ALERT))
            _logUnconditionally2(Priority::ALERT, message);
    }

    void Category::emerg(const char* stringFormat, ...) throw() {
        if (isPriorityEnabled(Priority::EMERG)) {
            va_list va;
            va_start(va,stringFormat);
            _logUnconditionally(Priority::EMERG, stringFormat, va);
            va_end(va);
        }
    }

    void Category::emerg(const std::string& message) throw() {
        if (isPriorityEnabled(Priority::EMERG))
            _logUnconditionally2(Priority::EMERG, message);
    }

    void Category::fatal(const char* stringFormat, ...) throw() {
        if (isPriorityEnabled(Priority::FATAL)) {
            va_list va;
            va_start(va,stringFormat);
            _logUnconditionally(Priority::FATAL, stringFormat, va);
            va_end(va);
        }
    }

    void Category::fatal(const std::string& message) throw() {
        if (isPriorityEnabled(Priority::FATAL))
            _logUnconditionally2(Priority::FATAL, message);
    }

    CategoryStream Category::getStream(Priority::Value priority) {
        return CategoryStream(*this, isPriorityEnabled(priority) ?
                              priority : Priority::NOTSET);
    }

    CategoryStream Category::operator<<(Priority::Value priority) {
        return getStream(priority);
    }
}

<commit_msg>added lock to getAllAppenders().<commit_after>/*
 * Category.cpp
 *
 * Copyright 2000, LifeLine Networks BV (www.lifeline.nl). All rights reserved.
 * Copyright 2000, Bastiaan Bakker. All rights reserved.
 *
 * See the COPYING file for the terms of usage and distribution.
 */

#include <log4cpp/Portability.hh>

#ifdef LOG4CPP_HAVE_UNISTD_H
#    include <unistd.h>
#endif

#include <log4cpp/OstringStream.hh>
#include <log4cpp/Category.hh>
#include <log4cpp/HierarchyMaintainer.hh>
#include <log4cpp/NDC.hh>

namespace log4cpp {

    Category& Category::getRoot() {
        return getInstance("");
    }

    void Category::setRootPriority(Priority::Value priority) {
        getRoot().setPriority(priority);
    }

    Priority::Value Category::getRootPriority() throw() {
        return getRoot().getPriority();
    }

    Category& Category::getInstance(const std::string& name) {
        return HierarchyMaintainer::getDefaultMaintainer().getInstance(name);
    }

    Category* Category::exists(const std::string& name) {
        return HierarchyMaintainer::getDefaultMaintainer().getExistingInstance(name);
    }

    std::vector<Category*>* Category::getCurrentCategories() {
        return HierarchyMaintainer::getDefaultMaintainer().
            getCurrentCategories();
    }

    void Category::shutdown() {
        HierarchyMaintainer::getDefaultMaintainer().shutdown();
    }

    Category::Category(const std::string& name, Category* parent, Priority::Value priority) :
        _name(name),
        _parent(parent),
        _priority(priority),
        _isAdditive(true) {
    }

    Category::~Category() {
        removeAllAppenders();
    }

    const std::string& Category::getName() const throw() {
        return _name;
    }

    Priority::Value Category::getPriority() const throw() {
        return _priority;
    }

    void Category::setPriority(Priority::Value priority)
    throw(std::invalid_argument) {
        if ((priority < Priority::NOTSET) || (getParent() != NULL)) {
            _priority = priority;
        } else {
            /* caller tried to set NOTSET priority to root Category.
               Bad caller!
            */
            throw std::invalid_argument("cannot set priority NOTSET on Root Category");
        }
    }

    Priority::Value Category::getChainedPriority() const throw() {
        // REQUIRE(rootCategory->getPriority() != Priority::NOTSET)

        const Category* c = this;
        while(c->getPriority() >= Priority::NOTSET) {
            c = c->getParent();
        }

        return c->getPriority();
    }

    void Category::addAppender(Appender* appender)
    throw(std::invalid_argument) {
        if (appender) {
            threading::ScopedLock lock(_appenderSetMutex);
            {
                AppenderSet::iterator i = _appender.find(appender);
                if (_appender.end() == i) {
                    // not found
                    _appender.insert(appender);
                    _ownsAppender[appender] = true;
                }
            }
        } else {
            throw std::invalid_argument("NULL appender");
        }
    }

    void Category::addAppender(Appender& appender) {
        threading::ScopedLock lock(_appenderSetMutex);
        {
            AppenderSet::iterator i = _appender.find(&appender);
            if (_appender.end() == i) {
                _appender.insert(&appender);
                _ownsAppender[&appender] = false;
            }
        }
    }

    Appender* Category::getAppender() const {
        threading::ScopedLock lock(_appenderSetMutex);
        {
            AppenderSet::const_iterator i = _appender.begin();
            return (_appender.end() == i) ? NULL : *i;
        }
    }

    Appender* Category::getAppender(const std::string& name) const {
        threading::ScopedLock lock(_appenderSetMutex);
        {
            AppenderSet::const_iterator i = _appender.begin();
            if (_appender.end() != i) {
                // found
                return((*i)->getAppender(name));
            }
            else {
                return(NULL);
            }
        }
    }

    AppenderSet Category::getAllAppenders() const {
        threading::ScopedLock lock(_appenderSetMutex);
        {
            return _appender;
        }
    }

    void Category::removeAllAppenders() {
        threading::ScopedLock lock(_appenderSetMutex);
        {
            for (AppenderSet::iterator i = _appender.begin();
                 i != _appender.end(); i++) {
                // found
                OwnsAppenderMap::iterator i2;
                if (ownsAppender(*i, i2)) {
                    delete (*i);
                }
            }

            _ownsAppender.clear();
            _appender.clear();
        }
    }

    void Category::removeAppender(Appender* appender) {
        threading::ScopedLock lock(_appenderSetMutex);
        {
            AppenderSet::iterator i = _appender.find(appender);
            if (_appender.end() != i) {
                OwnsAppenderMap::iterator i2;
                if (ownsAppender(*i, i2)) {
                    _ownsAppender.erase(i2);
                    delete (*i);
                }
                _appender.erase(i);
            } else {
                // appender not found
            }
        }
    }

    bool Category::ownsAppender(Appender* appender) const throw() {
        bool owned = false;

        threading::ScopedLock lock(_appenderSetMutex);
        {
            if (NULL != appender) {
                OwnsAppenderMap::const_iterator i =
                    _ownsAppender.find(appender);
                if (_ownsAppender.end() != i) {
                    owned = (*i).second;
                }
            }
        }

        return owned;
    }

    /* assume lock is held */
    bool Category::ownsAppender(Appender* appender,
                                Category::OwnsAppenderMap::iterator& i2) throw() {
        bool owned = false;

        if (NULL != appender) {
            OwnsAppenderMap::iterator i = _ownsAppender.find(appender);
            if (_ownsAppender.end() != i) {
                owned = (*i).second;
                if (owned) {
                    i2 = i;
                }
            }
        }

        return owned;
    }

    void Category::callAppenders(const LoggingEvent& event) throw() {
        threading::ScopedLock lock(_appenderSetMutex);
        {
            if (!_appender.empty()) {
                for(AppenderSet::const_iterator i = _appender.begin();
                    i != _appender.end(); i++) {
                    (*i)->doAppend(event);
                }
            }
        }
        if (getAdditivity() && (getParent() != NULL)) {
            getParent()->callAppenders(event);
        }
    }

    void Category::setAdditivity(bool additivity) {
        _isAdditive = additivity;
    }

    bool Category::getAdditivity() const throw() {
        return _isAdditive;
    }

    Category* Category::getParent() throw() {
        return _parent;
    }

    const Category* Category::getParent() const throw() {
        return _parent;
    }

    void Category::_logUnconditionally(Priority::Value priority,
                                       const char* format,
                                       va_list arguments) throw() {
        OstringStream messageBuffer;

        messageBuffer.vform(format, arguments);
        _logUnconditionally2(priority, messageBuffer.str());
    }

    void Category::_logUnconditionally2(Priority::Value priority,
                                        const std::string& message) throw() {
        LoggingEvent event(getName(), message, NDC::get(), priority);
        callAppenders(event);
    }

    bool Category::isPriorityEnabled(Priority::Value priority) const throw() {
        return(getChainedPriority() >= priority);
    }

    void Category::log(Priority::Value priority,
                       const char* stringFormat, ...) throw() {
        if (isPriorityEnabled(priority)) {
            va_list va;
            va_start(va, stringFormat);
            _logUnconditionally(priority, stringFormat, va);
            va_end(va);
        }
    }

    void Category::log(Priority::Value priority,
                       const std::string& message) throw() {
        if (isPriorityEnabled(priority))
            _logUnconditionally2(priority, message);
    }

    void Category::logva(Priority::Value priority,
                         const char* stringFormat,
                         va_list va) throw() {
        if (isPriorityEnabled(priority)) {
            _logUnconditionally(priority, stringFormat, va);
        }
    }

    void Category::debug(const char* stringFormat, ...) throw() {
        if (isPriorityEnabled(Priority::DEBUG)) {
            va_list va;
            va_start(va,stringFormat);
            _logUnconditionally(Priority::DEBUG, stringFormat, va);
            va_end(va);
        }
    }

    void Category::debug(const std::string& message) throw() {
        if (isPriorityEnabled(Priority::DEBUG))
            _logUnconditionally2(Priority::DEBUG, message);
    }

    void Category::info(const char* stringFormat, ...) throw() {
        if (isPriorityEnabled(Priority::INFO)) {
            va_list va;
            va_start(va,stringFormat);
            _logUnconditionally(Priority::INFO, stringFormat, va);
            va_end(va);
        }
    }

    void Category::info(const std::string& message) throw() {
        if (isPriorityEnabled(Priority::INFO))
            _logUnconditionally2(Priority::INFO, message);
    }

    void Category::notice(const char* stringFormat, ...) throw() {
        if (isPriorityEnabled(Priority::NOTICE)) {
            va_list va;
            va_start(va,stringFormat);
            _logUnconditionally(Priority::NOTICE, stringFormat, va);
            va_end(va);
        }
    }

    void Category::notice(const std::string& message) throw() {
        if (isPriorityEnabled(Priority::NOTICE))
            _logUnconditionally2(Priority::NOTICE, message);
    }

    void Category::warn(const char* stringFormat, ...) throw() {
        if (isPriorityEnabled(Priority::WARN)) {
            va_list va;
            va_start(va,stringFormat);
            _logUnconditionally(Priority::WARN, stringFormat, va);
            va_end(va);
        }
    }

    void Category::warn(const std::string& message) throw() {
        if (isPriorityEnabled(Priority::WARN))
            _logUnconditionally2(Priority::WARN, message);
    }

    void Category::error(const char* stringFormat, ...) throw() {
        if (isPriorityEnabled(Priority::ERROR)) {
            va_list va;
            va_start(va,stringFormat);
                       _logUnconditionally(Priority::ERROR, stringFormat, va);
            va_end(va);
        }
    }

    void Category::error(const std::string& message) throw() {
        if (isPriorityEnabled(Priority::ERROR))
            _logUnconditionally2(Priority::ERROR, message);
    }

    void Category::crit(const char* stringFormat, ...) throw() {
        if (isPriorityEnabled(Priority::CRIT)) {
            va_list va;
            va_start(va,stringFormat);
            _logUnconditionally(Priority::CRIT, stringFormat, va);
            va_end(va);
        }
    }

    void Category::crit(const std::string& message) throw() {
        if (isPriorityEnabled(Priority::CRIT))
            _logUnconditionally2(Priority::CRIT, message);
    }

    void Category::alert(const char* stringFormat, ...) throw() {
        if (isPriorityEnabled(Priority::ALERT)) {
            va_list va;
            va_start(va,stringFormat);
            _logUnconditionally(Priority::ALERT, stringFormat, va);
            va_end(va);
        }
    }

    void Category::alert(const std::string& message) throw() {
        if (isPriorityEnabled(Priority::ALERT))
            _logUnconditionally2(Priority::ALERT, message);
    }

    void Category::emerg(const char* stringFormat, ...) throw() {
        if (isPriorityEnabled(Priority::EMERG)) {
            va_list va;
            va_start(va,stringFormat);
            _logUnconditionally(Priority::EMERG, stringFormat, va);
            va_end(va);
        }
    }

    void Category::emerg(const std::string& message) throw() {
        if (isPriorityEnabled(Priority::EMERG))
            _logUnconditionally2(Priority::EMERG, message);
    }

    void Category::fatal(const char* stringFormat, ...) throw() {
        if (isPriorityEnabled(Priority::FATAL)) {
            va_list va;
            va_start(va,stringFormat);
            _logUnconditionally(Priority::FATAL, stringFormat, va);
            va_end(va);
        }
    }

    void Category::fatal(const std::string& message) throw() {
        if (isPriorityEnabled(Priority::FATAL))
            _logUnconditionally2(Priority::FATAL, message);
    }

    CategoryStream Category::getStream(Priority::Value priority) {
        return CategoryStream(*this, isPriorityEnabled(priority) ?
                              priority : Priority::NOTSET);
    }

    CategoryStream Category::operator<<(Priority::Value priority) {
        return getStream(priority);
    }
}

<|endoftext|>