<commit_before>// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/

#ifndef TAOCPP_PEGTL_INCLUDE_CONTRIB_RAW_STRING_HPP
#define TAOCPP_PEGTL_INCLUDE_CONTRIB_RAW_STRING_HPP

#include "../apply_mode.hpp"
#include "../config.hpp"
#include "../nothing.hpp"
#include "../rewind_mode.hpp"

#include "../internal/iterator.hpp"
#include "../internal/must.hpp"
#include "../internal/skip_control.hpp"
#include "../internal/state.hpp"
#include "../internal/until.hpp"

#include "../analysis/generic.hpp"

namespace tao
{
   namespace TAOCPP_PEGTL_NAMESPACE
   {
      namespace internal
      {
         template< char Open, char Marker, char Close >
         struct raw_string_tag
         {
         };

         template< bool use_action, bool use_apply0, typename Tag >
         struct raw_string_state_apply;

         template< typename Tag >
         struct raw_string_state_apply< false, false, Tag >
         {
            template< template< typename... > class,
                      template< typename... > class,
                      typename State,
                      typename Input,
                      typename... States >
            static void success( const State&, const Input&, States&&... )
            {
            }
         };

         void raw_adjust( const char*& i, const std::size_t s ) noexcept
         {
            i -= s;
         }

         void raw_adjust( internal::iterator& i, const std::size_t s ) noexcept
         {
            i.byte -= s;
            i.byte_in_line -= s;
            i.data -= s;
         }

         template< typename Tag >
         struct raw_string_state_apply< true, false, Tag >
         {
            template< template< typename... > class Action,
                      template< typename... > class Control,
                      typename State,
                      typename Input,
                      typename... States >
            static void success( const State& s, const Input& in, States&&... st )
            {
               auto dend = in.iterator();
               raw_adjust( dend, s.marker_size );
               Control< Tag >::template apply< typename Input::action_t, Action >( s.iter, dend, in.source(), st... );
            }
         };

         template< typename Tag >
         struct raw_string_state_apply< true, true, Tag >
         {
            template< template< typename... > class Action,
                      template< typename... > class Control,
                      typename State,
                      typename Input,
                      typename... States >
            static void success( const State&, const Input&, States&&... st )
            {
               Control< Tag >::template apply0< Action >( st... );
            }
         };

         template< typename Tag, typename Iterator >
         struct raw_string_state
         {
            template< typename Input, typename... States >
            raw_string_state( const Input&, States&&... )
            {
            }

            template< apply_mode A,
                      rewind_mode,
                      template< typename... > class Action,
                      template< typename... > class Control,
                      typename Input,
                      typename... States >
            void success( const Input& in, States&&... st ) const
            {
               constexpr bool use_action = ( A == apply_mode::ACTION ) && ( !is_nothing< Action, Tag >::value );
               constexpr bool use_apply0 = use_action && has_apply0< Action< Tag >, type_list< States... > >::value;
               raw_string_state_apply< use_action, use_apply0, Tag >::template success< Action, Control >( *this, in, st... );
            }

            raw_string_state( const raw_string_state& ) = delete;
            void operator=( const raw_string_state& ) = delete;

            Iterator iter;
            std::size_t marker_size = 0;
         };

         template< char Open, char Marker >
         struct raw_string_open
         {
            using analyze_t = analysis::generic< analysis::rule_type::ANY >;

            template< apply_mode A,
                      rewind_mode,
                      template< typename... > class Action,
                      template< typename... > class Control,
                      typename Input,
                      typename State >
            static bool match( Input& in, State& ls )
            {
               if( in.empty() || ( in.peek_char( 0 ) != Open ) ) {
                  return false;
               }
               for( std::size_t i = 1; i < in.size( i + 1 ); ++i ) {
                  switch( const auto c = in.peek_char( i ) ) {
                     case Open:
                        ls.marker_size = i + 1;
                        in.bump( ls.marker_size );
                        eol::match( in );
                        ls.iter = in.iterator();
                        return true;
                     case Marker:
                        break;
                     default:
                        return false;
                  }
               }
               return false;
            }
         };

         template< char Open, char Marker >
         struct skip_control< raw_string_open< Open, Marker > > : std::true_type
         {
         };

         template< char Marker, char Close >
         struct raw_string_close
         {
            using analyze_t = analysis::generic< analysis::rule_type::ANY >;

            template< apply_mode A,
                      rewind_mode,
                      template< typename... > class Action,
                      template< typename... > class Control,
                      typename Input,
                      typename State >
            static bool match( Input& in, const State& ls )
            {
               if( in.size( ls.marker_size ) < ls.marker_size ) {
                  return false;
               }
               if( in.peek_char( 0 ) != Close ) {
                  return false;
               }
               if( in.peek_char( ls.marker_size - 1 ) != Close ) {
                  return false;
               }
               for( std::size_t i = 0; i < ls.marker_size - 2; ++i ) {
                  if( in.peek_char( i + 1 ) != Marker ) {
                     return false;
                  }
               }
               in.bump( ls.marker_size );
               return true;
            }
         };

         template< char Marker, char Close >
         struct skip_control< raw_string_close< Marker, Close > > : std::true_type
         {
         };

         template< class Tag, typename... Rules >
         struct raw_string_switch_state
         {
            using analyze_t = analysis::generic< analysis::rule_type::SEQ, Rules... >;

            template< apply_mode A,
                      rewind_mode M,
                      template< typename... > class Action,
                      template< typename... > class Control,
                      typename Input,
                      typename... States >
            static bool match( Input& in, States&&... st )
            {
               using Iterator = typename Input::iterator_t;
               raw_string_state< Tag, Iterator > s( const_cast< const Input& >( in ), st... );

               if( duseltronik< seq< Rules... >, A, M, Action, Control >::match( in, s ) ) {
                  s.template success< A, M, Action, Control >( in, st... );
                  return true;
               }
               return false;
            }
         };

         template< typename Tag, typename... Rules >
         struct skip_control< raw_string_switch_state< Tag, Rules... > > : std::true_type
         {
         };

      }  // namespace internal

      // raw_string matches Lua-style long literals.
      //
      // The following description was taken from the Lua documentation
      // (see http://www.lua.org/docs.html):
      //
      // - An "opening long bracket of level n" is defined as an opening square
      //   bracket followed by n equal signs followed by another opening square
      //   bracket. So, an opening long bracket of level 0 is written as `[[`,
      //   an opening long bracket of level 1 is written as `[=[`, and so on.
      // - A "closing long bracket" is defined similarly; for instance, a closing
      //   long bracket of level 4 is written as `]====]`.
      // - A "long literal" starts with an opening long bracket of any level and
      //   ends at the first closing long bracket of the same level. It can
      //   contain any text except a closing bracket of the same level.
      // - Literals in this bracketed form can run for several lines, do not
      //   interpret any escape sequences, and ignore long brackets of any other
      //   level.
      // - For convenience, when the opening long bracket is immediately followed
      //   by a newline, the newline is not included in the string.
      //
      // Note that unlike Lua's long literal, a raw_string is customizable to use
      // other characters than `[`, `=` and `]` for matching. Also note that Lua
      // introduced newline-specific replacements in Lua 5.2, which we do not
      // support on the grammar level.

      template< char Open, char Marker, char Close, typename Tag = internal::raw_string_tag< Open, Marker, Close > >
      struct raw_string
         : internal::raw_string_switch_state< Tag,
                                              internal::raw_string_open< Open, Marker >,
                                              internal::must< internal::until< internal::raw_string_close< Marker, Close > > > >
      {
         // This is used to bind an action to the content.
         using content = Tag;

         // This is used for error-reporting when a raw string is not closed properly.
         using close = internal::until< internal::raw_string_close< Marker, Close > >;
      };

   }  // namespace TAOCPP_PEGTL_NAMESPACE

}  // namespace tao

#endif
<commit_msg>Simplify<commit_after>// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/

#ifndef TAOCPP_PEGTL_INCLUDE_CONTRIB_RAW_STRING_HPP
#define TAOCPP_PEGTL_INCLUDE_CONTRIB_RAW_STRING_HPP

#include "../apply_mode.hpp"
#include "../config.hpp"
#include "../nothing.hpp"
#include "../rewind_mode.hpp"

#include "../internal/iterator.hpp"
#include "../internal/must.hpp"
#include "../internal/skip_control.hpp"
#include "../internal/state.hpp"
#include "../internal/until.hpp"

#include "../analysis/generic.hpp"

namespace tao
{
   namespace TAOCPP_PEGTL_NAMESPACE
   {
      namespace internal
      {
         template< char Open, char Marker, char Close >
         struct raw_string_tag
         {
         };

         template< bool use_action, bool use_apply0, typename Tag >
         struct raw_string_state_apply;

         template< typename Tag >
         struct raw_string_state_apply< false, false, Tag >
         {
            template< template< typename... > class,
                      template< typename... > class,
                      typename State,
                      typename Input,
                      typename... States >
            static void success( const State&, const Input&, States&&... )
            {
            }
         };

         void raw_adjust( const char*& i, const std::size_t s ) noexcept
         {
            i -= s;
         }

         void raw_adjust( iterator& i, const std::size_t s ) noexcept
         {
            i.byte -= s;
            i.byte_in_line -= s;
            i.data -= s;
         }

         template< typename Tag >
         struct raw_string_state_apply< true, false, Tag >
         {
            template< template< typename... > class Action,
                      template< typename... > class Control,
                      typename State,
                      typename Input,
                      typename... States >
            static void success( const State& s, const Input& in, States&&... st )
            {
               auto dend = in.iterator();
               raw_adjust( dend, s.marker_size );
               Control< Tag >::template apply< typename Input::action_t, Action >( s.iter, dend, in.source(), st... );
            }
         };

         template< typename Tag >
         struct raw_string_state_apply< true, true, Tag >
         {
            template< template< typename... > class Action,
                      template< typename... > class Control,
                      typename State,
                      typename Input,
                      typename... States >
            static void success( const State&, const Input&, States&&... st )
            {
               Control< Tag >::template apply0< Action >( st... );
            }
         };

         template< typename Tag, typename Iterator >
         struct raw_string_state
         {
            template< typename Input, typename... States >
            raw_string_state( const Input&, States&&... )
            {
            }

            template< apply_mode A,
                      rewind_mode,
                      template< typename... > class Action,
                      template< typename... > class Control,
                      typename Input,
                      typename... States >
            void success( const Input& in, States&&... st ) const
            {
               constexpr bool use_action = ( A == apply_mode::ACTION ) && ( !is_nothing< Action, Tag >::value );
               constexpr bool use_apply0 = use_action && has_apply0< Action< Tag >, type_list< States... > >::value;
               raw_string_state_apply< use_action, use_apply0, Tag >::template success< Action, Control >( *this, in, st... );
            }

            raw_string_state( const raw_string_state& ) = delete;
            void operator=( const raw_string_state& ) = delete;

            Iterator iter;
            std::size_t marker_size = 0;
         };

         template< char Open, char Marker >
         struct raw_string_open
         {
            using analyze_t = analysis::generic< analysis::rule_type::ANY >;

            template< apply_mode A,
                      rewind_mode,
                      template< typename... > class Action,
                      template< typename... > class Control,
                      typename Input,
                      typename State >
            static bool match( Input& in, State& ls )
            {
               if( in.empty() || ( in.peek_char( 0 ) != Open ) ) {
                  return false;
               }
               for( std::size_t i = 1; i < in.size( i + 1 ); ++i ) {
                  switch( const auto c = in.peek_char( i ) ) {
                     case Open:
                        ls.marker_size = i + 1;
                        in.bump( ls.marker_size );
                        eol::match( in );
                        ls.iter = in.iterator();
                        return true;
                     case Marker:
                        break;
                     default:
                        return false;
                  }
               }
               return false;
            }
         };

         template< char Open, char Marker >
         struct skip_control< raw_string_open< Open, Marker > > : std::true_type
         {
         };

         template< char Marker, char Close >
         struct raw_string_close
         {
            using analyze_t = analysis::generic< analysis::rule_type::ANY >;

            template< apply_mode A,
                      rewind_mode,
                      template< typename... > class Action,
                      template< typename... > class Control,
                      typename Input,
                      typename State >
            static bool match( Input& in, const State& ls )
            {
               if( in.size( ls.marker_size ) < ls.marker_size ) {
                  return false;
               }
               if( in.peek_char( 0 ) != Close ) {
                  return false;
               }
               if( in.peek_char( ls.marker_size - 1 ) != Close ) {
                  return false;
               }
               for( std::size_t i = 0; i < ls.marker_size - 2; ++i ) {
                  if( in.peek_char( i + 1 ) != Marker ) {
                     return false;
                  }
               }
               in.bump( ls.marker_size );
               return true;
            }
         };

         template< char Marker, char Close >
         struct skip_control< raw_string_close< Marker, Close > > : std::true_type
         {
         };

         template< class Tag, typename... Rules >
         struct raw_string_switch_state
         {
            using analyze_t = analysis::generic< analysis::rule_type::SEQ, Rules... >;

            template< apply_mode A,
                      rewind_mode M,
                      template< typename... > class Action,
                      template< typename... > class Control,
                      typename Input,
                      typename... States >
            static bool match( Input& in, States&&... st )
            {
               using Iterator = typename Input::iterator_t;
               raw_string_state< Tag, Iterator > s( const_cast< const Input& >( in ), st... );

               if( duseltronik< seq< Rules... >, A, M, Action, Control >::match( in, s ) ) {
                  s.template success< A, M, Action, Control >( in, st... );
                  return true;
               }
               return false;
            }
         };

         template< typename Tag, typename... Rules >
         struct skip_control< raw_string_switch_state< Tag, Rules... > > : std::true_type
         {
         };

      }  // namespace internal

      // raw_string matches Lua-style long literals.
      //
      // The following description was taken from the Lua documentation
      // (see http://www.lua.org/docs.html):
      //
      // - An "opening long bracket of level n" is defined as an opening square
      //   bracket followed by n equal signs followed by another opening square
      //   bracket. So, an opening long bracket of level 0 is written as `[[`,
      //   an opening long bracket of level 1 is written as `[=[`, and so on.
      // - A "closing long bracket" is defined similarly; for instance, a closing
      //   long bracket of level 4 is written as `]====]`.
      // - A "long literal" starts with an opening long bracket of any level and
      //   ends at the first closing long bracket of the same level. It can
      //   contain any text except a closing bracket of the same level.
      // - Literals in this bracketed form can run for several lines, do not
      //   interpret any escape sequences, and ignore long brackets of any other
      //   level.
      // - For convenience, when the opening long bracket is immediately followed
      //   by a newline, the newline is not included in the string.
      //
      // Note that unlike Lua's long literal, a raw_string is customizable to use
      // other characters than `[`, `=` and `]` for matching. Also note that Lua
      // introduced newline-specific replacements in Lua 5.2, which we do not
      // support on the grammar level.

      template< char Open, char Marker, char Close >
      struct raw_string
         : internal::raw_string_switch_state< internal::raw_string_tag< Open, Marker, Close >,
                                              internal::raw_string_open< Open, Marker >,
                                              internal::must< internal::until< internal::raw_string_close< Marker, Close > > > >
      {
         // This is used to bind an action to the content.
         using content = internal::raw_string_tag< Open, Marker, Close >;

         // This is used for error-reporting when a raw string is not closed properly.
         using close = internal::until< internal::raw_string_close< Marker, Close > >;
      };

   }  // namespace TAOCPP_PEGTL_NAMESPACE

}  // namespace tao

#endif
<|endoftext|>


<commit_before>/***********************************************************************
    filename:   CEGUIExpatParser.cpp
    created:    Mon Mar 6 2006
    author:     Paul D Turner <paul@cegui.org.uk> (based on Dalfy's code)
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team
 *
 *   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, sublicense, 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 above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   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 NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS 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.
 ***************************************************************************/
#include "CEGUIExpatParser.h"
#include "CEGUIResourceProvider.h"
#include "CEGUISystem.h"
#include "CEGUIXMLHandler.h"
#include "CEGUIXMLAttributes.h"
#include "CEGUIExceptions.h"
#include "CEGUIPropertyHelper.h"
#include <expat.h>

// Start of CEGUI namespace section
namespace CEGUI
{
ExpatParser::ExpatParser(void)
{
    // set ID string
    d_identifierString = "CEGUI::ExpatParser - Official expat based parser module for CEGUI";
}

ExpatParser::~ExpatParser(void)
{
}

void ExpatParser::parseXMLFile(XMLHandler& handler, const String& filename, const String& schemaName, const String& resourceGroup)
{
    // All stuff goes here
    XML_Parser parser = XML_ParserCreate(0); // Create a parser

    if (! parser)
    {
        throw GenericException("ExpatParser::parseXMLFile - Unable to create a new Expat Parser");
    }

    XML_SetUserData(parser, (void*)&handler); // Initialise user data
    XML_SetElementHandler(parser, startElement, endElement); // Register callback for elements
    XML_SetCharacterDataHandler(parser, characterData); // Register callback for character data

    // Aquire resource using CEGUI ResourceProvider
    CEGUI::RawDataContainer rawXMLData;
    CEGUI::System::getSingleton().getResourceProvider()->loadRawDataContainer(filename, rawXMLData, resourceGroup);

    // Parse the data (note that the last true parameter tels Expat that this is the last chunk of the document
    if ( ! XML_Parse(parser, reinterpret_cast<const char*>(rawXMLData.getDataPtr()), rawXMLData.getSize(), true))
    {
        System::getSingleton().getResourceProvider()->unloadRawDataContainer(rawXMLData);
        // (We know it is a valid pointer, otherwise an exception would have been thrown above.)
        XML_ParserFree(parser);
        throw GenericException(String((const utf8*)"ExpatParser::parseXMLFile - XML Parsing error '") +
                                    String((const utf8*)XML_ErrorString(XML_GetErrorCode(parser))) +
                                    String((const utf8*)"' at line ") +
                                    PropertyHelper::uintToString(XML_GetCurrentLineNumber(parser)));
    }

    // Release resource
    CEGUI::System::getSingleton().getResourceProvider()->unloadRawDataContainer(rawXMLData);
    // (We know it is a valid pointer, otherwise an exception would have been thrown above.)
    XML_ParserFree(parser);
}

bool ExpatParser::initialiseImpl(void)
{
    return true;
}

void ExpatParser::cleanupImpl(void)
{

}

void ExpatParser::startElement(void* data, const char* element, const char** attr)
{
    XMLHandler* handler = static_cast<XMLHandler*>(data);
    XMLAttributes attrs;

    for(size_t i = 0 ; attr[i] ; i += 2)
        attrs.add((const utf8*)attr[i], (const utf8*)attr[i+1]);

    handler->elementStart((const utf8*)element, attrs);
}

void ExpatParser::endElement(void* data, const char* element)
{
    XMLHandler* handler = static_cast<XMLHandler*>(data);
    handler->elementEnd((const utf8*)element);
}

void ExpatParser::characterData(void *data, const char *text, int len)
{
    XMLHandler* handler = static_cast<XMLHandler*>(data);
    String str((const utf8*)text, static_cast<String::size_type>(len));
    handler->text(str);
}

} // End of  CEGUI namespace section
<commit_msg>-Addendum to the mem-leak fix: the exception handler still used 'parser' after the release of it :oops:<commit_after>/***********************************************************************
    filename:   CEGUIExpatParser.cpp
    created:    Mon Mar 6 2006
    author:     Paul D Turner <paul@cegui.org.uk> (based on Dalfy's code)
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team
 *
 *   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, sublicense, 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 above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   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 NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS 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.
 ***************************************************************************/
#include "CEGUIExpatParser.h"
#include "CEGUIResourceProvider.h"
#include "CEGUISystem.h"
#include "CEGUIXMLHandler.h"
#include "CEGUIXMLAttributes.h"
#include "CEGUIExceptions.h"
#include "CEGUIPropertyHelper.h"
#include <expat.h>

// Start of CEGUI namespace section
namespace CEGUI
{
ExpatParser::ExpatParser(void)
{
    // set ID string
    d_identifierString = "CEGUI::ExpatParser - Official expat based parser module for CEGUI";
}

ExpatParser::~ExpatParser(void)
{
}

void ExpatParser::parseXMLFile(XMLHandler& handler, const String& filename, const String& schemaName, const String& resourceGroup)
{
    // All stuff goes here
    XML_Parser parser = XML_ParserCreate(0); // Create a parser

    if (! parser)
    {
        throw GenericException("ExpatParser::parseXMLFile - Unable to create a new Expat Parser");
    }

    XML_SetUserData(parser, (void*)&handler); // Initialise user data
    XML_SetElementHandler(parser, startElement, endElement); // Register callback for elements
    XML_SetCharacterDataHandler(parser, characterData); // Register callback for character data

    // Aquire resource using CEGUI ResourceProvider
    CEGUI::RawDataContainer rawXMLData;
    CEGUI::System::getSingleton().getResourceProvider()->loadRawDataContainer(filename, rawXMLData, resourceGroup);

    // Parse the data (note that the last true parameter tels Expat that this is the last chunk of the document
    if ( ! XML_Parse(parser, reinterpret_cast<const char*>(rawXMLData.getDataPtr()), rawXMLData.getSize(), true))
    {
        System::getSingleton().getResourceProvider()->unloadRawDataContainer(rawXMLData);
        String exception (String((const utf8*)"ExpatParser::parseXMLFile - XML Parsing error '") +
                          String((const utf8*)XML_ErrorString(XML_GetErrorCode(parser))) +
                          String((const utf8*)"' at line ") +
                          PropertyHelper::uintToString(XML_GetCurrentLineNumber(parser)));
        // (We know it is a valid pointer, otherwise an exception would have been thrown above.)
        XML_ParserFree(parser);
        throw GenericException(exception);
    }

    // Release resource
    CEGUI::System::getSingleton().getResourceProvider()->unloadRawDataContainer(rawXMLData);
    // (We know it is a valid pointer, otherwise an exception would have been thrown above.)
    XML_ParserFree(parser);
}

bool ExpatParser::initialiseImpl(void)
{
    return true;
}

void ExpatParser::cleanupImpl(void)
{

}

void ExpatParser::startElement(void* data, const char* element, const char** attr)
{
    XMLHandler* handler = static_cast<XMLHandler*>(data);
    XMLAttributes attrs;

    for(size_t i = 0 ; attr[i] ; i += 2)
        attrs.add((const utf8*)attr[i], (const utf8*)attr[i+1]);

    handler->elementStart((const utf8*)element, attrs);
}

void ExpatParser::endElement(void* data, const char* element)
{
    XMLHandler* handler = static_cast<XMLHandler*>(data);
    handler->elementEnd((const utf8*)element);
}

void ExpatParser::characterData(void *data, const char *text, int len)
{
    XMLHandler* handler = static_cast<XMLHandler*>(data);
    String str((const utf8*)text, static_cast<String::size_type>(len));
    handler->text(str);
}

} // End of  CEGUI namespace section
<|endoftext|>


<commit_before>#include <NeuralNetwork/Perceptron/Perceptron.h>
#include <NeuralNetwork/Neuron/Neuron.h>
#include <NeuralNetwork/NeuralLayer/NeuralLayer.h>
#include <NeuralNetwork/Neuron/ActivationFunction/SigmoidFunction.h>
#include <NeuralNetwork/Neuron/ActivationFunction/TanhFunction.h>
#include <NeuralNetwork/Neuron/ActivationFunction/SoftmaxFunction.h>
#include <NeuralNetwork/Neuron/ActivationFunction/BiopolarSigmoidFunction.h>
#include <NeuralNetwork/LearningAlgorithm/BackPropagation/BepAlgorithm.h>
#include <NeuralNetwork/Neuron/ActivationFunction/LogScaleSoftmaxFunction.h>
//#include <NeuralNetwork/NeuralLayer/OpenCLNeuralLayer.h>
#include <NeuralNetwork/Config.h>
#include <cmath>

#ifndef BOOST_SYSTEM_NO_DEPRECATED
#define BOOST_SYSTEM_NO_DEPRECATED 1
#include <boost/filesystem.hpp>
#undef BOOST_SYSTEM_NO_DEPRECATED
#endif

#include <boost/archive/xml_iarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>
#include <fstream>
#include <iomanip>
#include <set>

#define png_infopp_NULL (png_infopp)NULL
#define int_p_NULL (int*)NULL

#if defined(NN_CC_MSVC)
# pragma warning(push)
// This function or variable may be unsafe
# pragma warning(disable:4996)
#endif

#include <boost/gil/gil_all.hpp>
#include <boost/gil/channel_algorithm.hpp>
#include <boost/gil/channel.hpp>
#include <boost/gil/image.hpp>
#include <boost/gil/extension/io/png_dynamic_io.hpp>
#include <boost/gil/extension/io/dynamic_io.hpp>
#include <boost/gil/extension/dynamic_image/any_image.hpp>
#include <boost/gil/extension/dynamic_image/dynamic_image_all.hpp>
#include "gil/extension/numeric/sampler.hpp"
#include "gil/extension/numeric/resample.hpp"

#if defined(NN_CC_MSVC)
# pragma warning(pop)
#endif

#include "Var.h"

typedef long double VarType;

using namespace boost::gil;
using namespace boost::gil::detail;
static const std::string alphabet("0123456789");
static const unsigned int width = 10;
static const unsigned int height = 14;
static const unsigned int inputsNumber = width * height;

typedef nn::Perceptron< VarType,
			nn::NeuralLayer<nn::Neuron, nn::SigmoidFunction, 10 , inputsNumber, 1000 >,
			nn::NeuralLayer<nn::Neuron, nn::SigmoidFunction, 80, 10, 1000>,
			nn::NeuralLayer<nn::Neuron, nn::SoftmaxFunction, 10, 1000>
		       > Perceptron;

typedef nn::Perceptron< VarType,
			nn::NeuralLayer<nn::Neuron, nn::SigmoidFunction, 20, inputsNumber, 1000>,
			nn::NeuralLayer<nn::Neuron, nn::SoftmaxFunction,  inputsNumber, 80, 1000 >
		      > AutoEncoder;

typedef nn::bp::BepAlgorithm< AutoEncoder, nn::bp::CrossEntropyError> AutoEncAlgo;
typedef nn::bp::BepAlgorithm< Perceptron, nn::bp::CrossEntropyError> Algo;

template <typename Out>
struct halfdiff_cast_channels {
    template <typename T>
    Out operator()(const T& in1, const T& in2) const {
        return Out( (in1-in2)/2 );
    }
};

template <typename SrcView, typename DstView>
void convert_color(const SrcView& src, const DstView& dst) {
    typedef typename channel_type<DstView>::type d_channel_t;
    typedef typename channel_convert_to_unsigned<d_channel_t>::type channel_t;
    typedef pixel<channel_t, gray_layout_t>  gray_pixel_t;

    copy_pixels(color_converted_view<gray_pixel_t>(src), dst);
}

template<typename Iterator>
void readImage(std::string fileName, Iterator out) {
    using namespace boost::gil;
    using namespace nn;
    using namespace nn::bp;

    rgb8_image_t srcImg;
    png_read_image(fileName.c_str(), srcImg);

    gray8_image_t dstImg(srcImg.dimensions());
    gray8_pixel_t white(255);
    fill_pixels(view(dstImg), white);

    gray8_image_t grayImage(srcImg.dimensions());
    convert_color( view(srcImg), view(grayImage) );
    auto grayView = view(grayImage);

    gray8_image_t scaledImage(width, height);
    resize_view(grayView, view(scaledImage), bilinear_sampler() );
    auto srcView = view(scaledImage);

    for (int y=0; y<srcView.height(); ++y) {
        gray8c_view_t::x_iterator src_it( srcView.row_begin(y) );
        for (int x=0; x<srcView.width(); ++x) {
            *out = src_it[x]/255.f;// < 130? 1.f: -1.f;//255.f;
            out++;
        }
    }
}

Perceptron readPerceptron(std::string fileName) {
    Perceptron perceptron;
    if( boost::filesystem::exists(fileName.c_str()) ){
      std::ifstream file(fileName);
      if( file.good() ) {
	  Perceptron::Memento memento;
	  boost::archive::xml_iarchive ia ( file );
	  ia  >> BOOST_SERIALIZATION_NVP ( memento );

	  perceptron.setMemento ( memento );
      } else {
	  throw nn::NNException("Invalid perceptron file name", __FILE__, __LINE__);
      }
    }

    return perceptron;
}

void recognize(std::string perceptron, std::string image) {
    try {
        std::array<VarType, inputsNumber> inputs = {0};
        readImage(image, inputs.begin() );
        std::vector<VarType> result(alphabet.length(), VarType(0.f) );
        readPerceptron(perceptron).calculate(inputs.begin(), inputs.end(), result.begin() );
        for( unsigned int i = 0; i < result.size(); i++ ) {
	  std::cout << "Symbol: " <<
		       alphabet[i] <<
		       " " <<
		       result[i] <<
		       std::endl;
        }

    } catch( const nn::NNException& e) {
        std::cout << e.what() << std::endl;
    } catch( const std::exception& e) {
        std::cout << e.what() << std::endl;
    } catch(...) {
        std::cout << "Unknown error" << std::endl;
    }
}

template<typename Perc>
void save(const Perc& perc, std::string name)
{
    typename Perc::Memento memento = perc.getMemento();
    std::ofstream strm( name );
    boost::archive::xml_oarchive oa ( strm );
    oa << BOOST_SERIALIZATION_NVP ( memento );
    strm.flush();
}

template<typename Files>
AutoEncoder calculateAutoEncoder(Files files){
    std::cout << "AutoEncoder calculation started" << std::endl;
    std::vector<AutoEncAlgo::Prototype> prototypes;
    for( auto image : files) {
        if( !boost::filesystem::is_directory( image ) ) {
            try {
                AutoEncAlgo::Prototype proto;
                readImage( image, std::get<0>(proto).begin() );
		std::copy( std::get<0>(proto).begin(),
			   std::get<0>(proto).end(),
			   std::get<1>(proto).begin());

                prototypes.push_back(proto);
            } catch(const std::exception&) {
                std::cout << "Invalid image found :" << image << std::endl;
            }
        }
    }

    static AutoEncAlgo autoEncAlgo(0.005f, 0.01f);

    static std::size_t counter = 0;
    static AutoEncoder enc = autoEncAlgo.calculate(prototypes.begin(),
							  prototypes.end(),
							  [](VarType error) {
							      counter++;
							      if(counter > 0){
								counter = 0;
								std::cout << error << std::endl;
							      }
							  });

    save(enc, "autoencoder.xml");
}

void calculateWeights(std::string imagesPath) {
    using namespace boost::filesystem;
    path directory(imagesPath);
    directory_iterator end_iter;

    std::vector< std::string > files;
    if ( exists(directory) && is_directory(directory))
    {
        for( directory_iterator dir_iter(directory) ; dir_iter != end_iter ; ++dir_iter)
        {
            if (is_regular_file(dir_iter->status()) )
            {
                files.push_back( dir_iter->path().string() );
            }
        }
    }

    static AutoEncoder autoEnc = calculateAutoEncoder(files);

    std::cout << "Perceptron calculation started" << std::endl;
    static Perceptron tmp = readPerceptron("perceptron.xml");
    static Algo algorithm (0.003f, 0.001f );
    algorithm.setMemento( tmp.getMemento() );

    std::vector<Algo::Prototype> prototypes;
    for( auto image : files ) {
        if( !boost::filesystem::is_directory( image ) ) {
            try {
                Algo::Prototype proto;
                readImage( image, std::get<0>(proto).begin() );
                std::fill(std::get<1>(proto).begin(), std::get<1>(proto).end(), 0.f);
                char ch = path(image).filename().string()[0];
                size_t pos = alphabet.find(ch);
                std::get<1>(proto)[pos] = 1.0f;
                prototypes.push_back(proto);
            } catch(const std::exception&) {
                std::cout << "Invalid image found :" << image << std::endl;
            }
        }
    }

    static std::size_t counter = 0;
    auto errorFunc = [](VarType error) {counter++;
					if(counter > 1000){
					  counter = 0;
					  std::cout << error << std::endl;
					}};

    static Perceptron perceptron = algorithm.calculate(prototypes.begin(),
						       prototypes.end(),
						       errorFunc);

    save(perceptron, "perceptron.xml");
}

int main(int argc, char** argv)
{
    int result = -1;
    if( argc == 3 ) {
        recognize(argv[1], argv[2]);
        result = 0;
    } else if( argc == 2 ) {
        calculateWeights(argv[1]);
        result = 0;
    } else {
        std::cout << std::endl << "Usage : " << std::endl << std::endl;
        std::cout << "./ocr [folder] where  [folder] is a directory with your samples, this command will generate a perceptron.xml file" << std::endl << std::endl;
        std::cout << "./ocr perceptron.xml [file] where [file] is a png image which has to be recognized" << std::endl << std::endl;
    }

    return result;
}

<commit_msg>Removed Math.h no need.<commit_after>#include <NeuralNetwork/Perceptron/Perceptron.h>
#include <NeuralNetwork/Neuron/Neuron.h>
#include <NeuralNetwork/NeuralLayer/NeuralLayer.h>
#include <NeuralNetwork/Neuron/ActivationFunction/SigmoidFunction.h>
#include <NeuralNetwork/Neuron/ActivationFunction/TanhFunction.h>
#include <NeuralNetwork/Neuron/ActivationFunction/SoftmaxFunction.h>
#include <NeuralNetwork/Neuron/ActivationFunction/BiopolarSigmoidFunction.h>
#include <NeuralNetwork/LearningAlgorithm/BackPropagation/BepAlgorithm.h>
#include <NeuralNetwork/Neuron/ActivationFunction/LogScaleSoftmaxFunction.h>
//#include <NeuralNetwork/NeuralLayer/OpenCLNeuralLayer.h>
#include <NeuralNetwork/Config.h>
#include <cmath>

#ifndef BOOST_SYSTEM_NO_DEPRECATED
#define BOOST_SYSTEM_NO_DEPRECATED 1
#include <boost/filesystem.hpp>
#undef BOOST_SYSTEM_NO_DEPRECATED
#endif

#include <boost/archive/xml_iarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>
#include <fstream>
#include <iomanip>
#include <set>

#define png_infopp_NULL (png_infopp)NULL
#define int_p_NULL (int*)NULL

#if defined(NN_CC_MSVC)
# pragma warning(push)
// This function or variable may be unsafe
# pragma warning(disable:4996)
#endif

#include <boost/gil/gil_all.hpp>
#include <boost/gil/channel_algorithm.hpp>
#include <boost/gil/channel.hpp>
#include <boost/gil/image.hpp>
#include <boost/gil/extension/io/png_dynamic_io.hpp>
#include <boost/gil/extension/io/dynamic_io.hpp>
#include <boost/gil/extension/dynamic_image/any_image.hpp>
#include <boost/gil/extension/dynamic_image/dynamic_image_all.hpp>
#include "gil/extension/numeric/sampler.hpp"
#include "gil/extension/numeric/resample.hpp"

#if defined(NN_CC_MSVC)
# pragma warning(pop)
#endif

#include "Var.h"

typedef long double VarType;

using namespace boost::gil;
using namespace boost::gil::detail;
static const std::string alphabet("0123456789");
static const unsigned int width = 49;
static const unsigned int height = 67;
static const unsigned int inputsNumber = width * height;

typedef nn::Perceptron< VarType,
			nn::NeuralLayer<nn::Neuron, nn::SigmoidFunction, 10 , inputsNumber, 1000 >,
			nn::NeuralLayer<nn::Neuron, nn::SigmoidFunction, 80, 10, 1000>,
			nn::NeuralLayer<nn::Neuron, nn::SoftmaxFunction, 10, 1000>
		       > Perceptron;

typedef nn::Perceptron< VarType,
			nn::NeuralLayer<nn::Neuron, nn::SigmoidFunction, 20, inputsNumber, 1000>,
			nn::NeuralLayer<nn::Neuron, nn::SoftmaxFunction,  inputsNumber, 80, 1000 >
		      > AutoEncoder;

typedef nn::bp::BepAlgorithm< AutoEncoder, nn::bp::CrossEntropyError> AutoEncAlgo;
typedef nn::bp::BepAlgorithm< Perceptron, nn::bp::CrossEntropyError> Algo;

template <typename Out>
struct halfdiff_cast_channels {
    template <typename T>
    Out operator()(const T& in1, const T& in2) const {
        return Out( (in1-in2)/2 );
    }
};

template <typename SrcView, typename DstView>
void convert_color(const SrcView& src, const DstView& dst) {
    typedef typename channel_type<DstView>::type d_channel_t;
    typedef typename channel_convert_to_unsigned<d_channel_t>::type channel_t;
    typedef pixel<channel_t, gray_layout_t>  gray_pixel_t;

    copy_pixels(color_converted_view<gray_pixel_t>(src), dst);
}

template<typename Iterator>
void readImage(std::string fileName, Iterator out) {
    using namespace boost::gil;
    using namespace nn;
    using namespace nn::bp;

    rgb8_image_t srcImg;
    png_read_image(fileName.c_str(), srcImg);

    gray8_image_t dstImg(srcImg.dimensions());
    gray8_pixel_t white(255);
    fill_pixels(view(dstImg), white);

    gray8_image_t grayImage(srcImg.dimensions());
    convert_color( view(srcImg), view(grayImage) );
    auto grayView = view(grayImage);

    gray8_image_t scaledImage(width, height);
    resize_view(grayView, view(scaledImage), bilinear_sampler() );
    auto srcView = view(scaledImage);

    for (int y=0; y<srcView.height(); ++y) {
        gray8c_view_t::x_iterator src_it( srcView.row_begin(y) );
        for (int x=0; x<srcView.width(); ++x) {
            *out = src_it[x]/255.f;// < 130? 1.f: -1.f;//255.f;
            out++;
        }
    }
}

Perceptron readPerceptron(std::string fileName) {
    Perceptron perceptron;
    if( boost::filesystem::exists(fileName.c_str()) ){
      std::ifstream file(fileName);
      if( file.good() ) {
	  Perceptron::Memento memento;
	  boost::archive::xml_iarchive ia ( file );
	  ia  >> BOOST_SERIALIZATION_NVP ( memento );

	  perceptron.setMemento ( memento );
      } else {
	  throw nn::NNException("Invalid perceptron file name", __FILE__, __LINE__);
      }
    }

    return perceptron;
}

void recognize(std::string perceptron, std::string image) {
    try {
        std::array<VarType, inputsNumber> inputs = {0};
        readImage(image, inputs.begin() );
        std::vector<VarType> result(alphabet.length(), VarType(0.f) );
        readPerceptron(perceptron).calculate(inputs.begin(), inputs.end(), result.begin() );
        for( unsigned int i = 0; i < result.size(); i++ ) {
	  std::cout << "Symbol: " <<
		       alphabet[i] <<
		       " " <<
		       result[i] <<
		       std::endl;
        }

    } catch( const nn::NNException& e) {
        std::cout << e.what() << std::endl;
    } catch( const std::exception& e) {
        std::cout << e.what() << std::endl;
    } catch(...) {
        std::cout << "Unknown error" << std::endl;
    }
}

template<typename Perc>
void save(const Perc& perc, std::string name)
{
    typename Perc::Memento memento = perc.getMemento();
    std::ofstream strm( name );
    boost::archive::xml_oarchive oa ( strm );
    oa << BOOST_SERIALIZATION_NVP ( memento );
    strm.flush();
}

template<typename Files>
AutoEncoder calculateAutoEncoder(Files files){
    std::cout << "AutoEncoder calculation started" << std::endl;
    std::vector<AutoEncAlgo::Prototype> prototypes;
    for( auto image : files) {
        if( !boost::filesystem::is_directory( image ) ) {
            try {
                AutoEncAlgo::Prototype proto;
                readImage( image, std::get<0>(proto).begin() );
		std::copy( std::get<0>(proto).begin(),
			   std::get<0>(proto).end(),
			   std::get<1>(proto).begin());

                prototypes.push_back(proto);
            } catch(const std::exception&) {
                std::cout << "Invalid image found :" << image << std::endl;
            }
        }
    }

    static AutoEncAlgo autoEncAlgo(0.005f, 0.01f);

    static std::size_t counter = 0;
    static AutoEncoder enc = autoEncAlgo.calculate(prototypes.begin(),
							  prototypes.end(),
							  [](VarType error) {
							      counter++;
							      if(counter > 0){
								counter = 0;
								std::cout << error << std::endl;
							      }
							  });

    save(enc, "autoencoder.xml");
}

void calculateWeights(std::string imagesPath) {
    using namespace boost::filesystem;
    path directory(imagesPath);
    directory_iterator end_iter;

    std::vector< std::string > files;
    if ( exists(directory) && is_directory(directory))
    {
        for( directory_iterator dir_iter(directory) ; dir_iter != end_iter ; ++dir_iter)
        {
            if (is_regular_file(dir_iter->status()) )
            {
                files.push_back( dir_iter->path().string() );
            }
        }
    }

    //static AutoEncoder autoEnc = calculateAutoEncoder(files);

    std::cout << "Perceptron calculation started" << std::endl;
    static Perceptron tmp = readPerceptron("perceptron.xml");
    static Algo algorithm (0.003f, 0.001f );
    algorithm.setMemento( tmp.getMemento() );

    std::vector<Algo::Prototype> prototypes;
    for( auto image : files ) {
        if( !boost::filesystem::is_directory( image ) ) {
            try {
                Algo::Prototype proto;
                readImage( image, std::get<0>(proto).begin() );
                std::fill(std::get<1>(proto).begin(), std::get<1>(proto).end(), 0.f);
                char ch = path(image).filename().string()[0];
                size_t pos = alphabet.find(ch);
                std::get<1>(proto)[pos] = 1.0f;
                prototypes.push_back(proto);
            } catch(const std::exception&) {
                std::cout << "Invalid image found :" << image << std::endl;
            }
        }
    }

    static std::size_t counter = 0;
    auto errorFunc = [](VarType error) {counter++;
					if(counter > 1000){
					  counter = 0;
					  std::cout << error << std::endl;
					}};

    static Perceptron perceptron = algorithm.calculate(prototypes.begin(),
						       prototypes.end(),
						       errorFunc);

    save(perceptron, "perceptron.xml");
}

int main(int argc, char** argv)
{
    int result = -1;
    if( argc == 3 ) {
        recognize(argv[1], argv[2]);
        result = 0;
    } else if( argc == 2 ) {
        calculateWeights(argv[1]);
        result = 0;
    } else {
        std::cout << std::endl << "Usage : " << std::endl << std::endl;
        std::cout << "./ocr [folder] where  [folder] is a directory with your samples, this command will generate a perceptron.xml file" << std::endl << std::endl;
        std::cout << "./ocr perceptron.xml [file] where [file] is a png image which has to be recognized" << std::endl << std::endl;
    }

    return result;
}

<|endoftext|>


<commit_before>//===--- ParseDeclCXX.cpp - C++ Declaration Parsing -----------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file implements the C++ Declaration portions of the Parser interfaces.
//
//===----------------------------------------------------------------------===//

#include "clang/Parse/Parser.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Parse/DeclSpec.h"
#include "clang/Parse/Scope.h"
using namespace clang;

/// ParseNamespace - We know that the current token is a namespace keyword. This
/// may either be a top level namespace or a block-level namespace alias.
///
///       namespace-definition: [C++ 7.3: basic.namespace]
///         named-namespace-definition
///         unnamed-namespace-definition
///
///       unnamed-namespace-definition:
///         'namespace' attributes[opt] '{' namespace-body '}'
///
///       named-namespace-definition:
///         original-namespace-definition
///         extension-namespace-definition
///
///       original-namespace-definition:
///         'namespace' identifier attributes[opt] '{' namespace-body '}'
///
///       extension-namespace-definition:
///         'namespace' original-namespace-name '{' namespace-body '}'
///
///       namespace-alias-definition:  [C++ 7.3.2: namespace.alias]
///         'namespace' identifier '=' qualified-namespace-specifier ';'
///
Parser::DeclTy *Parser::ParseNamespace(unsigned Context) {
  assert(Tok.is(tok::kw_namespace) && "Not a namespace!");
  SourceLocation NamespaceLoc = ConsumeToken();  // eat the 'namespace'.

  SourceLocation IdentLoc;
  IdentifierInfo *Ident = 0;

  if (Tok.is(tok::identifier)) {
    Ident = Tok.getIdentifierInfo();
    IdentLoc = ConsumeToken();  // eat the identifier.
  }

  // Read label attributes, if present.
  DeclTy *AttrList = 0;
  if (Tok.is(tok::kw___attribute))
    // FIXME: save these somewhere.
    AttrList = ParseAttributes();

  if (Tok.is(tok::equal)) {
    // FIXME: Verify no attributes were present.
    // FIXME: parse this.
  } else if (Tok.is(tok::l_brace)) {

    SourceLocation LBrace = ConsumeBrace();

    // Enter a scope for the namespace.
    EnterScope(Scope::DeclScope);

    DeclTy *NamespcDecl =
      Actions.ActOnStartNamespaceDef(CurScope, IdentLoc, Ident, LBrace);

    while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof))
      ParseExternalDeclaration();

    // Leave the namespace scope.
    ExitScope();

    SourceLocation RBrace = MatchRHSPunctuation(tok::r_brace, LBrace);
    Actions.ActOnFinishNamespaceDef(NamespcDecl, RBrace);

    return NamespcDecl;

  } else {
    unsigned D = Ident ? diag::err_expected_lbrace :
                         diag::err_expected_ident_lbrace;
    Diag(Tok.getLocation(), D);
  }

  return 0;
}

/// ParseLinkage - We know that the current token is a string_literal
/// and just before that, that extern was seen.
///
///       linkage-specification: [C++ 7.5p2: dcl.link]
///         'extern' string-literal '{' declaration-seq[opt] '}'
///         'extern' string-literal declaration
///
Parser::DeclTy *Parser::ParseLinkage(unsigned Context) {
  assert(Tok.is(tok::string_literal) && "Not a stringliteral!");
  llvm::SmallVector<char, 8> LangBuffer;
  // LangBuffer is guaranteed to be big enough.
  LangBuffer.resize(Tok.getLength());
  const char *LangBufPtr = &LangBuffer[0];
  unsigned StrSize = PP.getSpelling(Tok, LangBufPtr);

  SourceLocation Loc = ConsumeStringToken();
  DeclTy *D = 0;
  SourceLocation LBrace, RBrace;

  if (Tok.isNot(tok::l_brace)) {
    D = ParseDeclaration(Context);
  } else {
    LBrace = ConsumeBrace();
    while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
      // FIXME capture the decls.
      D = ParseExternalDeclaration();
    }

    RBrace = MatchRHSPunctuation(tok::r_brace, LBrace);
  }

  if (!D)
    return 0;

  return Actions.ActOnLinkageSpec(Loc, LBrace, RBrace, LangBufPtr, StrSize, D);
}

/// ParseClassSpecifier - Parse a C++ class-specifier [C++ class] or
/// elaborated-type-specifier [C++ dcl.type.elab]; we can't tell which
/// until we reach the start of a definition or see a token that
/// cannot start a definition.
///
///       class-specifier: [C++ class]
///         class-head '{' member-specification[opt] '}'
///         class-head '{' member-specification[opt] '}' attributes[opt]
///       class-head:
///         class-key identifier[opt] base-clause[opt]
///         class-key nested-name-specifier identifier base-clause[opt]
///         class-key nested-name-specifier[opt] simple-template-id
///                          base-clause[opt]
/// [GNU]   class-key attributes[opt] identifier[opt] base-clause[opt]
/// [GNU]   class-key attributes[opt] nested-name-specifier
///                          identifier base-clause[opt]
/// [GNU]   class-key attributes[opt] nested-name-specifier[opt]
///                          simple-template-id base-clause[opt]
///       class-key:
///         'class'
///         'struct'
///         'union'
///
///       elaborated-type-specifier: [C++ dcl.type.elab]
///         class-key ::[opt] nested-name-specifier[opt] identifier
///         class-key ::[opt] nested-name-specifier[opt] 'template'[opt]
///                          simple-template-id
///
///  Note that the C++ class-specifier and elaborated-type-specifier,
///  together, subsume the C99 struct-or-union-specifier:
///
///       struct-or-union-specifier: [C99 6.7.2.1]
///         struct-or-union identifier[opt] '{' struct-contents '}'
///         struct-or-union identifier
/// [GNU]   struct-or-union attributes[opt] identifier[opt] '{' struct-contents
///                                                         '}' attributes[opt]
/// [GNU]   struct-or-union attributes[opt] identifier
///       struct-or-union:
///         'struct'
///         'union'
void Parser::ParseClassSpecifier(DeclSpec &DS) {
  assert((Tok.is(tok::kw_class) ||
          Tok.is(tok::kw_struct) ||
          Tok.is(tok::kw_union)) &&
         "Not a class specifier");
  DeclSpec::TST TagType =
    Tok.is(tok::kw_class) ? DeclSpec::TST_class :
    Tok.is(tok::kw_struct) ? DeclSpec::TST_struct :
    DeclSpec::TST_union;

  SourceLocation StartLoc = ConsumeToken();

  AttributeList *Attr = 0;
  // If attributes exist after tag, parse them.
  if (Tok.is(tok::kw___attribute))
    Attr = ParseAttributes();

  // FIXME: Parse the (optional) nested-name-specifier.

  // Parse the (optional) class name.
  // FIXME: Alternatively, parse a simple-template-id.
  IdentifierInfo *Name = 0;
  SourceLocation NameLoc;
  if (Tok.is(tok::identifier)) {
    Name = Tok.getIdentifierInfo();
    NameLoc = ConsumeToken();
  }

  // There are three options here.  If we have 'struct foo;', then
  // this is a forward declaration.  If we have 'struct foo {...' or
  // 'struct fo :...' then this is a definition. Otherwise we have
  // something like 'struct foo xyz', a reference.
  Action::TagKind TK;
  if (Tok.is(tok::l_brace) || (getLang().CPlusPlus && Tok.is(tok::colon)))
    TK = Action::TK_Definition;
  else if (Tok.is(tok::semi))
    TK = Action::TK_Declaration;
  else
    TK = Action::TK_Reference;

  if (!Name && TK != Action::TK_Definition) {
    // We have a declaration or reference to an anonymous class.
    Diag(StartLoc, diag::err_anon_type_definition,
         DeclSpec::getSpecifierName(TagType));

    // Skip the rest of this declarator, up until the comma or semicolon.
    SkipUntil(tok::comma, true);
    return;
  }

  // Parse the tag portion of this.
  DeclTy *TagDecl = Actions.ActOnTag(CurScope, TagType, TK, StartLoc, Name,
                                     NameLoc, Attr);

  // Parse the optional base clause (C++ only).
  if (getLang().CPlusPlus && Tok.is(tok::colon)) {
    ParseBaseClause(TagDecl);
  }

  // If there is a body, parse it and inform the actions module.
  if (Tok.is(tok::l_brace))
    ParseStructUnionBody(StartLoc, TagType, TagDecl);
  else if (TK == Action::TK_Definition) {
    // FIXME: Complain that we have a base-specifier list but no
    // definition.
    Diag(Tok.getLocation(), diag::err_expected_lbrace);
  }

  const char *PrevSpec = 0;
  if (DS.SetTypeSpecType(TagType, StartLoc, PrevSpec, TagDecl))
    Diag(StartLoc, diag::err_invalid_decl_spec_combination, PrevSpec);
}

/// ParseBaseClause - Parse the base-clause of a C++ class [C++ class.derived].
///
///       base-clause : [C++ class.derived]
///         ':' base-specifier-list
///       base-specifier-list:
///         base-specifier '...'[opt]
///         base-specifier-list ',' base-specifier '...'[opt]
void Parser::ParseBaseClause(DeclTy *ClassDecl)
{
  assert(Tok.is(tok::colon) && "Not a base clause");
  ConsumeToken();

  while (true) {
    // Parse a base-specifier.
    if (ParseBaseSpecifier(ClassDecl)) {
      // Skip the rest of this base specifier, up until the comma or
      // opening brace.
      SkipUntil(tok::comma, tok::l_brace);
    }

    // If the next token is a comma, consume it and keep reading
    // base-specifiers.
    if (Tok.isNot(tok::comma)) break;

    // Consume the comma.
    ConsumeToken();
  }
}

/// ParseBaseSpecifier - Parse a C++ base-specifier. A base-specifier is
/// one entry in the base class list of a class specifier, for example:
///    class foo : public bar, virtual private baz {
/// 'public bar' and 'virtual private baz' are each base-specifiers.
///
///       base-specifier: [C++ class.derived]
///         ::[opt] nested-name-specifier[opt] class-name
///         'virtual' access-specifier[opt] ::[opt] nested-name-specifier[opt]
///                        class-name
///         access-specifier 'virtual'[opt] ::[opt] nested-name-specifier[opt]
///                        class-name
bool Parser::ParseBaseSpecifier(DeclTy *ClassDecl)
{
  bool IsVirtual = false;
  SourceLocation StartLoc = Tok.getLocation();

  // Parse the 'virtual' keyword.
  if (Tok.is(tok::kw_virtual))  {
    ConsumeToken();
    IsVirtual = true;
  }

  // Parse an (optional) access specifier.
  AccessSpecifier Access = getAccessSpecifierIfPresent();
  if (Access)
    ConsumeToken();

  // Parse the 'virtual' keyword (again!), in case it came after the
  // access specifier.
  if (Tok.is(tok::kw_virtual))  {
    SourceLocation VirtualLoc = ConsumeToken();
    if (IsVirtual) {
      // Complain about duplicate 'virtual'
      Diag(VirtualLoc, diag::err_dup_virtual);
    }

    IsVirtual = true;
  }

  // FIXME: Parse optional '::' and optional nested-name-specifier.

  // Parse the class-name.
  // FIXME: Alternatively, parse a simple-template-id.
  if (Tok.isNot(tok::identifier)) {
    Diag(Tok.getLocation(), diag::err_expected_class_name);
    return true;
  }

  // We have an identifier; check whether it is actually a type.
  DeclTy *BaseType = Actions.isTypeName(*Tok.getIdentifierInfo(), CurScope);
  if (!BaseType) {
    Diag(Tok.getLocation(), diag::err_expected_class_name);
    return true;
  }

  // The location of the base class itself.
  SourceLocation BaseLoc = Tok.getLocation();

  // Find the complete source range for the base-specifier.
  SourceRange Range(StartLoc, BaseLoc);

  // Consume the identifier token (finally!).
  ConsumeToken();

  // Notify semantic analysis that we have parsed a complete
  // base-specifier.
  Actions.ActOnBaseSpecifier(ClassDecl, Range, IsVirtual, Access, BaseType,
                             BaseLoc);
  return false;
}

/// getAccessSpecifierIfPresent - Determine whether the next token is
/// a C++ access-specifier.
///
///       access-specifier: [C++ class.derived]
///         'private'
///         'protected'
///         'public'
AccessSpecifier Parser::getAccessSpecifierIfPresent() const
{
  switch (Tok.getKind()) {
  default: return AS_none;
  case tok::kw_private: return AS_private;
  case tok::kw_protected: return AS_protected;
  case tok::kw_public: return AS_public;
  }
}
<commit_msg>Convert CRLF to LF.<commit_after>//===--- ParseDeclCXX.cpp - C++ Declaration Parsing -----------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file implements the C++ Declaration portions of the Parser interfaces.
//
//===----------------------------------------------------------------------===//

#include "clang/Parse/Parser.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Parse/DeclSpec.h"
#include "clang/Parse/Scope.h"
using namespace clang;

/// ParseNamespace - We know that the current token is a namespace keyword. This
/// may either be a top level namespace or a block-level namespace alias.
///
///       namespace-definition: [C++ 7.3: basic.namespace]
///         named-namespace-definition
///         unnamed-namespace-definition
///
///       unnamed-namespace-definition:
///         'namespace' attributes[opt] '{' namespace-body '}'
///
///       named-namespace-definition:
///         original-namespace-definition
///         extension-namespace-definition
///
///       original-namespace-definition:
///         'namespace' identifier attributes[opt] '{' namespace-body '}'
///
///       extension-namespace-definition:
///         'namespace' original-namespace-name '{' namespace-body '}'
///
///       namespace-alias-definition:  [C++ 7.3.2: namespace.alias]
///         'namespace' identifier '=' qualified-namespace-specifier ';'
///
Parser::DeclTy *Parser::ParseNamespace(unsigned Context) {
  assert(Tok.is(tok::kw_namespace) && "Not a namespace!");
  SourceLocation NamespaceLoc = ConsumeToken();  // eat the 'namespace'.

  SourceLocation IdentLoc;
  IdentifierInfo *Ident = 0;

  if (Tok.is(tok::identifier)) {
    Ident = Tok.getIdentifierInfo();
    IdentLoc = ConsumeToken();  // eat the identifier.
  }

  // Read label attributes, if present.
  DeclTy *AttrList = 0;
  if (Tok.is(tok::kw___attribute))
    // FIXME: save these somewhere.
    AttrList = ParseAttributes();

  if (Tok.is(tok::equal)) {
    // FIXME: Verify no attributes were present.
    // FIXME: parse this.
  } else if (Tok.is(tok::l_brace)) {

    SourceLocation LBrace = ConsumeBrace();

    // Enter a scope for the namespace.
    EnterScope(Scope::DeclScope);

    DeclTy *NamespcDecl =
      Actions.ActOnStartNamespaceDef(CurScope, IdentLoc, Ident, LBrace);

    while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof))
      ParseExternalDeclaration();

    // Leave the namespace scope.
    ExitScope();

    SourceLocation RBrace = MatchRHSPunctuation(tok::r_brace, LBrace);
    Actions.ActOnFinishNamespaceDef(NamespcDecl, RBrace);

    return NamespcDecl;

  } else {
    unsigned D = Ident ? diag::err_expected_lbrace :
                         diag::err_expected_ident_lbrace;
    Diag(Tok.getLocation(), D);
  }

  return 0;
}

/// ParseLinkage - We know that the current token is a string_literal
/// and just before that, that extern was seen.
///
///       linkage-specification: [C++ 7.5p2: dcl.link]
///         'extern' string-literal '{' declaration-seq[opt] '}'
///         'extern' string-literal declaration
///
Parser::DeclTy *Parser::ParseLinkage(unsigned Context) {
  assert(Tok.is(tok::string_literal) && "Not a stringliteral!");
  llvm::SmallVector<char, 8> LangBuffer;
  // LangBuffer is guaranteed to be big enough.
  LangBuffer.resize(Tok.getLength());
  const char *LangBufPtr = &LangBuffer[0];
  unsigned StrSize = PP.getSpelling(Tok, LangBufPtr);

  SourceLocation Loc = ConsumeStringToken();
  DeclTy *D = 0;
  SourceLocation LBrace, RBrace;

  if (Tok.isNot(tok::l_brace)) {
    D = ParseDeclaration(Context);
  } else {
    LBrace = ConsumeBrace();
    while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
      // FIXME capture the decls.
      D = ParseExternalDeclaration();
    }

    RBrace = MatchRHSPunctuation(tok::r_brace, LBrace);
  }

  if (!D)
    return 0;

  return Actions.ActOnLinkageSpec(Loc, LBrace, RBrace, LangBufPtr, StrSize, D);
}

/// ParseClassSpecifier - Parse a C++ class-specifier [C++ class] or
/// elaborated-type-specifier [C++ dcl.type.elab]; we can't tell which
/// until we reach the start of a definition or see a token that
/// cannot start a definition.
///
///       class-specifier: [C++ class]
///         class-head '{' member-specification[opt] '}'
///         class-head '{' member-specification[opt] '}' attributes[opt]
///       class-head:
///         class-key identifier[opt] base-clause[opt]
///         class-key nested-name-specifier identifier base-clause[opt]
///         class-key nested-name-specifier[opt] simple-template-id
///                          base-clause[opt]
/// [GNU]   class-key attributes[opt] identifier[opt] base-clause[opt]
/// [GNU]   class-key attributes[opt] nested-name-specifier
///                          identifier base-clause[opt]
/// [GNU]   class-key attributes[opt] nested-name-specifier[opt]
///                          simple-template-id base-clause[opt]
///       class-key:
///         'class'
///         'struct'
///         'union'
///
///       elaborated-type-specifier: [C++ dcl.type.elab]
///         class-key ::[opt] nested-name-specifier[opt] identifier
///         class-key ::[opt] nested-name-specifier[opt] 'template'[opt]
///                          simple-template-id
///
///  Note that the C++ class-specifier and elaborated-type-specifier,
///  together, subsume the C99 struct-or-union-specifier:
///
///       struct-or-union-specifier: [C99 6.7.2.1]
///         struct-or-union identifier[opt] '{' struct-contents '}'
///         struct-or-union identifier
/// [GNU]   struct-or-union attributes[opt] identifier[opt] '{' struct-contents
///                                                         '}' attributes[opt]
/// [GNU]   struct-or-union attributes[opt] identifier
///       struct-or-union:
///         'struct'
///         'union'
void Parser::ParseClassSpecifier(DeclSpec &DS) {
  assert((Tok.is(tok::kw_class) ||
          Tok.is(tok::kw_struct) ||
          Tok.is(tok::kw_union)) &&
         "Not a class specifier");
  DeclSpec::TST TagType =
    Tok.is(tok::kw_class) ? DeclSpec::TST_class :
    Tok.is(tok::kw_struct) ? DeclSpec::TST_struct :
    DeclSpec::TST_union;

  SourceLocation StartLoc = ConsumeToken();

  AttributeList *Attr = 0;
  // If attributes exist after tag, parse them.
  if (Tok.is(tok::kw___attribute))
    Attr = ParseAttributes();

  // FIXME: Parse the (optional) nested-name-specifier.

  // Parse the (optional) class name.
  // FIXME: Alternatively, parse a simple-template-id.
  IdentifierInfo *Name = 0;
  SourceLocation NameLoc;
  if (Tok.is(tok::identifier)) {
    Name = Tok.getIdentifierInfo();
    NameLoc = ConsumeToken();
  }

  // There are three options here.  If we have 'struct foo;', then
  // this is a forward declaration.  If we have 'struct foo {...' or
  // 'struct fo :...' then this is a definition. Otherwise we have
  // something like 'struct foo xyz', a reference.
  Action::TagKind TK;
  if (Tok.is(tok::l_brace) || (getLang().CPlusPlus && Tok.is(tok::colon)))
    TK = Action::TK_Definition;
  else if (Tok.is(tok::semi))
    TK = Action::TK_Declaration;
  else
    TK = Action::TK_Reference;

  if (!Name && TK != Action::TK_Definition) {
    // We have a declaration or reference to an anonymous class.
    Diag(StartLoc, diag::err_anon_type_definition,
         DeclSpec::getSpecifierName(TagType));

    // Skip the rest of this declarator, up until the comma or semicolon.
    SkipUntil(tok::comma, true);
    return;
  }

  // Parse the tag portion of this.
  DeclTy *TagDecl = Actions.ActOnTag(CurScope, TagType, TK, StartLoc, Name,
                                     NameLoc, Attr);

  // Parse the optional base clause (C++ only).
  if (getLang().CPlusPlus && Tok.is(tok::colon)) {
    ParseBaseClause(TagDecl);
  }

  // If there is a body, parse it and inform the actions module.
  if (Tok.is(tok::l_brace))
    ParseStructUnionBody(StartLoc, TagType, TagDecl);
  else if (TK == Action::TK_Definition) {
    // FIXME: Complain that we have a base-specifier list but no
    // definition.
    Diag(Tok.getLocation(), diag::err_expected_lbrace);
  }

  const char *PrevSpec = 0;
  if (DS.SetTypeSpecType(TagType, StartLoc, PrevSpec, TagDecl))
    Diag(StartLoc, diag::err_invalid_decl_spec_combination, PrevSpec);
}

/// ParseBaseClause - Parse the base-clause of a C++ class [C++ class.derived].
///
///       base-clause : [C++ class.derived]
///         ':' base-specifier-list
///       base-specifier-list:
///         base-specifier '...'[opt]
///         base-specifier-list ',' base-specifier '...'[opt]
void Parser::ParseBaseClause(DeclTy *ClassDecl)
{
  assert(Tok.is(tok::colon) && "Not a base clause");
  ConsumeToken();

  while (true) {
    // Parse a base-specifier.
    if (ParseBaseSpecifier(ClassDecl)) {
      // Skip the rest of this base specifier, up until the comma or
      // opening brace.
      SkipUntil(tok::comma, tok::l_brace);
    }

    // If the next token is a comma, consume it and keep reading
    // base-specifiers.
    if (Tok.isNot(tok::comma)) break;

    // Consume the comma.
    ConsumeToken();
  }
}

/// ParseBaseSpecifier - Parse a C++ base-specifier. A base-specifier is
/// one entry in the base class list of a class specifier, for example:
///    class foo : public bar, virtual private baz {
/// 'public bar' and 'virtual private baz' are each base-specifiers.
///
///       base-specifier: [C++ class.derived]
///         ::[opt] nested-name-specifier[opt] class-name
///         'virtual' access-specifier[opt] ::[opt] nested-name-specifier[opt]
///                        class-name
///         access-specifier 'virtual'[opt] ::[opt] nested-name-specifier[opt]
///                        class-name
bool Parser::ParseBaseSpecifier(DeclTy *ClassDecl)
{
  bool IsVirtual = false;
  SourceLocation StartLoc = Tok.getLocation();

  // Parse the 'virtual' keyword.
  if (Tok.is(tok::kw_virtual))  {
    ConsumeToken();
    IsVirtual = true;
  }

  // Parse an (optional) access specifier.
  AccessSpecifier Access = getAccessSpecifierIfPresent();
  if (Access)
    ConsumeToken();

  // Parse the 'virtual' keyword (again!), in case it came after the
  // access specifier.
  if (Tok.is(tok::kw_virtual))  {
    SourceLocation VirtualLoc = ConsumeToken();
    if (IsVirtual) {
      // Complain about duplicate 'virtual'
      Diag(VirtualLoc, diag::err_dup_virtual);
    }

    IsVirtual = true;
  }

  // FIXME: Parse optional '::' and optional nested-name-specifier.

  // Parse the class-name.
  // FIXME: Alternatively, parse a simple-template-id.
  if (Tok.isNot(tok::identifier)) {
    Diag(Tok.getLocation(), diag::err_expected_class_name);
    return true;
  }

  // We have an identifier; check whether it is actually a type.
  DeclTy *BaseType = Actions.isTypeName(*Tok.getIdentifierInfo(), CurScope);
  if (!BaseType) {
    Diag(Tok.getLocation(), diag::err_expected_class_name);
    return true;
  }

  // The location of the base class itself.
  SourceLocation BaseLoc = Tok.getLocation();

  // Find the complete source range for the base-specifier.
  SourceRange Range(StartLoc, BaseLoc);

  // Consume the identifier token (finally!).
  ConsumeToken();

  // Notify semantic analysis that we have parsed a complete
  // base-specifier.
  Actions.ActOnBaseSpecifier(ClassDecl, Range, IsVirtual, Access, BaseType,
                             BaseLoc);
  return false;
}

/// getAccessSpecifierIfPresent - Determine whether the next token is
/// a C++ access-specifier.
///
///       access-specifier: [C++ class.derived]
///         'private'
///         'protected'
///         'public'
AccessSpecifier Parser::getAccessSpecifierIfPresent() const
{
  switch (Tok.getKind()) {
  default: return AS_none;
  case tok::kw_private: return AS_private;
  case tok::kw_protected: return AS_protected;
  case tok::kw_public: return AS_public;
  }
}
<|endoftext|>


<commit_before>/*
 * Open Chinese Convert
 *
 * Copyright 2010-2014 BYVoid <byvoid@byvoid.com>
 *
 * 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.
 */

#pragma once

// Microsoft Visual C++ specific
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma warning(disable : 4251 4266 4350 4503 4512 4514 4710 4820)
#endif

#include <algorithm>
#include <fstream>
#include <iostream>
#include <list>
#include <map>
#include <memory>
#include <sstream>
#include <string>
#include <vector>

#include <cassert>
#include <cstddef>
#include <cstdio>
#include <cstring>
#include <ctime>

#include "Exception.hpp"
#include "Export.hpp"
#include "Optional.hpp"

using std::list;
using std::string;
using std::vector;

// Forward decalarations and alias
namespace opencc {
class BinaryDict;
class Config;
class Conversion;
class ConversionChain;
class Converter;
class DartsDict;
class Dict;
class DictEntry;
class DictGroup;
class Lexicon;
class MultiValueDictEntry;
class NoValueDictEntry;
class Segmentation;
class Segments;
class SerializableDict;
class SingleValueDictEntry;
class TextDict;
typedef std::shared_ptr<BinaryDict> BinaryDictPtr;
typedef std::shared_ptr<Conversion> ConversionPtr;
typedef std::shared_ptr<ConversionChain> ConversionChainPtr;
typedef std::shared_ptr<Converter> ConverterPtr;
typedef std::shared_ptr<DartsDict> DartsDictPtr;
typedef std::shared_ptr<Dict> DictPtr;
typedef std::shared_ptr<DictGroup> DictGroupPtr;
typedef std::shared_ptr<Lexicon> LexiconPtr;
typedef std::shared_ptr<Segmentation> SegmentationPtr;
typedef std::shared_ptr<Segments> SegmentsPtr;
typedef std::shared_ptr<SerializableDict> SerializableDictPtr;
typedef std::shared_ptr<TextDict> TextDictPtr;
}

#ifndef PKGDATADIR
const string PACKAGE_DATA_DIRECTORY = "";
#else // ifndef PKGDATADIR
const string PACKAGE_DATA_DIRECTORY = PKGDATADIR "/";
#endif // ifndef PKGDATADIR

#ifndef VERSION
#define VERSION "1.0.*"
#endif // ifndef VERSION
<commit_msg>Explicitly include <functional> for std::function template.<commit_after>/*
 * Open Chinese Convert
 *
 * Copyright 2010-2014 BYVoid <byvoid@byvoid.com>
 *
 * 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.
 */

#pragma once

// Microsoft Visual C++ specific
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma warning(disable : 4251 4266 4350 4503 4512 4514 4710 4820)
#endif

#include <algorithm>
#include <fstream>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <memory>
#include <sstream>
#include <string>
#include <vector>

#include <cassert>
#include <cstddef>
#include <cstdio>
#include <cstring>
#include <ctime>

#include "Exception.hpp"
#include "Export.hpp"
#include "Optional.hpp"

using std::list;
using std::string;
using std::vector;

// Forward decalarations and alias
namespace opencc {
class BinaryDict;
class Config;
class Conversion;
class ConversionChain;
class Converter;
class DartsDict;
class Dict;
class DictEntry;
class DictGroup;
class Lexicon;
class MultiValueDictEntry;
class NoValueDictEntry;
class Segmentation;
class Segments;
class SerializableDict;
class SingleValueDictEntry;
class TextDict;
typedef std::shared_ptr<BinaryDict> BinaryDictPtr;
typedef std::shared_ptr<Conversion> ConversionPtr;
typedef std::shared_ptr<ConversionChain> ConversionChainPtr;
typedef std::shared_ptr<Converter> ConverterPtr;
typedef std::shared_ptr<DartsDict> DartsDictPtr;
typedef std::shared_ptr<Dict> DictPtr;
typedef std::shared_ptr<DictGroup> DictGroupPtr;
typedef std::shared_ptr<Lexicon> LexiconPtr;
typedef std::shared_ptr<Segmentation> SegmentationPtr;
typedef std::shared_ptr<Segments> SegmentsPtr;
typedef std::shared_ptr<SerializableDict> SerializableDictPtr;
typedef std::shared_ptr<TextDict> TextDictPtr;
}

#ifndef PKGDATADIR
const string PACKAGE_DATA_DIRECTORY = "";
#else // ifndef PKGDATADIR
const string PACKAGE_DATA_DIRECTORY = PKGDATADIR "/";
#endif // ifndef PKGDATADIR

#ifndef VERSION
#define VERSION "1.0.*"
#endif // ifndef VERSION
<|endoftext|>


<commit_before>#include <iostream>

#include <CL/cl.hpp>
#include <EasyCl.h>
#include <fstream>

using namespace EasyCl;
using namespace std;

//////////////////////////////////////////////////////////////////////////
//DeviceManager								//
//////////////////////////////////////////////////////////////////////////

SourceCode::SourceCode(std::string path)
{
	load(path);
}

SourceCode::SourceCode()
{
}

int SourceCode::load(std::string path)
{
	isGood = false;

	std::ifstream file(path);
	if(file.good() == false)
	{
		cout << "Failed to load " << path << " ." << endl;
		return 0;
	}

	std::string sourceCode(
            std::istreambuf_iterator<char>(file),
            (std::istreambuf_iterator<char>()));

	source = cl::Program::Sources(1, std::make_pair(sourceCode.c_str(), sourceCode.length()+1));
	code = sourceCode;
	isGood = true;

	return 1;
}

bool SourceCode::good()
{
	return isGood;
}

//////////////////////////////////////////////////////////////////////////
//ComputeDevice								//
//////////////////////////////////////////////////////////////////////////

ComputeDevice::ComputeDevice(cl::Device dev,cl::Context con)
{
	device = dev;
	context = con;
	commandQueue = cl::CommandQueue(context, device);
}

//////////////////////////////////////////////////////////////////////////
//ComputeDeviceList							//
//////////////////////////////////////////////////////////////////////////

bool ComputeDevice::avliable()
{
	int inQueueComunt = commandQueue.getInfo<CL_QUEUE_REFERENCE_COUNT>();
	if(inQueueComunt == 0)
		return false;
	return true;
}

ComputeDevice* ComputeDeviceList::defaultDevice(cl_device_type deviceType)
{
	if(deviceType == CL_DEVICE_TYPE_ALL)
		return &devices[0];

	int deviceCount = devices.size();
	for(int i=0;i<deviceCount;i++)
	{
		cl_device_type type = devices[i].device.getInfo<CL_DEVICE_TYPE>();
		//NOTE: I shouldn't need deviceType == CL_DEVICE_TYPE_ALL here. Just for completeness.
		if((type & deviceType) != 0 || deviceType == CL_DEVICE_TYPE_ALL)
			return &devices[i];
	}

	return NULL;
}

ComputeDeviceList ComputeDeviceList::findDevice(std::string keyWord,cl_device_type deviceType)
{
	int deviceCount = devices.size();
	ComputeDeviceList list;
	for(int i=0;i<deviceCount;i++)
	{
		cl_device_type type = devices[i].device.getInfo<CL_DEVICE_TYPE>();
		if((type & deviceType) || deviceType == CL_DEVICE_TYPE_ALL)
			if(devices[i].device.getInfo<CL_DEVICE_NAME>().find(keyWord) != std::string::npos)
				list.devices.push_back(devices[i]);
	}

	return list;
}

//////////////////////////////////////////////////////////////////////////
//ComputeDevice								//
//////////////////////////////////////////////////////////////////////////

Software::Software(ComputeDevice* dev, SourceCode sou)
{
	//cl_int err = this->errorCode;
	device = dev;
	sourceCode = sou;

	program = cl::Program(device->context, sourceCode.source,&errorCode);
	if(errorCode != CL_SUCCESS)
	{
		cout << "Error while creating Software/cl::Program , code " << errorCode << endl;
		isGood = false;
	}
	else
		isGood = true;
}

Software::Software()
{
}

Software::~Software()
{
	int size = buffers.size();
	for(int i=0;i<size;i++)
		if(buffers[i] != NULL)
			delete buffers[i];
}

cl_int Software::build(string options)
{
	//HACK: This is a nasty way to make cl::Program::build() only build for one device
	std::vector<cl::Device> devs;
	devs.push_back(device->device);

	cl_int result = program.build(devs,options.c_str());
	if(result != CL_SUCCESS)
	{
		cl_int err = 0;
		//NOTE 2015/5/9 : nVidia OpenCL compiler SUCKS. the error message is mostly misleading.
		//Go for AMD or Intel if possible. Really.
		cout << program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(devs[0],&err) << endl;

		cout << "Error occured while compiling OpenCL program" << endl
			<< "Error Code: " << result << endl;
		return result;
	}
	return result;
}

bool Software::good()
{
	return isGood;
}

cl_int Software::getError()
{
	return errorCode;
}

cl_int Software::createBuffer(cl_mem_flags flags, size_t size, void* ptr,int& index)
{
	int buffersListSize = buffers.size();
	int emptyIndex = -1;
	for(int i=0;i<buffersListSize;i++)
		if(buffers[i] == NULL)
		{
			emptyIndex = i;
			break;
		}

	cl_int err = 0;
	cl::Buffer* newBuffer = new cl::Buffer(device->context,flags,size,ptr,&err);
	if(err != CL_SUCCESS)
	{
		cout << "Error creating cl::Buffer , code " << err << endl;
		return err;
	}
	if(ptr != NULL)
	{
		err = device->commandQueue.enqueueWriteBuffer(*newBuffer,CL_TRUE,0,size, ptr);
		if(err != CL_SUCCESS)
		{
			cout << "Error uploading data to device , code " << err << endl;
			delete newBuffer;
			return err;
		}
	}

	if(emptyIndex >= 0)
	{
		buffers[emptyIndex] = newBuffer;
		index = emptyIndex;
	}
	else
	{
		index = buffers.size();
		buffers.push_back(newBuffer);
	}
	return err;

}

void Software::releaseBuffer(int index)
{
	delete buffers[index];
	buffers[index] = NULL;
}

//////////////////////////////////////////////////////////////////////////
//DeviceManager								//
//////////////////////////////////////////////////////////////////////////

Kernel::Kernel(Software program, std::string funcName)
{
	software = program;
	cl_int err = 0;

	kernel = cl::Kernel(software.program, funcName.c_str(),&err);

	if(err != CL_SUCCESS)
	{
		cout << "Error creating kernel " << funcName << ", code " << err << endl;
		return;
	}

	int argCount = kernel.getInfo<CL_KERNEL_NUM_ARGS>();
	buffers = new cl::Buffer* [argCount];
	delProtect = new bool[argCount];
	for(int i=0;i<argCount;i++)
		buffers[i] = NULL, delProtect[i] = false;
}

Kernel::~Kernel()
{
	int argCount = kernel.getInfo<CL_KERNEL_NUM_ARGS>();
	for(int i=0;i<argCount;i++)
		if(buffers[i] != NULL && delProtect[i] == false)
		{
			//cout << this << " -> " << &buffers[i] << " : " << i << endl;
			delete buffers[i];
		}
	delete [] buffers;
	delete [] delProtect;
}

cl_int Kernel::setArgBuffer(int index, cl_mem_flags flags, size_t size, void* ptr)
{
	if(buffers[index] != NULL && delProtect[index] == false)
		delete buffers[index];

	cl_int err = 0;
	buffers[index] = new cl::Buffer(software.device->context,flags,size,ptr,&err);

	if(err != CL_SUCCESS)
	{
		cout << "Error creating cl::Buffer , code " << err << endl;
		return err;
	}

	if(ptr != NULL)
	{
		cl::Event event;
		err = software.device->commandQueue.enqueueWriteBuffer(*buffers[index],CL_TRUE,0,size, ptr,NULL,&event);
		if(err != CL_SUCCESS)
		{
			cout << "Error uploading data to device , code " << err << endl;
			//delete buffers[index];
			return err;
		}
		event.wait();
	}

	err = kernel.setArg(index, *buffers[index]);
	if(err != CL_SUCCESS)
	{
		cout << "Error set argumant to kernel , code " << err << endl;
		delete buffers[index];
		return err;
	}
	delProtect[index] = false;

	return err;
}

cl_int Kernel::setArg(int index, cl::Buffer& buf)
{
	if(buffers[index] != NULL && delProtect[index] == false)
		delete buffers[index];
	delProtect[index] = true;
	buffers[index] = &buf;
	cl_int err = kernel.setArg(index,buf);
	if(err != CL_SUCCESS)
	{
		cout << "Error set argumant to kernel , code " << err << endl;
		return err;
	}
	return err;
}

cl_int Kernel::enqueueNDRange(cl::NDRange offset, cl::NDRange global, cl::NDRange local)
{
	cl_int err = 0;
	cl::Event event;
	err = software.device->commandQueue.enqueueNDRangeKernel(kernel,offset,global,local,NULL,&event);
	if(err != CL_SUCCESS)
	{
		cout << "Error enqueuing NDRange Kernel, code " << err << endl;
		return err;
	}
	event.wait();
	return err;
}

cl_int Kernel::enqueueTask()
{
	cl_int err = 0;
	cl::Event event;
	err = software.device->commandQueue.enqueueTask(kernel,NULL,&event);
	if(err != CL_SUCCESS)
	{
		cout << "Error enqueuing Task, code " << err << endl;
		return err;
	}
	event.wait();
	return err;
}

cl_int Kernel::enqueueSPMD()
{
	cl_int err = 0;
	int preferWorkSizeBase =
		kernel.getWorkGroupInfo<CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE>
		(software.device->device);
	int maxComputeUnit = software.device->device.getInfo<CL_DEVICE_MAX_COMPUTE_UNITS>();
	int spmdSize = preferWorkSizeBase*maxComputeUnit;
	cl::NDRange global(spmdSize);
	cl::NDRange local(1);
	cl::Event event;
	err = software.device->commandQueue.enqueueNDRangeKernel(kernel,cl::NullRange,global,local,NULL,&event);
	if(err != CL_SUCCESS)
	{
		cout << "Error enqueuing NDRange Kernel, code " << err << endl;
		return err;
	}
	event.wait();
	return err;

}

cl_int Kernel::readBuffer(int index, size_t size, void* ptr)
{
	cl_int err = 0;
	err = software.device->commandQueue.enqueueReadBuffer(*buffers[index],CL_TRUE, 0, size, ptr);
	if(err != CL_SUCCESS)
	{
		cout << "Error reading bufer " << index << ", code " << err << endl;
		return err;
	}
	return err;
}

//////////////////////////////////////////////////////////////////////////
//DeviceManager								//
//////////////////////////////////////////////////////////////////////////

DeviceManager::DeviceManager()
{
	vector<cl::Platform> platforms;
	cl::Platform::get(&platforms);
	int platformCount = platforms.size();

	for(int i=0;i<platformCount;i++)
	{
		cl_context_properties properties[] =
			{ CL_CONTEXT_PLATFORM, (cl_context_properties)(platforms[i])(), 0};
		cl::Context context(CL_DEVICE_TYPE_ALL, properties);
		std::vector<cl::Device> platformDevice = context.getInfo<CL_CONTEXT_DEVICES>();
		ComputeDeviceList deviceList;
		int deviceCount = platformDevice.size();

		for(int j=0;j<deviceCount;j++)
		{
			ComputeDevice device(platformDevice[j],context);
			deviceList.devices.push_back(device);
		}

		deviceLists.push_back(deviceList);
	}
}

ComputeDevice* DeviceManager::defaultDevice(cl_device_type deviceType)
{
	int platformCount = deviceLists.size();

	for(int i=0;i<platformCount;i++)
	{
		ComputeDevice* device = deviceLists[i].defaultDevice(deviceType);
		if(device != NULL)
			return device;
	}

	return NULL;
}

ComputeDeviceList DeviceManager::findDevice(std::string keyWord,cl_device_type deviceType)
{
	ComputeDeviceList list;

	int platformCount = deviceLists.size();
	for(int i=0;i<platformCount;i++)
	{
		ComputeDeviceList found = deviceLists[i].findDevice(keyWord,deviceType);
		if(found.devices.size() != 0)
			list.devices.insert(list.devices.end(), found.devices.begin(), found.devices.end());
	}
	return list;
}
<commit_msg>fix code style<commit_after>#include <iostream>

#include <CL/cl.hpp>
#include <EasyCl.h>
#include <fstream>

using namespace EasyCl;
using namespace std;

//////////////////////////////////////////////////////////////////////////
//DeviceManager								//
//////////////////////////////////////////////////////////////////////////

SourceCode::SourceCode(string path)
{
	load(path);
}

SourceCode::SourceCode()
{
}

int SourceCode::load(string path)
{
	isGood = false;

	ifstream file(path);
	if(file.good() == false)
	{
		cout << "Failed to load " << path << " ." << endl;
		return 0;
	}

	string sourceCode(
            istreambuf_iterator<char>(file),
            (istreambuf_iterator<char>()));

	source = cl::Program::Sources(1, make_pair(sourceCode.c_str(), sourceCode.length()+1));
	code = sourceCode;
	isGood = true;

	return 1;
}

bool SourceCode::good()
{
	return isGood;
}

//////////////////////////////////////////////////////////////////////////
//ComputeDevice								//
//////////////////////////////////////////////////////////////////////////

ComputeDevice::ComputeDevice(cl::Device dev,cl::Context con)
{
	device = dev;
	context = con;
	commandQueue = cl::CommandQueue(context, device);
}

//////////////////////////////////////////////////////////////////////////
//ComputeDeviceList							//
//////////////////////////////////////////////////////////////////////////

bool ComputeDevice::avliable()
{
	int inQueueComunt = commandQueue.getInfo<CL_QUEUE_REFERENCE_COUNT>();
	if(inQueueComunt == 0)
		return false;
	return true;
}

ComputeDevice* ComputeDeviceList::defaultDevice(cl_device_type deviceType)
{
	if(deviceType == CL_DEVICE_TYPE_ALL)
		return &devices[0];

	int deviceCount = devices.size();
	for(int i=0;i<deviceCount;i++)
	{
		cl_device_type type = devices[i].device.getInfo<CL_DEVICE_TYPE>();
		//NOTE: I shouldn't need deviceType == CL_DEVICE_TYPE_ALL here. Just for completeness.
		if((type & deviceType) != 0 || deviceType == CL_DEVICE_TYPE_ALL)
			return &devices[i];
	}

	return NULL;
}

ComputeDeviceList ComputeDeviceList::findDevice(string keyWord,cl_device_type deviceType)
{
	int deviceCount = devices.size();
	ComputeDeviceList list;
	for(int i=0;i<deviceCount;i++)
	{
		cl_device_type type = devices[i].device.getInfo<CL_DEVICE_TYPE>();
		if((type & deviceType) || deviceType == CL_DEVICE_TYPE_ALL)
			if(devices[i].device.getInfo<CL_DEVICE_NAME>().find(keyWord) != string::npos)
				list.devices.push_back(devices[i]);
	}

	return list;
}

//////////////////////////////////////////////////////////////////////////
//ComputeDevice								//
//////////////////////////////////////////////////////////////////////////

Software::Software(ComputeDevice* dev, SourceCode sou)
{
	//cl_int err = this->errorCode;
	device = dev;
	sourceCode = sou;

	program = cl::Program(device->context, sourceCode.source,&errorCode);
	if(errorCode != CL_SUCCESS)
	{
		cout << "Error while creating Software/cl::Program , code " << errorCode << endl;
		isGood = false;
	}
	else
		isGood = true;
}

Software::Software()
{
}

Software::~Software()
{
	int size = buffers.size();
	for(int i=0;i<size;i++)
		if(buffers[i] != NULL)
			delete buffers[i];
}

cl_int Software::build(string options)
{
	//HACK: This is a nasty way to make cl::Program::build() only build for one device
	vector<cl::Device> devs;
	devs.push_back(device->device);

	cl_int result = program.build(devs,options.c_str());
	if(result != CL_SUCCESS)
	{
		cl_int err = 0;
		//NOTE 2015/5/9 : nVidia OpenCL compiler SUCKS. the error message is mostly misleading.
		//Go for AMD or Intel if possible. Really.
		cout << program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(devs[0],&err) << endl;

		cout << "Error occured while compiling OpenCL program" << endl
			<< "Error Code: " << result << endl;
		return result;
	}
	return result;
}

bool Software::good()
{
	return isGood;
}

cl_int Software::getError()
{
	return errorCode;
}

cl_int Software::createBuffer(cl_mem_flags flags, size_t size, void* ptr,int& index)
{
	int buffersListSize = buffers.size();
	int emptyIndex = -1;
	for(int i=0;i<buffersListSize;i++)
		if(buffers[i] == NULL)
		{
			emptyIndex = i;
			break;
		}

	cl_int err = 0;
	cl::Buffer* newBuffer = new cl::Buffer(device->context,flags,size,ptr,&err);
	if(err != CL_SUCCESS)
	{
		cout << "Error creating cl::Buffer , code " << err << endl;
		return err;
	}
	if(ptr != NULL)
	{
		err = device->commandQueue.enqueueWriteBuffer(*newBuffer,CL_TRUE,0,size, ptr);
		if(err != CL_SUCCESS)
		{
			cout << "Error uploading data to device , code " << err << endl;
			delete newBuffer;
			return err;
		}
	}

	if(emptyIndex >= 0)
	{
		buffers[emptyIndex] = newBuffer;
		index = emptyIndex;
	}
	else
	{
		index = buffers.size();
		buffers.push_back(newBuffer);
	}
	return err;

}

void Software::releaseBuffer(int index)
{
	delete buffers[index];
	buffers[index] = NULL;
}

//////////////////////////////////////////////////////////////////////////
//DeviceManager								//
//////////////////////////////////////////////////////////////////////////

Kernel::Kernel(Software program, string funcName)
{
	software = program;
	cl_int err = 0;

	kernel = cl::Kernel(software.program, funcName.c_str(),&err);

	if(err != CL_SUCCESS)
	{
		cout << "Error creating kernel " << funcName << ", code " << err << endl;
		return;
	}

	int argCount = kernel.getInfo<CL_KERNEL_NUM_ARGS>();
	buffers = new cl::Buffer* [argCount];
	delProtect = new bool[argCount];
	for(int i=0;i<argCount;i++)
		buffers[i] = NULL, delProtect[i] = false;
}

Kernel::~Kernel()
{
	int argCount = kernel.getInfo<CL_KERNEL_NUM_ARGS>();
	for(int i=0;i<argCount;i++)
		if(buffers[i] != NULL && delProtect[i] == false)
		{
			//cout << this << " -> " << &buffers[i] << " : " << i << endl;
			delete buffers[i];
		}
	delete [] buffers;
	delete [] delProtect;
}

cl_int Kernel::setArgBuffer(int index, cl_mem_flags flags, size_t size, void* ptr)
{
	if(buffers[index] != NULL && delProtect[index] == false)
		delete buffers[index];

	cl_int err = 0;
	buffers[index] = new cl::Buffer(software.device->context,flags,size,ptr,&err);

	if(err != CL_SUCCESS)
	{
		cout << "Error creating cl::Buffer , code " << err << endl;
		return err;
	}

	if(ptr != NULL)
	{
		cl::Event event;
		err = software.device->commandQueue.enqueueWriteBuffer(*buffers[index],CL_TRUE,0,size, ptr,NULL,&event);
		if(err != CL_SUCCESS)
		{
			cout << "Error uploading data to device , code " << err << endl;
			//delete buffers[index];
			return err;
		}
		event.wait();
	}

	err = kernel.setArg(index, *buffers[index]);
	if(err != CL_SUCCESS)
	{
		cout << "Error set argumant to kernel , code " << err << endl;
		delete buffers[index];
		return err;
	}
	delProtect[index] = false;

	return err;
}

cl_int Kernel::setArg(int index, cl::Buffer& buf)
{
	if(buffers[index] != NULL && delProtect[index] == false)
		delete buffers[index];
	delProtect[index] = true;
	buffers[index] = &buf;
	cl_int err = kernel.setArg(index,buf);
	if(err != CL_SUCCESS)
	{
		cout << "Error set argumant to kernel , code " << err << endl;
		return err;
	}
	return err;
}

cl_int Kernel::enqueueNDRange(cl::NDRange offset, cl::NDRange global, cl::NDRange local)
{
	cl_int err = 0;
	cl::Event event;
	err = software.device->commandQueue.enqueueNDRangeKernel(kernel,offset,global,local,NULL,&event);
	if(err != CL_SUCCESS)
	{
		cout << "Error enqueuing NDRange Kernel, code " << err << endl;
		return err;
	}
	event.wait();
	return err;
}

cl_int Kernel::enqueueTask()
{
	cl_int err = 0;
	cl::Event event;
	err = software.device->commandQueue.enqueueTask(kernel,NULL,&event);
	if(err != CL_SUCCESS)
	{
		cout << "Error enqueuing Task, code " << err << endl;
		return err;
	}
	event.wait();
	return err;
}

cl_int Kernel::enqueueSPMD()
{
	cl_int err = 0;
	int preferWorkSizeBase =
		kernel.getWorkGroupInfo<CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE>
		(software.device->device);
	int maxComputeUnit = software.device->device.getInfo<CL_DEVICE_MAX_COMPUTE_UNITS>();
	int spmdSize = preferWorkSizeBase*maxComputeUnit;
	cl::NDRange global(spmdSize);
	cl::NDRange local(1);
	cl::Event event;
	err = software.device->commandQueue.enqueueNDRangeKernel(kernel,cl::NullRange,global,local,NULL,&event);
	if(err != CL_SUCCESS)
	{
		cout << "Error enqueuing NDRange Kernel, code " << err << endl;
		return err;
	}
	event.wait();
	return err;

}

cl_int Kernel::readBuffer(int index, size_t size, void* ptr)
{
	cl_int err = 0;
	err = software.device->commandQueue.enqueueReadBuffer(*buffers[index],CL_TRUE, 0, size, ptr);
	if(err != CL_SUCCESS)
	{
		cout << "Error reading bufer " << index << ", code " << err << endl;
		return err;
	}
	return err;
}

//////////////////////////////////////////////////////////////////////////
//DeviceManager								//
//////////////////////////////////////////////////////////////////////////

DeviceManager::DeviceManager()
{
	vector<cl::Platform> platforms;
	cl::Platform::get(&platforms);
	int platformCount = platforms.size();

	for(int i=0;i<platformCount;i++)
	{
		cl_context_properties properties[] =
			{ CL_CONTEXT_PLATFORM, (cl_context_properties)(platforms[i])(), 0};
		cl::Context context(CL_DEVICE_TYPE_ALL, properties);
		vector<cl::Device> platformDevice = context.getInfo<CL_CONTEXT_DEVICES>();
		ComputeDeviceList deviceList;
		int deviceCount = platformDevice.size();

		for(int j=0;j<deviceCount;j++)
		{
			ComputeDevice device(platformDevice[j],context);
			deviceList.devices.push_back(device);
		}

		deviceLists.push_back(deviceList);
	}
}

ComputeDevice* DeviceManager::defaultDevice(cl_device_type deviceType)
{
	int platformCount = deviceLists.size();

	for(int i=0;i<platformCount;i++)
	{
		ComputeDevice* device = deviceLists[i].defaultDevice(deviceType);
		if(device != NULL)
			return device;
	}

	return NULL;
}

ComputeDeviceList DeviceManager::findDevice(string keyWord,cl_device_type deviceType)
{
	ComputeDeviceList list;

	int platformCount = deviceLists.size();
	for(int i=0;i<platformCount;i++)
	{
		ComputeDeviceList found = deviceLists[i].findDevice(keyWord,deviceType);
		if(found.devices.size() != 0)
			list.devices.insert(list.devices.end(), found.devices.begin(), found.devices.end());
	}
	return list;
}
<|endoftext|>