<commit_before>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// A general interface for filtering and only acting on classes in Chromium C++
// code.

#include "ChromeClassTester.h"

#include <sys/param.h>

#include "clang/Basic/FileManager.h"

using namespace clang;

namespace {

bool starts_with(const std::string& one, const std::string& two) {
  return one.substr(0, two.size()) == two;
}

bool ends_with(const std::string& one, const std::string& two) {
  if (two.size() > one.size())
    return false;

  return one.substr(one.size() - two.size(), two.size()) == two;
}

}  // namespace

ChromeClassTester::ChromeClassTester(CompilerInstance& instance)
    : instance_(instance),
      diagnostic_(instance.getDiagnostics()) {
  FigureOutSrcRoot();
  BuildBannedLists();
}

void ChromeClassTester::FigureOutSrcRoot() {
  char c_cwd[MAXPATHLEN];
  if (getcwd(c_cwd, MAXPATHLEN) > 0) {
    size_t pos = 1;
    std::string cwd = c_cwd;

    // Add a trailing '/' because the search below requires it.
    if (cwd[cwd.size() - 1] != '/')
      cwd += '/';

    // Search the directory tree downwards until we find a path that contains
    // "build/common.gypi" and assume that that is our srcroot.
    size_t next_slash = cwd.find('/', pos);
    while (next_slash != std::string::npos) {
      next_slash++;
      std::string candidate = cwd.substr(0, next_slash);

      if (ends_with(candidate, "src/")) {
        std::string common = candidate + "build/common.gypi";
        if (access(common.c_str(), F_OK) != -1) {
          src_root_ = candidate;
          break;
        }
      }

      pos = next_slash;
      next_slash = cwd.find('/', pos);
    }
  }

  if (src_root_.empty()) {
    unsigned id = diagnostic().getCustomDiagID(
        Diagnostic::Error,
        "WARNING: Can't figure out srcroot!\n");
    diagnostic().Report(id);
  }
}

void ChromeClassTester::BuildBannedLists() {
  banned_namespaces_.push_back("std");
  banned_namespaces_.push_back("__gnu_cxx");

  banned_directories_.push_back("third_party");
  banned_directories_.push_back("native_client");
  banned_directories_.push_back("breakpad");
  banned_directories_.push_back("courgette");
  banned_directories_.push_back("ppapi");
  banned_directories_.push_back("/usr");
  banned_directories_.push_back("testing");
  banned_directories_.push_back("googleurl");
  banned_directories_.push_back("v8");
  banned_directories_.push_back("sdch");

  // Don't check autogenerated headers.
  banned_directories_.push_back("out");
  banned_directories_.push_back("llvm");
  banned_directories_.push_back("xcodebuild");

  // You are standing in a mazy of twisty dependencies, all resolved by
  // putting everything in the header.
  banned_directories_.push_back("chrome/test/automation");

  // Used in really low level threading code that probably shouldn't be out of
  // lined.
  ignored_record_names_.push_back("ThreadLocalBoolean");

  // A complicated pickle derived struct that is all packed integers.
  ignored_record_names_.push_back("Header");

  // Part of the GPU system that uses multiple included header
  // weirdness. Never getting this right.
  ignored_record_names_.push_back("Validators");

  // RAII class that's simple enough (media/base/callback.h).
  ignored_record_names_.push_back("AutoTaskRunner");
  ignored_record_names_.push_back("AutoCallbackRunner");

  // Has a UNIT_TEST only constructor. Isn't *terribly* complex...
  ignored_record_names_.push_back("AutocompleteController");
  ignored_record_names_.push_back("HistoryURLProvider");

  // Because of chrome frame
  ignored_record_names_.push_back("ReliabilityTestSuite");

  // Used over in the net unittests. A large enough bundle of integers with 1
  // non-pod class member. Probably harmless.
  ignored_record_names_.push_back("MockTransaction");

  // Used heavily in app_unittests and once in views_unittests. Fixing this
  // isn't worth the overhead of an additional library.
  ignored_record_names_.push_back("TestAnimationDelegate");

  // Part of our public interface that nacl and friends use. (Arguably, this
  // should mean that this is a higher priority but fixing this looks hard.)
  ignored_record_names_.push_back("PluginVersionInfo");
}

ChromeClassTester::~ChromeClassTester() {}

void ChromeClassTester::HandleTagDeclDefinition(TagDecl* tag) {
  // We handle class types here where we have semantic information. We can only
  // check structs/classes/enums here, but we get a bunch of nice semantic
  // information instead of just parsing information.

  if (CXXRecordDecl* record = dyn_cast<CXXRecordDecl>(tag)) {
    // If this is a POD or a class template or a type dependent on a
    // templated class, assume there's no ctor/dtor/virtual method
    // optimization that we can do.
    if (record->isPOD() ||
        record->getDescribedClassTemplate() ||
        record->getTemplateSpecializationKind() ||
        record->isDependentType())
      return;

    if (InBannedNamespace(record))
      return;

    SourceLocation record_location = record->getInnerLocStart();
    if (InBannedDirectory(record_location))
      return;

    // We sadly need to maintain a blacklist of types that violate these
    // rules, but do so for good reason or due to limitations of this
    // checker (i.e., we don't handle extern templates very well).
    std::string base_name = record->getNameAsString();
    if (IsIgnoredType(base_name))
      return;

    // We ignore all classes that end with "Matcher" because they're probably
    // GMock artifacts.
    if (ends_with(base_name, "Matcher"))
        return;

    CheckChromeClass(record_location, record);
  }
}

void ChromeClassTester::HandleTranslationUnit(clang::ASTContext& ctx) {
  RecursivelyCheckTopLevels(ctx.getTranslationUnitDecl());
}

void ChromeClassTester::RecursivelyCheckTopLevels(Decl* d) {
  // Unlike HandleTagDeclDefinition, we can only rely on having parsing
  // information here. We absoluetly shouldn't check that any semantic data
  // here because we will assert.

  Decl::Kind kind = d->getKind();
  if (kind == Decl::UsingDirective) {
    UsingDirectiveDecl* record = cast<UsingDirectiveDecl>(d);
    SourceLocation record_location = record->getLocation();
    if (!InBannedDirectory(record_location))
      CheckChromeUsingDirective(record_location, record);
  }

  // If this is a DeclContext that isn't a function/method, recurse.
  if (DeclContext* context = dyn_cast<DeclContext>(d)) {
    if (context->isFileContext()) {
      for (DeclContext::decl_iterator it = context->decls_begin();
           it != context->decls_end(); ++it) {
        RecursivelyCheckTopLevels(*it);
      }
    }
  }
}

void ChromeClassTester::emitWarning(SourceLocation loc, const char* raw_error) {
  FullSourceLoc full(loc, instance().getSourceManager());
  std::string err;
  err = "[chromium-style] ";
  err += raw_error;
  Diagnostic::Level level =
      diagnostic().getWarningsAsErrors() ?
      Diagnostic::Error :
      Diagnostic::Warning;
  unsigned id = diagnostic().getCustomDiagID(level, err);
  DiagnosticBuilder B = diagnostic().Report(full, id);
}

bool ChromeClassTester::InTestingNamespace(Decl* record) {
  return GetNamespace(record).find("testing") != std::string::npos;
}

bool ChromeClassTester::InBannedNamespace(Decl* record) {
  std::string n = GetNamespace(record);
  if (n != "") {
    return std::find(banned_namespaces_.begin(), banned_namespaces_.end(), n)
        != banned_namespaces_.end();
  }

  return false;
}

std::string ChromeClassTester::GetNamespace(Decl* record) {
  return GetNamespaceImpl(record->getDeclContext(), "");
}

std::string ChromeClassTester::GetNamespaceImpl(const DeclContext* context,
                                                std::string candidate) {
  switch (context->getDeclKind()) {
    case Decl::TranslationUnit: {
      return candidate;
    }
    case Decl::Namespace: {
      const NamespaceDecl* decl = dyn_cast<NamespaceDecl>(context);
      std::string name_str;
      llvm::raw_string_ostream OS(name_str);
      if (decl->isAnonymousNamespace())
        OS << "<anonymous namespace>";
      else
        OS << decl;
      return GetNamespaceImpl(context->getParent(),
                              OS.str());
    }
    default: {
      return GetNamespaceImpl(context->getParent(), candidate);
    }
  }
}

bool ChromeClassTester::InBannedDirectory(SourceLocation loc) {
  const SourceManager &SM = instance_.getSourceManager();
  SourceLocation spelling_location = SM.getSpellingLoc(loc);
  PresumedLoc ploc = SM.getPresumedLoc(spelling_location);
  std::string buffer_name;
  if (ploc.isInvalid()) {
    // If we're in an invalid location, we're looking at things that aren't
    // actually stated in the source; treat this as a banned location instead
    // of going through our full lookup process.
    return true;
  } else {
    std::string b = ploc.getFilename();

    // We need to special case scratch space; which is where clang does its
    // macro expansion. We explicitly want to allow people to do otherwise bad
    // things through macros that were defined due to third party libraries.
    if (b == "<scratch space>")
      return true;

    // Don't complain about these things in implementation files.
    if (ends_with(b, ".cc") || ends_with(b, ".cpp") || ends_with(b, ".mm")) {
      return true;
    }

    // Don't complain about autogenerated protobuf files.
    if (ends_with(b, ".pb.h")) {
      return true;
    }

    // We need to munge the paths so that they are relative to the repository
    // srcroot. We first resolve the symlinktastic relative path and then
    // remove our known srcroot from it if needed.
    char resolvedPath[MAXPATHLEN];
    if (realpath(b.c_str(), resolvedPath)) {
      std::string resolved = resolvedPath;
      if (starts_with(resolved, src_root_)) {
        b = resolved.substr(src_root_.size());
      }
    }

    for (std::vector<std::string>::const_iterator it =
             banned_directories_.begin();
         it != banned_directories_.end(); ++it) {
      if (starts_with(b, *it)) {
        return true;
      }
    }
  }

  return false;
}

bool ChromeClassTester::IsIgnoredType(const std::string& base_name) {
  for (std::vector<std::string>::const_iterator it =
           ignored_record_names_.begin();
       it != ignored_record_names_.end(); ++it) {
    if (base_name == *it)
      return true;
  }

  return false;
}
<commit_msg>Fix clang bustage on Mac by blacklisting /Developer<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// A general interface for filtering and only acting on classes in Chromium C++
// code.

#include "ChromeClassTester.h"

#include <sys/param.h>

#include "clang/Basic/FileManager.h"

using namespace clang;

namespace {

bool starts_with(const std::string& one, const std::string& two) {
  return one.substr(0, two.size()) == two;
}

bool ends_with(const std::string& one, const std::string& two) {
  if (two.size() > one.size())
    return false;

  return one.substr(one.size() - two.size(), two.size()) == two;
}

}  // namespace

ChromeClassTester::ChromeClassTester(CompilerInstance& instance)
    : instance_(instance),
      diagnostic_(instance.getDiagnostics()) {
  FigureOutSrcRoot();
  BuildBannedLists();
}

void ChromeClassTester::FigureOutSrcRoot() {
  char c_cwd[MAXPATHLEN];
  if (getcwd(c_cwd, MAXPATHLEN) > 0) {
    size_t pos = 1;
    std::string cwd = c_cwd;

    // Add a trailing '/' because the search below requires it.
    if (cwd[cwd.size() - 1] != '/')
      cwd += '/';

    // Search the directory tree downwards until we find a path that contains
    // "build/common.gypi" and assume that that is our srcroot.
    size_t next_slash = cwd.find('/', pos);
    while (next_slash != std::string::npos) {
      next_slash++;
      std::string candidate = cwd.substr(0, next_slash);

      if (ends_with(candidate, "src/")) {
        std::string common = candidate + "build/common.gypi";
        if (access(common.c_str(), F_OK) != -1) {
          src_root_ = candidate;
          break;
        }
      }

      pos = next_slash;
      next_slash = cwd.find('/', pos);
    }
  }

  if (src_root_.empty()) {
    unsigned id = diagnostic().getCustomDiagID(
        Diagnostic::Error,
        "WARNING: Can't figure out srcroot!\n");
    diagnostic().Report(id);
  }
}

void ChromeClassTester::BuildBannedLists() {
  banned_namespaces_.push_back("std");
  banned_namespaces_.push_back("__gnu_cxx");

  banned_directories_.push_back("third_party");
  banned_directories_.push_back("native_client");
  banned_directories_.push_back("breakpad");
  banned_directories_.push_back("courgette");
  banned_directories_.push_back("ppapi");
  banned_directories_.push_back("testing");
  banned_directories_.push_back("googleurl");
  banned_directories_.push_back("v8");
  banned_directories_.push_back("sdch");

  // Don't check autogenerated headers.
  banned_directories_.push_back("out");
  banned_directories_.push_back("llvm");
  banned_directories_.push_back("xcodebuild");

  // You are standing in a mazy of twisty dependencies, all resolved by
  // putting everything in the header.
  banned_directories_.push_back("chrome/test/automation");

  // Don't check system headers.
  banned_directories_.push_back("/usr");
  banned_directories_.push_back("/Developer");

  // Used in really low level threading code that probably shouldn't be out of
  // lined.
  ignored_record_names_.push_back("ThreadLocalBoolean");

  // A complicated pickle derived struct that is all packed integers.
  ignored_record_names_.push_back("Header");

  // Part of the GPU system that uses multiple included header
  // weirdness. Never getting this right.
  ignored_record_names_.push_back("Validators");

  // RAII class that's simple enough (media/base/callback.h).
  ignored_record_names_.push_back("AutoTaskRunner");
  ignored_record_names_.push_back("AutoCallbackRunner");

  // Has a UNIT_TEST only constructor. Isn't *terribly* complex...
  ignored_record_names_.push_back("AutocompleteController");
  ignored_record_names_.push_back("HistoryURLProvider");

  // Because of chrome frame
  ignored_record_names_.push_back("ReliabilityTestSuite");

  // Used over in the net unittests. A large enough bundle of integers with 1
  // non-pod class member. Probably harmless.
  ignored_record_names_.push_back("MockTransaction");

  // Used heavily in app_unittests and once in views_unittests. Fixing this
  // isn't worth the overhead of an additional library.
  ignored_record_names_.push_back("TestAnimationDelegate");

  // Part of our public interface that nacl and friends use. (Arguably, this
  // should mean that this is a higher priority but fixing this looks hard.)
  ignored_record_names_.push_back("PluginVersionInfo");
}

ChromeClassTester::~ChromeClassTester() {}

void ChromeClassTester::HandleTagDeclDefinition(TagDecl* tag) {
  // We handle class types here where we have semantic information. We can only
  // check structs/classes/enums here, but we get a bunch of nice semantic
  // information instead of just parsing information.

  if (CXXRecordDecl* record = dyn_cast<CXXRecordDecl>(tag)) {
    // If this is a POD or a class template or a type dependent on a
    // templated class, assume there's no ctor/dtor/virtual method
    // optimization that we can do.
    if (record->isPOD() ||
        record->getDescribedClassTemplate() ||
        record->getTemplateSpecializationKind() ||
        record->isDependentType())
      return;

    if (InBannedNamespace(record))
      return;

    SourceLocation record_location = record->getInnerLocStart();
    if (InBannedDirectory(record_location))
      return;

    // We sadly need to maintain a blacklist of types that violate these
    // rules, but do so for good reason or due to limitations of this
    // checker (i.e., we don't handle extern templates very well).
    std::string base_name = record->getNameAsString();
    if (IsIgnoredType(base_name))
      return;

    // We ignore all classes that end with "Matcher" because they're probably
    // GMock artifacts.
    if (ends_with(base_name, "Matcher"))
        return;

    CheckChromeClass(record_location, record);
  }
}

void ChromeClassTester::HandleTranslationUnit(clang::ASTContext& ctx) {
  RecursivelyCheckTopLevels(ctx.getTranslationUnitDecl());
}

void ChromeClassTester::RecursivelyCheckTopLevels(Decl* d) {
  // Unlike HandleTagDeclDefinition, we can only rely on having parsing
  // information here. We absoluetly shouldn't check that any semantic data
  // here because we will assert.

  Decl::Kind kind = d->getKind();
  if (kind == Decl::UsingDirective) {
    UsingDirectiveDecl* record = cast<UsingDirectiveDecl>(d);
    SourceLocation record_location = record->getLocation();
    if (!InBannedDirectory(record_location))
      CheckChromeUsingDirective(record_location, record);
  }

  // If this is a DeclContext that isn't a function/method, recurse.
  if (DeclContext* context = dyn_cast<DeclContext>(d)) {
    if (context->isFileContext()) {
      for (DeclContext::decl_iterator it = context->decls_begin();
           it != context->decls_end(); ++it) {
        RecursivelyCheckTopLevels(*it);
      }
    }
  }
}

void ChromeClassTester::emitWarning(SourceLocation loc, const char* raw_error) {
  FullSourceLoc full(loc, instance().getSourceManager());
  std::string err;
  err = "[chromium-style] ";
  err += raw_error;
  Diagnostic::Level level =
      diagnostic().getWarningsAsErrors() ?
      Diagnostic::Error :
      Diagnostic::Warning;
  unsigned id = diagnostic().getCustomDiagID(level, err);
  DiagnosticBuilder B = diagnostic().Report(full, id);
}

bool ChromeClassTester::InTestingNamespace(Decl* record) {
  return GetNamespace(record).find("testing") != std::string::npos;
}

bool ChromeClassTester::InBannedNamespace(Decl* record) {
  std::string n = GetNamespace(record);
  if (n != "") {
    return std::find(banned_namespaces_.begin(), banned_namespaces_.end(), n)
        != banned_namespaces_.end();
  }

  return false;
}

std::string ChromeClassTester::GetNamespace(Decl* record) {
  return GetNamespaceImpl(record->getDeclContext(), "");
}

std::string ChromeClassTester::GetNamespaceImpl(const DeclContext* context,
                                                std::string candidate) {
  switch (context->getDeclKind()) {
    case Decl::TranslationUnit: {
      return candidate;
    }
    case Decl::Namespace: {
      const NamespaceDecl* decl = dyn_cast<NamespaceDecl>(context);
      std::string name_str;
      llvm::raw_string_ostream OS(name_str);
      if (decl->isAnonymousNamespace())
        OS << "<anonymous namespace>";
      else
        OS << decl;
      return GetNamespaceImpl(context->getParent(),
                              OS.str());
    }
    default: {
      return GetNamespaceImpl(context->getParent(), candidate);
    }
  }
}

bool ChromeClassTester::InBannedDirectory(SourceLocation loc) {
  const SourceManager &SM = instance_.getSourceManager();
  SourceLocation spelling_location = SM.getSpellingLoc(loc);
  PresumedLoc ploc = SM.getPresumedLoc(spelling_location);
  std::string buffer_name;
  if (ploc.isInvalid()) {
    // If we're in an invalid location, we're looking at things that aren't
    // actually stated in the source; treat this as a banned location instead
    // of going through our full lookup process.
    return true;
  } else {
    std::string b = ploc.getFilename();

    // We need to special case scratch space; which is where clang does its
    // macro expansion. We explicitly want to allow people to do otherwise bad
    // things through macros that were defined due to third party libraries.
    if (b == "<scratch space>")
      return true;

    // Don't complain about these things in implementation files.
    if (ends_with(b, ".cc") || ends_with(b, ".cpp") || ends_with(b, ".mm")) {
      return true;
    }

    // Don't complain about autogenerated protobuf files.
    if (ends_with(b, ".pb.h")) {
      return true;
    }

    // We need to munge the paths so that they are relative to the repository
    // srcroot. We first resolve the symlinktastic relative path and then
    // remove our known srcroot from it if needed.
    char resolvedPath[MAXPATHLEN];
    if (realpath(b.c_str(), resolvedPath)) {
      std::string resolved = resolvedPath;
      if (starts_with(resolved, src_root_)) {
        b = resolved.substr(src_root_.size());
      }
    }

    for (std::vector<std::string>::const_iterator it =
             banned_directories_.begin();
         it != banned_directories_.end(); ++it) {
      if (starts_with(b, *it)) {
        return true;
      }
    }
  }

  return false;
}

bool ChromeClassTester::IsIgnoredType(const std::string& base_name) {
  for (std::vector<std::string>::const_iterator it =
           ignored_record_names_.begin();
       it != ignored_record_names_.end(); ++it) {
    if (base_name == *it)
      return true;
  }

  return false;
}
<|endoftext|>


<commit_before>// Copyright 2006-2012, the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//    * Redistributions of source code must retain the above copyright
//      notice, this list of conditions and the following disclaimer.
//    * Redistributions in binary form must reproduce the above
//      copyright notice, this list of conditions and the following
//      disclaimer in the documentation and/or other materials provided
//      with the distribution.
//    * Neither the name of Google Inc. nor the names of its
//      contributors may be used to endorse or promote products derived
//      from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Modifications as part of cpp-ethereum under the following license:
//
// cpp-ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// cpp-ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.

#include <map>
#include <libsolidity/parsing/Token.h>
#include <boost/range/iterator_range.hpp>

using namespace std;

namespace dev
{
namespace solidity
{

void ElementaryTypeNameToken::assertDetails(Token::Value _baseType, unsigned const& _first, unsigned const& _second)
{
	solAssert(Token::isElementaryTypeName(_baseType), "");
	if (_baseType == Token::BytesM)
	{
		solAssert(_second == 0, "There should not be a second size argument to type bytesM.");
		solAssert(_first <= 32, "No elementary type bytes" + to_string(_first) + ".");
	}
	else if (_baseType == Token::UIntM || _baseType == Token::IntM)
	{
		solAssert(_second == 0, "There should not be a second size argument to type " + string(Token::toString(_baseType)) + ".");
		solAssert(
			_first <= 256 && _first % 8 == 0,
			"No elementary type " + string(Token::toString(_baseType)) + to_string(_first) + "."
		);
	}
	else if (_baseType == Token::UFixedMxN || _baseType == Token::FixedMxN)
	{
		solAssert(
			_first + _second <= 256 && _first % 8 == 0 && _second % 8 == 0,
			"No elementary type " + string(Token::toString(_baseType)) + to_string(_first) + "x" + to_string(_second) + "."
		);
	}
	m_token = _baseType;
	m_firstNumber = _first;
	m_secondNumber = _second;
}

#define T(name, string, precedence) #name,
char const* const Token::m_name[NUM_TOKENS] =
{
	TOKEN_LIST(T, T)
};
#undef T

#define T(name, string, precedence) string,
char const* const Token::m_string[NUM_TOKENS] =
{
	TOKEN_LIST(T, T)
};
#undef T

#define T(name, string, precedence) precedence,
int8_t const Token::m_precedence[NUM_TOKENS] =
{
	TOKEN_LIST(T, T)
};
#undef T

#define KT(a, b, c) 'T',
#define KK(a, b, c) 'K',
char const Token::m_tokenType[] =
{
	TOKEN_LIST(KT, KK)
};
int Token::parseSize(string::const_iterator _begin, string::const_iterator _end)
{
	try
	{
		unsigned int m = boost::lexical_cast<int>(boost::make_iterator_range(_begin, _end));
		return m;
	}
	catch(boost::bad_lexical_cast const&)
	{
		return -1;
	}
}
tuple<Token::Value, unsigned int, unsigned int> Token::fromIdentifierOrKeyword(string const& _literal)
{
	auto positionM = find_if(_literal.begin(), _literal.end(), ::isdigit);
	if (positionM != _literal.end())
	{
		string baseType(_literal.begin(), positionM);
		auto positionX = find_if_not(positionM, _literal.end(), ::isdigit);
		int m = parseSize(positionM, positionX);
		Token::Value keyword = keywordByName(baseType);
		if (keyword == Token::Bytes)
		{
			if (0 < m && m <= 32 && positionX == _literal.end())
				return make_tuple(Token::BytesM, m, 0);
		}
		else if (keyword == Token::UInt || keyword == Token::Int)
		{
			if (0 < m && m <= 256 && m % 8 == 0 && positionX == _literal.end())
			{
				if (keyword == Token::UInt)
					return make_tuple(Token::UIntM, m, 0);
				else
					return make_tuple(Token::IntM, m, 0);
			}
		}
		else if (keyword == Token::UFixed || keyword == Token::Fixed)
		{
			if (
				positionM < positionX &&
				positionX < _literal.end() &&
				*positionX == 'x' &&
				all_of(positionX + 1, _literal.end(), ::isdigit)
			) {
				int n = parseSize(positionX + 1, _literal.end());
				if (
					m + n > 0 &&
					m + n <= 256 &&
					m % 8 == 0 &&
					n % 8 == 0
				) {
					if (keyword == Token::UFixed)
						return make_tuple(Token::UFixedMxN, m, n);
					else
						return make_tuple(Token::FixedMxN, m, n);
				}
			}
		}
		return make_tuple(Token::Identifier, 0, 0);
	}
	return make_tuple(keywordByName(_literal), 0, 0);
}
Token::Value Token::keywordByName(string const& _name)
{
	// The following macros are used inside TOKEN_LIST and cause non-keyword tokens to be ignored
	// and keywords to be put inside the keywords variable.
#define KEYWORD(name, string, precedence) {string, Token::name},
#define TOKEN(name, string, precedence)
	static const map<string, Token::Value> keywords({TOKEN_LIST(TOKEN, KEYWORD)});
#undef KEYWORD
#undef TOKEN
	auto it = keywords.find(_name);
	return it == keywords.end() ? Token::Identifier : it->second;
}

#undef KT
#undef KK
}
}
<commit_msg>change lexical cast to unsigned int<commit_after>// Copyright 2006-2012, the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//    * Redistributions of source code must retain the above copyright
//      notice, this list of conditions and the following disclaimer.
//    * Redistributions in binary form must reproduce the above
//      copyright notice, this list of conditions and the following
//      disclaimer in the documentation and/or other materials provided
//      with the distribution.
//    * Neither the name of Google Inc. nor the names of its
//      contributors may be used to endorse or promote products derived
//      from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Modifications as part of cpp-ethereum under the following license:
//
// cpp-ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// cpp-ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.

#include <map>
#include <libsolidity/parsing/Token.h>
#include <boost/range/iterator_range.hpp>

using namespace std;

namespace dev
{
namespace solidity
{

void ElementaryTypeNameToken::assertDetails(Token::Value _baseType, unsigned const& _first, unsigned const& _second)
{
	solAssert(Token::isElementaryTypeName(_baseType), "");
	if (_baseType == Token::BytesM)
	{
		solAssert(_second == 0, "There should not be a second size argument to type bytesM.");
		solAssert(_first <= 32, "No elementary type bytes" + to_string(_first) + ".");
	}
	else if (_baseType == Token::UIntM || _baseType == Token::IntM)
	{
		solAssert(_second == 0, "There should not be a second size argument to type " + string(Token::toString(_baseType)) + ".");
		solAssert(
			_first <= 256 && _first % 8 == 0,
			"No elementary type " + string(Token::toString(_baseType)) + to_string(_first) + "."
		);
	}
	else if (_baseType == Token::UFixedMxN || _baseType == Token::FixedMxN)
	{
		solAssert(
			_first + _second <= 256 && _first % 8 == 0 && _second % 8 == 0,
			"No elementary type " + string(Token::toString(_baseType)) + to_string(_first) + "x" + to_string(_second) + "."
		);
	}
	m_token = _baseType;
	m_firstNumber = _first;
	m_secondNumber = _second;
}

#define T(name, string, precedence) #name,
char const* const Token::m_name[NUM_TOKENS] =
{
	TOKEN_LIST(T, T)
};
#undef T

#define T(name, string, precedence) string,
char const* const Token::m_string[NUM_TOKENS] =
{
	TOKEN_LIST(T, T)
};
#undef T

#define T(name, string, precedence) precedence,
int8_t const Token::m_precedence[NUM_TOKENS] =
{
	TOKEN_LIST(T, T)
};
#undef T

#define KT(a, b, c) 'T',
#define KK(a, b, c) 'K',
char const Token::m_tokenType[] =
{
	TOKEN_LIST(KT, KK)
};
int Token::parseSize(string::const_iterator _begin, string::const_iterator _end)
{
	try
	{
		unsigned int m = boost::lexical_cast<unsigned int>(boost::make_iterator_range(_begin, _end));
		return m;
	}
	catch(boost::bad_lexical_cast const&)
	{
		return -1;
	}
}
tuple<Token::Value, unsigned int, unsigned int> Token::fromIdentifierOrKeyword(string const& _literal)
{
	auto positionM = find_if(_literal.begin(), _literal.end(), ::isdigit);
	if (positionM != _literal.end())
	{
		string baseType(_literal.begin(), positionM);
		auto positionX = find_if_not(positionM, _literal.end(), ::isdigit);
		int m = parseSize(positionM, positionX);
		Token::Value keyword = keywordByName(baseType);
		if (keyword == Token::Bytes)
		{
			if (0 < m && m <= 32 && positionX == _literal.end())
				return make_tuple(Token::BytesM, m, 0);
		}
		else if (keyword == Token::UInt || keyword == Token::Int)
		{
			if (0 < m && m <= 256 && m % 8 == 0 && positionX == _literal.end())
			{
				if (keyword == Token::UInt)
					return make_tuple(Token::UIntM, m, 0);
				else
					return make_tuple(Token::IntM, m, 0);
			}
		}
		else if (keyword == Token::UFixed || keyword == Token::Fixed)
		{
			if (
				positionM < positionX &&
				positionX < _literal.end() &&
				*positionX == 'x' &&
				all_of(positionX + 1, _literal.end(), ::isdigit)
			) {
				int n = parseSize(positionX + 1, _literal.end());
				if (
					m + n > 0 &&
					m + n <= 256 &&
					m % 8 == 0 &&
					n % 8 == 0
				) {
					if (keyword == Token::UFixed)
						return make_tuple(Token::UFixedMxN, m, n);
					else
						return make_tuple(Token::FixedMxN, m, n);
				}
			}
		}
		return make_tuple(Token::Identifier, 0, 0);
	}
	return make_tuple(keywordByName(_literal), 0, 0);
}
Token::Value Token::keywordByName(string const& _name)
{
	// The following macros are used inside TOKEN_LIST and cause non-keyword tokens to be ignored
	// and keywords to be put inside the keywords variable.
#define KEYWORD(name, string, precedence) {string, Token::name},
#define TOKEN(name, string, precedence)
	static const map<string, Token::Value> keywords({TOKEN_LIST(TOKEN, KEYWORD)});
#undef KEYWORD
#undef TOKEN
	auto it = keywords.find(_name);
	return it == keywords.end() ? Token::Identifier : it->second;
}

#undef KT
#undef KK
}
}
<|endoftext|>


<commit_before>#pragma once

#include <type_traits>

#include <boost/mpl/contains.hpp>
#include <boost/mpl/vector.hpp>

#include "value.hpp"

namespace blackhole {

namespace attribute {

/*!
 * Helper metafunction that checks if the type `T` is compatible with attribute
 * internal implementation, i.e. `attribute::value_t` variant can be constructed
 * using type `T`.
 * @note: This metafunction ignores implicit type conversion.
 */
template<typename T>
struct is_supported :
    public boost::mpl::contains<
        value_t::types,
        typename std::decay<T>::type
    >
{};

/*!
 * Helper metafunction that checks if `attribute_value_t` can be constructed
 * using type `T`.
 */
template<typename T>
struct is_constructible {
    typedef boost::mpl::vector<
        const char*,    // Implicit literal to string conversion.
        char,
        unsigned char,
        short,
        unsigned short
    > additional_types;

    typedef typename std::conditional<
        boost::mpl::contains<
            additional_types,
            typename std::decay<T>::type
        >::value || is_supported<T>::value,
        std::true_type,
        std::false_type
    >::type type;

    static const bool value = type::value;
};

} // namespace attribute

} // namespace blackhole
<commit_msg>[Aux] Some notes added.<commit_after>#pragma once

#include <type_traits>

#include <boost/mpl/contains.hpp>
#include <boost/mpl/vector.hpp>

#include "value.hpp"

namespace blackhole {

namespace attribute {

/*!
 * Helper metafunction that checks if the type `T` is compatible with attribute
 * internal implementation, i.e. `attribute::value_t` variant can be constructed
 * using type `T`.
 * @note: This metafunction ignores implicit type conversion.
 */
template<typename T>
struct is_supported :
    public boost::mpl::contains<
        value_t::types,
        typename std::decay<T>::type
    >
{};

/*!
 * Helper metafunction that checks if `attribute::value_t` can be constructed
 * using type `T`.
 * @todo: I don't like it.
 */
template<typename T>
struct is_constructible {
    typedef boost::mpl::vector<
        const char*,    // Implicit literal to string conversion.
        char,
        unsigned char,
        short,
        unsigned short
    > additional_types;

    typedef typename std::conditional<
        boost::mpl::contains<
            additional_types,
            typename std::decay<T>::type
        >::value || is_supported<T>::value,
        std::true_type,
        std::false_type
    >::type type;

    static const bool value = type::value;
};

} // namespace attribute

} // namespace blackhole
<|endoftext|>


<commit_before>// $Id: fe_hermite.C,v 1.6 2007-05-23 23:36:11 roystgnr Exp $

// The libMesh Finite Element Library.
// Copyright (C) 2002-2005  Benjamin S. Kirk, John W. Peterson

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

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

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// Local includes
#include "elem.h"
#include "fe.h"
#include "fe_macro.h"

// ------------------------------------------------------------
// Hierarchic-specific implementations
template <unsigned int Dim, FEFamily T>
void FE<Dim,T>::nodal_soln(const Elem* elem,
			   const Order order,
			   const std::vector<Number>& elem_soln,
			   std::vector<Number>&       nodal_soln)
{
  const unsigned int n_nodes = elem->n_nodes();

  const ElemType type = elem->type();

  nodal_soln.resize(n_nodes);

  const Order totalorder = static_cast<Order>(order + elem->p_level());

  const unsigned int n_sf =
    FE<Dim,T>::n_shape_functions(type, totalorder);

  for (unsigned int n=0; n<n_nodes; n++)
    {
      const Point mapped_point = FE<Dim,T>::inverse_map(elem,
							elem->point(n));

      assert (elem_soln.size() == n_sf);

      // Zero before summation
      nodal_soln[n] = 0;

      // u_i = Sum (alpha_i phi_i)
      for (unsigned int i=0; i<n_sf; i++)
        nodal_soln[n] += elem_soln[i]*FE<Dim,T>::shape(elem,
						       order,
						       i,
						       mapped_point);
    }
}

template <unsigned int Dim, FEFamily T>
unsigned int FE<Dim,T>::n_dofs(const ElemType t, const Order o)
{
  assert (o > 2);
  // Piecewise (bi/tri)cubic C1 Hermite splines
  switch (t)
    {
    case EDGE2:
      assert (o < 4);
    case EDGE3:
      return (o+1);

    case QUAD4:
    case QUAD8:
      assert (o < 4);
    case QUAD9:
      return ((o+1)*(o+1));

    case HEX8:
    case HEX20:
      assert (o < 4);
    case HEX27:
      return ((o+1)*(o+1)*(o+1));

    default:
      {
#ifdef DEBUG
        std::cerr << "ERROR: Bad ElemType = " << t
		  << " for " << o << "th order approximation!"
		  << std::endl;
#endif
        error();
      }
    }

  error();
  return 0;
}

template <unsigned int Dim, FEFamily T>
unsigned int FE<Dim,T>::n_dofs_at_node(const ElemType t,
				       const Order o,
				       const unsigned int n)
{
  assert (o > 2);
  // Piecewise (bi/tri)cubic C1 Hermite splines
  switch (t)
    {
    case EDGE2:
    case EDGE3:
      {
        switch (n)
	{
	  case 0:
	  case 1:
	    return 2;
	  case 3:
//          Interior DoFs are carried on Elems
//	    return (o-3);
            return 0;

	  default:
	    error();
	}
      }

    case QUAD4:
      assert (o < 4);
    case QUAD8:
    case QUAD9:
      {
	switch (n)
	  {
          // Vertices
	  case 0:
	  case 1:
	  case 2:
	  case 3:
	    return 4;
          // Edges
	  case 4:
	  case 5:
	  case 6:
	  case 7:
	    return (2*(o-3));
	  case 8:
//          Interior DoFs are carried on Elems
//	    return ((o-3)*(o-3));
            return 0;

	  default:
	    error();
	  }
      }

    case HEX8:
    case HEX20:
      assert (o < 4);
    case HEX27:
      {
        switch (n)
	  {
          // Vertices
	  case 0:
	  case 1:
	  case 2:
	  case 3:
	  case 4:
	  case 5:
	  case 6:
	  case 7:
	    return 8;
          // Edges
	  case 8:
	  case 9:
	  case 10:
	  case 11:
	  case 12:
	  case 13:
	  case 14:
	  case 15:
	  case 16:
	  case 17:
	  case 18:
	  case 19:
	    return (4*(o-3));
          // Faces
	  case 20:
	  case 21:
	  case 22:
	  case 23:
	  case 24:
	  case 25:
	    return (2*(o-3)*(o-3));
	  case 26:
          // Interior DoFs are carried on Elems
//	    return ((o-3)*(o-3)*(o-3));
	    return 0;

	  default:
	    error();
	  }
      }

    default:
      {
#ifdef DEBUG
        std::cerr << "ERROR: Bad ElemType = " << t
		  << " for " << o << "th order approximation!"
		  << std::endl;
#endif
        error();
      }

    }

  error();

  return 0;
}

template <unsigned int Dim, FEFamily T>
unsigned int FE<Dim,T>::n_dofs_per_elem(const ElemType t,
					const Order o)
{
  assert (o > 2);

  switch (t)
    {
    case EDGE2:
    case EDGE3:
      return (o-3);
    case QUAD4:
      assert (o < 4);
    case QUAD8:
    case QUAD9:
      return ((o-3)*(o-3));
    case HEX8:
      assert (o < 4);
    case HEX20:
    case HEX27:
      return ((o-3)*(o-3)*(o-3));

    default:
      {
#ifdef DEBUG
        std::cerr << "ERROR: Bad ElemType = " << t
		  << " for " << o << "th order approximation!"
		  << std::endl;
#endif
        error();
      }
    }

  // Will never get here...
  error();
  return 0;
}

template <unsigned int Dim, FEFamily T>
FEContinuity FE<Dim,T>::get_continuity() const
{
  return C_ONE;
}

template <unsigned int Dim, FEFamily T>
bool FE<Dim,T>::is_hierarchic() const
{
  return true;
}

#ifdef ENABLE_AMR
template <unsigned int Dim, FEFamily T>
void FE<Dim,T>::compute_constraints (DofConstraints &constraints,
				     DofMap &dof_map,
				     const unsigned int variable_number,
				     const Elem* elem)
{
  compute_proj_constraints(constraints, dof_map, variable_number, elem);
}
#endif // #ifdef ENABLE_AMR

template <unsigned int Dim, FEFamily T>
bool FE<Dim,T>::shapes_need_reinit() const
{
  return true;
}

//--------------------------------------------------------------
// Explicit instantiation of member functions
INSTANTIATE_MBRF(1,HERMITE);
INSTANTIATE_MBRF(2,HERMITE);
INSTANTIATE_MBRF(3,HERMITE);

#ifdef ENABLE_AMR
template void FE<2,HERMITE>::compute_constraints(DofConstraints&, DofMap&,
                                                 const unsigned int,
                                                 const Elem*);
template void FE<3,HERMITE>::compute_constraints(DofConstraints&, DofMap&,
                                                 const unsigned int,
                                                 const Elem*);
#endif // #ifdef ENABLE_AMR
<commit_msg>Bugfix for 1D Hermites<commit_after>// $Id: fe_hermite.C,v 1.7 2007-10-18 20:31:28 roystgnr Exp $

// The libMesh Finite Element Library.
// Copyright (C) 2002-2005  Benjamin S. Kirk, John W. Peterson

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

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

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// Local includes
#include "elem.h"
#include "fe.h"
#include "fe_macro.h"

// ------------------------------------------------------------
// Hierarchic-specific implementations
template <unsigned int Dim, FEFamily T>
void FE<Dim,T>::nodal_soln(const Elem* elem,
			   const Order order,
			   const std::vector<Number>& elem_soln,
			   std::vector<Number>&       nodal_soln)
{
  const unsigned int n_nodes = elem->n_nodes();

  const ElemType type = elem->type();

  nodal_soln.resize(n_nodes);

  const Order totalorder = static_cast<Order>(order + elem->p_level());

  const unsigned int n_sf =
    FE<Dim,T>::n_shape_functions(type, totalorder);

  for (unsigned int n=0; n<n_nodes; n++)
    {
      const Point mapped_point = FE<Dim,T>::inverse_map(elem,
							elem->point(n));

      assert (elem_soln.size() == n_sf);

      // Zero before summation
      nodal_soln[n] = 0;

      // u_i = Sum (alpha_i phi_i)
      for (unsigned int i=0; i<n_sf; i++)
        nodal_soln[n] += elem_soln[i]*FE<Dim,T>::shape(elem,
						       order,
						       i,
						       mapped_point);
    }
}

template <unsigned int Dim, FEFamily T>
unsigned int FE<Dim,T>::n_dofs(const ElemType t, const Order o)
{
  assert (o > 2);
  // Piecewise (bi/tri)cubic C1 Hermite splines
  switch (t)
    {
    case EDGE2:
      assert (o < 4);
    case EDGE3:
      return (o+1);

    case QUAD4:
    case QUAD8:
      assert (o < 4);
    case QUAD9:
      return ((o+1)*(o+1));

    case HEX8:
    case HEX20:
      assert (o < 4);
    case HEX27:
      return ((o+1)*(o+1)*(o+1));

    default:
      {
#ifdef DEBUG
        std::cerr << "ERROR: Bad ElemType = " << t
		  << " for " << o << "th order approximation!"
		  << std::endl;
#endif
        error();
      }
    }

  error();
  return 0;
}

template <unsigned int Dim, FEFamily T>
unsigned int FE<Dim,T>::n_dofs_at_node(const ElemType t,
				       const Order o,
				       const unsigned int n)
{
  assert (o > 2);
  // Piecewise (bi/tri)cubic C1 Hermite splines
  switch (t)
    {
    case EDGE2:
    case EDGE3:
      {
        switch (n)
	{
	  case 0:
	  case 1:
	    return 2;
	  case 2:
//          Interior DoFs are carried on Elems
//	    return (o-3);
            return 0;

	  default:
	    error();
	}
      }

    case QUAD4:
      assert (o < 4);
    case QUAD8:
    case QUAD9:
      {
	switch (n)
	  {
          // Vertices
	  case 0:
	  case 1:
	  case 2:
	  case 3:
	    return 4;
          // Edges
	  case 4:
	  case 5:
	  case 6:
	  case 7:
	    return (2*(o-3));
	  case 8:
//          Interior DoFs are carried on Elems
//	    return ((o-3)*(o-3));
            return 0;

	  default:
	    error();
	  }
      }

    case HEX8:
    case HEX20:
      assert (o < 4);
    case HEX27:
      {
        switch (n)
	  {
          // Vertices
	  case 0:
	  case 1:
	  case 2:
	  case 3:
	  case 4:
	  case 5:
	  case 6:
	  case 7:
	    return 8;
          // Edges
	  case 8:
	  case 9:
	  case 10:
	  case 11:
	  case 12:
	  case 13:
	  case 14:
	  case 15:
	  case 16:
	  case 17:
	  case 18:
	  case 19:
	    return (4*(o-3));
          // Faces
	  case 20:
	  case 21:
	  case 22:
	  case 23:
	  case 24:
	  case 25:
	    return (2*(o-3)*(o-3));
	  case 26:
          // Interior DoFs are carried on Elems
//	    return ((o-3)*(o-3)*(o-3));
	    return 0;

	  default:
	    error();
	  }
      }

    default:
      {
#ifdef DEBUG
        std::cerr << "ERROR: Bad ElemType = " << t
		  << " for " << o << "th order approximation!"
		  << std::endl;
#endif
        error();
      }

    }

  error();

  return 0;
}

template <unsigned int Dim, FEFamily T>
unsigned int FE<Dim,T>::n_dofs_per_elem(const ElemType t,
					const Order o)
{
  assert (o > 2);

  switch (t)
    {
    case EDGE2:
    case EDGE3:
      return (o-3);
    case QUAD4:
      assert (o < 4);
    case QUAD8:
    case QUAD9:
      return ((o-3)*(o-3));
    case HEX8:
      assert (o < 4);
    case HEX20:
    case HEX27:
      return ((o-3)*(o-3)*(o-3));

    default:
      {
#ifdef DEBUG
        std::cerr << "ERROR: Bad ElemType = " << t
		  << " for " << o << "th order approximation!"
		  << std::endl;
#endif
        error();
      }
    }

  // Will never get here...
  error();
  return 0;
}

template <unsigned int Dim, FEFamily T>
FEContinuity FE<Dim,T>::get_continuity() const
{
  return C_ONE;
}

template <unsigned int Dim, FEFamily T>
bool FE<Dim,T>::is_hierarchic() const
{
  return true;
}

#ifdef ENABLE_AMR
template <unsigned int Dim, FEFamily T>
void FE<Dim,T>::compute_constraints (DofConstraints &constraints,
				     DofMap &dof_map,
				     const unsigned int variable_number,
				     const Elem* elem)
{
  compute_proj_constraints(constraints, dof_map, variable_number, elem);
}
#endif // #ifdef ENABLE_AMR

template <unsigned int Dim, FEFamily T>
bool FE<Dim,T>::shapes_need_reinit() const
{
  return true;
}

//--------------------------------------------------------------
// Explicit instantiation of member functions
INSTANTIATE_MBRF(1,HERMITE);
INSTANTIATE_MBRF(2,HERMITE);
INSTANTIATE_MBRF(3,HERMITE);

#ifdef ENABLE_AMR
template void FE<2,HERMITE>::compute_constraints(DofConstraints&, DofMap&,
                                                 const unsigned int,
                                                 const Elem*);
template void FE<3,HERMITE>::compute_constraints(DofConstraints&, DofMap&,
                                                 const unsigned int,
                                                 const Elem*);
#endif // #ifdef ENABLE_AMR
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2003-2007 Funambol, Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY, TITLE, NONINFRINGEMENT or FITNESS FOR A PARTICULAR
 * PURPOSE.  See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 * 02111-1307  USA
 */

#include "base/util/utils.h"
#include "vocl/VConverter.h"
#include "vocl/VObjectFactory.h"
#include "base/util/WString.h"
#include "base/quoted-printable.h"

VObject* VConverter::parse(const WCHAR* buffer) {

	WCHAR *objType = extractObjectType(buffer);
	WCHAR *objVersion = extractObjectVersion(buffer);
    if(!objType)
        return NULL;

	VObject* vo = VObjectFactory::createInstance(objType, objVersion);
    VProperty *prop;

    // Unfolding
    WCHAR* buffCopy = unfolding(buffer);

    while ( true ) {
        prop = readFieldHeader(buffCopy);
        if (!prop) {
            break;
        }
        if ( readFieldBody(buffCopy, prop )) {
            vo->addProperty(prop);
        }
        delete prop;
    }

    delete [] buffCopy; buffCopy  = NULL;

    return vo;
}

VProperty* VConverter::readFieldHeader(WCHAR* buffer) {

    WCHAR* headerIndex = NULL;
    WCHAR* quotaIndex = NULL;
    quotaIndex = wcschr(buffer, '"');
    headerIndex = wcschr(buffer, ':');

    if(!headerIndex)
        return NULL;
    bool quota = false;
    // If the header contains a quotation mark,
    // then rescan it starting directly after the _quotation mark_
    // (not after the end of the header, as in the original code)
    // to find the real end of the header.
    //
    // The reason for this code apparently is that the simple search above
    // might have found a headerIndex which points into the middle of
    // the quoted string.
    //
    // A better solution would be to always scan the header properly.
    if(quotaIndex && quotaIndex < headerIndex) {
        quota = true;
        int len = int(wcslen(buffer));
        for(int i = int(quotaIndex - buffer) + 1; i < len; i++) {
            if(buffer[i] == '"')
                quota = !quota;
            if(buffer[i] == ':' && !quota) {
                headerIndex = &buffer[i];
                break;
            }
        }
    }

    if(quota)
        return NULL;

    VProperty* prop = new VProperty(NULL);

    WCHAR* header = new WCHAR[wcslen(buffer) + 1];
    buffer[headerIndex - buffer] = '\0';
    wcscpy(header, buffer);
    // Shift the remaing string to the front of the buffer.
    // Using wcscpy() for that is incorrect because the standard
    // does not guarantee in which order bytes are moved!
    // wcscpy(buffer, ++headerIndex);
    ++headerIndex;
    memmove(buffer, headerIndex, (wcslen(headerIndex) + 1) * sizeof(*headerIndex));

    //if the header is folded (in .ics files)
    //we need to remove the folding
    WCHAR* headerFolding = NULL;
    if(headerFolding = wcsstr(header, TEXT("\n "))) {
        header[headerFolding - header] = '\0';
    }

    WCHAR seps[] = TEXT(";");
    WCHAR *token;
    bool first = true;

	token = wcstok( header, seps );
	while( token != NULL ) {
        if (first) {

            WCHAR* group = new WCHAR[wcslen(token) + 1];
            if(extractGroup(token, group))
                prop->addParameter(TEXT("GROUP"), group);
            else
                delete [] group; group= NULL;
            prop->setName(token);
            first = false;
        }
        else {
            WCHAR* paramIndex;
            paramIndex = wcschr(token, '=');

            if(paramIndex) {
                WCHAR* paramName = new WCHAR[wcslen(token) + 1];
                token[paramIndex - token] = '\0';
                wcscpy(paramName, token);
                ++paramIndex;
                memmove(token, paramIndex, (wcslen(paramIndex) + 1) * sizeof(*paramIndex));

                WCHAR* paramVal = new WCHAR[wcslen(token) + 1];
                wcscpy(paramVal, token);
                prop->addParameter(paramName, paramVal);

                delete [] paramName; paramName = NULL;
                delete [] paramVal; paramVal = NULL;
            }
            else {
                prop->addParameter(token,NULL);
            }
        }
        token = wcstok( NULL, seps );
    }

    delete [] header; header = NULL;
    delete token; token = NULL;

    return prop;
}

bool VConverter::readFieldBody(WCHAR* buffer, VProperty* vprop) {

    int i      = 0;
    int j      = 0;
    int len    = 0;
    int offset = 0;
    bool ret   = false;
    WCHAR* value     = NULL;
    WCHAR* allValues = NULL;
    WCHAR* c         = NULL;

    // Get length of all values
    while (buffer[i] != '\0') {
        if ((buffer[i] == '\r') || buffer[i] == '\n') {

            // Get offset of next property
            for (j=i+1; buffer[j] != '\0'; j++) {
                if((buffer[j] != '\r') && (buffer[j] != '\n'))
                    break;
            }
            offset = j;
            break;
        }
        i++;
    }
    len = i;

    if (!len) {
        // This field is empty, we MUST consider it adding an empty value
        // so any value on client will be deleted.
        vprop->addValue(TEXT(""));
        ret = true;
        goto finally;
    }

    // This is a string with all values for this property (to parse)
    allValues = new WCHAR[len + 1];
    wcsncpy(allValues, buffer, len);
    allValues[len] = 0;

    /* IT IS NOT POSSIBLE TO DECODE BASE64 PARAMETERS IN A WCHAR
    AND TAKE THE LENGHT OF A BINARY!!
    //
    // If needed, decode QP string and copy to 'allValues'.
    //
    if(vprop->equalsEncoding(TEXT("QUOTED-PRINTABLE"))) {

        char* buf = toMultibyte(allValues);
	    char* dec = qp_decode(buf);
        len = strlen(dec);
	    delete [] buf;

	    if (dec) {
            WCHAR* wdecoded = toWideChar(dec);
            delete [] dec;

            if (wdecoded) {
                wcsncpy(allValues, wdecoded, len);
                allValues[len] = 0;
                delete [] wdecoded;
            }
        }
        if (!len) {
            goto finally;
        }
    }

    //
    // If needed, decode B64 string and copy to 'allValues'.
    //
    if(vprop->equalsEncoding(TEXT("BASE64")) ||
       vprop->equalsEncoding(TEXT("B")) ||
       vprop->equalsEncoding(TEXT("b")) ) {

        char* buf = toMultibyte(allValues);
        char* dec = new char[2*strlen(buf) + 1];
        b64_decode(dec, buf);
        len = strlen(dec);
	    delete [] buf;

	    if (dec) {
            WCHAR* wdecoded = toWideChar(dec);
            delete [] dec;

            if (wdecoded) {
                wcsncpy(allValues, wdecoded, len);
                allValues[len] = 0;
                delete [] wdecoded;
            }
        }
        if (!len) {
            goto finally;
        }
    }
    */
    // This is a buffer for each single value
    value = new WCHAR[len + 1];
    wcscpy(value, TEXT(""));

    //
    // Extract values and add to Vproperty
    //
    j=0;
    c = allValues;
    for (i=0; i<len; i++) {

        // End of value
        if (c[i] == ';') {
            vprop->addValue(value);
            j = 0;
            wcscpy(value, TEXT(""));
        }

        else {
            // Manage escaped chars: jump back-slash
            if (c[i] == '\\') {
                if (c[i+1]=='n') {
                    // none: this is "\n" sequence (formatted line ending for 3.0)
                }
                else {
                    i++;
                    if (c[i] == '\0')
                        break;
                }
            }
            value[j] = c[i];
            j++;
            value[j] = '\0';
        }
    }

    vprop->addValue(value);
    ret = true;

finally:

    // Shift buffer for next property to parse
    //wcscpy(buffer, buffer+offset);
    memmove(buffer, buffer+offset, (wcslen(buffer+offset) + 1)*sizeof(*buffer));

    if (value) {
        delete [] value;     value = NULL;
    }
    if (allValues) {
        delete [] allValues; allValues = NULL;
    }

	return ret;
}

WCHAR* VConverter::extractObjectProperty(const WCHAR* buffer, const WCHAR *property,
                                           WCHAR * &buffCopy, size_t &buffCopyLen) {

    // Memory handling in extractObjectType() and
    // extractObjectVersion() was broken:
    // they allocated a buffer, then returned a pointer into
    // parts of this buffer as result. The caller cannot
    // free the result in this case. The functions were also
    // duplicating the same code.
    //
    // This partial fix reuses previously allocated
    // memory if the function is called a second time.

    size_t len = wcslen(buffer) + 1;
    if (buffCopyLen < len) {
        if (buffCopy) {
            delete [] buffCopy;
        }
        buffCopy = new WCHAR[len];
        buffCopyLen = len;
    }
    wcscpy(buffCopy, buffer);

    WCHAR seps[] = TEXT(":\n");
    WCHAR *token;

    token = wcstok( buffCopy, seps );
    while (token != NULL) {
        if(!wcscmp(token, property)) {
            token = wcstok( NULL, seps );
            WCHAR* index = wcschr(token,'\r');
            if(index)
                token[index-token] = '\0';
            return token;
        }
        token = wcstok( NULL, seps );
    }

    return NULL;
}

WCHAR* VConverter::extractObjectType(const WCHAR* buffer) {
    static WCHAR* buffCopy;
    static size_t buffCopyLen;

    return extractObjectProperty(buffer, TEXT("BEGIN"),
                                 buffCopy, buffCopyLen);
}

WCHAR* VConverter::extractObjectVersion(const WCHAR* buffer) {
    static WCHAR* buffCopy;
    static size_t buffCopyLen;

    return extractObjectProperty(buffer, TEXT("VERSION"),
                                 buffCopy, buffCopyLen);
}

bool VConverter::extractGroup(WCHAR* propertyName, WCHAR* propertyGroup) {

    WCHAR* groupIndex;
    groupIndex = wcschr(propertyName, '.');

    if(!groupIndex)
        return false;

    propertyName[groupIndex - propertyName] = '\0';
    wcscpy(propertyGroup, propertyName);
    wcscpy(propertyName, ++groupIndex);

    return true;
}
<commit_msg>fixed Quoted Printable decoding of vobject<commit_after>/*
 * Copyright (C) 2003-2007 Funambol, Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY, TITLE, NONINFRINGEMENT or FITNESS FOR A PARTICULAR
 * PURPOSE.  See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 * 02111-1307  USA
 */

#include "base/util/utils.h"
#include "vocl/VConverter.h"
#include "vocl/VObjectFactory.h"
#include "base/util/WString.h"
#include "base/quoted-printable.h"

VObject* VConverter::parse(const WCHAR* buffer) {

	WCHAR *objType = extractObjectType(buffer);
	WCHAR *objVersion = extractObjectVersion(buffer);
    if(!objType)
        return NULL;

	VObject* vo = VObjectFactory::createInstance(objType, objVersion);
    VProperty *prop;

    // Unfolding
    WCHAR* buffCopy = unfolding(buffer);

    while ( true ) {
        prop = readFieldHeader(buffCopy);
        if (!prop) {
            break;
        }
        if ( readFieldBody(buffCopy, prop )) {
            vo->addProperty(prop);
        }
        delete prop;
    }

    delete [] buffCopy; buffCopy  = NULL;

    return vo;
}

VProperty* VConverter::readFieldHeader(WCHAR* buffer) {

    WCHAR* headerIndex = NULL;
    WCHAR* quotaIndex = NULL;
    quotaIndex = wcschr(buffer, '"');
    headerIndex = wcschr(buffer, ':');

    if(!headerIndex)
        return NULL;
    bool quota = false;
    // If the header contains a quotation mark,
    // then rescan it starting directly after the _quotation mark_
    // (not after the end of the header, as in the original code)
    // to find the real end of the header.
    //
    // The reason for this code apparently is that the simple search above
    // might have found a headerIndex which points into the middle of
    // the quoted string.
    //
    // A better solution would be to always scan the header properly.
    if(quotaIndex && quotaIndex < headerIndex) {
        quota = true;
        int len = int(wcslen(buffer));
        for(int i = int(quotaIndex - buffer) + 1; i < len; i++) {
            if(buffer[i] == '"')
                quota = !quota;
            if(buffer[i] == ':' && !quota) {
                headerIndex = &buffer[i];
                break;
            }
        }
    }

    if(quota)
        return NULL;

    VProperty* prop = new VProperty(NULL);

    WCHAR* header = new WCHAR[wcslen(buffer) + 1];
    buffer[headerIndex - buffer] = '\0';
    wcscpy(header, buffer);
    // Shift the remaing string to the front of the buffer.
    // Using wcscpy() for that is incorrect because the standard
    // does not guarantee in which order bytes are moved!
    // wcscpy(buffer, ++headerIndex);
    ++headerIndex;
    memmove(buffer, headerIndex, (wcslen(headerIndex) + 1) * sizeof(*headerIndex));

    //if the header is folded (in .ics files)
    //we need to remove the folding
    WCHAR* headerFolding = NULL;
    if(headerFolding = wcsstr(header, TEXT("\n "))) {
        header[headerFolding - header] = '\0';
    }

    WCHAR seps[] = TEXT(";");
    WCHAR *token;
    bool first = true;

	token = wcstok( header, seps );
	while( token != NULL ) {
        if (first) {

            WCHAR* group = new WCHAR[wcslen(token) + 1];
            if(extractGroup(token, group))
                prop->addParameter(TEXT("GROUP"), group);
            else
                delete [] group; group= NULL;
            prop->setName(token);
            first = false;
        }
        else {
            WCHAR* paramIndex;
            paramIndex = wcschr(token, '=');

            if(paramIndex) {
                WCHAR* paramName = new WCHAR[wcslen(token) + 1];
                token[paramIndex - token] = '\0';
                wcscpy(paramName, token);
                ++paramIndex;
                memmove(token, paramIndex, (wcslen(paramIndex) + 1) * sizeof(*paramIndex));

                WCHAR* paramVal = new WCHAR[wcslen(token) + 1];
                wcscpy(paramVal, token);
                prop->addParameter(paramName, paramVal);

                delete [] paramName; paramName = NULL;
                delete [] paramVal; paramVal = NULL;
            }
            else {
                prop->addParameter(token,NULL);
            }
        }
        token = wcstok( NULL, seps );
    }

    delete [] header; header = NULL;
    delete token; token = NULL;

    return prop;
}

bool VConverter::readFieldBody(WCHAR* buffer, VProperty* vprop) {

    int i      = 0;
    int j      = 0;
    int len    = 0;
    int offset = 0;
    bool ret   = false;
    WCHAR* value     = NULL;
    WCHAR* allValues = NULL;
    WCHAR* c         = NULL;

    // Get length of all values
    while (buffer[i] != '\0') {
        if ((buffer[i] == '\r') || buffer[i] == '\n') {

            // Get offset of next property
            for (j=i+1; buffer[j] != '\0'; j++) {
                if((buffer[j] != '\r') && (buffer[j] != '\n'))
                    break;
            }
            offset = j;
            break;
        }
        i++;
    }
    len = i;

    if (!len) {
        // This field is empty, we MUST consider it adding an empty value
        // so any value on client will be deleted.
        vprop->addValue(TEXT(""));
        ret = true;
        goto finally;
    }

    // This is a string with all values for this property (to parse)
    allValues = new WCHAR[len + 1];
    wcsncpy(allValues, buffer, len);
    allValues[len] = 0;

    //
    // If needed, decode QP string and copy to 'allValues'.
    //
    if(vprop->equalsEncoding(TEXT("QUOTED-PRINTABLE"))) {

        char* buf = toMultibyte(allValues);
	    char* dec = qp_decode(buf);
        len = strlen(dec);
	    delete [] buf;

	    if (dec) {
            WCHAR* wdecoded = toWideChar(dec);
            delete [] dec;

            if (wdecoded) {
                wcsncpy(allValues, wdecoded, len);
                allValues[len] = 0;
                delete [] wdecoded;
            }
        }
        if (!len) {
            goto finally;
        }
    }

    /*
    --- base64 is not decoded ----
    IT IS NOT POSSIBLE TO DECODE BASE64 PARAMETERS IN A WCHAR
    AND TAKE THE LENGHT OF A BINARY!!
    */

    // This is a buffer for each single value
    value = new WCHAR[len + 1];
    wcscpy(value, TEXT(""));

    //
    // Extract values and add to Vproperty
    //
    j=0;
    c = allValues;
    for (i=0; i<len; i++) {

        // End of value
        if (c[i] == ';') {
            vprop->addValue(value);
            j = 0;
            wcscpy(value, TEXT(""));
        }

        else {
            // Manage escaped chars: jump back-slash
            if (c[i] == '\\') {
                if (c[i+1]=='n') {
                    // none: this is "\n" sequence (formatted line ending for 3.0)
                }
                else {
                    i++;
                    if (c[i] == '\0')
                        break;
                }
            }
            value[j] = c[i];
            j++;
            value[j] = '\0';
        }
    }

    vprop->addValue(value);
    ret = true;

finally:

    // Shift buffer for next property to parse
    //wcscpy(buffer, buffer+offset);
    memmove(buffer, buffer+offset, (wcslen(buffer+offset) + 1)*sizeof(*buffer));

    if (value) {
        delete [] value;     value = NULL;
    }
    if (allValues) {
        delete [] allValues; allValues = NULL;
    }

	return ret;
}

WCHAR* VConverter::extractObjectProperty(const WCHAR* buffer, const WCHAR *property,
                                           WCHAR * &buffCopy, size_t &buffCopyLen) {

    // Memory handling in extractObjectType() and
    // extractObjectVersion() was broken:
    // they allocated a buffer, then returned a pointer into
    // parts of this buffer as result. The caller cannot
    // free the result in this case. The functions were also
    // duplicating the same code.
    //
    // This partial fix reuses previously allocated
    // memory if the function is called a second time.

    size_t len = wcslen(buffer) + 1;
    if (buffCopyLen < len) {
        if (buffCopy) {
            delete [] buffCopy;
        }
        buffCopy = new WCHAR[len];
        buffCopyLen = len;
    }
    wcscpy(buffCopy, buffer);

    WCHAR seps[] = TEXT(":\n");
    WCHAR *token;

    token = wcstok( buffCopy, seps );
    while (token != NULL) {
        if(!wcscmp(token, property)) {
            token = wcstok( NULL, seps );
            WCHAR* index = wcschr(token,'\r');
            if(index)
                token[index-token] = '\0';
            return token;
        }
        token = wcstok( NULL, seps );
    }

    return NULL;
}

WCHAR* VConverter::extractObjectType(const WCHAR* buffer) {
    static WCHAR* buffCopy;
    static size_t buffCopyLen;

    return extractObjectProperty(buffer, TEXT("BEGIN"),
                                 buffCopy, buffCopyLen);
}

WCHAR* VConverter::extractObjectVersion(const WCHAR* buffer) {
    static WCHAR* buffCopy;
    static size_t buffCopyLen;

    return extractObjectProperty(buffer, TEXT("VERSION"),
                                 buffCopy, buffCopyLen);
}

bool VConverter::extractGroup(WCHAR* propertyName, WCHAR* propertyGroup) {

    WCHAR* groupIndex;
    groupIndex = wcschr(propertyName, '.');

    if(!groupIndex)
        return false;

    propertyName[groupIndex - propertyName] = '\0';
    wcscpy(propertyGroup, propertyName);
    wcscpy(propertyName, ++groupIndex);

    return true;
}
<|endoftext|>


<commit_before>

#include "ttimer.h"
#include "texception.h"

#ifdef _WIN32

#include <windows.h>

//moto strano: se togliamo l'include della glut non linka
#include <GL/glut.h>

//------------------------------------------------------------------------------

namespace
{

void CALLBACK ElapsedTimeCB(UINT uID, UINT uMsg,
							DWORD dwUser, DWORD dw1,
							DWORD dw2);
};

//------------------------------------------------------------------------------

class TTimer::Imp
{
public:
	Imp(std::string name, UINT timerRes, TTimer::Type type, TTimer *timer);
	~Imp();

	void start(UINT delay)
	{
		if (m_started)
			throw TException("The timer is already started");

		m_timerID = timeSetEvent(delay, m_timerRes,
								 (LPTIMECALLBACK)ElapsedTimeCB, (DWORD) this,
								 m_type | TIME_CALLBACK_FUNCTION);

		m_delay = delay;
		m_ticks = 0;
		if (m_timerID == NULL)
			throw TException("Unable to start timer");

		m_started = true;
	}

	void stop()
	{
		if (m_started)
			timeKillEvent(m_timerID);
		m_started = false;
	}

	std::string getName() { return m_name; }
	TUINT64 getTicks() { return m_ticks; }
	UINT getDelay() { return m_delay; }

	std::string m_name;

	UINT m_timerRes;
	UINT m_type;
	TTimer *m_timer;

	UINT m_timerID;
	UINT m_delay;
	TUINT64 m_ticks;
	bool m_started;

	TGenericTimerAction *m_action;
};

//------------------------------------------------------------------------------

TTimer::Imp::Imp(std::string name, UINT timerRes, TTimer::Type type, TTimer *timer)
	: m_name(name), m_timerRes(timerRes), m_timer(timer), m_type(type), m_timerID(NULL), m_ticks(0), m_delay(0), m_started(false), m_action(0)
{

	TIMECAPS tc;

	if (timeGetDevCaps(&tc, sizeof(TIMECAPS)) != TIMERR_NOERROR) {
		throw TException("Unable to create timer");
	}

	m_timerRes = tmin((int)tmax((int)tc.wPeriodMin, (int)m_timerRes), (int)tc.wPeriodMax);
	timeBeginPeriod(m_timerRes);

	switch (type) {
	case TTimer::OneShot:
		m_type = TIME_ONESHOT;
		break;

	case TTimer::Periodic:
		m_type = TIME_PERIODIC;
		break;

	default:
		throw TException("Unexpected timer type");
		break;
	}
}

//------------------------------------------------------------------------------

TTimer::Imp::~Imp()
{
	stop();
	timeEndPeriod(m_timerRes);

	if (m_action)
		delete m_action;
}

//------------------------------------------------------------------------------

namespace
{

void CALLBACK ElapsedTimeCB(UINT uID, UINT uMsg,
							DWORD dwUser, DWORD dw1,
							DWORD dw2)
{
	TTimer::Imp *imp = reinterpret_cast<TTimer::Imp *>(dwUser);
	imp->m_ticks++;
	if (imp->m_action)
		imp->m_action->sendCommand(imp->m_ticks);
}
};
#elif LINUX

#include <SDL/SDL_timer.h>
#include <SDL/SDL.h>
#include "tthread.h"
namespace
{
Uint32 ElapsedTimeCB(Uint32 interval, void *param);
}

class TTimer::Imp
{
public:
	Imp(std::string name, UINT timerRes, TTimer::Type type, TTimer *timer)
		: m_action(0), m_ticks(0)
	{
	}
	~Imp() {}

	void start(UINT delay)
	{
		static bool first = true;
		if (first) {
			SDL_Init(SDL_INIT_TIMER);
			first = false;
		}
		m_timerID = SDL_AddTimer(delay, ElapsedTimeCB, this);
	}

	void stop()
	{
		SDL_RemoveTimer(m_timerID);
	}

	std::string getName() { return m_name; }
	TUINT64 getTicks() { return m_ticks; }
	UINT getDelay() { return m_delay; }

	std::string m_name;

	UINT m_timerRes;
	UINT m_type;
	TTimer *m_timer;

	SDL_TimerID m_timerID;
	UINT m_delay;
	TUINT64 m_ticks;
	bool m_started;

	TGenericTimerAction *m_action;
};

class SendCommandMSG : public TThread::Msg
{
	TTimer::Imp *m_ztimp;

public:
	SendCommandMSG(TTimer::Imp *ztimp) : TThread::Msg(), m_ztimp(ztimp)
	{
	}
	~SendCommandMSG() {}
	TThread::Msg *clone() const { return new SendCommandMSG(*this); }
	void onDeliver()
	{
		if (m_ztimp->m_action)
			m_ztimp->m_action->sendCommand(m_ztimp->m_ticks);
	}
};

namespace
{
Uint32 ElapsedTimeCB(Uint32 interval, void *param)
{
	TTimer::Imp *imp = reinterpret_cast<TTimer::Imp *>(param);
	imp->m_ticks++;
	SendCommandMSG(imp).send();
	return interval;
}
}

#elif __sgi
class TTimer::Imp
{
public:
	Imp(std::string name, UINT timerRes, TTimer::Type type, TTimer *timer)
		: m_action(0) {}
	~Imp() {}

	void start(UINT delay)
	{
		if (m_started)
			throw TException("The timer is already started");

		m_started = true;
	}

	void stop()
	{
		m_started = false;
	}

	std::string getName() { return m_name; }
	TUINT64 getTicks() { return m_ticks; }
	UINT getDelay() { return m_delay; }

	std::string m_name;

	UINT m_timerRes;
	UINT m_type;
	TTimer *m_timer;

	UINT m_timerID;
	UINT m_delay;
	TUINT64 m_ticks;
	bool m_started;

	TGenericTimerAction *m_action;
};
#elif MACOSX
class TTimer::Imp
{
public:
	Imp(std::string name, UINT timerRes, TTimer::Type type, TTimer *timer)
		: m_action(0) {}
	~Imp() {}

	void start(UINT delay)
	{
		if (m_started)
			throw TException("The timer is already started");
		throw TException("The timer is not yet available under MAC :(");
		m_started = true;
	}

	void stop()
	{
		m_started = false;
	}

	std::string getName() { return m_name; }
	TUINT64 getTicks() { return m_ticks; }
	UINT getDelay() { return m_delay; }

	std::string m_name;

	UINT m_timerRes;
	UINT m_type;
	TTimer *m_timer;

	UINT m_timerID;
	UINT m_delay;
	TUINT64 m_ticks;
	bool m_started;

	TGenericTimerAction *m_action;
};

#endif

//===============================================================================
//
//  TTimer
//
//===============================================================================

TTimer::TTimer(const std::string &name, UINT timerRes, Type type)
	: m_imp(new TTimer::Imp(name, timerRes, type, this))
{
}

//--------------------------------------------------------------------------------

TTimer::~TTimer()
{
}

//--------------------------------------------------------------------------------

void TTimer::start(UINT delay)
{
	m_imp->start(delay);
}

//--------------------------------------------------------------------------------

bool TTimer::isStarted() const
{
	return m_imp->m_started;
}

//--------------------------------------------------------------------------------

void TTimer::stop()
{
	m_imp->stop();
}

//--------------------------------------------------------------------------------

std::string TTimer::getName() const
{
	return m_imp->getName();
}

//--------------------------------------------------------------------------------

TUINT64 TTimer::getTicks() const
{
	return m_imp->getTicks();
}

//--------------------------------------------------------------------------------

UINT TTimer::getDelay() const
{
	return m_imp->getDelay();
}

//--------------------------------------------------------------------------------

void TTimer::setAction(TGenericTimerAction *action)
{
	if (m_imp->m_action)
		delete m_imp->m_action;

	m_imp->m_action = action;
}
<commit_msg>Correct class use with TTimer on Linux<commit_after>

#include "ttimer.h"
#include "tthreadmessage.h"
#include "texception.h"

#ifdef _WIN32

#include <windows.h>

//moto strano: se togliamo l'include della glut non linka
#include <GL/glut.h>

//------------------------------------------------------------------------------

namespace
{

void CALLBACK ElapsedTimeCB(UINT uID, UINT uMsg,
							DWORD dwUser, DWORD dw1,
							DWORD dw2);
};

//------------------------------------------------------------------------------

class TTimer::Imp
{
public:
	Imp(std::string name, UINT timerRes, TTimer::Type type, TTimer *timer);
	~Imp();

	void start(UINT delay)
	{
		if (m_started)
			throw TException("The timer is already started");

		m_timerID = timeSetEvent(delay, m_timerRes,
								 (LPTIMECALLBACK)ElapsedTimeCB, (DWORD) this,
								 m_type | TIME_CALLBACK_FUNCTION);

		m_delay = delay;
		m_ticks = 0;
		if (m_timerID == NULL)
			throw TException("Unable to start timer");

		m_started = true;
	}

	void stop()
	{
		if (m_started)
			timeKillEvent(m_timerID);
		m_started = false;
	}

	std::string getName() { return m_name; }
	TUINT64 getTicks() { return m_ticks; }
	UINT getDelay() { return m_delay; }

	std::string m_name;

	UINT m_timerRes;
	UINT m_type;
	TTimer *m_timer;

	UINT m_timerID;
	UINT m_delay;
	TUINT64 m_ticks;
	bool m_started;

	TGenericTimerAction *m_action;
};

//------------------------------------------------------------------------------

TTimer::Imp::Imp(std::string name, UINT timerRes, TTimer::Type type, TTimer *timer)
	: m_name(name), m_timerRes(timerRes), m_timer(timer), m_type(type), m_timerID(NULL), m_ticks(0), m_delay(0), m_started(false), m_action(0)
{

	TIMECAPS tc;

	if (timeGetDevCaps(&tc, sizeof(TIMECAPS)) != TIMERR_NOERROR) {
		throw TException("Unable to create timer");
	}

	m_timerRes = tmin((int)tmax((int)tc.wPeriodMin, (int)m_timerRes), (int)tc.wPeriodMax);
	timeBeginPeriod(m_timerRes);

	switch (type) {
	case TTimer::OneShot:
		m_type = TIME_ONESHOT;
		break;

	case TTimer::Periodic:
		m_type = TIME_PERIODIC;
		break;

	default:
		throw TException("Unexpected timer type");
		break;
	}
}

//------------------------------------------------------------------------------

TTimer::Imp::~Imp()
{
	stop();
	timeEndPeriod(m_timerRes);

	if (m_action)
		delete m_action;
}

//------------------------------------------------------------------------------

namespace
{

void CALLBACK ElapsedTimeCB(UINT uID, UINT uMsg,
							DWORD dwUser, DWORD dw1,
							DWORD dw2)
{
	TTimer::Imp *imp = reinterpret_cast<TTimer::Imp *>(dwUser);
	imp->m_ticks++;
	if (imp->m_action)
		imp->m_action->sendCommand(imp->m_ticks);
}
};
#elif LINUX

#include <SDL/SDL_timer.h>
#include <SDL/SDL.h>
#include "tthread.h"
namespace
{
Uint32 ElapsedTimeCB(Uint32 interval, void *param);
}

class TTimer::Imp
{
public:
	Imp(std::string name, UINT timerRes, TTimer::Type type, TTimer *timer)
		: m_action(0), m_ticks(0)
	{
	}
	~Imp() {}

	void start(UINT delay)
	{
		static bool first = true;
		if (first) {
			SDL_Init(SDL_INIT_TIMER);
			first = false;
		}
		m_timerID = SDL_AddTimer(delay, ElapsedTimeCB, this);
	}

	void stop()
	{
		SDL_RemoveTimer(m_timerID);
	}

	std::string getName() { return m_name; }
	TUINT64 getTicks() { return m_ticks; }
	UINT getDelay() { return m_delay; }

	std::string m_name;

	UINT m_timerRes;
	UINT m_type;
	TTimer *m_timer;

	SDL_TimerID m_timerID;
	UINT m_delay;
	TUINT64 m_ticks;
	bool m_started;

	TGenericTimerAction *m_action;
};

class SendCommandMSG : public TThread::Message
{
	TTimer::Imp *m_ztimp;

public:
	SendCommandMSG(TTimer::Imp *ztimp) : TThread::Message(), m_ztimp(ztimp)
	{
	}
	~SendCommandMSG() {}
	TThread::Message *clone() const { return new SendCommandMSG(*this); }
	void onDeliver()
	{
		if (m_ztimp->m_action)
			m_ztimp->m_action->sendCommand(m_ztimp->m_ticks);
	}
};

namespace
{
Uint32 ElapsedTimeCB(Uint32 interval, void *param)
{
	TTimer::Imp *imp = reinterpret_cast<TTimer::Imp *>(param);
	imp->m_ticks++;
	SendCommandMSG(imp).send();
	return interval;
}
}

#elif __sgi
class TTimer::Imp
{
public:
	Imp(std::string name, UINT timerRes, TTimer::Type type, TTimer *timer)
		: m_action(0) {}
	~Imp() {}

	void start(UINT delay)
	{
		if (m_started)
			throw TException("The timer is already started");

		m_started = true;
	}

	void stop()
	{
		m_started = false;
	}

	std::string getName() { return m_name; }
	TUINT64 getTicks() { return m_ticks; }
	UINT getDelay() { return m_delay; }

	std::string m_name;

	UINT m_timerRes;
	UINT m_type;
	TTimer *m_timer;

	UINT m_timerID;
	UINT m_delay;
	TUINT64 m_ticks;
	bool m_started;

	TGenericTimerAction *m_action;
};
#elif MACOSX
class TTimer::Imp
{
public:
	Imp(std::string name, UINT timerRes, TTimer::Type type, TTimer *timer)
		: m_action(0) {}
	~Imp() {}

	void start(UINT delay)
	{
		if (m_started)
			throw TException("The timer is already started");
		throw TException("The timer is not yet available under MAC :(");
		m_started = true;
	}

	void stop()
	{
		m_started = false;
	}

	std::string getName() { return m_name; }
	TUINT64 getTicks() { return m_ticks; }
	UINT getDelay() { return m_delay; }

	std::string m_name;

	UINT m_timerRes;
	UINT m_type;
	TTimer *m_timer;

	UINT m_timerID;
	UINT m_delay;
	TUINT64 m_ticks;
	bool m_started;

	TGenericTimerAction *m_action;
};

#endif

//===============================================================================
//
//  TTimer
//
//===============================================================================

TTimer::TTimer(const std::string &name, UINT timerRes, Type type)
	: m_imp(new TTimer::Imp(name, timerRes, type, this))
{
}

//--------------------------------------------------------------------------------

TTimer::~TTimer()
{
}

//--------------------------------------------------------------------------------

void TTimer::start(UINT delay)
{
	m_imp->start(delay);
}

//--------------------------------------------------------------------------------

bool TTimer::isStarted() const
{
	return m_imp->m_started;
}

//--------------------------------------------------------------------------------

void TTimer::stop()
{
	m_imp->stop();
}

//--------------------------------------------------------------------------------

std::string TTimer::getName() const
{
	return m_imp->getName();
}

//--------------------------------------------------------------------------------

TUINT64 TTimer::getTicks() const
{
	return m_imp->getTicks();
}

//--------------------------------------------------------------------------------

UINT TTimer::getDelay() const
{
	return m_imp->getDelay();
}

//--------------------------------------------------------------------------------

void TTimer::setAction(TGenericTimerAction *action)
{
	if (m_imp->m_action)
		delete m_imp->m_action;

	m_imp->m_action = action;
}
<|endoftext|>