<commit_before>#include "PathUtils.h"

using namespace Framework;

#ifdef _WIN32

#if WINAPI_FAMILY_PARTITION(WINAPI_FAMILY_APP)

boost::filesystem::path PathUtils::GetPersonalDataPath()
{
	auto localFolder = Windows::Storage::ApplicationData::Current->LocalFolder;
	return boost::filesystem::path(localFolder->Path->Data());
}

#else	// !WINAPI_PARTITION_APP

#include <shlobj.h>

boost::filesystem::path PathUtils::GetPathFromCsidl(int csidl)
{
	wchar_t userPathString[MAX_PATH];
	if(FAILED(SHGetFolderPathW(NULL, csidl, NULL, 0, userPathString)))
	{
		throw std::runtime_error("Couldn't get path from csidl.");
	}
	return boost::filesystem::wpath(userPathString, boost::filesystem::native);
}

boost::filesystem::path PathUtils::GetRoamingDataPath()
{
	return GetPathFromCsidl(CSIDL_APPDATA);
}

boost::filesystem::path PathUtils::GetPersonalDataPath()
{
	return GetPathFromCsidl(CSIDL_PERSONAL);
}

boost::filesystem::path PathUtils::GetAppResourcesPath()
{
	return boost::filesystem::path(".");
}

#endif	// !WINAPI_PARTITION_APP

#endif	// _WIN32

#if defined(_POSIX_VERSION)

#if defined(__APPLE__)

#include <CoreFoundation/CoreFoundation.h>
#include <Foundation/Foundation.h>

boost::filesystem::path PathUtils::GetSettingsPath()
{
	NSArray* paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
	std::string directory = [[paths objectAtIndex: 0] UTF8String];
	return boost::filesystem::path(directory);
}

boost::filesystem::path PathUtils::GetRoamingDataPath()
{
	NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
	std::string directory = [[paths objectAtIndex: 0] UTF8String];
	return boost::filesystem::path(directory);
}

boost::filesystem::path PathUtils::GetAppResourcesPath()
{
	NSBundle* bundle = [NSBundle mainBundle];
	NSString* bundlePath = [bundle resourcePath];
	return boost::filesystem::path([bundlePath UTF8String]);
}

boost::filesystem::path PathUtils::GetPersonalDataPath()
{
	return GetRoamingDataPath();
}

#elif defined(__ANDROID__)

static boost::filesystem::path s_filesDirPath;

boost::filesystem::path PathUtils::GetAppResourcesPath()
{
	//This won't work for Android
	return boost::filesystem::path();
}

boost::filesystem::path PathUtils::GetRoamingDataPath()
{
	return s_filesDirPath;
}

boost::filesystem::path PathUtils::GetPersonalDataPath()
{
	return s_filesDirPath;
}

void PathUtils::SetFilesDirPath(const char* filesDirPath)
{
	s_filesDirPath = filesDirPath;
}

#else	// !DEFINED(__ANDROID__) || !DEFINED(__APPLE__)

#include <pwd.h>

boost::filesystem::path PathUtils::GetPersonalDataPath()
{
	passwd* userInfo = getpwuid(getuid());
	return boost::filesystem::path(userInfo->pw_dir);
}

#endif	// !DEFINED(__APPLE__)

#endif	// !DEFINED(_POSIX_VERSION)

void PathUtils::EnsurePathExists(const boost::filesystem::path& path)
{
	typedef boost::filesystem::path PathType;
	PathType buildPath;
	for(PathType::iterator pathIterator(path.begin());
		pathIterator != path.end(); pathIterator++)
	{
		buildPath /= (*pathIterator);
		boost::system::error_code existsErrorCode;
		bool exists = boost::filesystem::exists(buildPath, existsErrorCode);
		if(existsErrorCode)
		{
#ifdef WIN32
			if(existsErrorCode.value() == ERROR_ACCESS_DENIED)
			{
				//No problem, it exists, but we just don't have access
				continue;
			}
			else if(existsErrorCode.value() == ERROR_FILE_NOT_FOUND)
			{
				exists = false;
			}
#else
			if(existsErrorCode.value() == ENOENT)
			{
				exists = false;
			}
#endif
			else
			{
				throw std::runtime_error("Couldn't ensure that path exists.");
			}
		}
		if(!exists)
		{
			boost::filesystem::create_directory(buildPath);
		}
	}
}
<commit_msg>Force CSIDL path to be created when getting a special path.<commit_after>#include "PathUtils.h"

using namespace Framework;

#ifdef _WIN32

#if WINAPI_FAMILY_PARTITION(WINAPI_FAMILY_APP)

boost::filesystem::path PathUtils::GetPersonalDataPath()
{
	auto localFolder = Windows::Storage::ApplicationData::Current->LocalFolder;
	return boost::filesystem::path(localFolder->Path->Data());
}

#else	// !WINAPI_PARTITION_APP

#include <shlobj.h>

boost::filesystem::path PathUtils::GetPathFromCsidl(int csidl)
{
	wchar_t userPathString[MAX_PATH];
	if(FAILED(SHGetFolderPathW(NULL, csidl | CSIDL_FLAG_CREATE, NULL, 0, userPathString)))
	{
		throw std::runtime_error("Couldn't get path from csidl.");
	}
	return boost::filesystem::wpath(userPathString, boost::filesystem::native);
}

boost::filesystem::path PathUtils::GetRoamingDataPath()
{
	return GetPathFromCsidl(CSIDL_APPDATA);
}

boost::filesystem::path PathUtils::GetPersonalDataPath()
{
	return GetPathFromCsidl(CSIDL_PERSONAL);
}

boost::filesystem::path PathUtils::GetAppResourcesPath()
{
	return boost::filesystem::path(".");
}

#endif	// !WINAPI_PARTITION_APP

#endif	// _WIN32

#if defined(_POSIX_VERSION)

#if defined(__APPLE__)

#include <CoreFoundation/CoreFoundation.h>
#include <Foundation/Foundation.h>

boost::filesystem::path PathUtils::GetSettingsPath()
{
	NSArray* paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
	std::string directory = [[paths objectAtIndex: 0] UTF8String];
	return boost::filesystem::path(directory);
}

boost::filesystem::path PathUtils::GetRoamingDataPath()
{
	NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
	std::string directory = [[paths objectAtIndex: 0] UTF8String];
	return boost::filesystem::path(directory);
}

boost::filesystem::path PathUtils::GetAppResourcesPath()
{
	NSBundle* bundle = [NSBundle mainBundle];
	NSString* bundlePath = [bundle resourcePath];
	return boost::filesystem::path([bundlePath UTF8String]);
}

boost::filesystem::path PathUtils::GetPersonalDataPath()
{
	return GetRoamingDataPath();
}

#elif defined(__ANDROID__)

static boost::filesystem::path s_filesDirPath;

boost::filesystem::path PathUtils::GetAppResourcesPath()
{
	//This won't work for Android
	return boost::filesystem::path();
}

boost::filesystem::path PathUtils::GetRoamingDataPath()
{
	return s_filesDirPath;
}

boost::filesystem::path PathUtils::GetPersonalDataPath()
{
	return s_filesDirPath;
}

void PathUtils::SetFilesDirPath(const char* filesDirPath)
{
	s_filesDirPath = filesDirPath;
}

#else	// !DEFINED(__ANDROID__) || !DEFINED(__APPLE__)

#include <pwd.h>

boost::filesystem::path PathUtils::GetPersonalDataPath()
{
	passwd* userInfo = getpwuid(getuid());
	return boost::filesystem::path(userInfo->pw_dir);
}

#endif	// !DEFINED(__APPLE__)

#endif	// !DEFINED(_POSIX_VERSION)

void PathUtils::EnsurePathExists(const boost::filesystem::path& path)
{
	typedef boost::filesystem::path PathType;
	PathType buildPath;
	for(PathType::iterator pathIterator(path.begin());
		pathIterator != path.end(); pathIterator++)
	{
		buildPath /= (*pathIterator);
		boost::system::error_code existsErrorCode;
		bool exists = boost::filesystem::exists(buildPath, existsErrorCode);
		if(existsErrorCode)
		{
#ifdef WIN32
			if(existsErrorCode.value() == ERROR_ACCESS_DENIED)
			{
				//No problem, it exists, but we just don't have access
				continue;
			}
			else if(existsErrorCode.value() == ERROR_FILE_NOT_FOUND)
			{
				exists = false;
			}
#else
			if(existsErrorCode.value() == ENOENT)
			{
				exists = false;
			}
#endif
			else
			{
				throw std::runtime_error("Couldn't ensure that path exists.");
			}
		}
		if(!exists)
		{
			boost::filesystem::create_directory(buildPath);
		}
	}
}
<|endoftext|>


<commit_before>//===--- TextDiagnosticPrinter.cpp - Diagnostic Printer -------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This diagnostic client prints out their diagnostic messages.
//
//===----------------------------------------------------------------------===//

#include "clang/Driver/TextDiagnosticPrinter.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Lexer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/SmallString.h"
using namespace clang;

void TextDiagnosticPrinter::
PrintIncludeStack(SourceLocation Loc, const SourceManager &SM) {
  if (Loc.isInvalid()) return;

  PresumedLoc PLoc = SM.getPresumedLoc(Loc);

  // Print out the other include frames first.
  PrintIncludeStack(PLoc.getIncludeLoc(), SM);

  OS << "In file included from " << PLoc.getFilename()
     << ':' << PLoc.getLine() << ":\n";
}

/// HighlightRange - Given a SourceRange and a line number, highlight (with ~'s)
/// any characters in LineNo that intersect the SourceRange.
void TextDiagnosticPrinter::HighlightRange(const SourceRange &R,
                                           const SourceManager &SM,
                                           unsigned LineNo, FileID FID,
                                           std::string &CaretLine,
                                           const std::string &SourceLine) {
  assert(CaretLine.size() == SourceLine.size() &&
         "Expect a correspondence between source and caret line!");
  if (!R.isValid()) return;

  SourceLocation Begin = SM.getInstantiationLoc(R.getBegin());
  SourceLocation End = SM.getInstantiationLoc(R.getEnd());

  unsigned StartLineNo = SM.getInstantiationLineNumber(Begin);
  if (StartLineNo > LineNo || SM.getFileID(Begin) != FID)
    return;  // No intersection.

  unsigned EndLineNo = SM.getInstantiationLineNumber(End);
  if (EndLineNo < LineNo || SM.getFileID(End) != FID)
    return;  // No intersection.

  // Compute the column number of the start.
  unsigned StartColNo = 0;
  if (StartLineNo == LineNo) {
    StartColNo = SM.getInstantiationColumnNumber(Begin);
    if (StartColNo) --StartColNo;  // Zero base the col #.
  }

  // Pick the first non-whitespace column.
  while (StartColNo < SourceLine.size() &&
         (SourceLine[StartColNo] == ' ' || SourceLine[StartColNo] == '\t'))
    ++StartColNo;

  // Compute the column number of the end.
  unsigned EndColNo = CaretLine.size();
  if (EndLineNo == LineNo) {
    EndColNo = SM.getInstantiationColumnNumber(End);
    if (EndColNo) {
      --EndColNo;  // Zero base the col #.

      // Add in the length of the token, so that we cover multi-char tokens.
      EndColNo += Lexer::MeasureTokenLength(End, SM);
    } else {
      EndColNo = CaretLine.size();
    }
  }

  // Pick the last non-whitespace column.
  if (EndColNo <= SourceLine.size())
    while (EndColNo-1 &&
           (SourceLine[EndColNo-1] == ' ' || SourceLine[EndColNo-1] == '\t'))
      --EndColNo;
  else
    EndColNo = SourceLine.size();

  // Fill the range with ~'s.
  assert(StartColNo <= EndColNo && "Invalid range!");
  for (unsigned i = StartColNo; i < EndColNo; ++i)
    CaretLine[i] = '~';
}

void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
                                             const DiagnosticInfo &Info) {
  unsigned ColNo = 0;

  // If the location is specified, print out a file/line/col and include trace
  // if enabled.
  if (Info.getLocation().isValid()) {
    const SourceManager &SM = Info.getLocation().getManager();
    PresumedLoc PLoc = SM.getPresumedLoc(Info.getLocation());
    unsigned LineNo = PLoc.getLine();

    // First, if this diagnostic is not in the main file, print out the
    // "included from" lines.
    if (LastWarningLoc != PLoc.getIncludeLoc()) {
      LastWarningLoc = PLoc.getIncludeLoc();
      PrintIncludeStack(LastWarningLoc, SM);
    }

    // Compute the column number.
    ColNo = PLoc.getColumn();
    if (ShowLocation) {
      OS << PLoc.getFilename() << ':' << LineNo << ':';
      if (ColNo && ShowColumn)
        OS << ColNo << ':';
      OS << ' ';
    }
  }

  switch (Level) {
  case Diagnostic::Ignored: assert(0 && "Invalid diagnostic type");
  case Diagnostic::Note:    OS << "note: "; break;
  case Diagnostic::Warning: OS << "warning: "; break;
  case Diagnostic::Error:   OS << "error: "; break;
  case Diagnostic::Fatal:   OS << "fatal error: "; break;
  }

  llvm::SmallString<100> OutStr;
  Info.FormatDiagnostic(OutStr);
  OS.write(OutStr.begin(), OutStr.size());
  OS << '\n';

  // If caret diagnostics are enabled and we have location, we want to emit the
  // caret.  However, we only do this if the location moved from the last
  // diagnostic, or if the diagnostic has ranges.  We don't want to emit the
  // same caret multiple times if one loc has multiple diagnostics.
  if (CaretDiagnostics && Info.getLocation().isValid() &&
      ((LastLoc != Info.getLocation()) || Info.getNumRanges())) {
    // Cache the LastLoc, it allows us to omit duplicate source/caret spewage.
    LastLoc = Info.getLocation();

    // Inspect the actual instantiation point of the diagnostic, we don't care
    // about presumed locations anymore.
    FullSourceLoc ILoc = Info.getLocation().getInstantiationLoc();

    // Rewind from the current position to the start of the line.
    const char *TokInstantiationPtr = ILoc.getCharacterData();
    const char *LineStart = TokInstantiationPtr-ColNo+1; // Column # is 1-based.

    // Compute the line end.  Scan forward from the error position to the end of
    // the line.
    const char *BufEnd = ILoc.getBufferData().second;
    const char *LineEnd = TokInstantiationPtr;
    while (LineEnd != BufEnd &&
           *LineEnd != '\n' && *LineEnd != '\r')
      ++LineEnd;

    // Copy the line of code into an std::string for ease of manipulation.
    std::string SourceLine(LineStart, LineEnd);

    // Create a line for the caret that is filled with spaces that is the same
    // length as the line of source code.
    std::string CaretLine(LineEnd-LineStart, ' ');

    // Highlight all of the characters covered by Ranges with ~ characters.
    for (unsigned i = 0; i != Info.getNumRanges(); ++i)
      HighlightRange(Info.getRange(i), ILoc.getManager(),
                     ILoc.getInstantiationLineNumber(),
                     ILoc.getFileID(), CaretLine, SourceLine);

    // Next, insert the caret itself.
    if (ColNo-1 < CaretLine.size())
      CaretLine[ColNo-1] = '^';
    else
      CaretLine.push_back('^');

    // Scan the source line, looking for tabs.  If we find any, manually expand
    // them to 8 characters and update the CaretLine to match.
    for (unsigned i = 0; i != SourceLine.size(); ++i) {
      if (SourceLine[i] != '\t') continue;

      // Replace this tab with at least one space.
      SourceLine[i] = ' ';

      // Compute the number of spaces we need to insert.
      unsigned NumSpaces = ((i+8)&~7) - (i+1);
      assert(NumSpaces < 8 && "Invalid computation of space amt");

      // Insert spaces into the SourceLine.
      SourceLine.insert(i+1, NumSpaces, ' ');

      // Insert spaces or ~'s into CaretLine.
      CaretLine.insert(i+1, NumSpaces, CaretLine[i] == '~' ? '~' : ' ');
    }

    // Finally, remove any blank spaces from the end of CaretLine.
    while (CaretLine[CaretLine.size()-1] == ' ')
      CaretLine.erase(CaretLine.end()-1);

    // Emit what we have computed.
    OS << SourceLine << '\n';
    OS << CaretLine << '\n';
  }

  OS.flush();
}
<commit_msg>If a source range comes through a function-like macro expansion, highlight the arguments to the macro as well as the identifier.<commit_after>//===--- TextDiagnosticPrinter.cpp - Diagnostic Printer -------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This diagnostic client prints out their diagnostic messages.
//
//===----------------------------------------------------------------------===//

#include "clang/Driver/TextDiagnosticPrinter.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Lexer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/SmallString.h"
using namespace clang;

void TextDiagnosticPrinter::
PrintIncludeStack(SourceLocation Loc, const SourceManager &SM) {
  if (Loc.isInvalid()) return;

  PresumedLoc PLoc = SM.getPresumedLoc(Loc);

  // Print out the other include frames first.
  PrintIncludeStack(PLoc.getIncludeLoc(), SM);

  OS << "In file included from " << PLoc.getFilename()
     << ':' << PLoc.getLine() << ":\n";
}

/// HighlightRange - Given a SourceRange and a line number, highlight (with ~'s)
/// any characters in LineNo that intersect the SourceRange.
void TextDiagnosticPrinter::HighlightRange(const SourceRange &R,
                                           const SourceManager &SM,
                                           unsigned LineNo, FileID FID,
                                           std::string &CaretLine,
                                           const std::string &SourceLine) {
  assert(CaretLine.size() == SourceLine.size() &&
         "Expect a correspondence between source and caret line!");
  if (!R.isValid()) return;

  SourceLocation Begin = SM.getInstantiationLoc(R.getBegin());
  SourceLocation End = SM.getInstantiationLoc(R.getEnd());

  // If the End location and the start location are the same and are a macro
  // location, then the range was something that came from a macro expansion
  // or _Pragma.  If this is an object-like macro, the best we can do is to
  // highlight the range.  If this is a function-like macro, we'd also like to
  // highlight the arguments.
  if (Begin == End && R.getEnd().isMacroID())
    End = SM.getInstantiationRange(R.getEnd()).second;

  unsigned StartLineNo = SM.getInstantiationLineNumber(Begin);
  if (StartLineNo > LineNo || SM.getFileID(Begin) != FID)
    return;  // No intersection.

  unsigned EndLineNo = SM.getInstantiationLineNumber(End);
  if (EndLineNo < LineNo || SM.getFileID(End) != FID)
    return;  // No intersection.

  // Compute the column number of the start.
  unsigned StartColNo = 0;
  if (StartLineNo == LineNo) {
    StartColNo = SM.getInstantiationColumnNumber(Begin);
    if (StartColNo) --StartColNo;  // Zero base the col #.
  }

  // Pick the first non-whitespace column.
  while (StartColNo < SourceLine.size() &&
         (SourceLine[StartColNo] == ' ' || SourceLine[StartColNo] == '\t'))
    ++StartColNo;

  // Compute the column number of the end.
  unsigned EndColNo = CaretLine.size();
  if (EndLineNo == LineNo) {
    EndColNo = SM.getInstantiationColumnNumber(End);
    if (EndColNo) {
      --EndColNo;  // Zero base the col #.

      // Add in the length of the token, so that we cover multi-char tokens.
      EndColNo += Lexer::MeasureTokenLength(End, SM);
    } else {
      EndColNo = CaretLine.size();
    }
  }

  // Pick the last non-whitespace column.
  if (EndColNo <= SourceLine.size())
    while (EndColNo-1 &&
           (SourceLine[EndColNo-1] == ' ' || SourceLine[EndColNo-1] == '\t'))
      --EndColNo;
  else
    EndColNo = SourceLine.size();

  // Fill the range with ~'s.
  assert(StartColNo <= EndColNo && "Invalid range!");
  for (unsigned i = StartColNo; i < EndColNo; ++i)
    CaretLine[i] = '~';
}

void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
                                             const DiagnosticInfo &Info) {
  unsigned ColNo = 0;

  // If the location is specified, print out a file/line/col and include trace
  // if enabled.
  if (Info.getLocation().isValid()) {
    const SourceManager &SM = Info.getLocation().getManager();
    PresumedLoc PLoc = SM.getPresumedLoc(Info.getLocation());
    unsigned LineNo = PLoc.getLine();

    // First, if this diagnostic is not in the main file, print out the
    // "included from" lines.
    if (LastWarningLoc != PLoc.getIncludeLoc()) {
      LastWarningLoc = PLoc.getIncludeLoc();
      PrintIncludeStack(LastWarningLoc, SM);
    }

    // Compute the column number.
    ColNo = PLoc.getColumn();
    if (ShowLocation) {
      OS << PLoc.getFilename() << ':' << LineNo << ':';
      if (ColNo && ShowColumn)
        OS << ColNo << ':';
      OS << ' ';
    }
  }

  switch (Level) {
  case Diagnostic::Ignored: assert(0 && "Invalid diagnostic type");
  case Diagnostic::Note:    OS << "note: "; break;
  case Diagnostic::Warning: OS << "warning: "; break;
  case Diagnostic::Error:   OS << "error: "; break;
  case Diagnostic::Fatal:   OS << "fatal error: "; break;
  }

  llvm::SmallString<100> OutStr;
  Info.FormatDiagnostic(OutStr);
  OS.write(OutStr.begin(), OutStr.size());
  OS << '\n';

  // If caret diagnostics are enabled and we have location, we want to emit the
  // caret.  However, we only do this if the location moved from the last
  // diagnostic, or if the diagnostic has ranges.  We don't want to emit the
  // same caret multiple times if one loc has multiple diagnostics.
  if (CaretDiagnostics && Info.getLocation().isValid() &&
      ((LastLoc != Info.getLocation()) || Info.getNumRanges())) {
    // Cache the LastLoc, it allows us to omit duplicate source/caret spewage.
    LastLoc = Info.getLocation();

    // Inspect the actual instantiation point of the diagnostic, we don't care
    // about presumed locations anymore.
    FullSourceLoc ILoc = Info.getLocation().getInstantiationLoc();

    // Rewind from the current position to the start of the line.
    const char *TokInstantiationPtr = ILoc.getCharacterData();
    const char *LineStart = TokInstantiationPtr-ColNo+1; // Column # is 1-based.

    // Compute the line end.  Scan forward from the error position to the end of
    // the line.
    const char *BufEnd = ILoc.getBufferData().second;
    const char *LineEnd = TokInstantiationPtr;
    while (LineEnd != BufEnd &&
           *LineEnd != '\n' && *LineEnd != '\r')
      ++LineEnd;

    // Copy the line of code into an std::string for ease of manipulation.
    std::string SourceLine(LineStart, LineEnd);

    // Create a line for the caret that is filled with spaces that is the same
    // length as the line of source code.
    std::string CaretLine(LineEnd-LineStart, ' ');

    // Highlight all of the characters covered by Ranges with ~ characters.
    for (unsigned i = 0; i != Info.getNumRanges(); ++i)
      HighlightRange(Info.getRange(i), ILoc.getManager(),
                     ILoc.getInstantiationLineNumber(),
                     ILoc.getFileID(), CaretLine, SourceLine);

    // Next, insert the caret itself.
    if (ColNo-1 < CaretLine.size())
      CaretLine[ColNo-1] = '^';
    else
      CaretLine.push_back('^');

    // Scan the source line, looking for tabs.  If we find any, manually expand
    // them to 8 characters and update the CaretLine to match.
    for (unsigned i = 0; i != SourceLine.size(); ++i) {
      if (SourceLine[i] != '\t') continue;

      // Replace this tab with at least one space.
      SourceLine[i] = ' ';

      // Compute the number of spaces we need to insert.
      unsigned NumSpaces = ((i+8)&~7) - (i+1);
      assert(NumSpaces < 8 && "Invalid computation of space amt");

      // Insert spaces into the SourceLine.
      SourceLine.insert(i+1, NumSpaces, ' ');

      // Insert spaces or ~'s into CaretLine.
      CaretLine.insert(i+1, NumSpaces, CaretLine[i] == '~' ? '~' : ' ');
    }

    // Finally, remove any blank spaces from the end of CaretLine.
    while (CaretLine[CaretLine.size()-1] == ' ')
      CaretLine.erase(CaretLine.end()-1);

    // Emit what we have computed.
    OS << SourceLine << '\n';
    OS << CaretLine << '\n';
  }

  OS.flush();
}
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <cstdlib>
#include <fstream>
#include <vector>
#include <cmath>
#include <sstream>
#include <stdio.h>
#include <unistd.h>
#include <algorithm>
using namespace std;

#include "Processes.h"
#include "Base.h"
#include "Command.h"
#include "Andand.h"
#include "Oror.h"
#include "Test.h"

//Simple constructor
Processes::Processes()
{
    currCmds.resize(0);
}
//Simple destructor
Processes::~Processes()
{
    for(unsigned i = 0; i < currCmds.size(); ++i)
    {
        delete currCmds.at(i);
    }
}
//This executes all objects within the object's currCmds vector
int Processes::execute()
{
    int temp = 0;
    for(unsigned i = 0; i < currCmds.size(); ++i)
    {
        temp = currCmds.at(i)->execute();
    }
    return temp;
}
//Processes parses the code to split it into separate command lines
//should there be any semicolons present.
void Processes::parse(string input)
{
    vector<string> currCs;
    istringstream inSS(input);
    string currString;
    //Main loop for parsing input that contains semicolons
    if(count(input.begin(), input.end(), ';') >= 1)
    {
        while(input.find(";") != string::npos)
        {
            if(count(input.begin(), input.end(), ';') == 1
                && input.find(";") != input.size() - 1
                && (input.at(input.find(";") + 1)) == '"')
            {
                break;
            }
            if(count(input.begin(), input.end(), ';') == 1 && input.find(";") == input.size() - 1)
            {
                break;
            }
            bool hashtag = false;
            bool semicolon = false;
            bool first = false;
            currCs.resize(0);
            while(!semicolon)
            {
                inSS >> currString;
                input.erase(0, currString.size() + 1);
                //Tests for hashtag/semicolon presence
                if(currString.find("#") != string::npos)
                {
                    hashtag = true;
                    if(currString.find("#") != 0 && (!first))
                    {
                        currCs.push_back(currString);
                        first = true;
                    }
                }
                if(currString.find(";") != string::npos)
                {
                    semicolon = true;
                }
                string temp = "";
                for(unsigned g = 0; g < currString.size(); ++g)
                {
                    if(currString.at(g) == '"')
                    {
                        if(g > 0 && currString.at(g - 1) == '\\')
                        {
                            temp += currString.at(g);
                        }
                    }
                    else if(currString.at(g) != '\\')
                    {
                        temp += currString.at(g);
                    }
                }
                currString = temp;
                if(!hashtag)
                {
                    if(!semicolon)
                    {
                        currCs.push_back(currString);
                    }
                    else
                    {
                        currString.erase(currString.size() - 1, 1);
                        currCs.push_back(currString);
                    }
                }
            }
            //Here, we detect the presence of connectors.
            bool detected = false;
            for(unsigned j = 0; j < currCs.size(); ++j)
            {
                if(currCs.at(j) == "||" || currCs.at(j) == "&&")
                {
                    detected = true;
                    break;
                }
            }
            //If it detects one, it sends the vector to a loop
            //that runs until the end of the current command string.
            //It stops at the next connector, looks at the previous connector,
            //and creates objects and links them correspondingly.
            if(detected)
            {
                string prevConnector;
                string nextConnector;
                vector<string> firstCommand;
                unsigned i = 0;
                while(currCs.at(i) != "&&" && currCs.at(i) != "||")
                {
                    firstCommand.push_back(currCs.at(i));
                    ++i;
                }
                prevConnector = currCs.at(i);
                Base * temp3;
                if(firstCommand.at(0) == "test")
                {
                    temp3 = new Test(firstCommand);
                }
                else
                {
                    temp3 = new Command(firstCommand);
                }
                currCmds.push_back(temp3);
                ++i;
                vector<string> currCommand;
                for(;i < currCs.size(); ++i)
                {
                    currCommand.push_back(currCs.at(i));
                    if(currCs.at(i) == "&&" || currCs.at(i) == "||")
                    {
                        currCommand.pop_back();
                        if(currCommand.at(0) == "test")
                        {
                            Base *temp = new Test(currCommand);
                            nextConnector = currCs.at(i);
                            if(prevConnector == "&&")
                            {
                                Base *temp2 = new Andand(currCmds.at(
                                    currCmds.size() - 1), temp);
                                currCmds.pop_back();
                                currCmds.push_back(temp2);
                                currCommand.resize(0);
                            }
                            else
                            {
                                Base * temp2 = new Oror(currCmds.at(
                                    currCmds.size() - 1), temp);
                                currCmds.pop_back();
                                currCmds.push_back(temp2);
                                currCommand.resize(0);
                            }
                        }
                        else {
                            Base *temp = new Command(currCommand);
                            nextConnector = currCs.at(i);
                            if(prevConnector == "&&")
                            {
                                Base *temp2 = new Andand(currCmds.at(
                                    currCmds.size() - 1), temp);
                                currCmds.pop_back();
                                currCmds.push_back(temp2);
                                currCommand.resize(0);
                            }
                            else
                            {
                                Base * temp2 = new Oror(currCmds.at(
                                    currCmds.size() - 1), temp);
                                currCmds.pop_back();
                                currCmds.push_back(temp2);
                                currCommand.resize(0);
                            }
                        }
                    }
                }
            }
            //This runs if there no connectors left after semicolon detecting.
            else {
                vector<string> currCommand;
                for(unsigned k = 0; k < currCs.size(); ++k)
                {
                    currCommand.push_back(currCs.at(k));
                }
                Base *temp;
                if(currCommand.at(0) == "test")
                {
                    temp = new Test(currCommand);
                }
                else {
                    temp = new Command(currCommand);
                }
                currCmds.push_back(temp);
            }
        }
    }
    //Second loop that parses the remaining part of the input
    //Also, if the input never contained any semicolons,
    //the parse will go straight to this part of the code.
    currCs.resize(0);
    while(inSS >> currString)
    {
        if(currString.at(currString.size() - 1) == ';')
        {
            currString.erase(currString.size() - 1, 1);
        }
        string temp = "";
        for(unsigned g = 0; g < currString.size(); ++g)
        {
            if(currString.at(g) == '"')
            {
                if(g > 0 && currString.at(g - 1) == '\\')
                {
                    temp += currString.at(g);
                }
            }
            else if(currString.at(g) != '\\')
            {
                temp += currString.at(g);
            }
        }
        currString = temp;
        if(currString.find("#") != string::npos)
        {
            if(currString.find("#") != 0)
            {
                currCs.push_back(currString);
            }
            break;
        }
        currCs.push_back(currString);
    }
    //Again, detects whether the string has connectors.
    bool detected = false;
    for(unsigned j = 0; j < currCs.size(); ++j)
    {
        if(currCs.at(j) == "&&" || currCs.at(j) == "||")
        {
            detected = true;
            break;
        }
    }
    //If it detects them, it sends them to be parsed,
    //where connector objects are created after the first command is created
    //and subsequently linked until the end of parsing.
    if(detected)
    {
        string prevConnector;
        string nextConnector;
        vector<string> firstCommand;
        unsigned i = 0;
        while(currCs.at(i) != "&&" && currCs.at(i) != "||")
        {
            firstCommand.push_back(currCs.at(i));
            ++i;
        }
        prevConnector = currCs.at(i);
        Base *temp3;
        if(firstCommand.at(0) == "test")
        {
            temp3 = new Test(firstCommand);
        }
        else {
            temp3 = new Command(firstCommand);
        }
        currCmds.push_back(temp3);
        ++i;
        vector<string> currCommand;
        for(; i < currCs.size(); ++i)
        {
            currCommand.push_back(currCs.at(i));
            if(currCs.at(i) == "&&" || currCs.at(i) == "||")
            {
                currCommand.pop_back();
                Base *temp;
                if(currCommand.at(0) == "test")
                {
                    temp = new Test(currCommand);
                }
                else {
                    temp = new Command(currCommand);
                }
                nextConnector = currCs.at(i);
                if(prevConnector == "&&")
                {
                    Base *temp2 = new Andand(currCmds.at(currCmds.size() - 1),
                        temp);
                    currCmds.pop_back();
                    currCmds.push_back(temp2);
                    prevConnector = nextConnector;
                    currCommand.resize(0);
                }
                else
                {
                    Base * temp2 = new Oror(currCmds.at(currCmds.size() - 1),
                        temp);
                    currCmds.pop_back();
                    currCmds.push_back(temp2);
                    prevConnector = nextConnector;
                    currCommand.resize(0);
                }
            }
        }
        Base * temp;
        if(currCommand.at(0) == "test")
        {
            temp = new Test(currCommand);
        }
        else {
            temp = new Command(currCommand);
        }
        if(prevConnector == "&&")
            {
                Base *temp2 = new Andand(currCmds.at(currCmds.size() - 1),
                    temp);
                currCmds.pop_back();
                currCmds.push_back(temp2);
                currCommand.resize(0);
            }
        else
        {
            Base * temp2 = new Oror(currCmds.at(currCmds.size() - 1), temp);
            currCmds.pop_back();
            currCmds.push_back(temp2);
        }
    }
    else {
        vector<string> currCommand;
        for(unsigned k = 0; k < currCs.size(); ++k)
        {
            currCommand.push_back(currCs.at(k));
        }
        Base *temp;
        if(currCommand.at(0) == "test")
        {
            temp = new Test(currCommand);
        }
        else {
            temp = new Command(currCommand);
        }
        currCmds.push_back(temp);
    }
}
//This is used to clean up the Processes vector in order to gather further
//input from the user.
void Processes::reset()
{
    for(unsigned i = 0; i < currCmds.size(); ++i)
    {
        delete currCmds.at(i);
    }
    this->currCmds.resize(0);

}<commit_msg>building precedence<commit_after>#include <iostream>
#include <string>
#include <cstdlib>
#include <fstream>
#include <vector>
#include <cmath>
#include <sstream>
#include <stdio.h>
#include <unistd.h>
#include <algorithm>
using namespace std;

#include "Processes.h"
#include "Base.h"
#include "Command.h"
#include "Andand.h"
#include "Oror.h"
#include "Test.h"

//Simple constructor
Processes::Processes()
{
    currCmds.resize(0);
}
//Simple destructor
Processes::~Processes()
{
    for(unsigned i = 0; i < currCmds.size(); ++i)
    {
        delete currCmds.at(i);
    }
}
//This executes all objects within the object's currCmds vector
int Processes::execute()
{
    int temp = 0;
    for(unsigned i = 0; i < currCmds.size(); ++i)
    {
        temp = currCmds.at(i)->execute();
    }
    return temp;
}
//Processes parses the code to split it into separate command lines
//should there be any semicolons present.
void Processes::parse(string input)
{
    vector<string> currCs;
    istringstream inSS(input);
    string currString;
    //Main loop for parsing input that contains semicolons
    if(count(input.begin(), input.end(), ';') >= 1)
    {
        while(input.find(";") != string::npos)
        {
            if(count(input.begin(), input.end(), ';') == 1
                && input.find(";") != input.size() - 1
                && (input.at(input.find(";") + 1)) == '"')
            {
                break;
            }
            if(count(input.begin(), input.end(), ';') == 1 && input.find(";") == input.size() - 1)
            {
                break;
            }
            bool hashtag = false;
            bool semicolon = false;
            bool first = false;
            currCs.resize(0);
            while(!semicolon)
            {
                inSS >> currString;
                input.erase(0, currString.size() + 1);
                //Tests for hashtag/semicolon presence
                if(currString.find("#") != string::npos)
                {
                    hashtag = true;
                    if(currString.find("#") != 0 && (!first))
                    {
                        currCs.push_back(currString);
                        first = true;
                    }
                }
                if(currString.find(";") != string::npos)
                {
                    semicolon = true;
                }
                string temp = "";
                for(unsigned g = 0; g < currString.size(); ++g)
                {
                    if(currString.at(g) == '"')
                    {
                        if(g > 0 && currString.at(g - 1) == '\\')
                        {
                            temp += currString.at(g);
                        }
                    }
                    else if(currString.at(g) != '\\')
                    {
                        temp += currString.at(g);
                    }
                }
                currString = temp;
                if(!hashtag)
                {
                    if(!semicolon)
                    {
                        currCs.push_back(currString);
                    }
                    else
                    {
                        currString.erase(currString.size() - 1, 1);
                        currCs.push_back(currString);
                    }
                }
            }
            //Here, we detect the presence of connectors.
            bool detected = false;
            bool parenthesis = true;
            for(unsigned j = 0; j < currCs.size(); ++j)
            {
                if(currCs.at(j) == "||" || currCs.at(j) == "&&")
                {
                    detected = true;
                    break;
                }
                if(currCs.at(j).find("(") != string::npos)
                {
                    parenthesis = true;
                }
            }
            //If it detects one, it sends the vector to a loop
            //that runs until the end of the current command string.
            //It stops at the next connector, looks at the previous connector,
            //and creates objects and links them correspondingly.
            if(detected && !parenthsis)
            {
                string prevConnector;
                string nextConnector;
                vector<string> firstCommand;
                unsigned i = 0;
                while(currCs.at(i) != "&&" && currCs.at(i) != "||")
                {
                    firstCommand.push_back(currCs.at(i));
                    ++i;
                }
                prevConnector = currCs.at(i);
                Base * temp3;
                if(firstCommand.at(0) == "test")
                {
                    temp3 = new Test(firstCommand);
                }
                else
                {
                    temp3 = new Command(firstCommand);
                }
                currCmds.push_back(temp3);
                ++i;
                vector<string> currCommand;
                for(;i < currCs.size(); ++i)
                {
                    currCommand.push_back(currCs.at(i));
                    if(currCs.at(i) == "&&" || currCs.at(i) == "||")
                    {
                        currCommand.pop_back();
                        if(currCommand.at(0) == "test")
                        {
                            Base *temp = new Test(currCommand);
                            nextConnector = currCs.at(i);
                            if(prevConnector == "&&")
                            {
                                Base *temp2 = new Andand(currCmds.at(
                                    currCmds.size() - 1), temp);
                                currCmds.pop_back();
                                currCmds.push_back(temp2);
                                currCommand.resize(0);
                            }
                            else
                            {
                                Base * temp2 = new Oror(currCmds.at(
                                    currCmds.size() - 1), temp);
                                currCmds.pop_back();
                                currCmds.push_back(temp2);
                                currCommand.resize(0);
                            }
                        }
                        else {
                            Base *temp = new Command(currCommand);
                            nextConnector = currCs.at(i);
                            if(prevConnector == "&&")
                            {
                                Base *temp2 = new Andand(currCmds.at(
                                    currCmds.size() - 1), temp);
                                currCmds.pop_back();
                                currCmds.push_back(temp2);
                                currCommand.resize(0);
                            }
                            else
                            {
                                Base * temp2 = new Oror(currCmds.at(
                                    currCmds.size() - 1), temp);
                                currCmds.pop_back();
                                currCmds.push_back(temp2);
                                currCommand.resize(0);
                            }
                        }
                    }
                }
            }
            else if(detected && parenthesis)
            {

            }
            //This runs if there no connectors left after semicolon detecting.
            else {
                vector<string> currCommand;
                for(unsigned k = 0; k < currCs.size(); ++k)
                {
                    currCommand.push_back(currCs.at(k));
                }
                Base *temp;
                if(currCommand.at(0) == "test")
                {
                    temp = new Test(currCommand);
                }
                else {
                    temp = new Command(currCommand);
                }
                currCmds.push_back(temp);
            }
        }
    }
    //Second loop that parses the remaining part of the input
    //Also, if the input never contained any semicolons,
    //the parse will go straight to this part of the code.
    currCs.resize(0);
    while(inSS >> currString)
    {
        if(currString.at(currString.size() - 1) == ';')
        {
            currString.erase(currString.size() - 1, 1);
        }
        string temp = "";
        for(unsigned g = 0; g < currString.size(); ++g)
        {
            if(currString.at(g) == '"')
            {
                if(g > 0 && currString.at(g - 1) == '\\')
                {
                    temp += currString.at(g);
                }
            }
            else if(currString.at(g) != '\\')
            {
                temp += currString.at(g);
            }
        }
        currString = temp;
        if(currString.find("#") != string::npos)
        {
            if(currString.find("#") != 0)
            {
                currCs.push_back(currString);
            }
            break;
        }
        currCs.push_back(currString);
    }
    //Again, detects whether the string has connectors.
    bool detected = false;
    bool parenthesis = false;
    for(unsigned j = 0; j < currCs.size(); ++j)
    {
        if(currCs.at(j) == "&&" || currCs.at(j) == "||")
        {
            detected = true;
            break;
        }
    }
    //If it detects them, it sends them to be parsed,
    //where connector objects are created after the first command is created
    //and subsequently linked until the end of parsing.
    if(detected && !parenthesis)
    {
        string prevConnector;
        string nextConnector;
        vector<string> firstCommand;
        unsigned i = 0;
        while(currCs.at(i) != "&&" && currCs.at(i) != "||")
        {
            firstCommand.push_back(currCs.at(i));
            ++i;
        }
        prevConnector = currCs.at(i);
        Base *temp3;
        if(firstCommand.at(0) == "test")
        {
            temp3 = new Test(firstCommand);
        }
        else {
            temp3 = new Command(firstCommand);
        }
        currCmds.push_back(temp3);
        ++i;
        vector<string> currCommand;
        for(; i < currCs.size(); ++i)
        {
            currCommand.push_back(currCs.at(i));
            if(currCs.at(i) == "&&" || currCs.at(i) == "||")
            {
                currCommand.pop_back();
                Base *temp;
                if(currCommand.at(0) == "test")
                {
                    temp = new Test(currCommand);
                }
                else {
                    temp = new Command(currCommand);
                }
                nextConnector = currCs.at(i);
                if(prevConnector == "&&")
                {
                    Base *temp2 = new Andand(currCmds.at(currCmds.size() - 1),
                        temp);
                    currCmds.pop_back();
                    currCmds.push_back(temp2);
                    prevConnector = nextConnector;
                    currCommand.resize(0);
                }
                else
                {
                    Base * temp2 = new Oror(currCmds.at(currCmds.size() - 1),
                        temp);
                    currCmds.pop_back();
                    currCmds.push_back(temp2);
                    prevConnector = nextConnector;
                    currCommand.resize(0);
                }
            }
        }
        Base * temp;
        if(currCommand.at(0) == "test")
        {
            temp = new Test(currCommand);
        }
        else {
            temp = new Command(currCommand);
        }
        if(prevConnector == "&&")
            {
                Base *temp2 = new Andand(currCmds.at(currCmds.size() - 1),
                    temp);
                currCmds.pop_back();
                currCmds.push_back(temp2);
                currCommand.resize(0);
            }
        else
        {
            Base * temp2 = new Oror(currCmds.at(currCmds.size() - 1), temp);
            currCmds.pop_back();
            currCmds.push_back(temp2);
        }
    }
    else if(detected && parenthesis)
    {

    }
    else {
        vector<string> currCommand;
        for(unsigned k = 0; k < currCs.size(); ++k)
        {
            currCommand.push_back(currCs.at(k));
        }
        Base *temp;
        if(currCommand.at(0) == "test")
        {
            temp = new Test(currCommand);
        }
        else {
            temp = new Command(currCommand);
        }
        currCmds.push_back(temp);
    }
}
//This is used to clean up the Processes vector in order to gather further
//input from the user.
void Processes::reset()
{
    for(unsigned i = 0; i < currCmds.size(); ++i)
    {
        delete currCmds.at(i);
    }
    this->currCmds.resize(0);

}<|endoftext|>


<commit_before>#include "RayTracer.hpp"
#include <ctime>

//temporary variables
Vec3Df testRayOrigin;
Vec3Df testRayDestination;
string input;
extern unsigned int textures[2];

//use this function for any preprocessing of the mesh.
void init(int argc, char **argv){
    //load the mesh file
    //feel free to replace cube by a path to another model
    //please realize that not all OBJ files will successfully load.
    //Nonetheless, if they come from Blender, they should.
    //there is a difference between windows written objs and Linux written objs.
    //hence, some models might not yet work well.

    RayTracingResolutionX = 1000; // These resolutions should be the same as the window,
    RayTracingResolutionY = 1000; // otherwise unexpected behaviour occurs.

    if(argc == 2){
        input = argv[1];
    }else{
        cout
                << "Mesh file name: (0: monkey, 1: cube, 2: dodgeColorTest, 3: simple_monkey)"
                << endl << "You can omit the mesh/ path and the .obj extension."
                << endl;
        cin >> input;
    }

    if(input == "0")
        input = "cube";
    else if(input == "1")
        input = "simple_monkey";
    else if(input == "2")
        input = "monkey";
    else if(input == "3")
        input = "dodgeColorTest";

    input = string("mesh/").append(input).append(".obj");
    MyMesh.loadMesh(input.c_str(), true);

    MyMesh.computeVertexNormals();

    //one first move: initialize the first light source
    //at least ONE light source has to be in the scene!!!
    //here, we set it to the current location of the camera
    MyLightPositions.push_back(MyCameraPosition);
}

//transformer le x, y en position 3D
void produceRay(int x_I, int y_I, Vec3Df * origin, Vec3Df * dest){
    int viewport[4];
    double modelview[16];
    double projection[16];
    //point sur near plane
    //double positionN[3];
    //point sur far plane
    //double positionF[3];
    glGetDoublev(GL_MODELVIEW_MATRIX, modelview); //recuperer matrices
    glGetDoublev(GL_PROJECTION_MATRIX, projection); //recuperer matrices
    glGetIntegerv(GL_VIEWPORT, viewport); //viewport
    int y_new = viewport[3] - y_I;

    double x, y, z;

    gluUnProject(x_I, y_new, 0, modelview, projection, viewport, &x, &y, &z);
    origin->p[0] = float(x);
    origin->p[1] = float(y);
    origin->p[2] = float(z);
    gluUnProject(x_I, y_new, 1, modelview, projection, viewport, &x, &y, &z);
    dest->p[0] = float(x);
    dest->p[1] = float(y);
    dest->p[2] = float(z);
}

void produceRay(int x_I, int y_I, Vec3Df & origin, Vec3Df & dest){
    produceRay(x_I, y_I, &origin, &dest);
}

void startRayTracing(int texIndex, bool verbose){
    //C'est nouveau!!!
    //commencez ici et lancez vos propres fonctions par rayon.

	if (verbose) cout << "Raytracing" << endl;
	Image result(RayTracingResolutionX, RayTracingResolutionY);

    Vec3Df origin00, dest00;
    Vec3Df origin01, dest01;
    Vec3Df origin10, dest10;
    Vec3Df origin11, dest11;
    Vec3Df origin, dest;

    produceRay(0, 0, &origin00, &dest00);
    produceRay(0, RayTracingResolutionY - 1, &origin01, &dest01);
    produceRay(RayTracingResolutionX - 1, 0, &origin10, &dest10);
    produceRay(RayTracingResolutionX - 1, RayTracingResolutionY - 1, &origin11,
            &dest11);

    // Perform timing
    time_t start, end, ticks;
    start = clock();

	int stepsize = 8;
	if (verbose) stepsize = 1;

    for(float y = 0;y < RayTracingResolutionY; y += stepsize){
        for(float x = 0;x < RayTracingResolutionX; x += stepsize){
            //svp, decidez vous memes quels parametres vous allez passer à la fonction
            //e.g., maillage, triangles, sphères etc.
            const float xscale = 1.0f - x / (RayTracingResolutionX - 1);
#ifdef WIN32
            const float yscale = float(y) / (RayTracingResolutionY - 1);
#else
            const float yscale = 1.0f - y / (RayTracingResolutionY - 1);
#endif
            origin = yscale * (xscale * origin00 + (1 - xscale) * origin10)
                    + (1 - yscale)
                            * (xscale * origin01 + (1 - xscale) * origin11);
            dest = yscale * (xscale * dest00 + (1 - xscale) * dest10)
                    + (1 - yscale) * (xscale * dest01 + (1 - xscale) * dest11);

			Vec3Df color = performRayTracing(origin, dest);
			for (int xx = 0; xx < stepsize; xx++)
			for (int yy = 0; yy < stepsize; yy++)
				result.setPixel(x+xx, y+yy, color);
        }
    }

    // calculate elapsed time
    end = clock();
    ticks = end - start;
	start = end;
    int millis = ticks * 1000 / CLOCKS_PER_SEC;

    if (verbose) printf("Rendering took %d ms\n", millis);

    // write to texture
	glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, RayTracingResolutionX,
		RayTracingResolutionY, 0, GL_RGB, GL_FLOAT, &result._image[0]);

	// calculate elapsed time
	end = clock();
	ticks = end - start;
	millis = ticks * 1000 / CLOCKS_PER_SEC;

	if (verbose) printf("Uploading to GPU took %d ms\n", millis);

    if (verbose) result.writeImage("result");
}

#define rayOrig ray.orig
#define rayDir ray.dir
#define VEWY_HIGH 10e6f

Vec3Df black(0, 0, 0);

//return the color of your pixel.
Vec3Df performRayTracing(const Vec3Df & origin, const Vec3Df & dest){
	Ray ray = Ray(black, origin, dest);

	// calculate nearest triangle
	int idx = -1; /* the triangle that was hit */
	float hit = VEWY_HIGH; /* distance to hit triangle */
	unsigned int numTriangles = MyMesh.triangles.size();
	for (unsigned int i = 0; i < numTriangles; i++){
		float ins = ray.intersect(MyMesh.triangles[i]);
		if (ins < VEWY_HIGH && ins < hit && ins > 0) {
			hit = ins;
			idx = i;
		}
	}

	// using black
	if (idx == -1)
		return black;

	Vec3Df& normal = MyMesh.triangles[idx].normal;
	float angle = -dot(normal, origin) * 0.5;

	return Vec3Df(angle, angle, angle);
}

void yourDebugDraw(){
    //draw open gl debug stuff
    //this function is called every frame

    //as an example:
    glPushAttrib(GL_ALL_ATTRIB_BITS);
    glDisable(GL_LIGHTING);
    glColor3f(1, 0, 1);
    glBegin(GL_LINES);
    glVertex3f(testRayOrigin[0], testRayOrigin[1], testRayOrigin[2]);
    glVertex3f(testRayDestination[0], testRayDestination[1],
            testRayDestination[2]);
    glEnd();
    glPointSize(10);
    glBegin(GL_POINTS);
    glVertex3fv(MyLightPositions[0].pointer());
    glEnd();
    glPopAttrib();

}

void yourKeyboardFunc(char t, int x, int y){
    // do what you want with the keyboard input t.
    // x, y are the screen position

    //here I use it to get the coordinates of a ray, which I then draw in the debug function.
    produceRay(x, y, testRayOrigin, testRayDestination);

    std::cout << t << " pressed! The mouse was in location " << x << "," << y
            << "!" << std::endl;
}
<commit_msg>Added FPS counter, saves to local variable.<commit_after>#include "RayTracer.hpp"
#include <ctime>

//temporary variables
Vec3Df testRayOrigin;
Vec3Df testRayDestination;
string input;
extern unsigned int textures[2];
clock_t lastFrameTime;
float fps;

//use this function for any preprocessing of the mesh.
void init(int argc, char **argv){
    //load the mesh file
    //feel free to replace cube by a path to another model
    //please realize that not all OBJ files will successfully load.
    //Nonetheless, if they come from Blender, they should.
    //there is a difference between windows written objs and Linux written objs.
    //hence, some models might not yet work well.

	lastFrameTime = clock();

    RayTracingResolutionX = 1000; // These resolutions should be the same as the window,
    RayTracingResolutionY = 1000; // otherwise unexpected behaviour occurs.

    if(argc == 2){
        input = argv[1];
    }else{
        cout
                << "Mesh file name: (0: monkey, 1: cube, 2: dodgeColorTest, 3: simple_monkey)"
                << endl << "You can omit the mesh/ path and the .obj extension."
                << endl;
        cin >> input;
    }

    if(input == "0")
        input = "cube";
    else if(input == "1")
        input = "simple_monkey";
    else if(input == "2")
        input = "monkey";
    else if(input == "3")
        input = "dodgeColorTest";

    input = string("mesh/").append(input).append(".obj");
    MyMesh.loadMesh(input.c_str(), true);

    MyMesh.computeVertexNormals();

    //one first move: initialize the first light source
    //at least ONE light source has to be in the scene!!!
    //here, we set it to the current location of the camera
    MyLightPositions.push_back(MyCameraPosition);
}

//transformer le x, y en position 3D
void produceRay(int x_I, int y_I, Vec3Df * origin, Vec3Df * dest){
    int viewport[4];
    double modelview[16];
    double projection[16];
    //point sur near plane
    //double positionN[3];
    //point sur far plane
    //double positionF[3];
    glGetDoublev(GL_MODELVIEW_MATRIX, modelview); //recuperer matrices
    glGetDoublev(GL_PROJECTION_MATRIX, projection); //recuperer matrices
    glGetIntegerv(GL_VIEWPORT, viewport); //viewport
    int y_new = viewport[3] - y_I;

    double x, y, z;

    gluUnProject(x_I, y_new, 0, modelview, projection, viewport, &x, &y, &z);
    origin->p[0] = float(x);
    origin->p[1] = float(y);
    origin->p[2] = float(z);
    gluUnProject(x_I, y_new, 1, modelview, projection, viewport, &x, &y, &z);
    dest->p[0] = float(x);
    dest->p[1] = float(y);
    dest->p[2] = float(z);
}

void produceRay(int x_I, int y_I, Vec3Df & origin, Vec3Df & dest){
    produceRay(x_I, y_I, &origin, &dest);
}

void startRayTracing(int texIndex, bool verbose){
    //C'est nouveau!!!
    //commencez ici et lancez vos propres fonctions par rayon.

	if (verbose) cout << "Raytracing" << endl;
	Image result(RayTracingResolutionX, RayTracingResolutionY);

    Vec3Df origin00, dest00;
    Vec3Df origin01, dest01;
    Vec3Df origin10, dest10;
    Vec3Df origin11, dest11;
    Vec3Df origin, dest;

    produceRay(0, 0, &origin00, &dest00);
    produceRay(0, RayTracingResolutionY - 1, &origin01, &dest01);
    produceRay(RayTracingResolutionX - 1, 0, &origin10, &dest10);
    produceRay(RayTracingResolutionX - 1, RayTracingResolutionY - 1, &origin11,
            &dest11);

    // Perform timing
    time_t start, end, ticks;
    start = clock();

	int stepsize = 8;
	if (verbose) stepsize = 1;

    for(float y = 0;y < RayTracingResolutionY; y += stepsize){
        for(float x = 0;x < RayTracingResolutionX; x += stepsize){
            //svp, decidez vous memes quels parametres vous allez passer à la fonction
            //e.g., maillage, triangles, sphères etc.
            const float xscale = 1.0f - x / (RayTracingResolutionX - 1);
#ifdef WIN32
            const float yscale = float(y) / (RayTracingResolutionY - 1);
#else
            const float yscale = 1.0f - y / (RayTracingResolutionY - 1);
#endif
            origin = yscale * (xscale * origin00 + (1 - xscale) * origin10)
                    + (1 - yscale)
                            * (xscale * origin01 + (1 - xscale) * origin11);
            dest = yscale * (xscale * dest00 + (1 - xscale) * dest10)
                    + (1 - yscale) * (xscale * dest01 + (1 - xscale) * dest11);

			Vec3Df color = performRayTracing(origin, dest);
			for (int xx = 0; xx < stepsize; xx++)
			for (int yy = 0; yy < stepsize; yy++)
				result.setPixel(x+xx, y+yy, color);
        }
    }

    // calculate elapsed time
    end = clock();
    ticks = end - start;
	start = end;
    int millis = ticks * 1000 / CLOCKS_PER_SEC;

    if (verbose) printf("Rendering took %d ms\n", millis);

    // write to texture
	glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, RayTracingResolutionX,
		RayTracingResolutionY, 0, GL_RGB, GL_FLOAT, &result._image[0]);

	// calculate elapsed time
	end = clock();
	ticks = end - start;
	millis = ticks * 1000 / CLOCKS_PER_SEC;

	if (verbose) printf("Uploading to GPU took %d ms\n", millis);

    if (verbose) result.writeImage("result");
}

#define rayOrig ray.orig
#define rayDir ray.dir
#define VEWY_HIGH 10e6f

Vec3Df black(0, 0, 0);

//return the color of your pixel.
Vec3Df performRayTracing(const Vec3Df & origin, const Vec3Df & dest){
	Ray ray = Ray(black, origin, dest);

	// calculate nearest triangle
	int idx = -1; /* the triangle that was hit */
	float hit = VEWY_HIGH; /* distance to hit triangle */
	unsigned int numTriangles = MyMesh.triangles.size();
	for (unsigned int i = 0; i < numTriangles; i++){
		float ins = ray.intersect(MyMesh.triangles[i]);
		if (ins < VEWY_HIGH && ins < hit && ins > 0) {
			hit = ins;
			idx = i;
		}
	}

	// using black
	if (idx == -1)
		return black;

	Vec3Df& normal = MyMesh.triangles[idx].normal;
	float angle = -dot(normal, origin) * 0.5;

	return Vec3Df(angle, angle, angle);
}

void yourDebugDraw(){
    //draw open gl debug stuff
    //this function is called every frame

	clock_t diff = clock() - lastFrameTime;
	lastFrameTime = clock();
	fps = 1 / ((float)diff / (float)CLOCKS_PER_SEC);
	cout << fps << endl;

    //as an example:
    glPushAttrib(GL_ALL_ATTRIB_BITS);
    glDisable(GL_LIGHTING);
    glColor3f(1, 0, 1);
    glBegin(GL_LINES);
    glVertex3f(testRayOrigin[0], testRayOrigin[1], testRayOrigin[2]);
    glVertex3f(testRayDestination[0], testRayDestination[1],
            testRayDestination[2]);
    glEnd();
    glPointSize(10);
    glBegin(GL_POINTS);
    glVertex3fv(MyLightPositions[0].pointer());
    glEnd();
    glPopAttrib();

}

void yourKeyboardFunc(char t, int x, int y){
    // do what you want with the keyboard input t.
    // x, y are the screen position

    //here I use it to get the coordinates of a ray, which I then draw in the debug function.
    produceRay(x, y, testRayOrigin, testRayDestination);

    std::cout << t << " pressed! The mouse was in location " << x << "," << y
            << "!" << std::endl;
}
<|endoftext|>


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

#include <Reduction.hpp>

namespace TuneBench {

reductionConf::reductionConf() : isa::OpenCL::KernelConf(), nrItemsPerBlock(1) {}

std::string reductionConf::print() const {
  return isa::utils::toString(nrItemsPerBlock) + " " + isa::OpenCL::KernelConf::print();
}

std::string * getReductionOpenCL(const reductionConf & conf, const std::string & inputDataName, const std::string & outputDataName, const unsigned int inputSize) {
  std::string * code = new std::string();

  // Begin kernel's template
  *code = "__kernel void reduction(__global const " + inputDataName + " * const restrict input, __global " + outputDataName + " * const restrict output) {\n"
    "const unsigned int firstItem = (get_group_id(0) * " + isa::utils::toString(conf.getNrItemsPerBlock()) + ") + get_local_id(0);\n"
    "__local " + inputDataName + " buffer[" + isa::utils::toString(conf.getNrThreadsD0()) + "];\n"
    "<%DEF%>"
    "\n"
    "// First compute phase\n"
    "for ( unsigned int item = firstItem; (item < firstItem + " + isa::utils::toString(conf.getNrItemsPerBlock()) + ") && (item + " + isa::utils::toString((conf.getNrItemsD0() - 1) * conf.getNrThreadsD0()) + " < " + isa::utils::toString(inputSize) + "); item += " + isa::utils::toString(conf.getNrThreadsD0() * conf.getNrItemsD0()) + " ) {\n"
    "<%COMPUTE%>"
    "}\n"
    "// In-thread reduce phase\n"
    "<%REDUCE%>"
    "buffer[get_local_id(0)] = accumulator0;\n"
    "barrier(CLK_LOCAL_MEM_FENCE);\n"
    "// Parallel reduce phase\n"
    "unsigned int threshold = " + isa::utils::toString(conf.getNrThreadsD0() / 2) + ";\n"
    "for ( unsigned int item = get_local_id(0); threshold > 0; threshold /= 2 ) {\n"
    "if ( item < threshold ) {\n"
    "accumulator0 += buffer[item + threshold];\n"
    "buffer[item] = accumulator0;\n"
    "}\n"
    "barrier(CLK_LOCAL_MEM_FENCE);\n"
    "}\n"
    "// Store\n"
    "if ( get_local_id(0) == 0 ) {\n"
    "output[get_group_id(0)] = accumulator0;\n"
    "}\n"
    "}\n";
  std::string def_sTemplate = outputDataName + " accumulator<%NUM%> = 0;\n";
  std::string compute_sTemplate = "accumulator<%NUM%> += input[item + <%OFFSET%>];\n";
  std::string reduce_sTemplate = "accumulator0 += accumulator<%NUM%>;\n";
  // End kernel's template

  std::string * def_s = new std::string();
  std::string * compute_s = new std::string();
  std::string * reduce_s = new std::string();

  for ( unsigned int item = 0; item < conf.getNrItemsD0(); item++ ) {
    std::string item_s = isa::utils::toString(item);
    std::string offset_s = isa::utils::toString(item * conf.getNrThreadsD0());
    std::string * temp = 0;

    temp = isa::utils::replace(&def_sTemplate, "<%NUM%>", item_s);
    def_s->append(*temp);
    delete temp;
    temp = isa::utils::replace(&compute_sTemplate, "<%NUM%>", item_s);
    if ( item == 0 ) {
      std::string empty_s("");
      temp = isa::utils::replace(temp, " + <%OFFSET%>", empty_s, true);
    } else {
      temp = isa::utils::replace(temp, "<%OFFSET%>", offset_s, true);
    }
    compute_s->append(*temp);
    delete temp;
    if ( item > 0 ) {
      temp = isa::utils::replace(&reduce_sTemplate, "<%NUM%>", item_s);
      reduce_s->append(*temp);
      delete temp;
    }
  }
  code = isa::utils::replace(code, "<%DEF%>", *def_s, true);
  code = isa::utils::replace(code, "<%COMPUTE%>", *compute_s, true);
  code = isa::utils::replace(code, "<%REDUCE%>", *reduce_s, true);
  delete def_s;
  delete compute_s;
  delete reduce_s;

  return code;
}

} // TuneBench

<commit_msg>Simplifying the constraint on the first compute phase.<commit_after>// Copyright 2016 Alessio Sclocco <a.sclocco@vu.nl>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <Reduction.hpp>

namespace TuneBench {

reductionConf::reductionConf() : isa::OpenCL::KernelConf(), nrItemsPerBlock(1) {}

std::string reductionConf::print() const {
  return isa::utils::toString(nrItemsPerBlock) + " " + isa::OpenCL::KernelConf::print();
}

std::string * getReductionOpenCL(const reductionConf & conf, const std::string & inputDataName, const std::string & outputDataName, const unsigned int inputSize) {
  std::string * code = new std::string();

  // Begin kernel's template
  *code = "__kernel void reduction(__global const " + inputDataName + " * const restrict input, __global " + outputDataName + " * const restrict output) {\n"
    "const unsigned int firstItem = (get_group_id(0) * " + isa::utils::toString(conf.getNrItemsPerBlock()) + ") + get_local_id(0);\n"
    "__local " + inputDataName + " buffer[" + isa::utils::toString(conf.getNrThreadsD0()) + "];\n"
    "<%DEF%>"
    "\n"
    "// First compute phase\n"
    "for ( unsigned int item = firstItem; (item + " + isa::utils::toString((conf.getNrItemsD0() - 1) * conf.getNrThreadsD0()) + ") < firstItem + " + isa::utils::toString(conf.getNrItemsPerBlock()) + "; item += " + isa::utils::toString(conf.getNrThreadsD0() * conf.getNrItemsD0()) + " ) {\n"
    "<%COMPUTE%>"
    "}\n"
    "// In-thread reduce phase\n"
    "<%REDUCE%>"
    "buffer[get_local_id(0)] = accumulator0;\n"
    "barrier(CLK_LOCAL_MEM_FENCE);\n"
    "// Parallel reduce phase\n"
    "unsigned int threshold = " + isa::utils::toString(conf.getNrThreadsD0() / 2) + ";\n"
    "for ( unsigned int item = get_local_id(0); threshold > 0; threshold /= 2 ) {\n"
    "if ( item < threshold ) {\n"
    "accumulator0 += buffer[item + threshold];\n"
    "buffer[item] = accumulator0;\n"
    "}\n"
    "barrier(CLK_LOCAL_MEM_FENCE);\n"
    "}\n"
    "// Store\n"
    "if ( get_local_id(0) == 0 ) {\n"
    "output[get_group_id(0)] = accumulator0;\n"
    "}\n"
    "}\n";
  std::string def_sTemplate = outputDataName + " accumulator<%NUM%> = 0;\n";
  std::string compute_sTemplate = "accumulator<%NUM%> += input[item + <%OFFSET%>];\n";
  std::string reduce_sTemplate = "accumulator0 += accumulator<%NUM%>;\n";
  // End kernel's template

  std::string * def_s = new std::string();
  std::string * compute_s = new std::string();
  std::string * reduce_s = new std::string();

  for ( unsigned int item = 0; item < conf.getNrItemsD0(); item++ ) {
    std::string item_s = isa::utils::toString(item);
    std::string offset_s = isa::utils::toString(item * conf.getNrThreadsD0());
    std::string * temp = 0;

    temp = isa::utils::replace(&def_sTemplate, "<%NUM%>", item_s);
    def_s->append(*temp);
    delete temp;
    temp = isa::utils::replace(&compute_sTemplate, "<%NUM%>", item_s);
    if ( item == 0 ) {
      std::string empty_s("");
      temp = isa::utils::replace(temp, " + <%OFFSET%>", empty_s, true);
    } else {
      temp = isa::utils::replace(temp, "<%OFFSET%>", offset_s, true);
    }
    compute_s->append(*temp);
    delete temp;
    if ( item > 0 ) {
      temp = isa::utils::replace(&reduce_sTemplate, "<%NUM%>", item_s);
      reduce_s->append(*temp);
      delete temp;
    }
  }
  code = isa::utils::replace(code, "<%DEF%>", *def_s, true);
  code = isa::utils::replace(code, "<%COMPUTE%>", *compute_s, true);
  code = isa::utils::replace(code, "<%REDUCE%>", *reduce_s, true);
  delete def_s;
  delete compute_s;
  delete reduce_s;

  return code;
}

} // TuneBench

<|endoftext|>


<commit_before>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

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

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
 */
/**
 * @author Marek Kotewicz <marek@ethdev.com>
 * @date 2014
 * Unit tests for the solidity compiler JSON Interface output.
 */

#include <libsolidity/CompilerStack.h>
#include <jsonrpc/json/json.h>
#include <boost/test/unit_test.hpp>

namespace dev
{
namespace solidity
{
namespace test
{

class InterfaceChecker {
public:
	bool checkInterface(std::string const& _code, std::string const& _expectedInterfaceString)
	{
		m_compilerStack.compile(_code);
		std::string generatedInterfaceString = m_compilerStack.getInterface();
		Json::Value generatedInterface;
		m_reader.parse(generatedInterfaceString, generatedInterface);
		Json::Value expectedInterface;
		m_reader.parse(_expectedInterfaceString, expectedInterface);
		return expectedInterface == generatedInterface;
	}

private:
	CompilerStack m_compilerStack;
	Json::Reader m_reader;
};

BOOST_FIXTURE_TEST_SUITE(SolidityCompilerJSONInterfaceOutput, InterfaceChecker)

BOOST_AUTO_TEST_CASE(basic_test)
{
	char const* sourceCode = "contract test {\n"
	"  function f(uint a) returns(uint d) { return a * 7; }\n"
	"}\n";

	char const* interface = R"([
	{
		"name": "f",
		"inputs": [
		{
			"name": "a",
			"type": "uint256"
		}
		],
		"outputs": [
		{
			"name": "d",
			"type": "uint256"
		}
		]
	}
	])";

	BOOST_CHECK(checkInterface(sourceCode, interface));
}

BOOST_AUTO_TEST_CASE(empty_contract)
{
	char const* sourceCode = "contract test {\n"
	"}\n";

	char const* interface = "[]";

	BOOST_CHECK(checkInterface(sourceCode, interface));
}

BOOST_AUTO_TEST_CASE(multiple_methods)
{
	char const* sourceCode = "contract test {\n"
	"  function f(uint a) returns(uint d) { return a * 7; }\n"
	"  function g(uint b) returns(uint e) { return b * 8; }\n"
	"}\n";

	char const* interface = R"([
	{
		"name": "f",
		"inputs": [
		{
			"name": "a",
			"type": "uint256"
		}
		],
		"outputs": [
		{
			"name": "d",
			"type": "uint256"
		}
		]
	},
	{
		"name": "g",
		"inputs": [
		{
			"name": "b",
			"type": "uint256"
		}
		],
		"outputs": [
		{
			"name": "e",
			"type": "uint256"
		}
		]
	}
	])";

	BOOST_CHECK(checkInterface(sourceCode, interface));
}

BOOST_AUTO_TEST_CASE(multiple_params)
{
	char const* sourceCode = "contract test {\n"
	"  function f(uint a, uint b) returns(uint d) { return a + b; }\n"
	"}\n";

	char const* interface = R"([
	{
		"name": "f",
		"inputs": [
		{
			"name": "a",
			"type": "uint256"
		},
		{
			"name": "b",
			"type": "uint256"
		}
		],
		"outputs": [
		{
			"name": "d",
			"type": "uint256"
		}
		]
	}
	])";

	BOOST_CHECK(checkInterface(sourceCode, interface));
}

BOOST_AUTO_TEST_CASE(multiple_methods_order)
{
	// methods are expected to be in alpabetical order
	char const* sourceCode = "contract test {\n"
	"  function f(uint a) returns(uint d) { return a * 7; }\n"
	"  function c(uint b) returns(uint e) { return b * 8; }\n"
	"}\n";

	char const* interface = R"([
	{
		"name": "c",
		"inputs": [
		{
			"name": "b",
			"type": "uint256"
		}
		],
		"outputs": [
		{
			"name": "e",
			"type": "uint256"
		}
		]
	},
	{
		"name": "f",
		"inputs": [
		{
			"name": "a",
			"type": "uint256"
		}
		],
		"outputs": [
		{
			"name": "d",
			"type": "uint256"
		}
		]
	}
	])";

	BOOST_CHECK(checkInterface(sourceCode, interface));
}

BOOST_AUTO_TEST_SUITE_END()

}
}
}
<commit_msg>solidity json interface tests fixes<commit_after>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

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

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
 */
/**
 * @author Marek Kotewicz <marek@ethdev.com>
 * @date 2014
 * Unit tests for the solidity compiler JSON Interface output.
 */

#include <boost/test/unit_test.hpp>
#include <libsolidity/CompilerStack.h>
#include <jsonrpc/json/json.h>

namespace dev
{
namespace solidity
{
namespace test
{

class InterfaceChecker
{
public:
	bool checkInterface(std::string const& _code, std::string const& _expectedInterfaceString)
	{
		m_compilerStack.parse(_code);
		std::string generatedInterfaceString = m_compilerStack.getInterface();
		Json::Value generatedInterface;
		m_reader.parse(generatedInterfaceString, generatedInterface);
		Json::Value expectedInterface;
		m_reader.parse(_expectedInterfaceString, expectedInterface);
		return expectedInterface == generatedInterface;
	}

private:
	CompilerStack m_compilerStack;
	Json::Reader m_reader;
};

BOOST_FIXTURE_TEST_SUITE(SolidityCompilerJSONInterfaceOutput, InterfaceChecker)

BOOST_AUTO_TEST_CASE(basic_test)
{
	char const* sourceCode = "contract test {\n"
	"  function f(uint a) returns(uint d) { return a * 7; }\n"
	"}\n";

	char const* interface = R"([
	{
		"name": "f",
		"inputs": [
		{
			"name": "a",
			"type": "uint256"
		}
		],
		"outputs": [
		{
			"name": "d",
			"type": "uint256"
		}
		]
	}
	])";

	BOOST_CHECK(checkInterface(sourceCode, interface));
}

BOOST_AUTO_TEST_CASE(empty_contract)
{
	char const* sourceCode = "contract test {\n"
	"}\n";

	char const* interface = "[]";

	BOOST_CHECK(checkInterface(sourceCode, interface));
}

BOOST_AUTO_TEST_CASE(multiple_methods)
{
	char const* sourceCode = "contract test {\n"
	"  function f(uint a) returns(uint d) { return a * 7; }\n"
	"  function g(uint b) returns(uint e) { return b * 8; }\n"
	"}\n";

	char const* interface = R"([
	{
		"name": "f",
		"inputs": [
		{
			"name": "a",
			"type": "uint256"
		}
		],
		"outputs": [
		{
			"name": "d",
			"type": "uint256"
		}
		]
	},
	{
		"name": "g",
		"inputs": [
		{
			"name": "b",
			"type": "uint256"
		}
		],
		"outputs": [
		{
			"name": "e",
			"type": "uint256"
		}
		]
	}
	])";

	BOOST_CHECK(checkInterface(sourceCode, interface));
}

BOOST_AUTO_TEST_CASE(multiple_params)
{
	char const* sourceCode = "contract test {\n"
	"  function f(uint a, uint b) returns(uint d) { return a + b; }\n"
	"}\n";

	char const* interface = R"([
	{
		"name": "f",
		"inputs": [
		{
			"name": "a",
			"type": "uint256"
		},
		{
			"name": "b",
			"type": "uint256"
		}
		],
		"outputs": [
		{
			"name": "d",
			"type": "uint256"
		}
		]
	}
	])";

	BOOST_CHECK(checkInterface(sourceCode, interface));
}

BOOST_AUTO_TEST_CASE(multiple_methods_order)
{
	// methods are expected to be in alpabetical order
	char const* sourceCode = "contract test {\n"
	"  function f(uint a) returns(uint d) { return a * 7; }\n"
	"  function c(uint b) returns(uint e) { return b * 8; }\n"
	"}\n";

	char const* interface = R"([
	{
		"name": "c",
		"inputs": [
		{
			"name": "b",
			"type": "uint256"
		}
		],
		"outputs": [
		{
			"name": "e",
			"type": "uint256"
		}
		]
	},
	{
		"name": "f",
		"inputs": [
		{
			"name": "a",
			"type": "uint256"
		}
		],
		"outputs": [
		{
			"name": "d",
			"type": "uint256"
		}
		]
	}
	])";

	BOOST_CHECK(checkInterface(sourceCode, interface));
}

BOOST_AUTO_TEST_SUITE_END()

}
}
}
<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2011-2012, John Haddon. All rights reserved.
//  Copyright (c) 2011-2013, Image Engine Design Inc. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//      * Redistributions of source code must retain the above
//        copyright notice, this list of conditions and the following
//        disclaimer.
//
//      * Redistributions in binary form must reproduce the above
//        copyright notice, this list of conditions and the following
//        disclaimer in the documentation and/or other materials provided with
//        the distribution.
//
//      * Neither the name of John Haddon nor the names of
//        any other contributors to this software may be used to endorse or
//        promote products derived from this software without specific prior
//        written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#include "boost/python.hpp"
#include "boost/algorithm/string/replace.hpp"
#include "boost//format.hpp"

#include "IECorePython/IECoreBinding.h"
#include "IECorePython/RunTimeTypedBinding.h"
#include "IECorePython/ScopedGILRelease.h"

#include "Gaffer/CompoundNumericPlug.h"

#include "GafferBindings/ValuePlugBinding.h"

#include "CompoundNumericPlugBinding.h"

using namespace boost::python;
using namespace GafferBindings;
using namespace Gaffer;

namespace
{

template<typename T>
std::string maskedCompoundNumericPlugRepr( const T *plug, unsigned flagsMask, const Serialisation *serialisation = nullptr )
{
	std::string extraArgs = "";

	const IECore::GeometricData::Interpretation interpretation = plug->interpretation();

	if( interpretation != IECore::GeometricData::None )
	{
		boost::python::object interpretationAsPythonObject( interpretation );
		boost::python::object interpretationRepr = interpretationAsPythonObject.attr( "__repr__" )();
		extraArgs = "interpretation = " + std::string( boost::python::extract<std::string>( interpretationRepr ) );
		boost::replace_first( extraArgs, "_IECore", "GeometricData" );
	}

	return ValuePlugSerialiser::repr( plug, flagsMask, extraArgs, serialisation );
}

template<typename T>
std::string compoundNumericPlugRepr( const T *plug )
{
	return maskedCompoundNumericPlugRepr( plug, Plug::All );
}

template<typename T>
class CompoundNumericPlugSerialiser : public ValuePlugSerialiser
{
  public:

	std::string constructor( const Gaffer::GraphComponent *graphComponent, const Serialisation &serialisation ) const override
	{
		return maskedCompoundNumericPlugRepr( static_cast<const T *>( graphComponent ), Plug::All & ~Plug::ReadOnly, &serialisation );
	}

	protected :

		// Ideally we'll serialise the value as a single getValue() call for this plug,
		// but we can't do that if any of the children have input connections.
		bool valueNeedsSerialisation( const Gaffer::ValuePlug *plug, const Serialisation &serialisation ) const override
		{
			if( !ValuePlugSerialiser::valueNeedsSerialisation( plug, serialisation ) )
			{
				return false;
			}

			for( PlugIterator it( plug ); !it.done(); ++it )
			{
				if( (*it)->getInput() )
				{
					return false;
				}
			}
			return true;
		}

};

template<typename T>
void setValue( T *plug, const typename T::ValueType value )
{
	// we use a GIL release here to prevent a lock in the case where this triggers a graph
	// evaluation which decides to go back into python on another thread:
	IECorePython::ScopedGILRelease r;
	plug->setValue( value );
}

template<typename T>
typename T::ValueType getValue( const T *plug )
{
	// Must release GIL in case computation spawns threads which need
	// to reenter Python.
	IECorePython::ScopedGILRelease r;
	return plug->getValue();
}

template<typename T>
void gang( T *plug )
{
	// Must release GIL in case this triggers a graph evaluation
	// which wants to enter Python on another thread.
	IECorePython::ScopedGILRelease r;
	plug->gang();
}

template<typename T>
void ungang( T *plug )
{
	// Must release GIL in case this triggers a graph evaluation
	// which wants to enter Python on another thread.
	IECorePython::ScopedGILRelease r;
	plug->ungang();
}

template<typename T>
void bind()
{
	typedef typename T::ValueType V;

	PlugClass<T>()
		.def( init<const char *, Plug::Direction, V, V, V, unsigned, IECore::GeometricData::Interpretation>(
				(
					boost::python::arg_( "name" )=GraphComponent::defaultName<T>(),
					boost::python::arg_( "direction" )=Plug::In,
					boost::python::arg_( "defaultValue" )=V( 0 ),
					boost::python::arg_( "minValue" )=V(Imath::limits<typename V::BaseType>::min()),
					boost::python::arg_( "maxValue" )=V(Imath::limits<typename V::BaseType>::max()),
					boost::python::arg_( "flags" )=Plug::Default,
					boost::python::arg_( "interpretation" )=IECore::GeometricData::None
				)
			)
		)
		.def( "defaultValue", &T::defaultValue )
		.def( "hasMinValue", &T::hasMinValue )
		.def( "hasMaxValue", &T::hasMaxValue )
		.def( "minValue", &T::minValue )
		.def( "maxValue", &T::maxValue )
		.def( "setValue", &setValue<T> )
		.def( "getValue", &getValue<T> )
		.def( "interpretation", &T::interpretation )
		.def( "canGang", &T::canGang )
		.def( "gang", &gang<T> )
		.def( "isGanged", &T::isGanged )
		.def( "ungang", &ungang<T> )
		.def( "__repr__", &compoundNumericPlugRepr<T> )
	;

	Serialisation::registerSerialiser( T::staticTypeId(), new CompoundNumericPlugSerialiser<T>() );

}

} // namespace

void GafferModule::bindCompoundNumericPlug()
{
	bind<V2fPlug>();
	bind<V3fPlug>();
	bind<V2iPlug>();
	bind<V3iPlug>();
	bind<Color3fPlug>();
	bind<Color4fPlug>();
}
<commit_msg>CompoundNumericPlugBinding : Fix indentation<commit_after>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2011-2012, John Haddon. All rights reserved.
//  Copyright (c) 2011-2013, Image Engine Design Inc. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//      * Redistributions of source code must retain the above
//        copyright notice, this list of conditions and the following
//        disclaimer.
//
//      * Redistributions in binary form must reproduce the above
//        copyright notice, this list of conditions and the following
//        disclaimer in the documentation and/or other materials provided with
//        the distribution.
//
//      * Neither the name of John Haddon nor the names of
//        any other contributors to this software may be used to endorse or
//        promote products derived from this software without specific prior
//        written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#include "boost/python.hpp"
#include "boost/algorithm/string/replace.hpp"
#include "boost//format.hpp"

#include "IECorePython/IECoreBinding.h"
#include "IECorePython/RunTimeTypedBinding.h"
#include "IECorePython/ScopedGILRelease.h"

#include "Gaffer/CompoundNumericPlug.h"

#include "GafferBindings/ValuePlugBinding.h"

#include "CompoundNumericPlugBinding.h"

using namespace boost::python;
using namespace GafferBindings;
using namespace Gaffer;

namespace
{

template<typename T>
std::string maskedCompoundNumericPlugRepr( const T *plug, unsigned flagsMask, const Serialisation *serialisation = nullptr )
{
	std::string extraArgs = "";

	const IECore::GeometricData::Interpretation interpretation = plug->interpretation();

	if( interpretation != IECore::GeometricData::None )
	{
		boost::python::object interpretationAsPythonObject( interpretation );
		boost::python::object interpretationRepr = interpretationAsPythonObject.attr( "__repr__" )();
		extraArgs = "interpretation = " + std::string( boost::python::extract<std::string>( interpretationRepr ) );
		boost::replace_first( extraArgs, "_IECore", "GeometricData" );
	}

	return ValuePlugSerialiser::repr( plug, flagsMask, extraArgs, serialisation );
}

template<typename T>
std::string compoundNumericPlugRepr( const T *plug )
{
	return maskedCompoundNumericPlugRepr( plug, Plug::All );
}

template<typename T>
class CompoundNumericPlugSerialiser : public ValuePlugSerialiser
{

	public :

		std::string constructor( const Gaffer::GraphComponent *graphComponent, const Serialisation &serialisation ) const override
		{
			return maskedCompoundNumericPlugRepr( static_cast<const T *>( graphComponent ), Plug::All & ~Plug::ReadOnly, &serialisation );
		}

	protected :

		// Ideally we'll serialise the value as a single getValue() call for this plug,
		// but we can't do that if any of the children have input connections.
		bool valueNeedsSerialisation( const Gaffer::ValuePlug *plug, const Serialisation &serialisation ) const override
		{
			if( !ValuePlugSerialiser::valueNeedsSerialisation( plug, serialisation ) )
			{
				return false;
			}

			for( PlugIterator it( plug ); !it.done(); ++it )
			{
				if( (*it)->getInput() )
				{
					return false;
				}
			}
			return true;
		}

};

template<typename T>
void setValue( T *plug, const typename T::ValueType value )
{
	// we use a GIL release here to prevent a lock in the case where this triggers a graph
	// evaluation which decides to go back into python on another thread:
	IECorePython::ScopedGILRelease r;
	plug->setValue( value );
}

template<typename T>
typename T::ValueType getValue( const T *plug )
{
	// Must release GIL in case computation spawns threads which need
	// to reenter Python.
	IECorePython::ScopedGILRelease r;
	return plug->getValue();
}

template<typename T>
void gang( T *plug )
{
	// Must release GIL in case this triggers a graph evaluation
	// which wants to enter Python on another thread.
	IECorePython::ScopedGILRelease r;
	plug->gang();
}

template<typename T>
void ungang( T *plug )
{
	// Must release GIL in case this triggers a graph evaluation
	// which wants to enter Python on another thread.
	IECorePython::ScopedGILRelease r;
	plug->ungang();
}

template<typename T>
void bind()
{
	typedef typename T::ValueType V;

	PlugClass<T>()
		.def( init<const char *, Plug::Direction, V, V, V, unsigned, IECore::GeometricData::Interpretation>(
				(
					boost::python::arg_( "name" )=GraphComponent::defaultName<T>(),
					boost::python::arg_( "direction" )=Plug::In,
					boost::python::arg_( "defaultValue" )=V( 0 ),
					boost::python::arg_( "minValue" )=V(Imath::limits<typename V::BaseType>::min()),
					boost::python::arg_( "maxValue" )=V(Imath::limits<typename V::BaseType>::max()),
					boost::python::arg_( "flags" )=Plug::Default,
					boost::python::arg_( "interpretation" )=IECore::GeometricData::None
				)
			)
		)
		.def( "defaultValue", &T::defaultValue )
		.def( "hasMinValue", &T::hasMinValue )
		.def( "hasMaxValue", &T::hasMaxValue )
		.def( "minValue", &T::minValue )
		.def( "maxValue", &T::maxValue )
		.def( "setValue", &setValue<T> )
		.def( "getValue", &getValue<T> )
		.def( "interpretation", &T::interpretation )
		.def( "canGang", &T::canGang )
		.def( "gang", &gang<T> )
		.def( "isGanged", &T::isGanged )
		.def( "ungang", &ungang<T> )
		.def( "__repr__", &compoundNumericPlugRepr<T> )
	;

	Serialisation::registerSerialiser( T::staticTypeId(), new CompoundNumericPlugSerialiser<T>() );

}

} // namespace

void GafferModule::bindCompoundNumericPlug()
{
	bind<V2fPlug>();
	bind<V3fPlug>();
	bind<V2iPlug>();
	bind<V3iPlug>();
	bind<Color3fPlug>();
	bind<Color4fPlug>();
}
<|endoftext|>