<commit_before>// @(#)root/core/meta:$Id$
// Author: Paul Russo   30/07/2012

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TClingTypedefInfo                                                    //
//                                                                      //
// Emulation of the CINT TypedefInfo class.                             //
//                                                                      //
// The CINT C++ interpreter provides an interface to metadata about     //
// a typedef through the TypedefInfo class.  This class provides the    //
// same functionality, using an interface as close as possible to       //
// TypedefInfo but the typedef metadata comes from the Clang C++        //
// compiler, not CINT.                                                  //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TClingTypedefInfo.h"

#include "Property.h"
#include "TClingProperty.h"
#include "TError.h"
#include "TMetaUtils.h"
#include "Rtypes.h" // for gDebug

#include "cling/Interpreter/LookupHelper.h"
#include "cling/Utils/AST.h"

using namespace clang;

//______________________________________________________________________________
TClingTypedefInfo::TClingTypedefInfo(cling::Interpreter *interp,
                                     const char *name)
   : fInterp(interp), fFirstTime(true), fDescend(false), fDecl(0), fTitle("")
{
   // Lookup named typedef and initialize the iterator to point to it.
   if (gDebug > 0) {
      Info("TClingTypedefInfo::TClingTypedefInfo(interp,name)",
           "looking up typedef: %s\n", name);
   }
   fDecl = fInterp->getLookupHelper().findScope(name);
   if (fDecl && !llvm::isa<clang::TypedefDecl>(fDecl)) {
      // If what the lookup found is not a typedef, ignore it.
      fDecl = 0;
   }
   if (fDecl) {
      if (gDebug > 0) {
         Info("TClingTypedefInfo::TClingTypedefInfo(interp,name)",
              "found typedef name: %s  decl: 0x%lx\n", name, (long) fDecl);
      }
      // Initialize iterator to point at found typedef.
      AdvanceToDecl(fDecl);
   }
   else {
      if (gDebug > 0) {
         Info("TClingTypedefInfo::TClingTypedefInfo(interp,name)",
              "typedef not found name: %s\n", name);
      }
   }
}

TClingTypedefInfo::TClingTypedefInfo(cling::Interpreter *interp,
                                     const clang::TypedefDecl *TdefD)
   : fInterp(interp), fFirstTime(true), fDescend(false), fDecl(TdefD),
     fTitle("")
{
   // Lookup named typedef and initialize the iterator to point to it.
   if (gDebug > 0) {
      Info("TClingTypedefInfo::TClingTypedefInfo(interp,name)",
           "looking up typedef: %s\n", TdefD->getNameAsString().c_str());
   }
   if (fDecl) {
      if (gDebug > 0) {
         Info("TClingTypedefInfo::TClingTypedefInfo(interp,name)",
              "found typedef name: %s  decl: 0x%lx\n",
              TdefD->getNameAsString().c_str(), (long) fDecl);
      }
      // Initialize iterator to point at found typedef.
      AdvanceToDecl(fDecl);
   }
   else {
      if (gDebug > 0) {
         Info("TClingTypedefInfo::TClingTypedefInfo(interp,name)",
              "typedef not found name: %s\n", TdefD->getNameAsString().c_str());
      }
   }
}

//______________________________________________________________________________
const clang::Decl *TClingTypedefInfo::GetDecl() const
{
   // Get the current typedef declaration.
   return fDecl;
}

//______________________________________________________________________________
void TClingTypedefInfo::Init(const char *name)
{
   // Lookup named typedef and reset the iterator to point to it.
   if (gDebug > 0) {
      Info("TClingTypedefInfo::Init(name)", "looking up typedef: %s\n", name);
   }
   // Reset the iterator to invalid.
   fFirstTime = true;
   fDescend = false;
   fIter = clang::DeclContext::decl_iterator();
   fIterStack.clear();
   // Ask the cling interpreter to lookup the name for us.
   fDecl = fInterp->getLookupHelper().findScope(name);
   if (!fDecl) {
      if (gDebug > 0) {
         Info("TClingTypedefInfo::Init(name)",
              "typedef not found name: %s\n", name);
      }
      return;
   }
   if (gDebug > 0) {
      Info("TClingTypedefInfo::Init(name)", "found typedef name: "
           "%s  decl: 0x%lx\n", name, (long) fDecl);
   }
   // Initialize iterator to point at found typedef.
   AdvanceToDecl(fDecl);
}

//______________________________________________________________________________
bool TClingTypedefInfo::IsValid() const
{
   // Return true if the current iterator position is valid.
   return fDecl;
}

//______________________________________________________________________________
int TClingTypedefInfo::AdvanceToDecl(const clang::Decl *target_decl)
{
   // Set the iterator to point at the given declaration.
   const clang::TranslationUnitDecl *tu = target_decl->getTranslationUnitDecl();
   const clang::DeclContext *dc = llvm::cast<clang::DeclContext>(tu);
   fFirstTime = true;
   fDescend = false;
   fIter = dc->decls_begin();
   fDecl = 0;
   fIterStack.clear();
   while (InternalNext()) {
      if (fDecl == target_decl) {
         fFirstTime = true;
         return 1;
      }
   }
   return 0;
}

//______________________________________________________________________________
int TClingTypedefInfo::InternalNext()
{
   // Increment the iterator, return true if new position is valid.
   if (!*fIter) {
      // Iterator is already invalid.
      return 0;
   }
   while (true) {
      // Advance to next usable decl, or return if
      // there is no next usable decl.
      if (fFirstTime) {
         // The cint semantics are strange.
         fFirstTime = false;
      }
      else {
         // Advance the iterator one decl, descending into
         // the current decl context if necessary.
         if (!fDescend) {
            // Do not need to scan the decl context of the
            // current decl, move on to the next decl.
            ++fIter;
         }
         else {
            // Descend into the decl context of the current decl.
            fDescend = false;
            fIterStack.push_back(fIter);
            clang::DeclContext *dc = llvm::cast<clang::DeclContext>(*fIter);
            fIter = dc->decls_begin();
         }
         // Fix it if we went past the end.
         while (!*fIter && fIterStack.size()) {
            fIter = fIterStack.back();
            fIterStack.pop_back();
            ++fIter;
         }
         // Check for final termination.
         if (!*fIter) {
            // We have reached the end of the translation unit, all done.
            fDecl = 0;
            return 0;
         }
      }
      // Return if this decl is a typedef.
      if (llvm::isa<clang::TypedefDecl>(*fIter)) {
         fDecl = *fIter;
         return 1;
      }
      // Descend into namespaces and classes.
      clang::Decl::Kind dk = fIter->getKind();
      if ((dk == clang::Decl::Namespace) || (dk == clang::Decl::CXXRecord) ||
            (dk == clang::Decl::ClassTemplateSpecialization)) {
         fDescend = true;
      }
   }
}

//______________________________________________________________________________
int TClingTypedefInfo::Next()
{
   // Increment the iterator.
   return InternalNext();
}

//______________________________________________________________________________
long TClingTypedefInfo::Property() const
{
   // Return a bit mask of metadata about the current typedef.
   if (!IsValid()) {
      return 0L;
   }
   long property = 0L;
   property |= G__BIT_ISTYPEDEF;
   const clang::TypedefDecl *td = llvm::dyn_cast<clang::TypedefDecl>(fDecl);
   clang::QualType qt = td->getUnderlyingType().getCanonicalType();
   if (qt.isConstQualified()) {
      property |= G__BIT_ISCONSTANT;
   }
   while (1) {
      if (qt->isArrayType()) {
         qt = llvm::cast<clang::ArrayType>(qt)->getElementType();
         continue;
      }
      else if (qt->isReferenceType()) {
         property |= G__BIT_ISREFERENCE;
         qt = llvm::cast<clang::ReferenceType>(qt)->getPointeeType();
         continue;
      }
      else if (qt->isPointerType()) {
         property |= G__BIT_ISPOINTER;
         if (qt.isConstQualified()) {
            property |= G__BIT_ISPCONSTANT;
         }
         qt = llvm::cast<clang::PointerType>(qt)->getPointeeType();
         continue;
      }
      else if (qt->isMemberPointerType()) {
         qt = llvm::cast<clang::MemberPointerType>(qt)->getPointeeType();
         continue;
      }
      break;
   }
   if (qt->isBuiltinType()) {
      property |= G__BIT_ISFUNDAMENTAL;
   }
   if (qt.isConstQualified()) {
      property |= G__BIT_ISCONSTANT;
   }
   return property;
}

//______________________________________________________________________________
int TClingTypedefInfo::Size() const
{
   // Return the size in bytes of the underlying type of the current typedef.
   if (!IsValid()) {
      return 1;
   }
   clang::ASTContext &context = fDecl->getASTContext();
   const clang::TypedefDecl *td = llvm::dyn_cast<clang::TypedefDecl>(fDecl);
   clang::QualType qt = td->getUnderlyingType();
   if (qt->isDependentType()) {
      // The underlying type is dependent on a template parameter,
      // we have no idea what it is yet.
      return 0;
   }
   if (const clang::RecordType *rt = qt->getAs<clang::RecordType>()) {
      if (!rt->getDecl()->getDefinition()) {
         // This is a typedef to a forward-declared type.
         return 0;
      }
   }
   // Note: This is an int64_t.
   clang::CharUnits::QuantityType quantity =
      context.getTypeSizeInChars(qt).getQuantity();
   // Truncate cast to fit the CINT interface.
   return static_cast<int>(quantity);
}

//______________________________________________________________________________
const char *TClingTypedefInfo::TrueName(const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
{
   // Get the name of the underlying type of the current typedef.
   if (!IsValid()) {
      return "(unknown)";
   }
   // Note: This must be static because we return a pointer to the internals.
   static std::string truename;
   truename.clear();
   const clang::TypedefDecl *td = llvm::dyn_cast<clang::TypedefDecl>(fDecl);
   clang::QualType underlyingType = td->getUnderlyingType();
   if (underlyingType->isBooleanType()) {
      return "bool";
   }
   const clang::ASTContext &ctxt = fDecl->getASTContext();
   clang::QualType normalizedType = ctxt.getTypedefType(td);

   clang::PrintingPolicy Policy(ctxt.getPrintingPolicy());
   normalizedType = cling::utils::Transform::GetPartiallyDesugaredType(ctxt, normalizedType, normCtxt.GetTypeToSkip(), true /* fully qualify */);
   normalizedType = ROOT::TMetaUtils::AddDefaultParameters(normalizedType, *fInterp, normCtxt);
   normalizedType.getAsStringInternal(truename,Policy);

   return truename.c_str();
}

//______________________________________________________________________________
const char *TClingTypedefInfo::Name() const
{
   // Get the name of the current typedef.
   if (!IsValid()) {
      return "(unknown)";
   }
   // Note: This must be static because we return a pointer to the internals.
   static std::string fullname;
   fullname.clear();
   clang::PrintingPolicy Policy(fDecl->getASTContext().getPrintingPolicy());
   llvm::dyn_cast<clang::NamedDecl>(fDecl)->getNameForDiagnostic(fullname, Policy, /*Qualified=*/true);
   return fullname.c_str();
}

//______________________________________________________________________________
const char *TClingTypedefInfo::Title()
{
   if (!IsValid()) {
      return 0;
   }
   //NOTE: We can't use it as a cache due to the "thoughtful" self iterator
   //if (fTitle.size())
   //   return fTitle.c_str();

   // Try to get the comment either from the annotation or the header file if present

   // Iterate over the redeclarations, we can have muliple definitions in the
   // redecl chain (came from merging of pcms).
   if (const TypedefNameDecl *TND = llvm::dyn_cast<TypedefNameDecl>(GetDecl())) {
      if ( (TND = ROOT::TMetaUtils::GetAnnotatedRedeclarable(TND)) ) {
         if (AnnotateAttr *A = TND->getAttr<AnnotateAttr>()) {
            fTitle = A->getAnnotation().str();
            return fTitle.c_str();
         }
      }
   }

   // Try to get the comment from the header file if present
   fTitle = ROOT::TMetaUtils::GetComment(*GetDecl()).str();
   return fTitle.c_str();
}

<commit_msg>Use the same approach as TClingClassInfo: if initialized by a defined decl (through name or Decl*) mark the TypedefInfo as non-iterable. Saves 20% startup cost and thus makes debugging a bit faster. Also reduce code duplication (actually almost duplication, containing a necessary check in only 1 out of 2 places...)<commit_after>// @(#)root/core/meta:$Id$
// Author: Paul Russo   30/07/2012

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TClingTypedefInfo                                                    //
//                                                                      //
// Emulation of the CINT TypedefInfo class.                             //
//                                                                      //
// The CINT C++ interpreter provides an interface to metadata about     //
// a typedef through the TypedefInfo class.  This class provides the    //
// same functionality, using an interface as close as possible to       //
// TypedefInfo but the typedef metadata comes from the Clang C++        //
// compiler, not CINT.                                                  //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TClingTypedefInfo.h"

#include "Property.h"
#include "TClingProperty.h"
#include "TError.h"
#include "TMetaUtils.h"
#include "Rtypes.h" // for gDebug

#include "cling/Interpreter/LookupHelper.h"
#include "cling/Utils/AST.h"

using namespace clang;

//______________________________________________________________________________
TClingTypedefInfo::TClingTypedefInfo(cling::Interpreter *interp,
                                     const char *name)
   : fInterp(interp), fFirstTime(true), fDescend(false), fDecl(0), fTitle("")
{
   // Lookup named typedef and initialize the iterator to point to it.
   // Yields a non-iterable TClingTypedefInfo (fIter is invalid).
   Init(name);
}

TClingTypedefInfo::TClingTypedefInfo(cling::Interpreter *interp,
                                     const clang::TypedefDecl *TdefD)
   : fInterp(interp), fFirstTime(true), fDescend(false), fDecl(TdefD),
     fTitle("")
{
   // Initialize with a clang::TypedefDecl.
   // fIter is invalid; cannot call Next().
   if (gDebug > 0) {
      Info("TClingTypedefInfo::TClingTypedefInfo(interp,name)",
           "found typedef name: %s  decl: 0x%lx\n",
           TdefD->getNameAsString().c_str(), (long) fDecl);
   }
}

//______________________________________________________________________________
const clang::Decl *TClingTypedefInfo::GetDecl() const
{
   // Get the current typedef declaration.
   return fDecl;
}

//______________________________________________________________________________
void TClingTypedefInfo::Init(const char *name)
{
   // Lookup named typedef and reset the iterator to point to it.
   if (gDebug > 0) {
      Info("TClingTypedefInfo::Init(name)", "looking up typedef: %s\n", name);
   }
   // Reset the iterator to invalid.
   fFirstTime = true;
   fDescend = false;
   fIter = clang::DeclContext::decl_iterator();
   fIterStack.clear();
   // Ask the cling interpreter to lookup the name for us.
   fDecl = fInterp->getLookupHelper().findScope(name);
   if (!fDecl) {
      if (gDebug > 0) {
         Info("TClingTypedefInfo::Init(name)",
              "typedef not found name: %s\n", name);
      }
      return;
   }
   if (fDecl && !llvm::isa<clang::TypedefDecl>(fDecl)) {
      // If what the lookup found is not a typedef, ignore it.
      if (gDebug > 0) {
         Info("TClingTypedefInfo::Init(name)",
              "type not a typedef: %s\n", name);
      }
      fDecl = 0;
   }
   if (gDebug > 0) {
      Info("TClingTypedefInfo::Init(name)", "found typedef name: "
           "%s  decl: 0x%lx\n", name, (long) fDecl);
   }
}

//______________________________________________________________________________
bool TClingTypedefInfo::IsValid() const
{
   // Return true if the current iterator position is valid.
   return fDecl;
}

//______________________________________________________________________________
int TClingTypedefInfo::AdvanceToDecl(const clang::Decl *target_decl)
{
   // Set the iterator to point at the given declaration.
   const clang::TranslationUnitDecl *tu = target_decl->getTranslationUnitDecl();
   const clang::DeclContext *dc = llvm::cast<clang::DeclContext>(tu);
   fFirstTime = true;
   fDescend = false;
   fIter = dc->decls_begin();
   fDecl = 0;
   fIterStack.clear();
   while (InternalNext()) {
      if (fDecl == target_decl) {
         fFirstTime = true;
         return 1;
      }
   }
   return 0;
}

//______________________________________________________________________________
int TClingTypedefInfo::InternalNext()
{
   // Increment the iterator, return true if new position is valid.
   if (!*fIter) {
      // Iterator is already invalid.
      if (fFirstTime && fDecl) {
         std::string buf;
         clang::PrintingPolicy Policy(fDecl->getASTContext().getPrintingPolicy());
         llvm::dyn_cast<clang::NamedDecl>(fDecl)->getNameForDiagnostic(buf, Policy, /*Qualified=*/false);
         Error("TClingTypedefInfo::InternalNext","Next called but iteration not prepared for %s!",buf.c_str());
      }
      return 0;
   }
   while (true) {
      // Advance to next usable decl, or return if
      // there is no next usable decl.
      if (fFirstTime) {
         // The cint semantics are strange.
         fFirstTime = false;
      }
      else {
         // Advance the iterator one decl, descending into
         // the current decl context if necessary.
         if (!fDescend) {
            // Do not need to scan the decl context of the
            // current decl, move on to the next decl.
            ++fIter;
         }
         else {
            // Descend into the decl context of the current decl.
            fDescend = false;
            fIterStack.push_back(fIter);
            clang::DeclContext *dc = llvm::cast<clang::DeclContext>(*fIter);
            fIter = dc->decls_begin();
         }
         // Fix it if we went past the end.
         while (!*fIter && fIterStack.size()) {
            fIter = fIterStack.back();
            fIterStack.pop_back();
            ++fIter;
         }
         // Check for final termination.
         if (!*fIter) {
            // We have reached the end of the translation unit, all done.
            fDecl = 0;
            return 0;
         }
      }
      // Return if this decl is a typedef.
      if (llvm::isa<clang::TypedefDecl>(*fIter)) {
         fDecl = *fIter;
         return 1;
      }
      // Descend into namespaces and classes.
      clang::Decl::Kind dk = fIter->getKind();
      if ((dk == clang::Decl::Namespace) || (dk == clang::Decl::CXXRecord) ||
            (dk == clang::Decl::ClassTemplateSpecialization)) {
         fDescend = true;
      }
   }
}

//______________________________________________________________________________
int TClingTypedefInfo::Next()
{
   // Increment the iterator.
   return InternalNext();
}

//______________________________________________________________________________
long TClingTypedefInfo::Property() const
{
   // Return a bit mask of metadata about the current typedef.
   if (!IsValid()) {
      return 0L;
   }
   long property = 0L;
   property |= G__BIT_ISTYPEDEF;
   const clang::TypedefDecl *td = llvm::dyn_cast<clang::TypedefDecl>(fDecl);
   clang::QualType qt = td->getUnderlyingType().getCanonicalType();
   if (qt.isConstQualified()) {
      property |= G__BIT_ISCONSTANT;
   }
   while (1) {
      if (qt->isArrayType()) {
         qt = llvm::cast<clang::ArrayType>(qt)->getElementType();
         continue;
      }
      else if (qt->isReferenceType()) {
         property |= G__BIT_ISREFERENCE;
         qt = llvm::cast<clang::ReferenceType>(qt)->getPointeeType();
         continue;
      }
      else if (qt->isPointerType()) {
         property |= G__BIT_ISPOINTER;
         if (qt.isConstQualified()) {
            property |= G__BIT_ISPCONSTANT;
         }
         qt = llvm::cast<clang::PointerType>(qt)->getPointeeType();
         continue;
      }
      else if (qt->isMemberPointerType()) {
         qt = llvm::cast<clang::MemberPointerType>(qt)->getPointeeType();
         continue;
      }
      break;
   }
   if (qt->isBuiltinType()) {
      property |= G__BIT_ISFUNDAMENTAL;
   }
   if (qt.isConstQualified()) {
      property |= G__BIT_ISCONSTANT;
   }
   return property;
}

//______________________________________________________________________________
int TClingTypedefInfo::Size() const
{
   // Return the size in bytes of the underlying type of the current typedef.
   if (!IsValid()) {
      return 1;
   }
   clang::ASTContext &context = fDecl->getASTContext();
   const clang::TypedefDecl *td = llvm::dyn_cast<clang::TypedefDecl>(fDecl);
   clang::QualType qt = td->getUnderlyingType();
   if (qt->isDependentType()) {
      // The underlying type is dependent on a template parameter,
      // we have no idea what it is yet.
      return 0;
   }
   if (const clang::RecordType *rt = qt->getAs<clang::RecordType>()) {
      if (!rt->getDecl()->getDefinition()) {
         // This is a typedef to a forward-declared type.
         return 0;
      }
   }
   // Note: This is an int64_t.
   clang::CharUnits::QuantityType quantity =
      context.getTypeSizeInChars(qt).getQuantity();
   // Truncate cast to fit the CINT interface.
   return static_cast<int>(quantity);
}

//______________________________________________________________________________
const char *TClingTypedefInfo::TrueName(const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
{
   // Get the name of the underlying type of the current typedef.
   if (!IsValid()) {
      return "(unknown)";
   }
   // Note: This must be static because we return a pointer to the internals.
   static std::string truename;
   truename.clear();
   const clang::TypedefDecl *td = llvm::dyn_cast<clang::TypedefDecl>(fDecl);
   clang::QualType underlyingType = td->getUnderlyingType();
   if (underlyingType->isBooleanType()) {
      return "bool";
   }
   const clang::ASTContext &ctxt = fDecl->getASTContext();
   clang::QualType normalizedType = ctxt.getTypedefType(td);

   clang::PrintingPolicy Policy(ctxt.getPrintingPolicy());
   normalizedType = cling::utils::Transform::GetPartiallyDesugaredType(ctxt, normalizedType, normCtxt.GetTypeToSkip(), true /* fully qualify */);
   normalizedType = ROOT::TMetaUtils::AddDefaultParameters(normalizedType, *fInterp, normCtxt);
   normalizedType.getAsStringInternal(truename,Policy);

   return truename.c_str();
}

//______________________________________________________________________________
const char *TClingTypedefInfo::Name() const
{
   // Get the name of the current typedef.
   if (!IsValid()) {
      return "(unknown)";
   }
   // Note: This must be static because we return a pointer to the internals.
   static std::string fullname;
   fullname.clear();
   clang::PrintingPolicy Policy(fDecl->getASTContext().getPrintingPolicy());
   llvm::dyn_cast<clang::NamedDecl>(fDecl)->getNameForDiagnostic(fullname, Policy, /*Qualified=*/true);
   return fullname.c_str();
}

//______________________________________________________________________________
const char *TClingTypedefInfo::Title()
{
   if (!IsValid()) {
      return 0;
   }
   //NOTE: We can't use it as a cache due to the "thoughtful" self iterator
   //if (fTitle.size())
   //   return fTitle.c_str();

   // Try to get the comment either from the annotation or the header file if present

   // Iterate over the redeclarations, we can have muliple definitions in the
   // redecl chain (came from merging of pcms).
   if (const TypedefNameDecl *TND = llvm::dyn_cast<TypedefNameDecl>(GetDecl())) {
      if ( (TND = ROOT::TMetaUtils::GetAnnotatedRedeclarable(TND)) ) {
         if (AnnotateAttr *A = TND->getAttr<AnnotateAttr>()) {
            fTitle = A->getAnnotation().str();
            return fTitle.c_str();
         }
      }
   }

   // Try to get the comment from the header file if present
   fTitle = ROOT::TMetaUtils::GetComment(*GetDecl()).str();
   return fTitle.c_str();
}

<|endoftext|>


<commit_before>#import <Arduino.h>
#include "multiplexer.h"

// Function to call in the arduino setup function
Multiplexer::Multiplexer()
{
	// Digital pins that control the analog mux
	this->muxControlPin0 = 4;
	this->muxControlPin1 = 5;
	this->muxControlPin2 = 6;
	this->muxControlPin3 = 7;

	// Set the mux control pins as outputs
	pinMode(this->muxControlPin0, OUTPUT);
	pinMode(this->muxControlPin1, OUTPUT);
	pinMode(this->muxControlPin2, OUTPUT);
	pinMode(this->muxControlPin3, OUTPUT);

	// Default the control pins to low
	digitalWrite(this->muxControlPin0, LOW);
	digitalWrite(this->muxControlPin1, LOW);
	digitalWrite(this->muxControlPin2, LOW);
	digitalWrite(this->muxControlPin3, LOW);

	// Analog pin that reads the signal from the mux
	this->muxSignalPin = A0;

	// Set the selected input to 0
	this->selectedInput = 0;

	// Set the mux signal pin on the arduino as an INPUT
	pinMode(this->muxSignalPin, INPUT);
}

// Limits the input to between 0 and 15 inclusive
int Multiplexer::clampInputNumber(int inputNumber)
{
	// Clamp the inputNumber
	if(inputNumber < 0)
		inputNumber = 0;

	if(inputNumber > 15)
		inputNumber = 15;

	return inputNumber;
}

// Set the multiplexer to the provided input
// inputNumber = 0-indexed mux input number between 0 and 15
void Multiplexer::setInput(int inputNumber)
{
	// Clamp the inputNumber
	inputNumber = this->clampInputNumber(inputNumber);

	// Only update the control pins if the input number has changed
	if(this->selectedInput != inputNumber)
	{
		// Use bitwise & to set the correct control pins on / off
		digitalWrite(this->muxControlPin0, (inputNumber & 1));
		digitalWrite(this->muxControlPin1, (inputNumber & 2) / 2);
		digitalWrite(this->muxControlPin2, (inputNumber & 4) / 4);
		digitalWrite(this->muxControlPin3, (inputNumber & 8) / 8);

		// Keep track of the selected input
		this->selectedInput = inputNumber;
	}
}

// Read the provided input from the multiplexer
// inputNumber = mux input number between 0 and 15
int Multiplexer::readInput(int inputNumber)
{
	// Clamp the inputNumber
	inputNumber = this->clampInputNumber(inputNumber);

	// Set the mux to the provided input
	this->setInput(inputNumber);

	// Read the mux input and return
	return analogRead(this->muxSignalPin);
}

// Read a specific input from the mux and coverts it to an encoder angle
// inputNumber = mux input number between 0 and 15
float Multiplexer::readEncoder(int  inputNumber)
{
  int sensorValue = this->readInput(inputNumber);

  return sensorValue / 1023.0 * 360.0;
}
<commit_msg>Make sure Multiplexer::readEncoder does not return angles greater than 360<commit_after>#import <Arduino.h>
#include "multiplexer.h"

// Function to call in the arduino setup function
Multiplexer::Multiplexer()
{
	// Digital pins that control the analog mux
	this->muxControlPin0 = 4;
	this->muxControlPin1 = 5;
	this->muxControlPin2 = 6;
	this->muxControlPin3 = 7;

	// Set the mux control pins as outputs
	pinMode(this->muxControlPin0, OUTPUT);
	pinMode(this->muxControlPin1, OUTPUT);
	pinMode(this->muxControlPin2, OUTPUT);
	pinMode(this->muxControlPin3, OUTPUT);

	// Default the control pins to low
	digitalWrite(this->muxControlPin0, LOW);
	digitalWrite(this->muxControlPin1, LOW);
	digitalWrite(this->muxControlPin2, LOW);
	digitalWrite(this->muxControlPin3, LOW);

	// Analog pin that reads the signal from the mux
	this->muxSignalPin = A0;

	// Set the selected input to 0
	this->selectedInput = 0;

	// Set the mux signal pin on the arduino as an INPUT
	pinMode(this->muxSignalPin, INPUT);
}

// Limits the input to between 0 and 15 inclusive
int Multiplexer::clampInputNumber(int inputNumber)
{
	// Clamp the inputNumber
	if(inputNumber < 0)
		inputNumber = 0;

	if(inputNumber > 15)
		inputNumber = 15;

	return inputNumber;
}

// Set the multiplexer to the provided input
// inputNumber = 0-indexed mux input number between 0 and 15
void Multiplexer::setInput(int inputNumber)
{
	// Clamp the inputNumber
	inputNumber = this->clampInputNumber(inputNumber);

	// Only update the control pins if the input number has changed
	if(this->selectedInput != inputNumber)
	{
		// Use bitwise & to set the correct control pins on / off
		digitalWrite(this->muxControlPin0, (inputNumber & 1));
		digitalWrite(this->muxControlPin1, (inputNumber & 2) / 2);
		digitalWrite(this->muxControlPin2, (inputNumber & 4) / 4);
		digitalWrite(this->muxControlPin3, (inputNumber & 8) / 8);

		// Keep track of the selected input
		this->selectedInput = inputNumber;
	}
}

// Read the provided input from the multiplexer
// inputNumber = mux input number between 0 and 15
int Multiplexer::readInput(int inputNumber)
{
	// Clamp the inputNumber
	inputNumber = this->clampInputNumber(inputNumber);

	// Set the mux to the provided input
	this->setInput(inputNumber);

	// Read the mux input and return
	return analogRead(this->muxSignalPin);
}

// Read a specific input from the mux and coverts it to an encoder angle
// inputNumber = mux input number between 0 and 15
float Multiplexer::readEncoder(int  inputNumber)
{
  int sensorValue = this->readInput(inputNumber);

  return (sensorValue / 1023.0 * 360.0) % 360.0;
}
<|endoftext|>


<commit_before>#include <sys/socket.h>

#include "utils.h"

#include "client_http.h"

//
// Xapian http client
//

HttpClient::HttpClient(ev::loop_ref &loop, int sock_, DatabasePool *database_pool_, double active_timeout_, double idle_timeout_)
	: BaseClient(loop, sock_, database_pool_, active_timeout_, idle_timeout_)
{
	parser.data = this;
	http_parser_init(&parser, HTTP_REQUEST);
	log(this, "Got connection (sock=%d), %d http client(s) connected.\n", sock, ++total_clients);
}

HttpClient::~HttpClient()
{
	log(this, "Lost connection (sock=%d), %d http client(s) connected.\n", sock, --total_clients);
}

void HttpClient::read_cb(ev::io &watcher)
{
	char buf[1024];

	ssize_t received = ::read(watcher.fd, buf, sizeof(buf));

	if (received < 0) {
		if (errno != EAGAIN) perror("read error");
		return;
	}

	if (received == 0) {
		// The peer has closed its half side of the connection.
		log(this, "Received EOF (sock=%d)!\n", sock);
		destroy();
	} else {
		// log(this, "<<< '%s'\n", repr(buf, received).c_str());

		size_t parsed = http_parser_execute(&parser, &settings, buf, received);
		if (parsed == received) {
			if (parser.state == 1 || parser.state == 18) { // dead or message_complete
				try {
					log(this, "METHOD: %d\n", parser.method);
					log(this, "PATH: '%s'\n", repr(path).c_str());
					log(this, "BODY: '%s'\n", repr(body).c_str());
					write("HTTP/1.1 200 OK\r\n"
						  "Content-Length: 3\r\n"
						  "Connection: close\r\n"
						  "\r\n"
						  "OK!");
					close();
				} catch (...) {
					log(this, "ERROR!\n");
				}
			}
		} else {
			// Handle error. Just close the connection.
			destroy();
		}
	}
}

//
// HTTP parser callbacks.
//

const http_parser_settings HttpClient::settings = {
	.on_message_begin = on_info,
	.on_headers_complete = on_info,
	.on_message_complete = on_info,
	.on_header_field = on_data,
	.on_header_value = on_data,
	.on_url = on_data,
	.on_status = on_data,
	.on_body = on_data
};

int HttpClient::on_info(http_parser* p) {
	HttpClient *self = static_cast<HttpClient *>(p->data);

	// log(self, "%3d. (INFO)\n", p->state);

	switch (p->state) {
		case 18:  // message_complete
			break;
		case 19:  // message_begin
			self->path.clear();
			self->body.clear();
			break;
	}

	return 0;
}

int HttpClient::on_data(http_parser* p, const char *at, size_t length) {
	HttpClient *self = static_cast<HttpClient *>(p->data);

	// log(self, "%3d. %s\n", p->state, repr(at, length).c_str());

	switch (p->state) {
		case 32: // path
			self->path = std::string(at, length);
			break;
		case 62: // data
			self->body = std::string(at, length);
			break;
	}

	return 0;
}
<commit_msg>Be more verbose about HTTP errors (logs)<commit_after>#include <sys/socket.h>

#include "utils.h"

#include "client_http.h"

//
// Xapian http client
//

HttpClient::HttpClient(ev::loop_ref &loop, int sock_, DatabasePool *database_pool_, double active_timeout_, double idle_timeout_)
	: BaseClient(loop, sock_, database_pool_, active_timeout_, idle_timeout_)
{
	parser.data = this;
	http_parser_init(&parser, HTTP_REQUEST);
	log(this, "Got connection (sock=%d), %d http client(s) connected.\n", sock, ++total_clients);
}

HttpClient::~HttpClient()
{
	log(this, "Lost connection (sock=%d), %d http client(s) connected.\n", sock, --total_clients);
}

void HttpClient::read_cb(ev::io &watcher)
{
	char buf[1024];

	ssize_t received = ::read(watcher.fd, buf, sizeof(buf));

	if (received < 0) {
		if (errno != EAGAIN) perror("read error");
		return;
	}

	if (received == 0) {
		// The peer has closed its half side of the connection.
		log(this, "Received EOF (sock=%d)!\n", sock);
		destroy();
	} else {
		// log(this, "<<< '%s'\n", repr(buf, received).c_str());

		size_t parsed = http_parser_execute(&parser, &settings, buf, received);
		if (parsed == received) {
			if (parser.state == 1 || parser.state == 18) { // dead or message_complete
				try {
					log(this, "METHOD: %d\n", parser.method);
					log(this, "PATH: '%s'\n", repr(path).c_str());
					log(this, "BODY: '%s'\n", repr(body).c_str());
					write("HTTP/1.1 200 OK\r\n"
						  "Content-Length: 3\r\n"
						  "Connection: close\r\n"
						  "\r\n"
						  "OK!");
					close();
				} catch (...) {
					log(this, "ERROR!\n");
				}
			}
		} else {
			enum http_errno err = HTTP_PARSER_ERRNO(&parser);
			const char *desc = http_errno_description(err);
			const char *msg = err != HPE_OK ? desc : "incomplete request";
			log(this, msg);
			// Handle error. Just close the connection.
			destroy();
		}
	}
}

//
// HTTP parser callbacks.
//

const http_parser_settings HttpClient::settings = {
	.on_message_begin = on_info,
	.on_headers_complete = on_info,
	.on_message_complete = on_info,
	.on_header_field = on_data,
	.on_header_value = on_data,
	.on_url = on_data,
	.on_status = on_data,
	.on_body = on_data
};

int HttpClient::on_info(http_parser* p) {
	HttpClient *self = static_cast<HttpClient *>(p->data);

	// log(self, "%3d. (INFO)\n", p->state);

	switch (p->state) {
		case 18:  // message_complete
			break;
		case 19:  // message_begin
			self->path.clear();
			self->body.clear();
			break;
	}

	return 0;
}

int HttpClient::on_data(http_parser* p, const char *at, size_t length) {
	HttpClient *self = static_cast<HttpClient *>(p->data);

	// log(self, "%3d. %s\n", p->state, repr(at, length).c_str());

	switch (p->state) {
		case 32: // path
			self->path = std::string(at, length);
			break;
		case 62: // data
			self->body = std::string(at, length);
			break;
	}

	return 0;
}
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2015 - The CM Authors <legal@clickmatcher.com>
 *   All Rights Reserved.
 *
 * This file is CONFIDENTIAL -- Distribution or duplication of this material or
 * the information contained herein is strictly forbidden unless prior written
 * permission is obtained.
 */
#include <stdlib.h>
#include <unistd.h>
#include "fnord-base/io/filerepository.h"
#include "fnord-base/io/fileutil.h"
#include "fnord-base/application.h"
#include "fnord-base/random.h"
#include "fnord-base/thread/eventloop.h"
#include "fnord-base/thread/threadpool.h"
#include "fnord-rpc/ServerGroup.h"
#include "fnord-rpc/RPC.h"
#include "fnord-base/cli/flagparser.h"
#include "fnord-json/json.h"
#include "fnord-json/jsonrpc.h"
#include "fnord-json/JSONRPCCodec.h"
#include "fnord-http/httprouter.h"
#include "fnord-http/httpserver.h"
#include "fnord-feeds/FeedService.h"
#include "fnord-feeds/RemoteFeedWriter.h"
#include "fnord-http/statshttpservlet.h"
#include "fnord-base/stats/statsdagent.h"
#include "fnord-rpc/RPCClient.h"
#include "CustomerNamespace.h"
#include "frontend/CMFrontend.h"
#include "frontend/LookupServlet.h"

using fnord::StringUtil;

int main(int argc, const char** argv) {
  fnord::Application::init();
  fnord::Application::logToStderr();

  fnord::cli::FlagParser flags;

  flags.defineFlag(
      "cmdata",
      cli::FlagParser::T_STRING,
      true,
      NULL,
      NULL,
      "clickmatcher app data dir",
      "<path>");

  flags.defineFlag(
      "public_http_port",
      fnord::cli::FlagParser::T_INTEGER,
      false,
      NULL,
      "8000",
      "Start the public http server on this port",
      "<port>");

  flags.defineFlag(
      "internal_http_port",
      fnord::cli::FlagParser::T_INTEGER,
      false,
      NULL,
      "7000",
      "Start the internal http server on this port",
      "<port>");

  flags.defineFlag(
      "loglevel",
      fnord::cli::FlagParser::T_STRING,
      false,
      NULL,
      "INFO",
      "loglevel",
      "<level>");

  flags.defineFlag(
      "statsd_addr",
      fnord::cli::FlagParser::T_STRING,
      false,
      NULL,
      "127.0.0.1:8192",
      "Statsd addr",
      "<addr>");

  flags.parseArgv(argc, argv);

  Logger::get()->setMinimumLogLevel(
      strToLogLevel(flags.getString("loglevel")));

  fnord::thread::EventLoop event_loop;
  HTTPRPCClient rpc_client(&event_loop);

  /* set up cmdata */
  auto cmdata_path = flags.getString("cmdata");
  if (!FileUtil::isDirectory(cmdata_path)) {
    RAISEF(kIOError, "no such directory: $0", cmdata_path);
  }

  /* set up tracker log feed writer */
  fnord::feeds::RemoteFeedWriter tracker_log_feed(&rpc_client);
  tracker_log_feed.addTargetFeed(
      URI("http://s01.nue01.production.fnrd.net:7001/rpc"),
      "tracker_log.feedserver01.nue01.production.fnrd.net",
      16);

  tracker_log_feed.addTargetFeed(
      URI("http://s02.nue01.production.fnrd.net:7001/rpc"),
      "tracker_log.feedserver02.nue01.production.fnrd.net",
      16);

  tracker_log_feed.exportStats("/cm-frontend/global/tracker_log_writer");

  /* set up frontend */
  cm::CMFrontend frontend(&tracker_log_feed);

  /* set up dawanda */
  auto dwn_ns = new cm::CustomerNamespace("dawanda");
  dwn_ns->addVHost("dwnapps.net");
  dwn_ns->loadTrackingJS("cm-config/customer_dawanda/track.js");

  RefPtr<feeds::RemoteFeedWriter> dwn_index_request_feed(
      new feeds::RemoteFeedWriter(&rpc_client));

  dwn_index_request_feed->addTargetFeed(
      URI("http://s01.nue01.production.fnrd.net:7001/rpc"),
      "dawanda.index_requests.feedserver01.nue01.production.fnrd.net",
      16);

  dwn_index_request_feed->addTargetFeed(
      URI("http://s02.nue01.production.fnrd.net:7001/rpc"),
      "dawanda.index_requests.feedserver02.nue01.production.fnrd.net",
      16);

  dwn_index_request_feed->exportStats(
      "/cm-frontend/global/index_request_writer");

  frontend.addCustomer(dwn_ns, dwn_index_request_feed);

  /* set up public http server */
  fnord::http::HTTPRouter public_http_router;
  public_http_router.addRouteByPrefixMatch("/", &frontend);
  fnord::http::HTTPServer public_http_server(&public_http_router, &event_loop);
  public_http_server.listen(flags.getInt("public_http_port"));
  public_http_server.stats()->exportStats(
      "/cm-frontend/global/http/inbound");
  public_http_server.stats()->exportStats(
      StringUtil::format(
          "/cm-frontend/by-host/$0/http/inbound",
          cm::cmHostname()));

  /* setup internal http server */
  fnord::http::HTTPRouter rpc_http_router;
  fnord::http::HTTPServer rpc_http_server(&rpc_http_router, &event_loop);
  rpc_http_server.listen(flags.getInt("internal_http_port"));

  /* lookup servlet */
  cm::LookupServlet lookup_servlet(cmdata_path);
  rpc_http_router.addRouteByPrefixMatch("/lookup", &lookup_servlet);

  /* stats servlet and reporting */
  fnord::stats::StatsHTTPServlet stats_servlet;
  rpc_http_router.addRouteByPrefixMatch("/stats", &stats_servlet);

  fnord::stats::StatsdAgent statsd_agent(
      fnord::net::InetAddr::resolve(flags.getString("statsd_addr")),
      10 * fnord::kMicrosPerSecond);

  statsd_agent.start();

  event_loop.run();
  return 0;
}

<commit_msg>clean up frontend<commit_after>/**
 * Copyright (c) 2015 - The CM Authors <legal@clickmatcher.com>
 *   All Rights Reserved.
 *
 * This file is CONFIDENTIAL -- Distribution or duplication of this material or
 * the information contained herein is strictly forbidden unless prior written
 * permission is obtained.
 */
#include <stdlib.h>
#include <unistd.h>
#include "fnord-base/io/filerepository.h"
#include "fnord-base/io/fileutil.h"
#include "fnord-base/application.h"
#include "fnord-base/random.h"
#include "fnord-base/thread/eventloop.h"
#include "fnord-base/thread/threadpool.h"
#include "fnord-rpc/ServerGroup.h"
#include "fnord-rpc/RPC.h"
#include "fnord-base/cli/flagparser.h"
#include "fnord-json/json.h"
#include "fnord-json/jsonrpc.h"
#include "fnord-json/JSONRPCCodec.h"
#include "fnord-http/httprouter.h"
#include "fnord-http/httpserver.h"
#include "fnord-feeds/FeedService.h"
#include "fnord-feeds/RemoteFeedWriter.h"
#include "fnord-http/statshttpservlet.h"
#include "fnord-base/stats/statsdagent.h"
#include "fnord-rpc/RPCClient.h"
#include "CustomerNamespace.h"
#include "frontend/CMFrontend.h"
#include "frontend/LookupServlet.h"

using fnord::StringUtil;

int main(int argc, const char** argv) {
  fnord::Application::init();
  fnord::Application::logToStderr();

  fnord::cli::FlagParser flags;

  flags.defineFlag(
      "http_port",
      fnord::cli::FlagParser::T_INTEGER,
      false,
      NULL,
      "8000",
      "Start the public http server on this port",
      "<port>");

  flags.defineFlag(
      "loglevel",
      fnord::cli::FlagParser::T_STRING,
      false,
      NULL,
      "INFO",
      "loglevel",
      "<level>");

  flags.defineFlag(
      "statsd_addr",
      fnord::cli::FlagParser::T_STRING,
      false,
      NULL,
      "127.0.0.1:8192",
      "Statsd addr",
      "<addr>");

  flags.parseArgv(argc, argv);

  Logger::get()->setMinimumLogLevel(
      strToLogLevel(flags.getString("loglevel")));

  fnord::thread::EventLoop event_loop;
  HTTPRPCClient rpc_client(&event_loop);

  /* set up tracker log feed writer */
  fnord::feeds::RemoteFeedWriter tracker_log_feed(&rpc_client);
  tracker_log_feed.addTargetFeed(
      URI("http://s01.nue01.production.fnrd.net:7001/rpc"),
      "tracker_log.feedserver01.nue01.production.fnrd.net",
      16);

  tracker_log_feed.addTargetFeed(
      URI("http://s02.nue01.production.fnrd.net:7001/rpc"),
      "tracker_log.feedserver02.nue01.production.fnrd.net",
      16);

  tracker_log_feed.exportStats("/cm-frontend/global/tracker_log_writer");

  /* set up frontend */
  cm::CMFrontend frontend(&tracker_log_feed);

  /* set up dawanda */
  auto dwn_ns = new cm::CustomerNamespace("dawanda");
  dwn_ns->addVHost("dwnapps.net");
  dwn_ns->loadTrackingJS("cm-config/customer_dawanda/track.js");

  RefPtr<feeds::RemoteFeedWriter> dwn_index_request_feed(
      new feeds::RemoteFeedWriter(&rpc_client));

  dwn_index_request_feed->addTargetFeed(
      URI("http://s01.nue01.production.fnrd.net:7001/rpc"),
      "dawanda.index_requests.feedserver01.nue01.production.fnrd.net",
      16);

  dwn_index_request_feed->addTargetFeed(
      URI("http://s02.nue01.production.fnrd.net:7001/rpc"),
      "dawanda.index_requests.feedserver02.nue01.production.fnrd.net",
      16);

  dwn_index_request_feed->exportStats(
      "/cm-frontend/global/index_request_writer");

  frontend.addCustomer(dwn_ns, dwn_index_request_feed);

  /* set up public http server */
  fnord::http::HTTPRouter public_http_router;
  public_http_router.addRouteByPrefixMatch("/", &frontend);
  fnord::http::HTTPServer public_http_server(&public_http_router, &event_loop);
  public_http_server.listen(flags.getInt("public_http_port"));
  public_http_server.stats()->exportStats(
      "/cm-frontend/global/http/inbound");
  public_http_server.stats()->exportStats(
      StringUtil::format(
          "/cm-frontend/by-host/$0/http/inbound",
          cm::cmHostname()));

  /* stats reporting */
  fnord::stats::StatsdAgent statsd_agent(
      fnord::net::InetAddr::resolve(flags.getString("statsd_addr")),
      10 * fnord::kMicrosPerSecond);

  statsd_agent.start();

  event_loop.run();
  return 0;
}

<|endoftext|>


<commit_before>#include "NWUnitTest.h"

#ifdef __linux
 #include "NanoWinMFCAfxStr.h"
#else
 #include <windows.h>
#endif

NW_BEGIN_TEST_GROUP_SIMPLE(NanoWinMFCAfxStrTestGroup)

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringReplaceSimpleTCHARTest)
{
	CString cString("abc abc abc");

	int n = cString.Replace('a', 'q');

	NW_CHECK_EQUAL(3, n);
	NW_CHECK_EQUAL_STRCMP(cString, "qbc qbc qbc");

	n = cString.Replace('w', 'q');

	NW_CHECK_EQUAL(0, n);
	NW_CHECK_EQUAL_STRCMP(cString, "qbc qbc qbc");
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringReplaceSimpleLPCTSTRTest)
{
	CString cString("abc abc abc");

	LPCTSTR strOld = "a";
	LPCTSTR strNew = "q";

	int n = cString.Replace(strOld, strNew);

	NW_CHECK_EQUAL(3, n);
	NW_CHECK_EQUAL_STRCMP(cString, "qbc qbc qbc");
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringReplaceNullLPCTSTRTest)
{
	CString cString("abc abc abc");

	LPCTSTR strOld = "ab";
	LPCTSTR strNew = NULL;

	int n = cString.Replace(strOld, strNew);

	NW_CHECK_EQUAL(3, n);
	NW_CHECK_EQUAL_STRCMP(cString, "c c c");
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringReplaceDifferentLengthLPCTSTRTest)
{
	CString cString("abc abc abc qwe");

	LPCTSTR strOld = "abc";
	LPCTSTR strNew = "de";

	int n = cString.Replace(strOld, strNew);

	NW_CHECK_EQUAL(3, n);
	NW_CHECK_EQUAL_STRCMP(cString, "de de de qwe");
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringFindSimpleTCHARTest)
{
	CString cString("abcdef");
	int n = cString.Find('b');

	NW_CHECK_EQUAL(1, n);

	n = cString.Find('q');
	NW_CHECK_EQUAL(-1, n);
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringFindWithStartPosTCHARTest)
{
	CString cString("abcdef abcdef");

	int n = cString.Find('b', 4);

	NW_CHECK_EQUAL(8, n);

	n = cString.Find('q', 5);

	NW_CHECK_EQUAL(-1, n);
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringFindSimpleLPCTSTRTest)
{
	CString cString("abcdef");
	LPCTSTR sub = "b";

	int n = cString.Find(sub);

	NW_CHECK_EQUAL(1, n);

	sub = "def";
	n = cString.Find(sub);

	NW_CHECK_EQUAL(3, n);

	sub = "qqq";
	n = cString.Find(sub);

	NW_CHECK_EQUAL(-1, n);
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringFindWithStartPosLPCTSTRTest)
{
	CString cString("abcdef abcdef");
	LPCTSTR sub = "b";

	int n = cString.Find(sub, 4);

	NW_CHECK_EQUAL(8, n);

	sub = "def";
	n = cString.Find(sub, 5);

	NW_CHECK_EQUAL(10, n);
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringReverseFindSimpleTCHARTest)
{
	CString cString("abc abc abc");

	int n = cString.ReverseFind('a');

	NW_CHECK_EQUAL(8, n);

	n = cString.ReverseFind('q');

	NW_CHECK_EQUAL(-1, n);
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringMakeLowerTest)
{
	CString cString("aBcDeFZzZ");

	cString.MakeLower();

	NW_CHECK_EQUAL_STRCMP(cString, "abcdefzzz");
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringMakeUpperTest)
{
	CString cString("aBcDeFZzZ");

	cString.MakeUpper();

	NW_CHECK_EQUAL_STRCMP(cString, "ABCDEFZZZ");
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringMakeReverseTest)
{
	CString cString("abcdef");

	cString.MakeReverse();

	NW_CHECK_EQUAL_STRCMP(cString, "fedcba");
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringRightTest)
{
	CString cString("abcdef");

	CString resStr = cString.Right(3);

	NW_CHECK_EQUAL_STRCMP(resStr, "def");
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringMidTest)
{
	CString cString("abcdef");

	CString resStr = cString.Mid(2);

	NW_CHECK_EQUAL_STRCMP(resStr, "cdef");
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringMidWithCounterTest)
{
	CString cString("abcdefabcdef");

	CString resStr = cString.Mid(2, 5);

	NW_CHECK_EQUAL_STRCMP("cdefa", resStr);
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringLeftTest)
{
	CString cString("abcdef");

	CString resStr = cString.Left(3);

	NW_CHECK_EQUAL_STRCMP("abc", resStr);
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringInsertTCHARTest)
{
	CString cString("abcdef");

	int n = cString.Insert(3, 'z');

	NW_CHECK_EQUAL(7, n);
	NW_CHECK_EQUAL_STRCMP("abczdef", cString);
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringInsertIndexHigherThanLengthTCHARTest)
{
	CString cString("abcdef");

	int n = cString.Insert(100, 'z');

	NW_CHECK_EQUAL(7, n);
	NW_CHECK_EQUAL_STRCMP("abcdefz", cString);
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringInsertLPCTSTRTest)
{
	CString cString("abcdef");

	int n = cString.Insert(0, "zzz");

	NW_CHECK_EQUAL(9, n);
	NW_CHECK_EQUAL_STRCMP("zzzabcdef", cString);
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringDeleteTest)
{
	CString cString("abcdefabc");

	int n = cString.Delete(3, 3);

	NW_CHECK_EQUAL(6, n);
	NW_CHECK_EQUAL_STRCMP("abcabc", cString);

	n = cString.Delete(3, 100);

	NW_CHECK_EQUAL(3, n);
	NW_CHECK_EQUAL_STRCMP("abc", cString);
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringRemoveTest)
{
	CString cString("abcdefabc");

	int n = cString.Remove('a');

	NW_CHECK_EQUAL(2, n);
	NW_CHECK_EQUAL_STRCMP("bcdefbc", cString);

	n = cString.Remove('q');

	NW_CHECK_EQUAL(0, n);
	NW_CHECK_EQUAL_STRCMP("bcdefbc", cString);
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringTrimLeftTest)
{
	CString cString("	  abcdefabc ");

	CString resStr = cString.TrimLeft();

	NW_CHECK_EQUAL_STRCMP("abcdefabc ", resStr);
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringTrimRightTest)
{
	CString cString(" abcdefabc		  ");

	CString resStr = cString.TrimRight();

	NW_CHECK_EQUAL_STRCMP(" abcdefabc", resStr);
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringTrimTest)
{
	CString cString("	  abcdefabc		  ");

	CString resStr = cString.Trim();

	NW_CHECK_EQUAL_STRCMP("abcdefabc", resStr);
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringCompareTest)
{
	CString cString("abcdef");

	int res = cString.Compare("abcdef");
	NW_CHECK_EQUAL(0, res);

	res = cString.Compare("A");
	NW_CHECK(res > 0);

	res = cString.Compare("abcdefabc");
	NW_CHECK(res < 0);
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringCompareNoCaseTest)
{
	CString cString("abcdef");

	int res = cString.CompareNoCase("ABcdEF");
	NW_CHECK_EQUAL(0, res);

	res = cString.CompareNoCase("ABcdE");
	NW_CHECK(res > 0);
}
/*
NW_TEST(NanoWinMFCAfxStrTestGroup, CStringFormatTest)
{
	CString str;

	str.Format("%d%s%d%s%d", 2, " * ", 2, " equal ", 4);

	NW_CHECK_EQUAL_STRCMP("2 * 2 equal 4", str);
}
*/
NW_TEST(NanoWinMFCAfxStrTestGroup, CStringOperatorAssignTest)
{
	CString cString("zzz");

	cString = "a";

	NW_CHECK_EQUAL_STRCMP("a", cString);
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringOperatorPlusAssignTest)
{
	CString cString("zzz");

	cString += "www";

	NW_CHECK_EQUAL_STRCMP("zzzwww", cString);

	CString strAdd = "aaa";

	cString += strAdd;

	NW_CHECK_EQUAL_STRCMP("zzzwwwaaa", cString);

	cString += 'b';

	NW_CHECK_EQUAL_STRCMP("zzzwwwaaab", cString);
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringOperatorPlusTest)
{
	CString str1("zzz");
	CString str2("aaa");

	CString resStr = str1 + str2;

	NW_CHECK_EQUAL_STRCMP("zzzaaa", resStr);
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringCompareOperatorsTest)
{
	NW_CHECK_TRUE(CString("abc") == CString("abc"));
	NW_CHECK_TRUE(CString("abc") == "abc");
	NW_CHECK_FALSE(CString("abc") == CString("abcde"));
	NW_CHECK_FALSE("abcde" == CString("abc"));

	NW_CHECK_TRUE(CString("abc") != CString("abcde"));
	NW_CHECK_TRUE(CString("abc") != "abcde");
	NW_CHECK_FALSE(CString("abc") != CString("abc"));
	NW_CHECK_FALSE("abc" != CString("abc"));

	NW_CHECK_TRUE(CString("abc") > CString("ab"));
	NW_CHECK_TRUE(CString("abc") > "aaa");
	NW_CHECK_FALSE("aaa" > CString("abc"));

	NW_CHECK_TRUE(CString("ab") < CString("abc"));
	NW_CHECK_TRUE(CString("aaa") < "abc");
	NW_CHECK_FALSE("abc" < CString("aaa"));

	NW_CHECK_TRUE(CString("abc") >= CString("abc"));
	NW_CHECK_TRUE(CString("abc") >= "aaa");
	NW_CHECK_FALSE("abc" >= CString("abcd"));

	NW_CHECK_TRUE(CString("abc") <= CString("abc"));
	NW_CHECK_TRUE(CString("aaa") <= "abc");
	NW_CHECK_FALSE("abcd" <= CString("abc"));
}

NW_END_TEST_GROUP()<commit_msg>CString::Format test enabled<commit_after>#include "NWUnitTest.h"

#ifdef __linux
 #include "NanoWinMFCAfxStr.h"
#else
 #include <windows.h>
#endif

NW_BEGIN_TEST_GROUP_SIMPLE(NanoWinMFCAfxStrTestGroup)

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringReplaceSimpleTCHARTest)
{
	CString cString("abc abc abc");

	int n = cString.Replace('a', 'q');

	NW_CHECK_EQUAL(3, n);
	NW_CHECK_EQUAL_STRCMP(cString, "qbc qbc qbc");

	n = cString.Replace('w', 'q');

	NW_CHECK_EQUAL(0, n);
	NW_CHECK_EQUAL_STRCMP(cString, "qbc qbc qbc");
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringReplaceSimpleLPCTSTRTest)
{
	CString cString("abc abc abc");

	LPCTSTR strOld = "a";
	LPCTSTR strNew = "q";

	int n = cString.Replace(strOld, strNew);

	NW_CHECK_EQUAL(3, n);
	NW_CHECK_EQUAL_STRCMP(cString, "qbc qbc qbc");
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringReplaceNullLPCTSTRTest)
{
	CString cString("abc abc abc");

	LPCTSTR strOld = "ab";
	LPCTSTR strNew = NULL;

	int n = cString.Replace(strOld, strNew);

	NW_CHECK_EQUAL(3, n);
	NW_CHECK_EQUAL_STRCMP(cString, "c c c");
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringReplaceDifferentLengthLPCTSTRTest)
{
	CString cString("abc abc abc qwe");

	LPCTSTR strOld = "abc";
	LPCTSTR strNew = "de";

	int n = cString.Replace(strOld, strNew);

	NW_CHECK_EQUAL(3, n);
	NW_CHECK_EQUAL_STRCMP(cString, "de de de qwe");
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringFindSimpleTCHARTest)
{
	CString cString("abcdef");
	int n = cString.Find('b');

	NW_CHECK_EQUAL(1, n);

	n = cString.Find('q');
	NW_CHECK_EQUAL(-1, n);
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringFindWithStartPosTCHARTest)
{
	CString cString("abcdef abcdef");

	int n = cString.Find('b', 4);

	NW_CHECK_EQUAL(8, n);

	n = cString.Find('q', 5);

	NW_CHECK_EQUAL(-1, n);
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringFindSimpleLPCTSTRTest)
{
	CString cString("abcdef");
	LPCTSTR sub = "b";

	int n = cString.Find(sub);

	NW_CHECK_EQUAL(1, n);

	sub = "def";
	n = cString.Find(sub);

	NW_CHECK_EQUAL(3, n);

	sub = "qqq";
	n = cString.Find(sub);

	NW_CHECK_EQUAL(-1, n);
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringFindWithStartPosLPCTSTRTest)
{
	CString cString("abcdef abcdef");
	LPCTSTR sub = "b";

	int n = cString.Find(sub, 4);

	NW_CHECK_EQUAL(8, n);

	sub = "def";
	n = cString.Find(sub, 5);

	NW_CHECK_EQUAL(10, n);
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringReverseFindSimpleTCHARTest)
{
	CString cString("abc abc abc");

	int n = cString.ReverseFind('a');

	NW_CHECK_EQUAL(8, n);

	n = cString.ReverseFind('q');

	NW_CHECK_EQUAL(-1, n);
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringMakeLowerTest)
{
	CString cString("aBcDeFZzZ");

	cString.MakeLower();

	NW_CHECK_EQUAL_STRCMP(cString, "abcdefzzz");
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringMakeUpperTest)
{
	CString cString("aBcDeFZzZ");

	cString.MakeUpper();

	NW_CHECK_EQUAL_STRCMP(cString, "ABCDEFZZZ");
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringMakeReverseTest)
{
	CString cString("abcdef");

	cString.MakeReverse();

	NW_CHECK_EQUAL_STRCMP(cString, "fedcba");
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringRightTest)
{
	CString cString("abcdef");

	CString resStr = cString.Right(3);

	NW_CHECK_EQUAL_STRCMP(resStr, "def");
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringMidTest)
{
	CString cString("abcdef");

	CString resStr = cString.Mid(2);

	NW_CHECK_EQUAL_STRCMP(resStr, "cdef");
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringMidWithCounterTest)
{
	CString cString("abcdefabcdef");

	CString resStr = cString.Mid(2, 5);

	NW_CHECK_EQUAL_STRCMP("cdefa", resStr);
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringLeftTest)
{
	CString cString("abcdef");

	CString resStr = cString.Left(3);

	NW_CHECK_EQUAL_STRCMP("abc", resStr);
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringInsertTCHARTest)
{
	CString cString("abcdef");

	int n = cString.Insert(3, 'z');

	NW_CHECK_EQUAL(7, n);
	NW_CHECK_EQUAL_STRCMP("abczdef", cString);
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringInsertIndexHigherThanLengthTCHARTest)
{
	CString cString("abcdef");

	int n = cString.Insert(100, 'z');

	NW_CHECK_EQUAL(7, n);
	NW_CHECK_EQUAL_STRCMP("abcdefz", cString);
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringInsertLPCTSTRTest)
{
	CString cString("abcdef");

	int n = cString.Insert(0, "zzz");

	NW_CHECK_EQUAL(9, n);
	NW_CHECK_EQUAL_STRCMP("zzzabcdef", cString);
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringDeleteTest)
{
	CString cString("abcdefabc");

	int n = cString.Delete(3, 3);

	NW_CHECK_EQUAL(6, n);
	NW_CHECK_EQUAL_STRCMP("abcabc", cString);

	n = cString.Delete(3, 100);

	NW_CHECK_EQUAL(3, n);
	NW_CHECK_EQUAL_STRCMP("abc", cString);
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringRemoveTest)
{
	CString cString("abcdefabc");

	int n = cString.Remove('a');

	NW_CHECK_EQUAL(2, n);
	NW_CHECK_EQUAL_STRCMP("bcdefbc", cString);

	n = cString.Remove('q');

	NW_CHECK_EQUAL(0, n);
	NW_CHECK_EQUAL_STRCMP("bcdefbc", cString);
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringTrimLeftTest)
{
	CString cString("	  abcdefabc ");

	CString resStr = cString.TrimLeft();

	NW_CHECK_EQUAL_STRCMP("abcdefabc ", resStr);
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringTrimRightTest)
{
	CString cString(" abcdefabc		  ");

	CString resStr = cString.TrimRight();

	NW_CHECK_EQUAL_STRCMP(" abcdefabc", resStr);
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringTrimTest)
{
	CString cString("	  abcdefabc		  ");

	CString resStr = cString.Trim();

	NW_CHECK_EQUAL_STRCMP("abcdefabc", resStr);
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringCompareTest)
{
	CString cString("abcdef");

	int res = cString.Compare("abcdef");
	NW_CHECK_EQUAL(0, res);

	res = cString.Compare("A");
	NW_CHECK(res > 0);

	res = cString.Compare("abcdefabc");
	NW_CHECK(res < 0);
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringCompareNoCaseTest)
{
	CString cString("abcdef");

	int res = cString.CompareNoCase("ABcdEF");
	NW_CHECK_EQUAL(0, res);

	res = cString.CompareNoCase("ABcdE");
	NW_CHECK(res > 0);
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringFormatTest)
{
	CString str;

	str.Format("%d%s%d%s%d", 2, " * ", 2, " equal ", 4);

	NW_CHECK_EQUAL_STRCMP("2 * 2 equal 4", str);
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringOperatorAssignTest)
{
	CString cString("zzz");

	cString = "a";

	NW_CHECK_EQUAL_STRCMP("a", cString);
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringOperatorPlusAssignTest)
{
	CString cString("zzz");

	cString += "www";

	NW_CHECK_EQUAL_STRCMP("zzzwww", cString);

	CString strAdd = "aaa";

	cString += strAdd;

	NW_CHECK_EQUAL_STRCMP("zzzwwwaaa", cString);

	cString += 'b';

	NW_CHECK_EQUAL_STRCMP("zzzwwwaaab", cString);
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringOperatorPlusTest)
{
	CString str1("zzz");
	CString str2("aaa");

	CString resStr = str1 + str2;

	NW_CHECK_EQUAL_STRCMP("zzzaaa", resStr);
}

NW_TEST(NanoWinMFCAfxStrTestGroup, CStringCompareOperatorsTest)
{
	NW_CHECK_TRUE(CString("abc") == CString("abc"));
	NW_CHECK_TRUE(CString("abc") == "abc");
	NW_CHECK_FALSE(CString("abc") == CString("abcde"));
	NW_CHECK_FALSE("abcde" == CString("abc"));

	NW_CHECK_TRUE(CString("abc") != CString("abcde"));
	NW_CHECK_TRUE(CString("abc") != "abcde");
	NW_CHECK_FALSE(CString("abc") != CString("abc"));
	NW_CHECK_FALSE("abc" != CString("abc"));

	NW_CHECK_TRUE(CString("abc") > CString("ab"));
	NW_CHECK_TRUE(CString("abc") > "aaa");
	NW_CHECK_FALSE("aaa" > CString("abc"));

	NW_CHECK_TRUE(CString("ab") < CString("abc"));
	NW_CHECK_TRUE(CString("aaa") < "abc");
	NW_CHECK_FALSE("abc" < CString("aaa"));

	NW_CHECK_TRUE(CString("abc") >= CString("abc"));
	NW_CHECK_TRUE(CString("abc") >= "aaa");
	NW_CHECK_FALSE("abc" >= CString("abcd"));

	NW_CHECK_TRUE(CString("abc") <= CString("abc"));
	NW_CHECK_TRUE(CString("aaa") <= "abc");
	NW_CHECK_FALSE("abcd" <= CString("abc"));
}

NW_END_TEST_GROUP()<|endoftext|>


<commit_before>/*
Copyright (c) 2015-2016 Advanced Micro Devices, Inc. All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, 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.
*/

#include "hip_runtime.h"
#include "test_common.h"

int main(int argc, char *argv[])
{
    HipTest::parseStandardArguments(argc, argv, true);

    HIPCHECK(hipInit(0));

    hipDevice_t device;
    hipDevice_t device1;
    hipCtx_t    ctx;
    hipCtx_t    ctx1;

    HIPCHECK(hipDeviceGetFromId(&device, 0));
    HIPCHECK(hipCtxCreate(&ctx, 0, device));
    HIPCHECK(hipCtxGetCurrent(&ctx1));
    HIPCHECK(hipCtxGetDevice(&device1));
    HIPCHECK(hipCtxPopCurrent(&ctx1));
    HIPCHECK(hipCtxGetCurrent(&ctx1));

    HIPCHECK(hipCtxDestroy(ctx));

    passed();
};
<commit_msg>Directed tests: Fix hipCtx_simple on NVCC<commit_after>/*
Copyright (c) 2015-2016 Advanced Micro Devices, Inc. All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, 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.
*/

#include "hip_runtime.h"
#include "test_common.h"

int main(int argc, char *argv[])
{
    HipTest::parseStandardArguments(argc, argv, true);

    HIPCHECK(hipInit(0));

    hipDevice_t device;
    hipDevice_t device1;
    hipCtx_t    ctx;
    hipCtx_t    ctx1;

    HIPCHECK(hipDeviceGet(&device, 0));
    HIPCHECK(hipCtxCreate(&ctx, 0, device));
    HIPCHECK(hipCtxGetCurrent(&ctx1));
    HIPCHECK(hipCtxGetDevice(&device1));
    HIPCHECK(hipCtxPopCurrent(&ctx1));
    HIPCHECK(hipCtxGetCurrent(&ctx1));

    HIPCHECK(hipCtxDestroy(ctx));

    passed();
};
<|endoftext|>


<commit_before>// -----------------------------------------------------------------------------
//
// MIT License
//
// Copyright (c) 2016 Alberto Sola
//
// 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.
//
// -----------------------------------------------------------------------------

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

#include "cmd/cmdget.hpp"

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

CmdGet::CmdGet(int argc, char * argv[]){
  add_option("-f"); // Show finished only
  add_option("-a"); // Show all
  parse(argc,argv);
}

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

void CmdGet::execute(){
  /*
    Show tasks.
    Default: not finished tasks.
    -a: show all tasks.
    -f: show finished tasks.

    If a task end date is today, the color is bold green.
  */
  bool show_finished = false;
  Date today_date;
  std::vector<Task> task_list;

  // Get tasks
  tasker -> get_task_list(task_list);

  // Get current date
  today_date.set_current();

  // Show header
  std::cout << std::endl;
  std::cout << "-------------------------------------------" << std::endl;
  std::cout << "ID" << " | " << "Task" << std::endl;
  std::cout << "-------------------------------------------" << std::endl;

  // Print finished tasks
  if(check_option("-f")){

    for(auto & task: task_list){

      if(task.is_finished())
        std::cout << task.get_id() << " | " << task.get_task() << std::endl;

    }

  }
  else{
    // Check "all" option
    show_finished = check_option("-a");

    // Print tasks
    for(auto & task: task_list){

      if(!task.is_finished()){
        // Text: bold green
        if(task.get_end_date() == today_date)
          std::cout << "\033[32;1m";

        std::cout << task.get_id() << " | " << task.get_task() << std::endl;
      }
      else if(show_finished){
        std::cout << "\033[9m";
        std::cout << task.get_id() << " | " << task.get_task() << std::endl;
      }

      // Clear text effects
      std::cout << "\033[0m";

    }

  }

  std::cout << "-------------------------------------------" << std::endl;
  std::cout << std::endl;
}

// -----------------------------------------------------------------------------
<commit_msg>Red tasks.<commit_after>// -----------------------------------------------------------------------------
//
// MIT License
//
// Copyright (c) 2016 Alberto Sola
//
// 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.
//
// -----------------------------------------------------------------------------

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

#include "cmd/cmdget.hpp"

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

CmdGet::CmdGet(int argc, char * argv[]){
  add_option("-f"); // Show finished only
  add_option("-a"); // Show all
  parse(argc,argv);
}

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

void CmdGet::execute(){
  /*
    Show tasks.
    Default: not finished tasks.
    -a: show all tasks.
    -f: show finished tasks.

    If a task end date is today, the color is bold green.
  */
  bool show_finished = false;
  Date today_date;
  Date end_date;
  std::vector<Task> task_list;

  // Get tasks
  tasker -> get_task_list(task_list);

  // Get current date
  today_date.set_current();

  // Show header
  std::cout << std::endl;
  std::cout << "-------------------------------------------" << std::endl;
  std::cout << "ID" << " | " << "Task" << std::endl;
  std::cout << "-------------------------------------------" << std::endl;

  // Print finished tasks
  if(check_option("-f")){

    for(auto & task: task_list){

      if(task.is_finished())
        std::cout << task.get_id() << " | " << task.get_task() << std::endl;

    }

  }
  else{
    // Check "all" option
    show_finished = check_option("-a");

    // Print tasks
    for(auto & task: task_list){

      if(!task.is_finished()){

        end_date = task.get_end_date();

        // Text: bold green
        if(end_date == today_date)
          std::cout << "\033[32;1m";
        // Text: bold red
        else if(!end_date.empty() && end_date < today_date)
          std::cout << "\033[31;1m";

        std::cout << task.get_id() << " | " << task.get_task() << std::endl;
      }
      else if(show_finished){
        std::cout << "\033[9m";
        std::cout << task.get_id() << " | " << task.get_task() << std::endl;
      }

      // Clear text effects
      std::cout << "\033[0m";

    }

  }

  std::cout << "-------------------------------------------" << std::endl;
  std::cout << std::endl;
}

// -----------------------------------------------------------------------------
<|endoftext|>


<commit_before>//===-- Timer.cpp - Interval Timing Support -------------------------------===//
//
//                     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.
//
//===----------------------------------------------------------------------===//
//
// Interval Timing implementation.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/Timer.h"
#include "llvm/Support/CommandLine.h"
#include <algorithm>
#include <iostream>
#include <functional>
#include <fstream>
#include <map>
#include "llvm/Config/sys/resource.h"
#include "llvm/Config/sys/time.h"
#include "llvm/Config/unistd.h"
#include "llvm/Config/malloc.h"
#include "llvm/Config/windows.h"
using namespace llvm;

// GetLibSupportInfoOutputFile - Return a file stream to print our output on.
namespace llvm { extern std::ostream *GetLibSupportInfoOutputFile(); }

// getLibSupportInfoOutputFilename - This ugly hack is brought to you courtesy
// of constructor/destructor ordering being unspecified by C++.  Basically the
// problem is that a Statistic<> object gets destroyed, which ends up calling
// 'GetLibSupportInfoOutputFile()' (below), which calls this function.
// LibSupportInfoOutputFilename used to be a global variable, but sometimes it
// would get destroyed before the Statistic, causing havoc to ensue.  We "fix"
// this by creating the string the first time it is needed and never destroying
// it.
static std::string &getLibSupportInfoOutputFilename() {
  static std::string *LibSupportInfoOutputFilename = new std::string();
  return *LibSupportInfoOutputFilename;
}

namespace {
#ifdef HAVE_MALLINFO
  cl::opt<bool>
  TrackSpace("track-memory", cl::desc("Enable -time-passes memory "
                                      "tracking (this may be slow)"),
             cl::Hidden);
#endif

  cl::opt<std::string, true>
  InfoOutputFilename("info-output-file", cl::value_desc("filename"),
                     cl::desc("File to append -stats and -timer output to"),
                   cl::Hidden, cl::location(getLibSupportInfoOutputFilename()));
}

static TimerGroup *DefaultTimerGroup = 0;
static TimerGroup *getDefaultTimerGroup() {
  if (DefaultTimerGroup) return DefaultTimerGroup;
  return DefaultTimerGroup = new TimerGroup("Miscellaneous Ungrouped Timers");
}

Timer::Timer(const std::string &N)
  : Elapsed(0), UserTime(0), SystemTime(0), MemUsed(0), PeakMem(0), Name(N),
    Started(false), TG(getDefaultTimerGroup()) {
  TG->addTimer();
}

Timer::Timer(const std::string &N, TimerGroup &tg)
  : Elapsed(0), UserTime(0), SystemTime(0), MemUsed(0), PeakMem(0), Name(N),
    Started(false), TG(&tg) {
  TG->addTimer();
}

Timer::Timer(const Timer &T) {
  TG = T.TG;
  if (TG) TG->addTimer();
  operator=(T);
}

// Copy ctor, initialize with no TG member.
Timer::Timer(bool, const Timer &T) {
  TG = T.TG;     // Avoid assertion in operator=
  operator=(T);  // Copy contents
  TG = 0;
}

Timer::~Timer() {
  if (TG) {
    if (Started) {
      Started = false;
      TG->addTimerToPrint(*this);
    }
    TG->removeTimer();
  }
}

static long getMemUsage() {
#ifdef HAVE_MALLINFO
  if (TrackSpace) {
    struct mallinfo MI = mallinfo();
    return MI.uordblks/*+MI.hblkhd*/;
  }
#endif
  return 0;
}

struct TimeRecord {
  double Elapsed, UserTime, SystemTime;
  long MemUsed;
};

static TimeRecord getTimeRecord(bool Start) {
#if defined(HAVE_WINDOWS_H)
  unsigned __int64 ProcCreate, ProcExit, KernelTime, UserTime, CurTime;

  GetProcessTimes(GetCurrentProcess(), (FILETIME*)&ProcCreate,
                  (FILETIME*)&ProcExit, (FILETIME*)&KernelTime,
                  (FILETIME*)&UserTime);
  GetSystemTimeAsFileTime((FILETIME*)&CurTime);

  // FILETIME's are # of 100 nanosecond ticks.
  double ScaleFactor = 1.0/(10*1000*1000);

  TimeRecord Result;
  Result.Elapsed    = (CurTime-ProcCreate)*ScaleFactor;  // Wall time
  Result.UserTime   = UserTime*ScaleFactor;
  Result.SystemTime = KernelTime*ScaleFactor;
  return Result;
#elif defined(HAVE_GETRUSAGE)
  struct rusage RU;
  struct timeval T;
  long MemUsed = 0;
  if (Start) {
    MemUsed = getMemUsage();
    if (getrusage(RUSAGE_SELF, &RU))
      perror("getrusage call failed: -time-passes info incorrect!");
  }
  gettimeofday(&T, 0);

  if (!Start) {
    if (getrusage(RUSAGE_SELF, &RU))
      perror("getrusage call failed: -time-passes info incorrect!");
    MemUsed = getMemUsage();
  }

  TimeRecord Result;
  Result.Elapsed    = double(T.tv_sec) + T.tv_usec/1000000.0;
  Result.UserTime   = RU.ru_utime.tv_sec + RU.ru_utime.tv_usec/1000000.0;
  Result.SystemTime = RU.ru_stime.tv_sec + RU.ru_stime.tv_usec/1000000.0;
  Result.MemUsed = MemUsed;
  return Result;
#else
  // Can't get resource usage.
  return TimeRecord();
#endif
}

static std::vector<Timer*> ActiveTimers;

void Timer::startTimer() {
  Started = true;
  TimeRecord TR = getTimeRecord(true);
  Elapsed    -= TR.Elapsed;
  UserTime   -= TR.UserTime;
  SystemTime -= TR.SystemTime;
  MemUsed    -= TR.MemUsed;
  PeakMemBase = TR.MemUsed;
  ActiveTimers.push_back(this);
}

void Timer::stopTimer() {
  TimeRecord TR = getTimeRecord(false);
  Elapsed    += TR.Elapsed;
  UserTime   += TR.UserTime;
  SystemTime += TR.SystemTime;
  MemUsed    += TR.MemUsed;

  if (ActiveTimers.back() == this) {
    ActiveTimers.pop_back();
  } else {
    std::vector<Timer*>::iterator I =
      std::find(ActiveTimers.begin(), ActiveTimers.end(), this);
    assert(I != ActiveTimers.end() && "stop but no startTimer?");
    ActiveTimers.erase(I);
  }
}

void Timer::sum(const Timer &T) {
  Elapsed    += T.Elapsed;
  UserTime   += T.UserTime;
  SystemTime += T.SystemTime;
  MemUsed    += T.MemUsed;
  PeakMem    += T.PeakMem;
}

/// addPeakMemoryMeasurement - This method should be called whenever memory
/// usage needs to be checked.  It adds a peak memory measurement to the
/// currently active timers, which will be printed when the timer group prints
///
void Timer::addPeakMemoryMeasurement() {
  long MemUsed = getMemUsage();

  for (std::vector<Timer*>::iterator I = ActiveTimers.begin(),
         E = ActiveTimers.end(); I != E; ++I)
    (*I)->PeakMem = std::max((*I)->PeakMem, MemUsed-(*I)->PeakMemBase);
}

//===----------------------------------------------------------------------===//
//   NamedRegionTimer Implementation
//===----------------------------------------------------------------------===//

static Timer &getNamedRegionTimer(const std::string &Name) {
  static std::map<std::string, Timer> NamedTimers;

  std::map<std::string, Timer>::iterator I = NamedTimers.lower_bound(Name);
  if (I != NamedTimers.end() && I->first == Name)
    return I->second;

  return NamedTimers.insert(I, std::make_pair(Name, Timer(Name)))->second;
}

NamedRegionTimer::NamedRegionTimer(const std::string &Name)
  : TimeRegion(getNamedRegionTimer(Name)) {}

//===----------------------------------------------------------------------===//
//   TimerGroup Implementation
//===----------------------------------------------------------------------===//

// printAlignedFP - Simulate the printf "%A.Bf" format, where A is the
// TotalWidth size, and B is the AfterDec size.
//
static void printAlignedFP(double Val, unsigned AfterDec, unsigned TotalWidth,
                           std::ostream &OS) {
  assert(TotalWidth >= AfterDec+1 && "Bad FP Format!");
  OS.width(TotalWidth-AfterDec-1);
  char OldFill = OS.fill();
  OS.fill(' ');
  OS << (int)Val;  // Integer part;
  OS << ".";
  OS.width(AfterDec);
  OS.fill('0');
  unsigned ResultFieldSize = 1;
  while (AfterDec--) ResultFieldSize *= 10;
  OS << (int)(Val*ResultFieldSize) % ResultFieldSize;
  OS.fill(OldFill);
}

static void printVal(double Val, double Total, std::ostream &OS) {
  if (Total < 1e-7)   // Avoid dividing by zero...
    OS << "        -----     ";
  else {
    OS << "  ";
    printAlignedFP(Val, 4, 7, OS);
    OS << " (";
    printAlignedFP(Val*100/Total, 1, 5, OS);
    OS << "%)";
  }
}

void Timer::print(const Timer &Total, std::ostream &OS) {
  if (Total.UserTime)
    printVal(UserTime, Total.UserTime, OS);
  if (Total.SystemTime)
    printVal(SystemTime, Total.SystemTime, OS);
  if (Total.getProcessTime())
    printVal(getProcessTime(), Total.getProcessTime(), OS);
  printVal(Elapsed, Total.Elapsed, OS);

  OS << "  ";

  if (Total.MemUsed) {
    OS.width(9);
    OS << MemUsed << "  ";
  }
  if (Total.PeakMem) {
    if (PeakMem) {
      OS.width(9);
      OS << PeakMem << "  ";
    } else
      OS << "           ";
  }
  OS << Name << "\n";

  Started = false;  // Once printed, don't print again
}

// GetLibSupportInfoOutputFile - Return a file stream to print our output on...
std::ostream *
llvm::GetLibSupportInfoOutputFile() {
  std::string &LibSupportInfoOutputFilename = getLibSupportInfoOutputFilename();
  if (LibSupportInfoOutputFilename.empty())
    return &std::cerr;
  if (LibSupportInfoOutputFilename == "-")
    return &std::cout;

  std::ostream *Result = new std::ofstream(LibSupportInfoOutputFilename.c_str(),
                                           std::ios::app);
  if (!Result->good()) {
    std::cerr << "Error opening info-output-file '"
              << LibSupportInfoOutputFilename << " for appending!\n";
    delete Result;
    return &std::cerr;
  }
  return Result;
}

void TimerGroup::removeTimer() {
  if (--NumTimers == 0 && !TimersToPrint.empty()) { // Print timing report...
    // Sort the timers in descending order by amount of time taken...
    std::sort(TimersToPrint.begin(), TimersToPrint.end(),
              std::greater<Timer>());

    // Figure out how many spaces to indent TimerGroup name...
    unsigned Padding = (80-Name.length())/2;
    if (Padding > 80) Padding = 0;         // Don't allow "negative" numbers

    std::ostream *OutStream = GetLibSupportInfoOutputFile();

    ++NumTimers;
    {  // Scope to contain Total timer... don't allow total timer to drop us to
       // zero timers...
      Timer Total("TOTAL");

      for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i)
        Total.sum(TimersToPrint[i]);

      // Print out timing header...
      *OutStream << "===" << std::string(73, '-') << "===\n"
                 << std::string(Padding, ' ') << Name << "\n"
                 << "===" << std::string(73, '-')
                 << "===\n  Total Execution Time: ";

      printAlignedFP(Total.getProcessTime(), 4, 5, *OutStream);
      *OutStream << " seconds (";
      printAlignedFP(Total.getWallTime(), 4, 5, *OutStream);
      *OutStream << " wall clock)\n\n";

      if (Total.UserTime)
        *OutStream << "   ---User Time---";
      if (Total.SystemTime)
        *OutStream << "   --System Time--";
      if (Total.getProcessTime())
        *OutStream << "   --User+System--";
      *OutStream << "   ---Wall Time---";
      if (Total.getMemUsed())
        *OutStream << "  ---Mem---";
      if (Total.getPeakMem())
        *OutStream << "  -PeakMem-";
      *OutStream << "  --- Name ---\n";

      // Loop through all of the timing data, printing it out...
      for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i)
        TimersToPrint[i].print(Total, *OutStream);

      Total.print(Total, *OutStream);
      *OutStream << std::endl;  // Flush output
    }
    --NumTimers;

    TimersToPrint.clear();

    if (OutStream != &std::cerr && OutStream != &std::cout)
      delete OutStream;   // Close the file...
  }

  // Delete default timer group!
  if (NumTimers == 0 && this == DefaultTimerGroup) {
    delete DefaultTimerGroup;
    DefaultTimerGroup = 0;
  }
}

<commit_msg>Undo last change as its unnecessary.<commit_after>//===-- Timer.cpp - Interval Timing Support -------------------------------===//
//
//                     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.
//
//===----------------------------------------------------------------------===//
//
// Interval Timing implementation.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/Timer.h"
#include "llvm/Support/CommandLine.h"
#include <algorithm>
#include <iostream>
#include <functional>
#include <fstream>
#include <map>
#include "llvm/Config/sys/resource.h"
#include "llvm/Config/sys/time.h"
#include "llvm/Config/unistd.h"
#include "llvm/Config/malloc.h"
#include "llvm/Config/windows.h"
using namespace llvm;

// GetLibSupportInfoOutputFile - Return a file stream to print our output on.
namespace llvm { extern std::ostream *GetLibSupportInfoOutputFile(); }

// getLibSupportInfoOutputFilename - This ugly hack is brought to you courtesy
// of constructor/destructor ordering being unspecified by C++.  Basically the
// problem is that a Statistic<> object gets destroyed, which ends up calling
// 'GetLibSupportInfoOutputFile()' (below), which calls this function.
// LibSupportInfoOutputFilename used to be a global variable, but sometimes it
// would get destroyed before the Statistic, causing havoc to ensue.  We "fix"
// this by creating the string the first time it is needed and never destroying
// it.
static std::string &getLibSupportInfoOutputFilename() {
  static std::string *LibSupportInfoOutputFilename = new std::string();
  return *LibSupportInfoOutputFilename;
}

namespace {
#ifdef HAVE_MALLINFO
  cl::opt<bool>
  TrackSpace("track-memory", cl::desc("Enable -time-passes memory "
                                      "tracking (this may be slow)"),
             cl::Hidden);
#endif

  cl::opt<std::string, true>
  InfoOutputFilename("info-output-file", cl::value_desc("filename"),
                     cl::desc("File to append -stats and -timer output to"),
                   cl::Hidden, cl::location(getLibSupportInfoOutputFilename()));
}

static TimerGroup *DefaultTimerGroup = 0;
static TimerGroup *getDefaultTimerGroup() {
  if (DefaultTimerGroup) return DefaultTimerGroup;
  return DefaultTimerGroup = new TimerGroup("Miscellaneous Ungrouped Timers");
}

Timer::Timer(const std::string &N)
  : Elapsed(0), UserTime(0), SystemTime(0), MemUsed(0), PeakMem(0), Name(N),
    Started(false), TG(getDefaultTimerGroup()) {
  TG->addTimer();
}

Timer::Timer(const std::string &N, TimerGroup &tg)
  : Elapsed(0), UserTime(0), SystemTime(0), MemUsed(0), PeakMem(0), Name(N),
    Started(false), TG(&tg) {
  TG->addTimer();
}

Timer::Timer(const Timer &T) {
  TG = T.TG;
  if (TG) TG->addTimer();
  operator=(T);
}

// Copy ctor, initialize with no TG member.
Timer::Timer(bool, const Timer &T) {
  TG = T.TG;     // Avoid assertion in operator=
  operator=(T);  // Copy contents
  TG = 0;
}

Timer::~Timer() {
  if (TG) {
    if (Started) {
      Started = false;
      TG->addTimerToPrint(*this);
    }
    TG->removeTimer();
  }
}

static long getMemUsage() {
#ifdef HAVE_MALLINFO
  if (TrackSpace) {
    struct mallinfo MI = mallinfo();
    return MI.uordblks/*+MI.hblkhd*/;
  }
#endif
  return 0;
}

struct TimeRecord {
  double Elapsed, UserTime, SystemTime;
  long MemUsed;
};

static TimeRecord getTimeRecord(bool Start) {
#if defined(HAVE_WINDOWS_H)
  unsigned __int64 ProcCreate, ProcExit, KernelTime, UserTime, CurTime;

  GetProcessTimes(GetCurrentProcess(), (FILETIME*)&ProcCreate,
                  (FILETIME*)&ProcExit, (FILETIME*)&KernelTime,
                  (FILETIME*)&UserTime);
  GetSystemTimeAsFileTime((FILETIME*)&CurTime);

  // FILETIME's are # of 100 nanosecond ticks.
  double ScaleFactor = 1.0/(10*1000*1000);

  TimeRecord Result;
  Result.Elapsed    = (CurTime-ProcCreate)*ScaleFactor;  // Wall time
  Result.UserTime   = UserTime*ScaleFactor;
  Result.SystemTime = KernelTime*ScaleFactor;
  return Result;
#elif defined(HAVE_GETRUSAGE)
  struct rusage RU;
  struct timeval T;
  long MemUsed = 0;
  if (Start) {
    MemUsed = getMemUsage();
    if (getrusage(RUSAGE_SELF, &RU))
      perror("getrusage call failed: -time-passes info incorrect!");
  }
  gettimeofday(&T, 0);

  if (!Start) {
    if (getrusage(RUSAGE_SELF, &RU))
      perror("getrusage call failed: -time-passes info incorrect!");
    MemUsed = getMemUsage();
  }

  TimeRecord Result;
  Result.Elapsed    =           T.tv_sec +           T.tv_usec/1000000.0;
  Result.UserTime   = RU.ru_utime.tv_sec + RU.ru_utime.tv_usec/1000000.0;
  Result.SystemTime = RU.ru_stime.tv_sec + RU.ru_stime.tv_usec/1000000.0;
  Result.MemUsed = MemUsed;
  return Result;
#else
  // Can't get resource usage.
  return TimeRecord();
#endif
}

static std::vector<Timer*> ActiveTimers;

void Timer::startTimer() {
  Started = true;
  TimeRecord TR = getTimeRecord(true);
  Elapsed    -= TR.Elapsed;
  UserTime   -= TR.UserTime;
  SystemTime -= TR.SystemTime;
  MemUsed    -= TR.MemUsed;
  PeakMemBase = TR.MemUsed;
  ActiveTimers.push_back(this);
}

void Timer::stopTimer() {
  TimeRecord TR = getTimeRecord(false);
  Elapsed    += TR.Elapsed;
  UserTime   += TR.UserTime;
  SystemTime += TR.SystemTime;
  MemUsed    += TR.MemUsed;

  if (ActiveTimers.back() == this) {
    ActiveTimers.pop_back();
  } else {
    std::vector<Timer*>::iterator I =
      std::find(ActiveTimers.begin(), ActiveTimers.end(), this);
    assert(I != ActiveTimers.end() && "stop but no startTimer?");
    ActiveTimers.erase(I);
  }
}

void Timer::sum(const Timer &T) {
  Elapsed    += T.Elapsed;
  UserTime   += T.UserTime;
  SystemTime += T.SystemTime;
  MemUsed    += T.MemUsed;
  PeakMem    += T.PeakMem;
}

/// addPeakMemoryMeasurement - This method should be called whenever memory
/// usage needs to be checked.  It adds a peak memory measurement to the
/// currently active timers, which will be printed when the timer group prints
///
void Timer::addPeakMemoryMeasurement() {
  long MemUsed = getMemUsage();

  for (std::vector<Timer*>::iterator I = ActiveTimers.begin(),
         E = ActiveTimers.end(); I != E; ++I)
    (*I)->PeakMem = std::max((*I)->PeakMem, MemUsed-(*I)->PeakMemBase);
}

//===----------------------------------------------------------------------===//
//   NamedRegionTimer Implementation
//===----------------------------------------------------------------------===//

static Timer &getNamedRegionTimer(const std::string &Name) {
  static std::map<std::string, Timer> NamedTimers;

  std::map<std::string, Timer>::iterator I = NamedTimers.lower_bound(Name);
  if (I != NamedTimers.end() && I->first == Name)
    return I->second;

  return NamedTimers.insert(I, std::make_pair(Name, Timer(Name)))->second;
}

NamedRegionTimer::NamedRegionTimer(const std::string &Name)
  : TimeRegion(getNamedRegionTimer(Name)) {}

//===----------------------------------------------------------------------===//
//   TimerGroup Implementation
//===----------------------------------------------------------------------===//

// printAlignedFP - Simulate the printf "%A.Bf" format, where A is the
// TotalWidth size, and B is the AfterDec size.
//
static void printAlignedFP(double Val, unsigned AfterDec, unsigned TotalWidth,
                           std::ostream &OS) {
  assert(TotalWidth >= AfterDec+1 && "Bad FP Format!");
  OS.width(TotalWidth-AfterDec-1);
  char OldFill = OS.fill();
  OS.fill(' ');
  OS << (int)Val;  // Integer part;
  OS << ".";
  OS.width(AfterDec);
  OS.fill('0');
  unsigned ResultFieldSize = 1;
  while (AfterDec--) ResultFieldSize *= 10;
  OS << (int)(Val*ResultFieldSize) % ResultFieldSize;
  OS.fill(OldFill);
}

static void printVal(double Val, double Total, std::ostream &OS) {
  if (Total < 1e-7)   // Avoid dividing by zero...
    OS << "        -----     ";
  else {
    OS << "  ";
    printAlignedFP(Val, 4, 7, OS);
    OS << " (";
    printAlignedFP(Val*100/Total, 1, 5, OS);
    OS << "%)";
  }
}

void Timer::print(const Timer &Total, std::ostream &OS) {
  if (Total.UserTime)
    printVal(UserTime, Total.UserTime, OS);
  if (Total.SystemTime)
    printVal(SystemTime, Total.SystemTime, OS);
  if (Total.getProcessTime())
    printVal(getProcessTime(), Total.getProcessTime(), OS);
  printVal(Elapsed, Total.Elapsed, OS);

  OS << "  ";

  if (Total.MemUsed) {
    OS.width(9);
    OS << MemUsed << "  ";
  }
  if (Total.PeakMem) {
    if (PeakMem) {
      OS.width(9);
      OS << PeakMem << "  ";
    } else
      OS << "           ";
  }
  OS << Name << "\n";

  Started = false;  // Once printed, don't print again
}

// GetLibSupportInfoOutputFile - Return a file stream to print our output on...
std::ostream *
llvm::GetLibSupportInfoOutputFile() {
  std::string &LibSupportInfoOutputFilename = getLibSupportInfoOutputFilename();
  if (LibSupportInfoOutputFilename.empty())
    return &std::cerr;
  if (LibSupportInfoOutputFilename == "-")
    return &std::cout;

  std::ostream *Result = new std::ofstream(LibSupportInfoOutputFilename.c_str(),
                                           std::ios::app);
  if (!Result->good()) {
    std::cerr << "Error opening info-output-file '"
              << LibSupportInfoOutputFilename << " for appending!\n";
    delete Result;
    return &std::cerr;
  }
  return Result;
}

void TimerGroup::removeTimer() {
  if (--NumTimers == 0 && !TimersToPrint.empty()) { // Print timing report...
    // Sort the timers in descending order by amount of time taken...
    std::sort(TimersToPrint.begin(), TimersToPrint.end(),
              std::greater<Timer>());

    // Figure out how many spaces to indent TimerGroup name...
    unsigned Padding = (80-Name.length())/2;
    if (Padding > 80) Padding = 0;         // Don't allow "negative" numbers

    std::ostream *OutStream = GetLibSupportInfoOutputFile();

    ++NumTimers;
    {  // Scope to contain Total timer... don't allow total timer to drop us to
       // zero timers...
      Timer Total("TOTAL");

      for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i)
        Total.sum(TimersToPrint[i]);

      // Print out timing header...
      *OutStream << "===" << std::string(73, '-') << "===\n"
                 << std::string(Padding, ' ') << Name << "\n"
                 << "===" << std::string(73, '-')
                 << "===\n  Total Execution Time: ";

      printAlignedFP(Total.getProcessTime(), 4, 5, *OutStream);
      *OutStream << " seconds (";
      printAlignedFP(Total.getWallTime(), 4, 5, *OutStream);
      *OutStream << " wall clock)\n\n";

      if (Total.UserTime)
        *OutStream << "   ---User Time---";
      if (Total.SystemTime)
        *OutStream << "   --System Time--";
      if (Total.getProcessTime())
        *OutStream << "   --User+System--";
      *OutStream << "   ---Wall Time---";
      if (Total.getMemUsed())
        *OutStream << "  ---Mem---";
      if (Total.getPeakMem())
        *OutStream << "  -PeakMem-";
      *OutStream << "  --- Name ---\n";

      // Loop through all of the timing data, printing it out...
      for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i)
        TimersToPrint[i].print(Total, *OutStream);

      Total.print(Total, *OutStream);
      *OutStream << std::endl;  // Flush output
    }
    --NumTimers;

    TimersToPrint.clear();

    if (OutStream != &std::cerr && OutStream != &std::cout)
      delete OutStream;   // Close the file...
  }

  // Delete default timer group!
  if (NumTimers == 0 && this == DefaultTimerGroup) {
    delete DefaultTimerGroup;
    DefaultTimerGroup = 0;
  }
}

<|endoftext|>