<commit_before>//===-- Function.cpp - Implement the Global object classes ----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the Function class for the VMCore library.
//
//===----------------------------------------------------------------------===//

#include "llvm/Module.h"
#include "llvm/DerivedTypes.h"
#include "llvm/ParameterAttributes.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/Support/LeakDetector.h"
#include "SymbolTableListTraitsImpl.h"
#include "llvm/ADT/StringExtras.h"
using namespace llvm;

BasicBlock *ilist_traits<BasicBlock>::createSentinel() {
  BasicBlock *Ret = new BasicBlock();
  // This should not be garbage monitored.
  LeakDetector::removeGarbageObject(Ret);
  return Ret;
}

iplist<BasicBlock> &ilist_traits<BasicBlock>::getList(Function *F) {
  return F->getBasicBlockList();
}

Argument *ilist_traits<Argument>::createSentinel() {
  Argument *Ret = new Argument(Type::Int32Ty);
  // This should not be garbage monitored.
  LeakDetector::removeGarbageObject(Ret);
  return Ret;
}

iplist<Argument> &ilist_traits<Argument>::getList(Function *F) {
  return F->getArgumentList();
}

// Explicit instantiations of SymbolTableListTraits since some of the methods
// are not in the public header file...
template class SymbolTableListTraits<Argument, Function, Function>;
template class SymbolTableListTraits<BasicBlock, Function, Function>;

//===----------------------------------------------------------------------===//
// Argument Implementation
//===----------------------------------------------------------------------===//

Argument::Argument(const Type *Ty, const std::string &Name, Function *Par)
  : Value(Ty, Value::ArgumentVal) {
  Parent = 0;

  // Make sure that we get added to a function
  LeakDetector::addGarbageObject(this);

  if (Par)
    Par->getArgumentList().push_back(this);
  setName(Name);
}

void Argument::setParent(Function *parent) {
  if (getParent())
    LeakDetector::addGarbageObject(this);
  Parent = parent;
  if (getParent())
    LeakDetector::removeGarbageObject(this);
}

//===----------------------------------------------------------------------===//
// ParamAttrsList Implementation
//===----------------------------------------------------------------------===//

uint16_t
ParamAttrsList::getParamAttrs(uint16_t Index) const {
  unsigned limit = attrs.size();
  for (unsigned i = 0; i < limit; ++i)
    if (attrs[i].index == Index)
      return attrs[i].attrs;
  return ParamAttr::None;
}

std::string
ParamAttrsList::getParamAttrsText(uint16_t Attrs) {
  std::string Result;
  if (Attrs & ParamAttr::ZExt)
    Result += "zext ";
  if (Attrs & ParamAttr::SExt)
    Result += "sext ";
  if (Attrs & ParamAttr::NoReturn)
    Result += "noreturn ";
  if (Attrs & ParamAttr::NoUnwind)
    Result += "nounwind ";
  if (Attrs & ParamAttr::InReg)
    Result += "inreg ";
  if (Attrs & ParamAttr::StructRet)
    Result += "sret ";
  return Result;
}

void
ParamAttrsList::addAttributes(uint16_t Index, uint16_t Attrs) {
  // First, try to replace an existing one
  for (unsigned i = 0; i < attrs.size(); ++i)
    if (attrs[i].index == Index) {
      attrs[i].attrs |= Attrs;
      return;
    }

  // If not found, add a new one
  ParamAttrsWithIndex Val;
  Val.attrs = Attrs;
  Val.index = Index;
  attrs.push_back(Val);
}

void
ParamAttrsList::removeAttributes(uint16_t Index, uint16_t Attrs) {
  // Find the index from which to remove the attributes
  for (unsigned i = 0; i < attrs.size(); ++i)
    if (attrs[i].index == Index) {
      attrs[i].attrs &= ~Attrs;
      if (attrs[i].attrs == ParamAttr::None)
        attrs.erase(&attrs[i]);
      return;
    }

  // The index wasn't found above
  assert(0 && "Index not found for removeAttributes");
}

//===----------------------------------------------------------------------===//
// Function Implementation
//===----------------------------------------------------------------------===//

Function::Function(const FunctionType *Ty, LinkageTypes Linkage,
                   const std::string &name, Module *ParentModule)
  : GlobalValue(PointerType::get(Ty), Value::FunctionVal, 0, 0, Linkage, name) {
  ParamAttrs = 0;
  CallingConvention = 0;
  BasicBlocks.setItemParent(this);
  BasicBlocks.setParent(this);
  ArgumentList.setItemParent(this);
  ArgumentList.setParent(this);
  SymTab = new ValueSymbolTable();

  assert((getReturnType()->isFirstClassType() ||getReturnType() == Type::VoidTy)
         && "LLVM functions cannot return aggregate values!");

  // Create the arguments vector, all arguments start out unnamed.
  for (unsigned i = 0, e = Ty->getNumParams(); i != e; ++i) {
    assert(Ty->getParamType(i) != Type::VoidTy &&
           "Cannot have void typed arguments!");
    ArgumentList.push_back(new Argument(Ty->getParamType(i)));
  }

  // Make sure that we get added to a function
  LeakDetector::addGarbageObject(this);

  if (ParentModule)
    ParentModule->getFunctionList().push_back(this);
}

Function::~Function() {
  dropAllReferences();    // After this it is safe to delete instructions.

  // Delete all of the method arguments and unlink from symbol table...
  ArgumentList.clear();
  ArgumentList.setParent(0);
  delete SymTab;
}

void Function::setParent(Module *parent) {
  if (getParent())
    LeakDetector::addGarbageObject(this);
  Parent = parent;
  if (getParent())
    LeakDetector::removeGarbageObject(this);
}

const FunctionType *Function::getFunctionType() const {
  return cast<FunctionType>(getType()->getElementType());
}

bool Function::isVarArg() const {
  return getFunctionType()->isVarArg();
}

const Type *Function::getReturnType() const {
  return getFunctionType()->getReturnType();
}

void Function::removeFromParent() {
  getParent()->getFunctionList().remove(this);
}

void Function::eraseFromParent() {
  getParent()->getFunctionList().erase(this);
}

// dropAllReferences() - This function causes all the subinstructions to "let
// go" of all references that they are maintaining.  This allows one to
// 'delete' a whole class at a time, even though there may be circular
// references... first all references are dropped, and all use counts go to
// zero.  Then everything is deleted for real.  Note that no operations are
// valid on an object that has "dropped all references", except operator
// delete.
//
void Function::dropAllReferences() {
  for (iterator I = begin(), E = end(); I != E; ++I)
    I->dropAllReferences();
  BasicBlocks.clear();    // Delete all basic blocks...
}

/// getIntrinsicID - This method returns the ID number of the specified
/// function, or Intrinsic::not_intrinsic if the function is not an
/// intrinsic, or if the pointer is null.  This value is always defined to be
/// zero to allow easy checking for whether a function is intrinsic or not.  The
/// particular intrinsic functions which correspond to this value are defined in
/// llvm/Intrinsics.h.
///
unsigned Function::getIntrinsicID(bool noAssert) const {
  const ValueName *ValName = this->getValueName();
  unsigned Len = ValName->getKeyLength();
  const char *Name = ValName->getKeyData();

  if (Len <= 5 || Name[4] != '.' || Name[0] != 'l' || Name[1] != 'l'
      || Name[2] != 'v' || Name[3] != 'm')
    return 0;  // All intrinsics start with 'llvm.'

  assert((Len != 5 || noAssert) && "'llvm.' is an invalid intrinsic name!");

#define GET_FUNCTION_RECOGNIZER
#include "llvm/Intrinsics.gen"
#undef GET_FUNCTION_RECOGNIZER
  assert(noAssert && "Invalid LLVM intrinsic name");
  return 0;
}

std::string Intrinsic::getName(ID id, const Type **Tys, unsigned numTys) {
  assert(id < num_intrinsics && "Invalid intrinsic ID!");
  const char * const Table[] = {
    "not_intrinsic",
#define GET_INTRINSIC_NAME_TABLE
#include "llvm/Intrinsics.gen"
#undef GET_INTRINSIC_NAME_TABLE
  };
  if (numTys == 0)
    return Table[id];
  std::string Result(Table[id]);
  for (unsigned i = 0; i < numTys; ++i)
    if (Tys[i])
      Result += "." + Tys[i]->getDescription();
  return Result;
}

const FunctionType *Intrinsic::getType(ID id, const Type **Tys,
                                       uint32_t numTys) {
  const Type *ResultTy = NULL;
  std::vector<const Type*> ArgTys;
  bool IsVarArg = false;

#define GET_INTRINSIC_GENERATOR
#include "llvm/Intrinsics.gen"
#undef GET_INTRINSIC_GENERATOR

  return FunctionType::get(ResultTy, ArgTys, IsVarArg);
}

Function *Intrinsic::getDeclaration(Module *M, ID id, const Type **Tys,
                                    unsigned numTys) {
// There can never be multiple globals with the same name of different types,
// because intrinsics must be a specific type.
  return cast<Function>(M->getOrInsertFunction(getName(id, Tys, numTys),
                                               getType(id, Tys, numTys)));
}

Value *IntrinsicInst::StripPointerCasts(Value *Ptr) {
  if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Ptr)) {
    if (CE->getOpcode() == Instruction::BitCast) {
      if (isa<PointerType>(CE->getOperand(0)->getType()))
        return StripPointerCasts(CE->getOperand(0));
    } else if (CE->getOpcode() == Instruction::GetElementPtr) {
      for (unsigned i = 1, e = CE->getNumOperands(); i != e; ++i)
        if (!CE->getOperand(i)->isNullValue())
          return Ptr;
      return StripPointerCasts(CE->getOperand(0));
    }
    return Ptr;
  }

  if (BitCastInst *CI = dyn_cast<BitCastInst>(Ptr)) {
    if (isa<PointerType>(CI->getOperand(0)->getType()))
      return StripPointerCasts(CI->getOperand(0));
  } else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Ptr)) {
    for (unsigned i = 1, e = GEP->getNumOperands(); i != e; ++i)
      if (!isa<Constant>(GEP->getOperand(i)) ||
          !cast<Constant>(GEP->getOperand(i))->isNullValue())
        return Ptr;
    return StripPointerCasts(GEP->getOperand(0));
  }
  return Ptr;
}

// vim: sw=2 ai
<commit_msg>Fix test/CodeGen/Generic/vector-constantexpr.ll<commit_after>//===-- Function.cpp - Implement the Global object classes ----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the Function class for the VMCore library.
//
//===----------------------------------------------------------------------===//

#include "llvm/Module.h"
#include "llvm/DerivedTypes.h"
#include "llvm/ParameterAttributes.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/Support/LeakDetector.h"
#include "SymbolTableListTraitsImpl.h"
#include "llvm/ADT/StringExtras.h"
using namespace llvm;

BasicBlock *ilist_traits<BasicBlock>::createSentinel() {
  BasicBlock *Ret = new BasicBlock();
  // This should not be garbage monitored.
  LeakDetector::removeGarbageObject(Ret);
  return Ret;
}

iplist<BasicBlock> &ilist_traits<BasicBlock>::getList(Function *F) {
  return F->getBasicBlockList();
}

Argument *ilist_traits<Argument>::createSentinel() {
  Argument *Ret = new Argument(Type::Int32Ty);
  // This should not be garbage monitored.
  LeakDetector::removeGarbageObject(Ret);
  return Ret;
}

iplist<Argument> &ilist_traits<Argument>::getList(Function *F) {
  return F->getArgumentList();
}

// Explicit instantiations of SymbolTableListTraits since some of the methods
// are not in the public header file...
template class SymbolTableListTraits<Argument, Function, Function>;
template class SymbolTableListTraits<BasicBlock, Function, Function>;

//===----------------------------------------------------------------------===//
// Argument Implementation
//===----------------------------------------------------------------------===//

Argument::Argument(const Type *Ty, const std::string &Name, Function *Par)
  : Value(Ty, Value::ArgumentVal) {
  Parent = 0;

  // Make sure that we get added to a function
  LeakDetector::addGarbageObject(this);

  if (Par)
    Par->getArgumentList().push_back(this);
  setName(Name);
}

void Argument::setParent(Function *parent) {
  if (getParent())
    LeakDetector::addGarbageObject(this);
  Parent = parent;
  if (getParent())
    LeakDetector::removeGarbageObject(this);
}

//===----------------------------------------------------------------------===//
// ParamAttrsList Implementation
//===----------------------------------------------------------------------===//

uint16_t
ParamAttrsList::getParamAttrs(uint16_t Index) const {
  unsigned limit = attrs.size();
  for (unsigned i = 0; i < limit; ++i)
    if (attrs[i].index == Index)
      return attrs[i].attrs;
  return ParamAttr::None;
}

std::string
ParamAttrsList::getParamAttrsText(uint16_t Attrs) {
  std::string Result;
  if (Attrs & ParamAttr::ZExt)
    Result += "zext ";
  if (Attrs & ParamAttr::SExt)
    Result += "sext ";
  if (Attrs & ParamAttr::NoReturn)
    Result += "noreturn ";
  if (Attrs & ParamAttr::NoUnwind)
    Result += "nounwind ";
  if (Attrs & ParamAttr::InReg)
    Result += "inreg ";
  if (Attrs & ParamAttr::StructRet)
    Result += "sret ";
  return Result;
}

void
ParamAttrsList::addAttributes(uint16_t Index, uint16_t Attrs) {
  // First, try to replace an existing one
  for (unsigned i = 0; i < attrs.size(); ++i)
    if (attrs[i].index == Index) {
      attrs[i].attrs |= Attrs;
      return;
    }

  // If not found, add a new one
  ParamAttrsWithIndex Val;
  Val.attrs = Attrs;
  Val.index = Index;
  attrs.push_back(Val);
}

void
ParamAttrsList::removeAttributes(uint16_t Index, uint16_t Attrs) {
  // Find the index from which to remove the attributes
  for (unsigned i = 0; i < attrs.size(); ++i)
    if (attrs[i].index == Index) {
      attrs[i].attrs &= ~Attrs;
      if (attrs[i].attrs == ParamAttr::None)
        attrs.erase(&attrs[i]);
      return;
    }

  // The index wasn't found above
  assert(0 && "Index not found for removeAttributes");
}

//===----------------------------------------------------------------------===//
// Function Implementation
//===----------------------------------------------------------------------===//

Function::Function(const FunctionType *Ty, LinkageTypes Linkage,
                   const std::string &name, Module *ParentModule)
  : GlobalValue(PointerType::get(Ty), Value::FunctionVal, 0, 0, Linkage, name) {
  ParamAttrs = 0;
  CallingConvention = 0;
  BasicBlocks.setItemParent(this);
  BasicBlocks.setParent(this);
  ArgumentList.setItemParent(this);
  ArgumentList.setParent(this);
  SymTab = new ValueSymbolTable();

  assert((getReturnType()->isFirstClassType() ||getReturnType() == Type::VoidTy)
         && "LLVM functions cannot return aggregate values!");

  // Create the arguments vector, all arguments start out unnamed.
  for (unsigned i = 0, e = Ty->getNumParams(); i != e; ++i) {
    assert(Ty->getParamType(i) != Type::VoidTy &&
           "Cannot have void typed arguments!");
    ArgumentList.push_back(new Argument(Ty->getParamType(i)));
  }

  // Make sure that we get added to a function
  LeakDetector::addGarbageObject(this);

  if (ParentModule)
    ParentModule->getFunctionList().push_back(this);
}

Function::~Function() {
  dropAllReferences();    // After this it is safe to delete instructions.

  // Delete all of the method arguments and unlink from symbol table...
  ArgumentList.clear();
  ArgumentList.setParent(0);
  delete SymTab;
}

void Function::setParent(Module *parent) {
  if (getParent())
    LeakDetector::addGarbageObject(this);
  Parent = parent;
  if (getParent())
    LeakDetector::removeGarbageObject(this);
}

const FunctionType *Function::getFunctionType() const {
  return cast<FunctionType>(getType()->getElementType());
}

bool Function::isVarArg() const {
  return getFunctionType()->isVarArg();
}

const Type *Function::getReturnType() const {
  return getFunctionType()->getReturnType();
}

void Function::removeFromParent() {
  getParent()->getFunctionList().remove(this);
}

void Function::eraseFromParent() {
  getParent()->getFunctionList().erase(this);
}

// dropAllReferences() - This function causes all the subinstructions to "let
// go" of all references that they are maintaining.  This allows one to
// 'delete' a whole class at a time, even though there may be circular
// references... first all references are dropped, and all use counts go to
// zero.  Then everything is deleted for real.  Note that no operations are
// valid on an object that has "dropped all references", except operator
// delete.
//
void Function::dropAllReferences() {
  for (iterator I = begin(), E = end(); I != E; ++I)
    I->dropAllReferences();
  BasicBlocks.clear();    // Delete all basic blocks...
}

/// getIntrinsicID - This method returns the ID number of the specified
/// function, or Intrinsic::not_intrinsic if the function is not an
/// intrinsic, or if the pointer is null.  This value is always defined to be
/// zero to allow easy checking for whether a function is intrinsic or not.  The
/// particular intrinsic functions which correspond to this value are defined in
/// llvm/Intrinsics.h.
///
unsigned Function::getIntrinsicID(bool noAssert) const {
  const ValueName *ValName = this->getValueName();
  if (!ValName)
    return 0;
  unsigned Len = ValName->getKeyLength();
  const char *Name = ValName->getKeyData();

  if (Len <= 5 || Name[4] != '.' || Name[0] != 'l' || Name[1] != 'l'
      || Name[2] != 'v' || Name[3] != 'm')
    return 0;  // All intrinsics start with 'llvm.'

  assert((Len != 5 || noAssert) && "'llvm.' is an invalid intrinsic name!");

#define GET_FUNCTION_RECOGNIZER
#include "llvm/Intrinsics.gen"
#undef GET_FUNCTION_RECOGNIZER
  assert(noAssert && "Invalid LLVM intrinsic name");
  return 0;
}

std::string Intrinsic::getName(ID id, const Type **Tys, unsigned numTys) {
  assert(id < num_intrinsics && "Invalid intrinsic ID!");
  const char * const Table[] = {
    "not_intrinsic",
#define GET_INTRINSIC_NAME_TABLE
#include "llvm/Intrinsics.gen"
#undef GET_INTRINSIC_NAME_TABLE
  };
  if (numTys == 0)
    return Table[id];
  std::string Result(Table[id]);
  for (unsigned i = 0; i < numTys; ++i)
    if (Tys[i])
      Result += "." + Tys[i]->getDescription();
  return Result;
}

const FunctionType *Intrinsic::getType(ID id, const Type **Tys,
                                       uint32_t numTys) {
  const Type *ResultTy = NULL;
  std::vector<const Type*> ArgTys;
  bool IsVarArg = false;

#define GET_INTRINSIC_GENERATOR
#include "llvm/Intrinsics.gen"
#undef GET_INTRINSIC_GENERATOR

  return FunctionType::get(ResultTy, ArgTys, IsVarArg);
}

Function *Intrinsic::getDeclaration(Module *M, ID id, const Type **Tys,
                                    unsigned numTys) {
// There can never be multiple globals with the same name of different types,
// because intrinsics must be a specific type.
  return cast<Function>(M->getOrInsertFunction(getName(id, Tys, numTys),
                                               getType(id, Tys, numTys)));
}

Value *IntrinsicInst::StripPointerCasts(Value *Ptr) {
  if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Ptr)) {
    if (CE->getOpcode() == Instruction::BitCast) {
      if (isa<PointerType>(CE->getOperand(0)->getType()))
        return StripPointerCasts(CE->getOperand(0));
    } else if (CE->getOpcode() == Instruction::GetElementPtr) {
      for (unsigned i = 1, e = CE->getNumOperands(); i != e; ++i)
        if (!CE->getOperand(i)->isNullValue())
          return Ptr;
      return StripPointerCasts(CE->getOperand(0));
    }
    return Ptr;
  }

  if (BitCastInst *CI = dyn_cast<BitCastInst>(Ptr)) {
    if (isa<PointerType>(CI->getOperand(0)->getType()))
      return StripPointerCasts(CI->getOperand(0));
  } else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Ptr)) {
    for (unsigned i = 1, e = GEP->getNumOperands(); i != e; ++i)
      if (!isa<Constant>(GEP->getOperand(i)) ||
          !cast<Constant>(GEP->getOperand(i))->isNullValue())
        return Ptr;
    return StripPointerCasts(GEP->getOperand(0));
  }
  return Ptr;
}

// vim: sw=2 ai
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2014 Artem Pavlenko
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_JSON_ERROR_HANDLER_HPP
#define MAPNIK_JSON_ERROR_HANDLER_HPP

#include <string>
#include <sstream>
#include <boost/spirit/home/support/info.hpp>

namespace mapnik { namespace json {

template <typename Iterator>
struct error_handler
{
    using result_type = void;
    void operator() (
        Iterator, Iterator last,
        Iterator err_pos, boost::spirit::info const& what) const
    {
        std::stringstream s;
        s << what << " expected but got: " << std::string(err_pos, std::min(err_pos + 16,last));
        throw std::runtime_error(s.str());
    }
};

}}

#endif // MAPNIK_JSON_ERROR_HANDLER_HPP
<commit_msg>use std::advance to work with std::iterators<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2014 Artem Pavlenko
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_JSON_ERROR_HANDLER_HPP
#define MAPNIK_JSON_ERROR_HANDLER_HPP

#include <string>
#include <sstream>
#include <boost/spirit/home/support/info.hpp>

namespace mapnik { namespace json {

template <typename Iterator>
struct error_handler
{
    using result_type = void;
    void operator() (
        Iterator, Iterator last,
        Iterator err_pos, boost::spirit::info const& what) const
    {
        std::stringstream s;
        auto start = err_pos;
        std::advance(err_pos,16);
        auto end = err_pos;
        s << what << " expected but got: " << std::string(start, end);
        throw std::runtime_error(s.str());
    }
};

}}

#endif // MAPNIK_JSON_ERROR_HANDLER_HPP
<|endoftext|>


<commit_before>#ifndef CORE_STORAGE_TPP
#define CORE_STORAGE_TPP

#include "../storage.hpp"
#include "nnlib/serialization/serialized.hpp"

namespace nnlib
{

template <typename T>
Storage<T>::Storage(size_t n, const T &defaultValue) :
    m_ptr(new T[n]),
    m_size(n),
    m_capacity(n)
{
    for(size_t i = 0; i < n; ++i)
        m_ptr[i] = defaultValue;
}

template <typename T>
Storage<T>::Storage(const Storage<T> &copy) :
    m_ptr(new T[copy.size()]),
    m_size(copy.size()),
    m_capacity(copy.size())
{
    size_t index = 0;
    for(const T &value : copy)
    {
        m_ptr[index] = value;
        ++index;
    }
}

template <typename T>
Storage<T>::Storage(Storage<T> &&rhs) :
    m_ptr(rhs.m_ptr),
    m_size(rhs.m_size),
    m_capacity(rhs.m_capacity)
{
    rhs.m_ptr		= nullptr;
    rhs.m_size		= 0;
    rhs.m_capacity	= 0;
}

template <typename T>
Storage<T>::Storage(const std::initializer_list<T> &values) :
    m_ptr(new T[values.size()]),
    m_size(values.size()),
    m_capacity(values.size())
{
    size_t index = 0;
    for(const T &value : values)
    {
        m_ptr[index] = value;
        ++index;
    }
}

template <typename T>
Storage<T>::Storage(const Serialized &node) :
    m_ptr(new T[node.size()]),
    m_size(node.size()),
    m_capacity(node.size())
{
    node.get(begin(), end());
}

template <typename T>
Storage<T>::~Storage()
{
    delete[] m_ptr;
}

template <typename T>
Storage<T> &Storage<T>::operator=(const Storage<T> &copy)
{
    if(this != &copy)
    {
        resize(copy.size());
        size_t index = 0;
        for(const T &value : copy)
        {
            m_ptr[index] = value;
            ++index;
        }
    }
    return *this;
}

template <typename T>
Storage<T> &Storage<T>::operator=(const std::initializer_list<T> &values)
{
    resize(values.size());
    size_t index = 0;
    for(const T &value : values)
    {
        m_ptr[index] = value;
        ++index;
    }
    return *this;
}

template <typename T>
Storage<T> &Storage<T>::resize(size_t n, const T &defaultValue)
{
    reserve(n);
    for(size_t i = m_size; i < n; ++i)
        m_ptr[i] = defaultValue;
    m_size = n;
    return *this;
}

template <typename T>
Storage<T> &Storage<T>::reserve(size_t n)
{
    if(n > m_capacity)
    {
        T *ptr = new T[n];
        for(size_t i = 0; i < m_size; ++i)
            ptr[i] = m_ptr[i];
        delete[] m_ptr;
        m_ptr = ptr;
        m_capacity = n;
    }
    return *this;
}

template <typename T>
Storage<T> &Storage<T>::push_back(const T &value)
{
    resize(m_size + 1);
    m_ptr[m_size - 1] = value;
    return *this;
}

template <typename T>
Storage<T> &Storage<T>::pop_back()
{
    --m_size;
    return *this;
}

template <typename T>
Storage<T> &Storage<T>::append(const Storage<T> &other)
{
    reserve(m_size + other.m_size);
    for(const T &value : other)
        push_back(value);
    return *this;
}

template <typename T>
Storage<T> &Storage<T>::erase(size_t index)
{
    NNAssertLessThan(index, m_size, "Attempted to erase an index that is out of bounds!");
    for(size_t i = index + 1; i < m_size; ++i)
    {
        m_ptr[i - 1] = m_ptr[i];
    }
    --m_size;
    return *this;
}

template <typename T>
Storage<T> &Storage<T>::clear()
{
    m_size = 0;
    return *this;
}

template <typename T>
T *Storage<T>::ptr()
{
    return m_ptr;
}

template <typename T>
const T *Storage<T>::ptr() const
{
    return m_ptr;
}

template <typename T>
size_t Storage<T>::size() const
{
    return m_size;
}

template <typename T>
bool Storage<T>::operator==(const Storage<T> &other) const
{
    if(this == &other)
    {
        return true;
    }
    if(m_size != other.m_size)
    {
        return false;
    }
    for(size_t i = 0; i < other.m_size; ++i)
    {
        if(m_ptr[i] != other.m_ptr[i])
        {
            return false;
        }
    }
    return true;
}

template <typename T>
bool Storage<T>::operator!=(const Storage<T> &other) const
{
    return !(*this == other);
}

template <typename T>
T &Storage<T>::at(size_t i)
{
    NNAssertLessThan(i, m_size, "Attempted to access an index that is out of bounds!");
    return m_ptr[i];
}

template <typename T>
const T &Storage<T>::at(size_t i) const
{
    NNAssertLessThan(i, m_size, "Attempted to access an index that is out of bounds!");
    return m_ptr[i];
}

template <typename T>
T &Storage<T>::operator[](size_t i)
{
    NNAssertLessThan(i, m_size, "Attempted to access an index that is out of bounds!");
    return m_ptr[i];
}

template <typename T>
const T &Storage<T>::operator[](size_t i) const
{
    NNAssertLessThan(i, m_size, "Attempted to access an index that is out of bounds!");
    return m_ptr[i];
}

template <typename T>
T &Storage<T>::front()
{
    NNAssertGreaterThan(m_size, 0, "Attempted to access an index that is out of bounds!");
    return *m_ptr;
}

template <typename T>
const T &Storage<T>::front() const
{
    NNAssertGreaterThan(m_size, 0, "Attempted to access an index that is out of bounds!");
    return *m_ptr;
}

template <typename T>
T &Storage<T>::back()
{
    NNAssertGreaterThan(m_size, 0, "Attempted to access an index that is out of bounds!");
    return m_ptr[m_size - 1];
}

template <typename T>
const T &Storage<T>::back() const
{
    NNAssertGreaterThan(m_size, 0, "Attempted to access an index that is out of bounds!");
    return m_ptr[m_size - 1];
}

template <typename T>
T *Storage<T>::begin()
{
    return m_ptr;
}

template <typename T>
const T *Storage<T>::begin() const
{
    return m_ptr;
}

template <typename T>
T *Storage<T>::end()
{
    return m_ptr + m_size;
}

template <typename T>
const T *Storage<T>::end() const
{
    return m_ptr + m_size;
}

template <typename T>
void Storage<T>::save(Serialized &node) const
{
    node.set(begin(), end());
}

}

#endif
<commit_msg>Changed some formatting things.<commit_after>#ifndef CORE_STORAGE_TPP
#define CORE_STORAGE_TPP

#include "../storage.hpp"
#include "nnlib/serialization/serialized.hpp"

namespace nnlib
{

template <typename T>
Storage<T>::Storage(size_t n, const T &defaultValue) :
    m_ptr(new T[n]),
    m_size(n),
    m_capacity(n)
{
    for(size_t i = 0; i < n; ++i)
        m_ptr[i] = defaultValue;
}

template <typename T>
Storage<T>::Storage(const Storage<T> &copy) :
    m_ptr(new T[copy.size()]),
    m_size(copy.size()),
    m_capacity(copy.size())
{
    size_t index = 0;
    for(const T &value : copy)
    {
        m_ptr[index] = value;
        ++index;
    }
}

template <typename T>
Storage<T>::Storage(Storage<T> &&rhs) :
    m_ptr(rhs.m_ptr),
    m_size(rhs.m_size),
    m_capacity(rhs.m_capacity)
{
    rhs.m_ptr		= nullptr;
    rhs.m_size		= 0;
    rhs.m_capacity	= 0;
}

template <typename T>
Storage<T>::Storage(const std::initializer_list<T> &values) :
    m_ptr(new T[values.size()]),
    m_size(values.size()),
    m_capacity(values.size())
{
    size_t index = 0;
    for(const T &value : values)
    {
        m_ptr[index] = value;
        ++index;
    }
}

template <typename T>
Storage<T>::Storage(const Serialized &node) :
    m_ptr(new T[node.size()]),
    m_size(node.size()),
    m_capacity(node.size())
{
    node.get(begin(), end());
}

template <typename T>
Storage<T>::~Storage()
{
    delete[] m_ptr;
}

template <typename T>
Storage<T> &Storage<T>::operator=(const Storage<T> &copy)
{
    if(this != &copy)
    {
        resize(copy.size());
        size_t index = 0;
        for(const T &value : copy)
        {
            m_ptr[index] = value;
            ++index;
        }
    }
    return *this;
}

template <typename T>
Storage<T> &Storage<T>::operator=(const std::initializer_list<T> &values)
{
    resize(values.size());
    size_t index = 0;
    for(const T &value : values)
    {
        m_ptr[index] = value;
        ++index;
    }
    return *this;
}

template <typename T>
Storage<T> &Storage<T>::resize(size_t n, const T &defaultValue)
{
    reserve(n);
    for(size_t i = m_size; i < n; ++i)
        m_ptr[i] = defaultValue;
    m_size = n;
    return *this;
}

template <typename T>
Storage<T> &Storage<T>::reserve(size_t n)
{
    if(n > m_capacity)
    {
        T *ptr = new T[n];
        for(size_t i = 0; i < m_size; ++i)
            ptr[i] = m_ptr[i];
        delete[] m_ptr;
        m_ptr = ptr;
        m_capacity = n;
    }
    return *this;
}

template <typename T>
Storage<T> &Storage<T>::push_back(const T &value)
{
    resize(m_size + 1);
    m_ptr[m_size - 1] = value;
    return *this;
}

template <typename T>
Storage<T> &Storage<T>::pop_back()
{
    --m_size;
    return *this;
}

template <typename T>
Storage<T> &Storage<T>::append(const Storage<T> &other)
{
    reserve(m_size + other.m_size);
    for(const T &value : other)
        push_back(value);
    return *this;
}

template <typename T>
Storage<T> &Storage<T>::erase(size_t index)
{
    NNAssertLessThan(index, m_size, "Attempted to erase an index that is out of bounds!");
    for(size_t i = index + 1; i < m_size; ++i)
        m_ptr[i - 1] = m_ptr[i];
    --m_size;
    return *this;
}

template <typename T>
Storage<T> &Storage<T>::clear()
{
    m_size = 0;
    return *this;
}

template <typename T>
T *Storage<T>::ptr()
{
    return m_ptr;
}

template <typename T>
const T *Storage<T>::ptr() const
{
    return m_ptr;
}

template <typename T>
size_t Storage<T>::size() const
{
    return m_size;
}

template <typename T>
bool Storage<T>::operator==(const Storage<T> &other) const
{
    if(this == &other)
        return true;
    else if(m_size != other.m_size)
        return false;

    for(size_t i = 0; i < other.m_size; ++i)
        if(m_ptr[i] != other.m_ptr[i])
            return false;

    return true;
}

template <typename T>
bool Storage<T>::operator!=(const Storage<T> &other) const
{
    return !(*this == other);
}

template <typename T>
T &Storage<T>::at(size_t i)
{
    NNAssertLessThan(i, m_size, "Attempted to access an index that is out of bounds!");
    return m_ptr[i];
}

template <typename T>
const T &Storage<T>::at(size_t i) const
{
    NNAssertLessThan(i, m_size, "Attempted to access an index that is out of bounds!");
    return m_ptr[i];
}

template <typename T>
T &Storage<T>::operator[](size_t i)
{
    NNAssertLessThan(i, m_size, "Attempted to access an index that is out of bounds!");
    return m_ptr[i];
}

template <typename T>
const T &Storage<T>::operator[](size_t i) const
{
    NNAssertLessThan(i, m_size, "Attempted to access an index that is out of bounds!");
    return m_ptr[i];
}

template <typename T>
T &Storage<T>::front()
{
    NNAssertGreaterThan(m_size, 0, "Attempted to access an index that is out of bounds!");
    return *m_ptr;
}

template <typename T>
const T &Storage<T>::front() const
{
    NNAssertGreaterThan(m_size, 0, "Attempted to access an index that is out of bounds!");
    return *m_ptr;
}

template <typename T>
T &Storage<T>::back()
{
    NNAssertGreaterThan(m_size, 0, "Attempted to access an index that is out of bounds!");
    return m_ptr[m_size - 1];
}

template <typename T>
const T &Storage<T>::back() const
{
    NNAssertGreaterThan(m_size, 0, "Attempted to access an index that is out of bounds!");
    return m_ptr[m_size - 1];
}

template <typename T>
T *Storage<T>::begin()
{
    return m_ptr;
}

template <typename T>
const T *Storage<T>::begin() const
{
    return m_ptr;
}

template <typename T>
T *Storage<T>::end()
{
    return m_ptr + m_size;
}

template <typename T>
const T *Storage<T>::end() const
{
    return m_ptr + m_size;
}

template <typename T>
void Storage<T>::save(Serialized &node) const
{
    node.set(begin(), end());
}

}

#endif
<|endoftext|>


<commit_before>/* ************************************************************************* */
/* This file is part of Shard.                                               */
/*                                                                           */
/* Shard is free software: you can redistribute it and/or modify             */
/* it under the terms of the GNU Affero General Public License 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 or FITNESS FOR A PARTICULAR PURPOSE. See the              */
/* GNU Affero General Public License for more details.                       */
/*                                                                           */
/* You should have received a copy of the GNU Affero General Public License  */
/* along with this program. If not, see <http://www.gnu.org/licenses/>.      */
/* ************************************************************************* */

#pragma once

/* ************************************************************************* */

// Shard
#include "shard/Path.hpp"
#include "shard/Assert.hpp"
#include "shard/String.hpp"
#include "shard/ViewPtr.hpp"
#include "shard/tokenizer/Source.hpp"
#include "shard/tokenizer/KeywordType.hpp"
#include "shard/tokenizer/TokenType.hpp"
#include "shard/tokenizer/Token.hpp"
#include "shard/tokenizer/TokenizerException.hpp"

/* ************************************************************************* */

namespace shard {
inline namespace v1 {
namespace tokenizer {

/* ************************************************************************* */

class Tokenizer; //FWD declaration

/* ************************************************************************* */

/**
 * @brief Input iterator from Shard lexical analyzer.
 */
class TokenizerIterator
{

protected:

    ViewPtr<Tokenizer> m_tokenizer;

public:

    /**
     * @brief constructs empty TokenizerIterator.
     */
    TokenizerIterator() = default;

    /**
     * @brief constructs TokenizerIterator for given Tokenizer.
     */
    explicit TokenizerIterator(ViewPtr<Tokenizer> tokenizer):
        m_tokenizer(tokenizer) {}

    inline const Token& operator*() const;
    inline TokenizerIterator& operator++();
    inline TokenizerIterator operator++(int);

    /**
     * @brief returns pointer to related tokenizer.
     */
    inline ViewPtr<Tokenizer> getTokenizer() const noexcept
    {
        return m_tokenizer;
    }
};

/* ************************************************************************* */

/**
 * @brief checks whether lhs or rhs is at final token.
 *
 * This operator serves for range-for purposes.
 */
inline bool operator==(const TokenizerIterator& lhs, const TokenizerIterator& rhs)
{
    return (lhs.getTokenizer() == nullptr || (*lhs).getType() == TokenType::End)
        && (rhs.getTokenizer() == nullptr || (*rhs).getType() == TokenType::End);
}

inline bool operator!=(const TokenizerIterator& lhs, const TokenizerIterator& rhs)
{
    return !(lhs == rhs);
}

/* ************************************************************************* */

/**
 * @brief Shard lexical analyzer.
 */
class Tokenizer
{

protected:

    Source m_src;
    Token m_current;

    static constexpr char string_literal_border = '"';
    static constexpr char char_literal_border = '\'';

/* ************************************************************************* */

public:

    /**
     * @brief constructs Tokenizer which reads from file.
     */
    explicit Tokenizer(const Path& path): m_src(path)
    {
        next();
    }

    /**
     * @brief constructs Tokenizer which reads from String.
     */
    explicit Tokenizer(const String& source): m_src(source)
    {
        next();
    }

/* ************************************************************************* */

protected:

    /**
     * @brief returns if current character is between two chars in the ASCII table.
     */
    inline bool isBetween(char value1, char value2) noexcept
    {
        return !empty() && (m_src.get() >= value1) && (m_src.get() <= value2);
    }

    /**
    * @brief returns if current character is whitespace.
    */
    inline bool isWhitespace() noexcept
    {
        return isBetween('\1', ' ');
    }

    /**
     * @brief returns if current character is a letter.
     */
    inline bool isLetter() noexcept
    {
        return isBetween('a', 'z') || isBetween('A', 'Z');
    }

    /**
     * @brief returns if current character is a letter, number or '_'.
     */
    inline bool isIdentifier() noexcept
    {
        return isBetween('a', 'z') || isBetween('A', 'Z') || isDigit() || is('_');
    }

    /**
     * @brief returns if current character is a number in given numeric system.
     */
    inline bool isDigit(int base = 10) noexcept
    {
        SHARD_ASSERT(base == 10 || base == 16 || base == 8 || base == 2);
        switch (base)
        {
            case 10: return isBetween('0', '9');
            case 16: return isBetween('0', '9') || isBetween('a', 'f') || isBetween('A', 'F');
            case 8: return isBetween('0', '7');
            case 2: return isBetween('0', '1');
        }
    }

    /**
     * @brief returns if current character is tested character.
     */
    inline bool is(char value) noexcept
    {
        return !empty() && m_src.get() == value;
    }

    /**
     * @brief returns if current character is one of tested characters.
     */
    template<typename... Chars>
    inline bool is(char a, Chars... options) noexcept
    {
        char chars[]{a, options...};
        for (const char option : chars)
        {
            if (is(option))
            {
                return true;
            }
        }
        return false;
    }

    /**
     * @brief returns if current character is tested character.
     * If so, moves to next character.
     */
    inline bool match(char value) noexcept
    {
        if (is(value))
        {
            m_src.toss();
            return true;
        }
        return false;
    }

    /**
     * @brief returns if current character is one of tested characters.
     * If so, moves to next character.
     */
    template<typename... Chars>
    inline bool match(Chars... options) noexcept
    {
        const char chars[]{options...};
        for (const char option : chars)
        {
            if (is(option))
            {
                m_src.toss();
                return true;
            }
        }
        return false;
    }

/* ************************************************************************* */

protected:

    /**
     * @brief Iterates to next non-whitespace char.
     */
    inline void skipWhitespace() noexcept
    {
        while (isWhitespace())
        {
            m_src.toss();
        }
    }

    /**
     * @brief chcecks if source is empty.
     */
    inline bool empty()
    {
        return m_src.empty();
    }

/* ************************************************************************* */

protected:

    /**
     * @brief tokenizes tokentype number.
     */
    void tokenizeNumber();

    /**
     * @brief tokenizes string into identifier.
     */
    void tokenizeIdentifier() noexcept;

    /**
     * @brief tokenizes string value into keyword, function or identifier.
     */
    void tokenizeString();

    /**
     * @brief tokenizes string value into keyword, function or identifier.
     */
    void tokenizeChar();

    /**
     * @brief tokenizes operators.
     */
    void tokenizeOperator();

/* ************************************************************************* */

public:

    /**
     * @brief go to next token.
     */
    void next();

    /**
     * @brief get current token.
     */
    inline const Token& get() const noexcept
    {
        return m_current;
    }

    /**
     * @brief get current token an move to next.
     */
    inline Token extract()
    {
        auto tmp = m_current;
        next();
        return tmp;
    }

    /**
     * @brief checks if there is non-ending token available.
     */
    inline bool isEof()
    {
        return m_current.getType() == TokenType::End;
    }

/* ************************************************************************* */

public:

    /**
     * @brief returns tokenizer iterator pointing to currect token.
     */
    inline TokenizerIterator begin() noexcept
    {
        return TokenizerIterator(this);
    }

    /**
     * @brief returns tokenizer iterator pointing to token with end.
     */
    inline TokenizerIterator end() noexcept
    {
        return TokenizerIterator(nullptr);
    }
};

/* ************************************************************************* */

inline const Token& TokenizerIterator::operator*() const
{
    return m_tokenizer->get();
}

inline TokenizerIterator& TokenizerIterator::operator++()
{
    m_tokenizer->next();
    return *this;
}

inline TokenizerIterator TokenizerIterator::operator++(int)
{
    TokenizerIterator tmp(*this);
    operator++();
    return tmp;
}

/* ************************************************************************* */

}
}
}

/* ************************************************************************* */

<commit_msg>fixed comments<commit_after>/* ************************************************************************* */
/* This file is part of Shard.                                               */
/*                                                                           */
/* Shard is free software: you can redistribute it and/or modify             */
/* it under the terms of the GNU Affero General Public License 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 or FITNESS FOR A PARTICULAR PURPOSE. See the              */
/* GNU Affero General Public License for more details.                       */
/*                                                                           */
/* You should have received a copy of the GNU Affero General Public License  */
/* along with this program. If not, see <http://www.gnu.org/licenses/>.      */
/* ************************************************************************* */

#pragma once

/* ************************************************************************* */

// Shard
#include "shard/Path.hpp"
#include "shard/Assert.hpp"
#include "shard/String.hpp"
#include "shard/ViewPtr.hpp"
#include "shard/tokenizer/Source.hpp"
#include "shard/tokenizer/KeywordType.hpp"
#include "shard/tokenizer/TokenType.hpp"
#include "shard/tokenizer/Token.hpp"
#include "shard/tokenizer/TokenizerException.hpp"

/* ************************************************************************* */

namespace shard {
inline namespace v1 {
namespace tokenizer {

/* ************************************************************************* */

class Tokenizer; //FWD declaration

/* ************************************************************************* */

/**
 * @brief Input iterator from Shard lexical analyzer.
 */
class TokenizerIterator
{

protected:

    ViewPtr<Tokenizer> m_tokenizer;

public:

    /**
     * @brief constructs empty TokenizerIterator.
     */
    TokenizerIterator() = default;

    /**
     * @brief constructs TokenizerIterator for given Tokenizer.
     */
    explicit TokenizerIterator(ViewPtr<Tokenizer> tokenizer):
        m_tokenizer(tokenizer) {}

    inline const Token& operator*() const;
    inline TokenizerIterator& operator++();
    inline TokenizerIterator operator++(int);

    /**
     * @brief returns pointer to related tokenizer.
     */
    inline ViewPtr<Tokenizer> getTokenizer() const noexcept
    {
        return m_tokenizer;
    }
};

/* ************************************************************************* */

/**
 * @brief checks whether lhs or rhs is at final token.
 *
 * This operator serves for range-for purposes.
 */
inline bool operator==(const TokenizerIterator& lhs, const TokenizerIterator& rhs)
{
    return (lhs.getTokenizer() == nullptr || (*lhs).getType() == TokenType::End)
        && (rhs.getTokenizer() == nullptr || (*rhs).getType() == TokenType::End);
}

inline bool operator!=(const TokenizerIterator& lhs, const TokenizerIterator& rhs)
{
    return !(lhs == rhs);
}

/* ************************************************************************* */

/**
 * @brief Shard lexical analyzer.
 */
class Tokenizer
{

protected:

    Source m_src;
    Token m_current;

    static constexpr char string_literal_border = '"';
    static constexpr char char_literal_border = '\'';

/* ************************************************************************* */

public:

    /**
     * @brief constructs Tokenizer which reads from file.
     */
    explicit Tokenizer(const Path& path): m_src(path)
    {
        next();
    }

    /**
     * @brief constructs Tokenizer which reads from String.
     */
    explicit Tokenizer(const String& source): m_src(source)
    {
        next();
    }

/* ************************************************************************* */

protected:

    /**
     * @brief returns if current character is between two chars in the ASCII table.
     */
    inline bool isBetween(char value1, char value2) noexcept
    {
        return !empty() && (m_src.get() >= value1) && (m_src.get() <= value2);
    }

    /**
    * @brief returns if current character is whitespace.
    */
    inline bool isWhitespace() noexcept
    {
        return isBetween('\1', ' ');
    }

    /**
     * @brief returns if current character is a letter.
     */
    inline bool isLetter() noexcept
    {
        return isBetween('a', 'z') || isBetween('A', 'Z');
    }

    /**
     * @brief returns if current character is a letter, number or '_'.
     */
    inline bool isIdentifier() noexcept
    {
        return isBetween('a', 'z') || isBetween('A', 'Z') || isDigit() || is('_');
    }

    /**
     * @brief returns if current character is a number in given numeric system.
     */
    inline bool isDigit(int base = 10) noexcept
    {
        SHARD_ASSERT(base == 10 || base == 16 || base == 8 || base == 2);
        switch (base)
        {
            case 10: return isBetween('0', '9');
            case 16: return isBetween('0', '9') || isBetween('a', 'f') || isBetween('A', 'F');
            case 8: return isBetween('0', '7');
            case 2: return isBetween('0', '1');
        }
    }

    /**
     * @brief returns if current character is tested character.
     */
    inline bool is(char value) noexcept
    {
        return !empty() && m_src.get() == value;
    }

    /**
     * @brief returns if current character is one of tested characters.
     */
    template<typename... Chars>
    inline bool is(char a, Chars... options) noexcept
    {
        char chars[]{a, options...};
        for (const char option : chars)
        {
            if (is(option))
            {
                return true;
            }
        }
        return false;
    }

    /**
     * @brief returns if current character is tested character.
     * If so, moves to next character.
     */
    inline bool match(char value) noexcept
    {
        if (is(value))
        {
            m_src.toss();
            return true;
        }
        return false;
    }

    /**
     * @brief returns if current character is one of tested characters.
     * If so, moves to next character.
     */
    template<typename... Chars>
    inline bool match(Chars... options) noexcept
    {
        const char chars[]{options...};
        for (const char option : chars)
        {
            if (is(option))
            {
                m_src.toss();
                return true;
            }
        }
        return false;
    }

/* ************************************************************************* */

protected:

    /**
     * @brief Iterates to next non-whitespace char.
     */
    inline void skipWhitespace() noexcept
    {
        while (isWhitespace())
        {
            m_src.toss();
        }
    }

    /**
     * @brief chcecks if source is empty.
     */
    inline bool empty()
    {
        return m_src.empty();
    }

/* ************************************************************************* */

protected:

    /**
     * @brief tokenizes tokentype number.
     */
    void tokenizeNumber();

    /**
     * @brief tokenizes string into identifier.
     */
    void tokenizeIdentifier() noexcept;

    /**
     * @brief tokenizes string value into keyword, function or identifier.
     */
    void tokenizeString();

    /**
     * @brief tokenizes string value into keyword, function or identifier.
     */
    void tokenizeChar();

    /**
     * @brief tokenizes operators.
     */
    void tokenizeOperator();

/* ************************************************************************* */

public:

    /**
     * @brief go to next token.
     */
    void next();

    /**
     * @brief get current token.
     */
    inline const Token& get() const noexcept
    {
        return m_current;
    }

    /**
     * @brief get current token and move to next.
     */
    inline Token extract()
    {
        auto tmp = m_current;
        next();
        return tmp;
    }

    /**
     * @brief checks if current token is final EOF type.
     */
    inline bool isEof()
    {
        return m_current.getType() == TokenType::End;
    }

/* ************************************************************************* */

public:

    /**
     * @brief returns tokenizer iterator pointing to currect token.
     */
    inline TokenizerIterator begin() noexcept
    {
        return TokenizerIterator(this);
    }

    /**
     * @brief returns tokenizer iterator pointing to token with end.
     */
    inline TokenizerIterator end() noexcept
    {
        return TokenizerIterator(nullptr);
    }
};

/* ************************************************************************* */

inline const Token& TokenizerIterator::operator*() const
{
    return m_tokenizer->get();
}

inline TokenizerIterator& TokenizerIterator::operator++()
{
    m_tokenizer->next();
    return *this;
}

inline TokenizerIterator TokenizerIterator::operator++(int)
{
    TokenizerIterator tmp(*this);
    operator++();
    return tmp;
}

/* ************************************************************************* */

}
}
}

/* ************************************************************************* */

<|endoftext|>


<commit_before>/** @mainpage C++11 Proton Library
*
* @authors Lenx Tao Wei (lenx.wei at gmail.com)
*
* @section intro Introduction
* Proton is a library to provide Python-like interfaces for C++11,
* which try to make porting from Python to C++11 easier,
* and make programming in C++11 more convenient :)
*
* The main git repository is at https://github.com/LenxWei/libproton.
*
* @section install Install
* Download site:
* - http://code.google.com/p/libproton/downloads/list
* - https://github.com/LenxWei/libproton/downloads
*
* Need a compiler supporting c++11, such as gcc 4.7, clang 3.2 or higher.

* Install Boost C++ Library 1.48 or higher first.
*
* After that, just standard "./configure; make; make check; make install"
*
* @section modules Modules
* You can find documents about modules here.
*

* @todo add tutorial
* @todo add weak_
* @todo 1.2 milestone
* @todo add os module
* @todo add socket module(?)
* @todo add server/client module
* @todo add regex module
* @todo add threading
* @todo 1.4 milestone
* @todo add gc support
* @todo 1.6 milestone
*
* @defgroup ref Smart reference
* Provide basic reference support for proton.
* @{
*  @defgroup ref_ ref_
*  Core reference template supporting interface through inheritance/multiple inheritance.
*
*  @defgroup functor func_
*  General functor interface template.
*
* @}
*
* @defgroup stl Containers
* Repack stl containers in new templates following python's habits.
* @{
*  @defgroup seq common
*  common container operations
*
*  @defgroup str str
*  like string in python.
*
*  @defgroup vector_ vector_
*  like list in python, better for small sequences
*
*  @defgroup deque_ deque_
*  like list in python, better for long sequences.
*
*  @defgroup map_ map_
*  like dict in python.
*
*  @defgroup set_ set_
*  like set in python.
*
*  @defgroup tuple tuple
*  like tuple in python.
*
* @}
*
* @defgroup util Utilities
* @{
*
*  @defgroup getopt getopt
*  get options
*
*  @defgroup debug Debug utilities
*  Macros, global variables, classes for debug.
*
*  @defgroup pool Smart allocator
*  A high-performance and smart allocator.
*
* @}
*
*/
<commit_msg>add 1.3 note<commit_after>/** @mainpage C++11 Proton Library
*
* @authors Lenx Tao Wei (lenx.wei at gmail.com)
*
* @section intro Introduction
* Proton is a library to provide Python-like interfaces for C++11,
* which try to make porting from Python to C++11 easier,
* and make programming in C++11 more convenient :)
*
* The main git repository is at https://github.com/LenxWei/libproton.
*
* @section install Install
* Download site:
* - http://code.google.com/p/libproton/downloads/list
* - https://github.com/LenxWei/libproton/downloads
*
* Need a compiler supporting c++11, such as gcc 4.7, clang 3.2 or higher.

* Install Boost C++ Library 1.48 or higher first.
*
* After that, just standard "./configure; make; make check; make install"
*
* @section modules Modules
* You can find documents about modules here.
*

* @todo add tutorial
* @todo add weak_
* @todo 1.2 milestone
* @todo add os module
* @todo add socket module(?)
* @todo add server/client module
* @todo add regex module
* @todo 1.3 milestone
* @todo add threading
* @todo 1.4 milestone
* @todo add gc support
* @todo 1.6 milestone
*
* @defgroup ref Smart reference
* Provide basic reference support for proton.
* @{
*  @defgroup ref_ ref_
*  Core reference template supporting interface through inheritance/multiple inheritance.
*
*  @defgroup functor func_
*  General functor interface template.
*
* @}
*
* @defgroup stl Containers
* Repack stl containers in new templates following python's habits.
* @{
*  @defgroup seq common
*  common container operations
*
*  @defgroup str str
*  like string in python.
*
*  @defgroup vector_ vector_
*  like list in python, better for small sequences
*
*  @defgroup deque_ deque_
*  like list in python, better for long sequences.
*
*  @defgroup map_ map_
*  like dict in python.
*
*  @defgroup set_ set_
*  like set in python.
*
*  @defgroup tuple tuple
*  like tuple in python.
*
* @}
*
* @defgroup util Utilities
* @{
*
*  @defgroup getopt getopt
*  get options
*
*  @defgroup debug Debug utilities
*  Macros, global variables, classes for debug.
*
*  @defgroup pool Smart allocator
*  A high-performance and smart allocator.
*
* @}
*
*/
<|endoftext|>


<commit_before>/*
 * MIT License
 *
 * Copyright (c) 2016 Jacek Galowicz
 *
 * 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 OR COPYRIGHT HOLDERS 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.
 */
#pragma once

#include "stl_symbols.hpp"
#include "charlist.hpp"

namespace pprintpp {

template <typename T> struct always_false { static constexpr bool value {false}; };

using namespace typelist;
using namespace charlist;

template <typename T> struct type2fmt;

template <> struct type2fmt<char>                { using type = char_tl_t<'c'>; };
template <> struct type2fmt<short>               { using type = char_tl_t<'d'>; };
template <> struct type2fmt<int>                 { using type = char_tl_t<'d'>; };
template <> struct type2fmt<long int>            { using type = char_tl_t<'l', 'd'>; };
template <> struct type2fmt<long long int>       { using type = char_tl_t<'l', 'l', 'd'>; };
template <> struct type2fmt<unsigned char>       { using type = char_tl_t<'u'>; };
template <> struct type2fmt<unsigned short>      { using type = char_tl_t<'u'>; };
template <> struct type2fmt<unsigned>            { using type = char_tl_t<'u'>; };
template <> struct type2fmt<unsigned long>       { using type = char_tl_t<'l', 'u'>; };
template <> struct type2fmt<unsigned long long>  { using type = char_tl_t<'l', 'l', 'u'>; };

template <> struct type2fmt<bool>                { using type = char_tl_t<'d'>; };

template <> struct type2fmt<float>  { using type = char_tl_t<'f'>; };
template <> struct type2fmt<double> { using type = char_tl_t<'l', 'f'>; };

template <> struct type2fmt<nullptr_t> { using type = char_tl_t<'p'>; };
template <typename T> struct type2fmt<T*>   { using type = char_tl_t<'p'>; };

template <typename T, typename FL>
struct format_str {
    using raw_T = remove_cv_t<T>;
    static constexpr bool s_fmt {contains<FL, char_t<'s'>>::value};
    static constexpr bool is_str {std::is_same<char,
        remove_cv_t<typename std::remove_pointer<raw_T>::type>>::value};

    static constexpr bool is_uint {std::is_unsigned<raw_T>::value};
    static constexpr bool has_x   {contains<FL, char_t<'x'>>::value};

    using raw_fmt = typename type2fmt<T>::type;

    using uint_x_fmt = typename std::conditional<is_uint && has_x,
          substitute_t<raw_fmt, char_t<'u'>, char_t<'x'>>,
          raw_fmt
        >::type;

    using fmt_type = typename std::conditional<s_fmt && is_str,
          substitute_t<raw_fmt, char_t<'p'>, char_t<'s'>>,
          uint_x_fmt
        >::type;

    using filtered_fl = remove_t<remove_t<FL, char_t<'x'>>, char_t<'s'>>;

    using type = append_t<filtered_fl, fmt_type>;
};

template <class InList, class OutList, size_t Counter>
struct find_brace;

template <class InList, class OutList>
struct find_brace<tl<char_t<'}'>, InList>, OutList, 1> {
    using before = OutList;
    using after  = InList;
};

template <char C, class InList, class OutList, size_t N>
struct find_brace<tl<char_t<C>, InList>, OutList, N>
    : public find_brace<InList, append_t<OutList, char_t<C>>, N>
{
    static_assert(C != '{', "Found nested braces: {...{...}...}!"
                            " Maybe you want to mask the outer one?");
};

template <class OutList, size_t N>
struct find_brace<null_t, OutList, N>
{
    static_assert(N + 1 == N, "Missing } after {.");
};

template <typename SL, typename TL>
struct autoformat;

template <>
struct autoformat<null_t, null_t> { using type = null_t; };

template <typename TL>
struct autoformat<null_t, TL> {
    using type = null_t;
    static_assert(always_false<TL>::value, "There are more vars than format tokens!");
};

template <typename SL, typename TL>
struct autoformat<tl<char_t<'%'>, tl<char_t<'%'>, SL>>, TL>
{
    using type = tl<char_t<'%'>, tl<char_t<'%'>, typename autoformat<SL, TL>::type>>;
};

template <typename SL, typename T, typename TL>
struct autoformat<tl<char_t<'%'>, SL>, tl<T, TL>>
{
    using type = tl<char_t<'%'>, typename autoformat<SL, TL>::type>;
};

template <typename SL, typename TL>
struct autoformat<tl<char_t<'\\'>, tl<char_t<'{'>, SL>>, TL>
{
    using type = tl<char_t<'{'>, typename autoformat<SL, TL>::type>;
};

template <typename SL, typename TL>
struct autoformat<tl<char_t<'{'>, SL>, TL>
{
    using other_brace  = find_brace<SL, null_t, 1>;
    using format_block = typename other_brace::before;
    using rest_str     = typename other_brace::after;

    static_assert(!std::is_same<TL, null_t>::value, "There are more {} than arguments to print");
    using T = typename TL::head;
    using fmt_str = typename format_str<T, format_block>::type;

    using type = tl<char_t<'%'>,
                    append_t<fmt_str, typename autoformat<rest_str, typename TL::tail>::type>>;
};

template <typename C, typename SL, typename TL>
struct autoformat<tl<C, SL>, TL> {
    using type = tl<C, typename autoformat<SL, TL>::type>;
};

template <typename StringProvider, typename PtList>
using autoformat_t =
    tl_to_varlist<
        typename autoformat<string_list_t<StringProvider>, PtList>::type
    >;

template <typename ... Ts>
make_t<Ts...> tie_types(Ts...);

#define AUTOFORMAT(s, ...) \
    ({ \
        struct strprov { static constexpr const char * const str() { return s; } }; \
        using paramtypes = decltype(pprintpp::tie_types(__VA_ARGS__)); \
        using af = pprintpp::autoformat_t<strprov, paramtypes>; \
        af::str(); \
    })

#define pprintf(s, ...) printf(AUTOFORMAT(s, ## __VA_ARGS__), ## __VA_ARGS__);

}
<commit_msg>Outsource std::is_same from pprintpp.hpp<commit_after>/*
 * MIT License
 *
 * Copyright (c) 2016 Jacek Galowicz
 *
 * 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 OR COPYRIGHT HOLDERS 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.
 */
#pragma once

#include "stl_symbols.hpp"
#include "charlist.hpp"

namespace pprintpp {

template <typename T> struct always_false { static constexpr bool value {false}; };

using namespace typelist;
using namespace charlist;

template <typename T> struct type2fmt;

template <> struct type2fmt<char>                { using type = char_tl_t<'c'>; };
template <> struct type2fmt<short>               { using type = char_tl_t<'d'>; };
template <> struct type2fmt<int>                 { using type = char_tl_t<'d'>; };
template <> struct type2fmt<long int>            { using type = char_tl_t<'l', 'd'>; };
template <> struct type2fmt<long long int>       { using type = char_tl_t<'l', 'l', 'd'>; };
template <> struct type2fmt<unsigned char>       { using type = char_tl_t<'u'>; };
template <> struct type2fmt<unsigned short>      { using type = char_tl_t<'u'>; };
template <> struct type2fmt<unsigned>            { using type = char_tl_t<'u'>; };
template <> struct type2fmt<unsigned long>       { using type = char_tl_t<'l', 'u'>; };
template <> struct type2fmt<unsigned long long>  { using type = char_tl_t<'l', 'l', 'u'>; };

template <> struct type2fmt<bool>                { using type = char_tl_t<'d'>; };

template <> struct type2fmt<float>  { using type = char_tl_t<'f'>; };
template <> struct type2fmt<double> { using type = char_tl_t<'l', 'f'>; };

template <> struct type2fmt<nullptr_t> { using type = char_tl_t<'p'>; };
template <typename T> struct type2fmt<T*>   { using type = char_tl_t<'p'>; };

template <typename T, typename FL>
struct format_str {
    using raw_T = remove_cv_t<T>;
    static constexpr bool s_fmt {contains<FL, char_t<'s'>>::value};
    static constexpr bool is_str {is_same<char,
        remove_cv_t<typename std::remove_pointer<raw_T>::type>>::value};

    static constexpr bool is_uint {std::is_unsigned<raw_T>::value};
    static constexpr bool has_x   {contains<FL, char_t<'x'>>::value};

    using raw_fmt = typename type2fmt<T>::type;

    using uint_x_fmt = typename std::conditional<is_uint && has_x,
          substitute_t<raw_fmt, char_t<'u'>, char_t<'x'>>,
          raw_fmt
        >::type;

    using fmt_type = typename std::conditional<s_fmt && is_str,
          substitute_t<raw_fmt, char_t<'p'>, char_t<'s'>>,
          uint_x_fmt
        >::type;

    using filtered_fl = remove_t<remove_t<FL, char_t<'x'>>, char_t<'s'>>;

    using type = append_t<filtered_fl, fmt_type>;
};

template <class InList, class OutList, size_t Counter>
struct find_brace;

template <class InList, class OutList>
struct find_brace<tl<char_t<'}'>, InList>, OutList, 1> {
    using before = OutList;
    using after  = InList;
};

template <char C, class InList, class OutList, size_t N>
struct find_brace<tl<char_t<C>, InList>, OutList, N>
    : public find_brace<InList, append_t<OutList, char_t<C>>, N>
{
    static_assert(C != '{', "Found nested braces: {...{...}...}!"
                            " Maybe you want to mask the outer one?");
};

template <class OutList, size_t N>
struct find_brace<null_t, OutList, N>
{
    static_assert(N + 1 == N, "Missing } after {.");
};

template <typename SL, typename TL>
struct autoformat;

template <>
struct autoformat<null_t, null_t> { using type = null_t; };

template <typename TL>
struct autoformat<null_t, TL> {
    using type = null_t;
    static_assert(always_false<TL>::value, "There are more vars than format tokens!");
};

template <typename SL, typename TL>
struct autoformat<tl<char_t<'%'>, tl<char_t<'%'>, SL>>, TL>
{
    using type = tl<char_t<'%'>, tl<char_t<'%'>, typename autoformat<SL, TL>::type>>;
};

template <typename SL, typename T, typename TL>
struct autoformat<tl<char_t<'%'>, SL>, tl<T, TL>>
{
    using type = tl<char_t<'%'>, typename autoformat<SL, TL>::type>;
};

template <typename SL, typename TL>
struct autoformat<tl<char_t<'\\'>, tl<char_t<'{'>, SL>>, TL>
{
    using type = tl<char_t<'{'>, typename autoformat<SL, TL>::type>;
};

template <typename SL, typename TL>
struct autoformat<tl<char_t<'{'>, SL>, TL>
{
    using other_brace  = find_brace<SL, null_t, 1>;
    using format_block = typename other_brace::before;
    using rest_str     = typename other_brace::after;

    static_assert(!is_same<TL, null_t>::value, "There are more {} than arguments to print");
    using T = typename TL::head;
    using fmt_str = typename format_str<T, format_block>::type;

    using type = tl<char_t<'%'>,
                    append_t<fmt_str, typename autoformat<rest_str, typename TL::tail>::type>>;
};

template <typename C, typename SL, typename TL>
struct autoformat<tl<C, SL>, TL> {
    using type = tl<C, typename autoformat<SL, TL>::type>;
};

template <typename StringProvider, typename PtList>
using autoformat_t =
    tl_to_varlist<
        typename autoformat<string_list_t<StringProvider>, PtList>::type
    >;

template <typename ... Ts>
make_t<Ts...> tie_types(Ts...);

#define AUTOFORMAT(s, ...) \
    ({ \
        struct strprov { static constexpr const char * const str() { return s; } }; \
        using paramtypes = decltype(pprintpp::tie_types(__VA_ARGS__)); \
        using af = pprintpp::autoformat_t<strprov, paramtypes>; \
        af::str(); \
    })

#define pprintf(s, ...) printf(AUTOFORMAT(s, ## __VA_ARGS__), ## __VA_ARGS__);

}
<|endoftext|>


<commit_before>/**
 * @file lldrawpool.cpp
 * @brief LLDrawPoolMaterials class implementation
 * @author Jonathan "Geenz" Goodman
 *
 * $LicenseInfo:firstyear=2002&license=viewerlgpl$
 * Second Life Viewer Source Code
 * Copyright (C) 2013, Linden Research, Inc.
 *
 * 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;
 * version 2.1 of the License only.
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 * $/LicenseInfo$
 */

#include "llviewerprecompiledheaders.h"

#include "lldrawpoolmaterials.h"
#include "llviewershadermgr.h"
#include "pipeline.h"

S32 diffuse_channel = -1;

LLDrawPoolMaterials::LLDrawPoolMaterials()
:  LLRenderPass(LLDrawPool::POOL_MATERIALS)
{

}

void LLDrawPoolMaterials::prerender()
{
	mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
}

void LLDrawPoolMaterials::beginDeferredPass(S32 pass)
{
	LLFastTimer t(FTM_RENDER_MATERIALS);
}

void LLDrawPoolMaterials::endDeferredPass(S32 pass)
{
	LLFastTimer t(FTM_RENDER_MATERIALS);
	LLRenderPass::endRenderPass(pass);
}

void LLDrawPoolMaterials::renderDeferred(S32 pass)
{
	U32 type = LLRenderPass::PASS_MATERIALS;
	LLCullResult::drawinfo_iterator begin = gPipeline.beginRenderMap(type);
	LLCullResult::drawinfo_iterator end = gPipeline.endRenderMap(type);

	for (LLCullResult::drawinfo_iterator i = begin; i != end; ++i)
	{
		LLDrawInfo& params = **i;

		switch (params.mDiffuseAlphaMode)
		{
			case 0:
				mShader = &gDeferredMaterialShinyNormal;
				mShader->bind();
				break;
			case 1: // Alpha blending not supported in the opaque draw pool.
				return;
			case 2:
				mShader = &gDeferredMaterialShinyNormalAlphaTest;
				mShader->bind();
				mShader->setMinimumAlpha(params.mAlphaMaskCutoff);
				break;
			case 3:
				mShader = &gDeferredMaterialShinyNormalEmissive;
				mShader->bind();
				break;
		};

		mShader->uniform4f(LLShaderMgr::SPECULAR_COLOR, params.mSpecColor.mV[0], params.mSpecColor.mV[1], params.mSpecColor.mV[2], params.mSpecColor.mV[3]);
		mShader->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, params.mEnvIntensity);

		params.mNormalMap->addTextureStats(params.mVSize);
		bindNormalMap(params.mNormalMap);

		params.mSpecularMap->addTextureStats(params.mVSize);
		bindSpecularMap(params.mSpecularMap);

		diffuse_channel = mShader->enableTexture(LLShaderMgr::DIFFUSE_MAP);
		pushBatch(params, VERTEX_DATA_MASK, TRUE);
		mShader->disableTexture(LLShaderMgr::DIFFUSE_MAP);
		mShader->unbind();
	}
}

void LLDrawPoolMaterials::bindSpecularMap(LLViewerTexture* tex)
{
	mShader->bindTexture(LLShaderMgr::SPECULAR_MAP, tex);
}

void LLDrawPoolMaterials::bindNormalMap(LLViewerTexture* tex)
{
	mShader->bindTexture(LLShaderMgr::BUMP_MAP, tex);
}

void LLDrawPoolMaterials::beginRenderPass(S32 pass)
{
	LLFastTimer t(FTM_RENDER_MATERIALS);

	// Materials isn't supported under forward rendering.
	// Use the simple shaders to handle it instead.
	// This is basically replicated from LLDrawPoolSimple.

	if (LLPipeline::sUnderWaterRender)
	{
		mShader = &gObjectSimpleWaterProgram;
	}
	else
	{
		mShader = &gObjectSimpleProgram;
	}

	if (mVertexShaderLevel > 0)
	{
		mShader->bind();
	}
	else
	{
		// don't use shaders!
		if (gGLManager.mHasShaderObjects)
		{
			LLGLSLShader::bindNoShader();
		}
	}
}

void LLDrawPoolMaterials::endRenderPass(S32 pass)
{
	LLFastTimer t(FTM_RENDER_MATERIALS);
	stop_glerror();
	LLRenderPass::endRenderPass(pass);
	stop_glerror();
	if (mVertexShaderLevel > 0)
	{
		mShader->unbind();
	}
}

void LLDrawPoolMaterials::render(S32 pass)
{
	LLGLDisable blend(GL_BLEND);

	{ //render simple
		LLFastTimer t(FTM_RENDER_MATERIALS);
		gPipeline.enableLightsDynamic();

		if (mVertexShaderLevel > 0)
		{
			U32 mask = getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX;

			pushBatches(LLRenderPass::PASS_MATERIALS, mask, TRUE, TRUE);
		}
		else
		{
			LLGLDisable alpha_test(GL_ALPHA_TEST);
			renderTexture(LLRenderPass::PASS_MATERIALS, getVertexDataMask());
		}
	}
}

void LLDrawPoolMaterials::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures)
{
	applyModelMatrix(params);

	bool tex_setup = false;

	if (batch_textures && params.mTextureList.size() > 1)
	{
		for (U32 i = 0; i < params.mTextureList.size(); ++i)
		{
			if (params.mTextureList[i].notNull())
			{
				gGL.getTexUnit(i)->bind(params.mTextureList[i], TRUE);
			}
		}
	}
	else
	{ //not batching textures or batch has only 1 texture -- might need a texture matrix
		if (params.mTextureMatrix)
		{
			//if (mShiny)
			{
				gGL.getTexUnit(0)->activate();
				gGL.matrixMode(LLRender::MM_TEXTURE);
			}

			gGL.loadMatrix((GLfloat*) params.mTextureMatrix->mMatrix);
			gPipeline.mTextureMatrixOps++;

			tex_setup = true;
		}

		if (mVertexShaderLevel > 1 && texture)
		{
			if (params.mTexture.notNull())
			{
				gGL.getTexUnit(diffuse_channel)->bind(params.mTexture);
				params.mTexture->addTextureStats(params.mVSize);
			}
			else
			{
				gGL.getTexUnit(diffuse_channel)->unbind(LLTexUnit::TT_TEXTURE);
			}
		}
	}

	if (params.mGroup)
	{
		params.mGroup->rebuildMesh();
	}
	params.mVertexBuffer->setBuffer(mask);
	params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
	gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode);
	if (tex_setup)
	{
		gGL.getTexUnit(0)->activate();
		gGL.loadIdentity();
		gGL.matrixMode(LLRender::MM_MODELVIEW);
	}
}
<commit_msg>protect against missing mNormalMap or mSpecularMap<commit_after>/**
 * @file lldrawpool.cpp
 * @brief LLDrawPoolMaterials class implementation
 * @author Jonathan "Geenz" Goodman
 *
 * $LicenseInfo:firstyear=2002&license=viewerlgpl$
 * Second Life Viewer Source Code
 * Copyright (C) 2013, Linden Research, Inc.
 *
 * 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;
 * version 2.1 of the License only.
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 * $/LicenseInfo$
 */

#include "llviewerprecompiledheaders.h"

#include "lldrawpoolmaterials.h"
#include "llviewershadermgr.h"
#include "pipeline.h"

S32 diffuse_channel = -1;

LLDrawPoolMaterials::LLDrawPoolMaterials()
:  LLRenderPass(LLDrawPool::POOL_MATERIALS)
{

}

void LLDrawPoolMaterials::prerender()
{
	mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
}

void LLDrawPoolMaterials::beginDeferredPass(S32 pass)
{
	LLFastTimer t(FTM_RENDER_MATERIALS);
}

void LLDrawPoolMaterials::endDeferredPass(S32 pass)
{
	LLFastTimer t(FTM_RENDER_MATERIALS);
	LLRenderPass::endRenderPass(pass);
}

void LLDrawPoolMaterials::renderDeferred(S32 pass)
{
	U32 type = LLRenderPass::PASS_MATERIALS;
	LLCullResult::drawinfo_iterator begin = gPipeline.beginRenderMap(type);
	LLCullResult::drawinfo_iterator end = gPipeline.endRenderMap(type);

	for (LLCullResult::drawinfo_iterator i = begin; i != end; ++i)
	{
		LLDrawInfo& params = **i;

		switch (params.mDiffuseAlphaMode)
		{
			case 0:
				mShader = &gDeferredMaterialShinyNormal;
				mShader->bind();
				break;
			case 1: // Alpha blending not supported in the opaque draw pool.
				return;
			case 2:
				mShader = &gDeferredMaterialShinyNormalAlphaTest;
				mShader->bind();
				mShader->setMinimumAlpha(params.mAlphaMaskCutoff);
				break;
			case 3:
				mShader = &gDeferredMaterialShinyNormalEmissive;
				mShader->bind();
				break;
		};

		mShader->uniform4f(LLShaderMgr::SPECULAR_COLOR, params.mSpecColor.mV[0], params.mSpecColor.mV[1], params.mSpecColor.mV[2], params.mSpecColor.mV[3]);
		mShader->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, params.mEnvIntensity);

		if (params.mNormalMap)
		{
			params.mNormalMap->addTextureStats(params.mVSize);
			bindNormalMap(params.mNormalMap);
		}

		if (params.mSpecularMap)
		{
			params.mSpecularMap->addTextureStats(params.mVSize);
			bindSpecularMap(params.mSpecularMap);
		}

		diffuse_channel = mShader->enableTexture(LLShaderMgr::DIFFUSE_MAP);
		pushBatch(params, VERTEX_DATA_MASK, TRUE);
		mShader->disableTexture(LLShaderMgr::DIFFUSE_MAP);
		mShader->unbind();
	}
}

void LLDrawPoolMaterials::bindSpecularMap(LLViewerTexture* tex)
{
	mShader->bindTexture(LLShaderMgr::SPECULAR_MAP, tex);
}

void LLDrawPoolMaterials::bindNormalMap(LLViewerTexture* tex)
{
	mShader->bindTexture(LLShaderMgr::BUMP_MAP, tex);
}

void LLDrawPoolMaterials::beginRenderPass(S32 pass)
{
	LLFastTimer t(FTM_RENDER_MATERIALS);

	// Materials isn't supported under forward rendering.
	// Use the simple shaders to handle it instead.
	// This is basically replicated from LLDrawPoolSimple.

	if (LLPipeline::sUnderWaterRender)
	{
		mShader = &gObjectSimpleWaterProgram;
	}
	else
	{
		mShader = &gObjectSimpleProgram;
	}

	if (mVertexShaderLevel > 0)
	{
		mShader->bind();
	}
	else
	{
		// don't use shaders!
		if (gGLManager.mHasShaderObjects)
		{
			LLGLSLShader::bindNoShader();
		}
	}
}

void LLDrawPoolMaterials::endRenderPass(S32 pass)
{
	LLFastTimer t(FTM_RENDER_MATERIALS);
	stop_glerror();
	LLRenderPass::endRenderPass(pass);
	stop_glerror();
	if (mVertexShaderLevel > 0)
	{
		mShader->unbind();
	}
}

void LLDrawPoolMaterials::render(S32 pass)
{
	LLGLDisable blend(GL_BLEND);

	{ //render simple
		LLFastTimer t(FTM_RENDER_MATERIALS);
		gPipeline.enableLightsDynamic();

		if (mVertexShaderLevel > 0)
		{
			U32 mask = getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX;

			pushBatches(LLRenderPass::PASS_MATERIALS, mask, TRUE, TRUE);
		}
		else
		{
			LLGLDisable alpha_test(GL_ALPHA_TEST);
			renderTexture(LLRenderPass::PASS_MATERIALS, getVertexDataMask());
		}
	}
}

void LLDrawPoolMaterials::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures)
{
	applyModelMatrix(params);

	bool tex_setup = false;

	if (batch_textures && params.mTextureList.size() > 1)
	{
		for (U32 i = 0; i < params.mTextureList.size(); ++i)
		{
			if (params.mTextureList[i].notNull())
			{
				gGL.getTexUnit(i)->bind(params.mTextureList[i], TRUE);
			}
		}
	}
	else
	{ //not batching textures or batch has only 1 texture -- might need a texture matrix
		if (params.mTextureMatrix)
		{
			//if (mShiny)
			{
				gGL.getTexUnit(0)->activate();
				gGL.matrixMode(LLRender::MM_TEXTURE);
			}

			gGL.loadMatrix((GLfloat*) params.mTextureMatrix->mMatrix);
			gPipeline.mTextureMatrixOps++;

			tex_setup = true;
		}

		if (mVertexShaderLevel > 1 && texture)
		{
			if (params.mTexture.notNull())
			{
				gGL.getTexUnit(diffuse_channel)->bind(params.mTexture);
				params.mTexture->addTextureStats(params.mVSize);
			}
			else
			{
				gGL.getTexUnit(diffuse_channel)->unbind(LLTexUnit::TT_TEXTURE);
			}
		}
	}

	if (params.mGroup)
	{
		params.mGroup->rebuildMesh();
	}
	params.mVertexBuffer->setBuffer(mask);
	params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
	gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode);
	if (tex_setup)
	{
		gGL.getTexUnit(0)->activate();
		gGL.loadIdentity();
		gGL.matrixMode(LLRender::MM_MODELVIEW);
	}
}
<|endoftext|>