<commit_before>#include "jaci.h"

using namespace std;

static vector<string> flags;
static vector<string> include_dirs;
static vector<string> lib_dirs;
static vector<string> libs;

static string cFilename = "__jaci_committed_staged_merged__.c";
static string cRunnable = "__jaci_executable__";

static int quitsig;
void quitprog(int signo) {
  quitsig--;
  if (quitsig == 0) {
    exit(1);
  }
}

void printAbout(void) {
  printf("Jaci v0.0.1\n"
      "Type \"$().help()\" for more information.\n"
      );
}

/** This function tries to determine whether or not the inputted line
 *  is a "special" Jaci cmd [indicated by $()], or just a regular C line
 *  @param line a line from the console
 *  @return true if this is a "special" command (has $ in the front),
 *  false otherwise
 */
bool isJaci(string &line) {
  return line.size() >= 4 && line.substr(0, 4) == "$().";
}

/** Return the latter part of the command, (eg. "$().exit()\n" => "exit()\n")
 *  @param line a line from the console
 *  @return the latter part of the command
 */
string getJaciCmd(string &line) {
  return line.substr(4);
}

/** "Runs" the Jasi command, given that it is the latter part
 *  eg. Good input: "exit()\n"
 *      Bad input: "$().exit()\n"
 *      Bad input: "exit()"
 *  @param line the latter part of the Jasi command
 *  @param committed the list of currently committed C commands
 */
void runJaciCmd(string &line, vector<string> &committed) {
  // TODO: implement features
  if (line == "help()\n") {
    printf("\nFunctions to use:\n"
        "\t$().help()    \tView the help prompt\n"
        "\t$().exit()    \tQuit the program\n"
        "\t$().save(f)   \tSave the current program to the filename f\n"
        "\t$().pop()     \tRemove the last command off the program list\n"
        "\t$().addflag(f)\tAdd flag f to the compilation line\n"
        "\t$().addlib(l) \tAdd library l to the compilation line\n"
        "\n");
  } else if (line == "exit()\n") {
    quitsig = 0;
  } else if (line.substr(0, 7) == "addlib(") {
    string libname = line.substr(7, line.size() - 9);
    libs.push_back(libname);
  } else if (line.substr(0, 8) == "addflag(") {
    string flagname = line.substr(8, line.size() - 10);
    flags.push_back(flagname);
  }
}

/** Gets the number of braces in the current line
 *  eg. { => 1
 *      {} => 0
 *      {{} => 1
 *      {}} => -1
 *  @param line a line from the console
 *  @return number of braces
 */
int getNumBrace(string &line) {
  int numBrace = 0;
  for (char &c : line) {
    if (c == '{') {
      numBrace++;
    } else if (c == '}') {
      numBrace--;
    }
  }
  return numBrace;
}

/** Switches the boolean inMain from either true or false, to indicate
 *  whether or not we are in the main function
 *  @param inMain the boolean that can be changed
 *  @param line a line from the console
 *  @param numBrace the current number of braces
 */
void toggleInMain(bool &inMain, string &line, int numBrace) {
  if (numBrace <= 0) {
    inMain = false;
  } else if (line.find("main") != string::npos && (line.find("//") == string::npos ||
      (line.find("//") > line.find("main")))) {
    inMain = true;
  }
}

/** Run a command line on Bash
 *  @param the line to run on bash
 *  @return the exit code
 */
int runConsoleCmd(string &cmd) {
  int status;
  status = system(cmd.c_str());
  return status;
}

/** Create a compile line, execute the compile line, and then finally,
 *  if run is true, then execute the resulting executable
 *  @param run if true, will execute the executable, otherwise it will not
 *  @return true if compiled (and ran) successfully, false if an error has occurred
 */
bool compileAndRun(bool run) {
  string compileCmd = "gcc";
  for (string &flag : flags) {
    compileCmd += " " + flag;
  }
  for (string &include_dir : include_dirs) {
    compileCmd += " " + include_dir;
  }
  compileCmd += " -o " + cRunnable;
  if (!run) {
    compileCmd += ".o";
    compileCmd += " -c " + cFilename;
  } else {
    compileCmd += " " + cFilename;
    for (string &lib_dir : lib_dirs) {
      compileCmd += " " + lib_dir;
    }
    for (string &lib : libs) {
      compileCmd += " " + lib;
    }
  }
  if (runConsoleCmd(compileCmd) != 0) { // run the make
    return false;
  }
  if (run) {
    string execCmd = "./" + cRunnable;
    int status = runConsoleCmd(execCmd);
    unlink(cRunnable.c_str());
    if (status != 0) { // run the exec
      return false;
    }
  }
  if (!run) {
    unlink((cRunnable + ".o").c_str());
  }
  return true;
}

/** Returns whether or not a file exists
 *  @param fname the name of the file
 *  @return true if the file exists, false otherwise
 */
bool fileExists(string &fname) {
  struct stat buffer;
  return (stat(fname.c_str(), &buffer) == 0);
}

/** First creates a C program, then calls compileAndRun()
 *  @param committed list of commited lines
 *  @param staged list of lines that need to be tried; if successful, adds to committed
 *  @param inMain whether or not we are in the main method
 *  @param numBrace the number of braces
 *  @return true if successful in compiling (and running), otherwise false
 */
bool evaluate(vector<string> &committed, vector<string> &staged, bool inMain, int numBrace) {
  // write a program file with the list of c lines
  if (fileExists(cFilename)) {
    unlink(cFilename.c_str());
  }
  ofstream programFile;
  programFile.open(cFilename);
  bool insertStaged = true;
  for (string &line : committed) {
    programFile << line;
  }
  for (string &line : staged) {
    programFile << line;
  }
  if (numBrace > 0 && inMain) {
    numBrace--; // just temporarily
    programFile << "}\n";
  }
  programFile.close();
  // try running the program that we just wrote
  bool status = compileAndRun(inMain);
  unlink(cFilename.c_str());
  if (status) {
    for (string &line : staged) {
      committed.push_back(line);
    }
  }
  staged.clear();
  return status;
}

/** Insert a line into the staged list
 *  @param staged the staged list
 *  @param line a line from the console
 */
void insertToStaged(vector<string> &staged, string &line) {
  staged.push_back(line);
}

int main(int argc, char *argv[]) {
  signal(SIGINT, quitprog);
  printAbout();
  int numBrace = 0;
  bool inMain = false;
  vector<string> committed;
  vector<string> staged;

  // start up a process?
  quitsig++;
  while (quitsig > 0) {
    if (numBrace == 0 || (numBrace == 1 && inMain)) {
      cout << ">>> ";
    }

    // read a line from the console
    string cmdline;
    getline(cin, cmdline);
    cmdline += "\n";

    // evaluate to see if it is special
    if (isJaci(cmdline)) {
      string jaciCmd = getJaciCmd(cmdline);
      runJaciCmd(jaciCmd, committed);
    } else {
      // if not special, then evaluate as so
      numBrace += getNumBrace(cmdline);
      toggleInMain(inMain, cmdline, numBrace);
      insertToStaged(staged, cmdline);
      if (numBrace == 0 || (numBrace == 1 && inMain)) {
        // this function does the interpretation
        evaluate(committed, staged, inMain, numBrace);
      }
    }
  }
  return 0;
}
<commit_msg>file saving now works<commit_after>#include "jaci.h"

using namespace std;

static vector<string> flags;
static vector<string> include_dirs;
static vector<string> lib_dirs;
static vector<string> libs;

static string cFilename = "__jaci_committed_staged_merged__.c";
static string cRunnable = "__jaci_executable__";

static void saveToFile(string &filename, string &content);

static int quitsig;
void quitprog(int signo) {
  quitsig--;
  if (quitsig == 0) {
    exit(1);
  }
}

void printAbout(void) {
  printf("Jaci v0.0.1\n"
      "Type \"$().help()\" for more information.\n"
      );
}

/** This function tries to determine whether or not the inputted line
 *  is a "special" Jaci cmd [indicated by $()], or just a regular C line
 *  @param line a line from the console
 *  @return true if this is a "special" command (has $ in the front),
 *  false otherwise
 */
bool isJaci(string &line) {
  return line.size() >= 4 && line.substr(0, 4) == "$().";
}

/** Return the latter part of the command, (eg. "$().exit()\n" => "exit()\n")
 *  @param line a line from the console
 *  @return the latter part of the command
 */
string getJaciCmd(string &line) {
  return line.substr(4);
}

/** "Runs" the Jasi command, given that it is the latter part
 *  eg. Good input: "exit()\n"
 *      Bad input: "$().exit()\n"
 *      Bad input: "exit()"
 *  @param line the latter part of the Jasi command
 *  @param committed the list of currently committed C commands
 */
void runJaciCmd(string &line, vector<string> &committed) {
  // TODO: implement features
  if (line == "help()\n") {
    printf("\nFunctions to use:\n"
        "\t$().help()    \tView the help prompt\n"
        "\t$().exit()    \tQuit the program\n"
        "\t$().save(f)   \tSave the current program to the filename f\n"
        "\t$().pop()     \tRemove the last command off the program list\n"
        "\t$().addflag(f)\tAdd flag f to the compilation line\n"
        "\t$().addlib(l) \tAdd library l to the compilation line\n"
        "\n");
  } else if (line == "exit()\n") {
    quitsig = 0;
  } else if (line.substr(0, 5) == "save(") {
    string filename = line.substr(5, line.size() - 7);
    string content = "";
    for (string &line : committed) {
      content += line;
    }
    saveToFile(filename, content);
  } else if (line.substr(0, 7) == "addlib(") {
    string libname = line.substr(7, line.size() - 9);
    libs.push_back(libname);
  } else if (line.substr(0, 8) == "addflag(") {
    string flagname = line.substr(8, line.size() - 10);
    flags.push_back(flagname);
  }
}

/** Gets the number of braces in the current line
 *  eg. { => 1
 *      {} => 0
 *      {{} => 1
 *      {}} => -1
 *  @param line a line from the console
 *  @return number of braces
 */
int getNumBrace(string &line) {
  int numBrace = 0;
  for (char &c : line) {
    if (c == '{') {
      numBrace++;
    } else if (c == '}') {
      numBrace--;
    }
  }
  return numBrace;
}

/** Switches the boolean inMain from either true or false, to indicate
 *  whether or not we are in the main function
 *  @param inMain the boolean that can be changed
 *  @param line a line from the console
 *  @param numBrace the current number of braces
 */
void toggleInMain(bool &inMain, string &line, int numBrace) {
  if (numBrace <= 0) {
    inMain = false;
  } else if (line.find("main") != string::npos && (line.find("//") == string::npos ||
      (line.find("//") > line.find("main")))) {
    inMain = true;
  }
}

/** Run a command line on Bash
 *  @param the line to run on bash
 *  @return the exit code
 */
int runConsoleCmd(string &cmd) {
  int status;
  status = system(cmd.c_str());
  return status;
}

/** Create a compile line, execute the compile line, and then finally,
 *  if run is true, then execute the resulting executable
 *  @param run if true, will execute the executable, otherwise it will not
 *  @return true if compiled (and ran) successfully, false if an error has occurred
 */
bool compileAndRun(bool run) {
  string compileCmd = "gcc";
  for (string &flag : flags) {
    compileCmd += " " + flag;
  }
  for (string &include_dir : include_dirs) {
    compileCmd += " " + include_dir;
  }
  compileCmd += " -o " + cRunnable;
  if (!run) {
    compileCmd += ".o";
    compileCmd += " -c " + cFilename;
  } else {
    compileCmd += " " + cFilename;
    for (string &lib_dir : lib_dirs) {
      compileCmd += " " + lib_dir;
    }
    for (string &lib : libs) {
      compileCmd += " " + lib;
    }
  }
  if (runConsoleCmd(compileCmd) != 0) { // run the make
    return false;
  }
  if (run) {
    string execCmd = "./" + cRunnable;
    int status = runConsoleCmd(execCmd);
    unlink(cRunnable.c_str());
    if (status != 0) { // run the exec
      return false;
    }
  }
  if (!run) {
    unlink((cRunnable + ".o").c_str());
  }
  return true;
}

/** Returns whether or not a file exists
 *  @param fname the name of the file
 *  @return true if the file exists, false otherwise
 */
bool fileExists(string &fname) {
  struct stat buffer;
  return (stat(fname.c_str(), &buffer) == 0);
}

/** First creates a C program, then calls compileAndRun()
 *  @param committed list of commited lines
 *  @param staged list of lines that need to be tried; if successful, adds to committed
 *  @param inMain whether or not we are in the main method
 *  @param numBrace the number of braces
 *  @return true if successful in compiling (and running), otherwise false
 */
bool evaluate(vector<string> &committed, vector<string> &staged, bool inMain, int numBrace) {
  // write a program file with the list of c lines
  if (fileExists(cFilename)) {
    unlink(cFilename.c_str());
  }
  ofstream programFile;
  programFile.open(cFilename);
  bool insertStaged = true;
  for (string &line : committed) {
    programFile << line;
  }
  for (string &line : staged) {
    programFile << line;
  }
  if (numBrace > 0 && inMain) {
    numBrace--; // just temporarily
    programFile << "}\n";
  }
  programFile.close();
  // try running the program that we just wrote
  bool status = compileAndRun(inMain);
  unlink(cFilename.c_str());
  if (status) {
    for (string &line : staged) {
      committed.push_back(line);
    }
  }
  staged.clear();
  return status;
}

/** Insert a line into the staged list
 *  @param staged the staged list
 *  @param line a line from the console
 */
void insertToStaged(vector<string> &staged, string &line) {
  staged.push_back(line);
}

int main(int argc, char *argv[]) {
  signal(SIGINT, quitprog);
  printAbout();
  int numBrace = 0;
  bool inMain = false;
  vector<string> committed;
  vector<string> staged;

  // start up a process?
  quitsig++;
  while (quitsig > 0) {
    if (numBrace == 0 || (numBrace == 1 && inMain)) {
      cout << ">>> ";
    }

    // read a line from the console
    string cmdline;
    getline(cin, cmdline);
    cmdline += "\n";

    // evaluate to see if it is special
    if (isJaci(cmdline)) {
      string jaciCmd = getJaciCmd(cmdline);
      runJaciCmd(jaciCmd, committed);
    } else {
      // if not special, then evaluate as so
      numBrace += getNumBrace(cmdline);
      toggleInMain(inMain, cmdline, numBrace);
      insertToStaged(staged, cmdline);
      if (numBrace == 0 || (numBrace == 1 && inMain)) {
        // this function does the interpretation
        evaluate(committed, staged, inMain, numBrace);
      }
    }
  }
  return 0;
}

/** Open a file with nothing in it, and place the content inside
 *  @param filename name of the file
 *  @param content the content to place inside te file
 */
static void saveToFile(string &filename, string &content) {
  if (fileExists(filename)) {
    unlink(filename.c_str());
  }
  ofstream fp;
  fp.open(filename);
  fp << content;
  fp.close();
}
<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2007-2008, 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 Image Engine Design 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 "IECore/SimpleTypedData.h"
#include "IECore/TypedData.inl"

#include <iostream>

namespace IECore
{

LongDataAlias::TypeDescription<IntData> LongDataAlias::m_typeDescription( LongDataTypeId, "LongData" );

#define IE_CORE_DEFINEBASETYPEDDATASPECIALISATION( TNAME, TID )			\
	IE_CORE_DEFINECOMMONTYPEDDATASPECIALISATION( TNAME, TID )			\

#define IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( TNAME, TID, N )		\
	IE_CORE_DEFINECOMMONTYPEDDATASPECIALISATION( TNAME, TID )			\
	IE_CORE_DEFINEBASETYPEDDATAIOSPECIALISATION( TNAME, N )				\

IE_CORE_DEFINEBASETYPEDDATASPECIALISATION( BoolData, BoolDataTypeId )
IE_CORE_DEFINEBASETYPEDDATASPECIALISATION( FloatData, FloatDataTypeId )
IE_CORE_DEFINEBASETYPEDDATASPECIALISATION( DoubleData, DoubleDataTypeId )
IE_CORE_DEFINEBASETYPEDDATASPECIALISATION( IntData, IntDataTypeId )
IE_CORE_DEFINEBASETYPEDDATASPECIALISATION( UIntData, UIntDataTypeId )
IE_CORE_DEFINEBASETYPEDDATASPECIALISATION( CharData, CharDataTypeId )
IE_CORE_DEFINEBASETYPEDDATASPECIALISATION( UCharData, UCharDataTypeId )
IE_CORE_DEFINEBASETYPEDDATASPECIALISATION( HalfData, HalfDataTypeId )
IE_CORE_DEFINEBASETYPEDDATASPECIALISATION( ShortData, ShortDataTypeId )
IE_CORE_DEFINEBASETYPEDDATASPECIALISATION( UShortData, UShortDataTypeId )
IE_CORE_DEFINEBASETYPEDDATASPECIALISATION( Int64Data, Int64DataTypeId )
IE_CORE_DEFINEBASETYPEDDATASPECIALISATION( UInt64Data, UInt64DataTypeId )

IE_CORE_DEFINECOMMONTYPEDDATASPECIALISATION( StringData, StringDataTypeId )
IE_CORE_DEFINETYPEDDATANOBASESIZE( StringData )

IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( V2iData, V2iDataTypeId, 2 )
IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( V3iData, V3iDataTypeId, 3 )
IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( V2fData, V2fDataTypeId, 2 )
IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( V3fData, V3fDataTypeId, 3 )
IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( V2dData, V2dDataTypeId, 2 )
IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( V3dData, V3dDataTypeId, 3 )
IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( Color3fData, Color3fDataTypeId, 3 )
IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( Color4fData, Color4fDataTypeId, 4 )
IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( Color3dData, Color3dDataTypeId, 3 )
IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( Color4dData, Color4dDataTypeId, 4 )
IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( Box2iData, Box2iDataTypeId, 4 )
IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( Box3iData, Box3iDataTypeId, 6 )
IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( Box2fData, Box2fDataTypeId, 4 )
IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( Box3fData, Box3fDataTypeId, 6 )
IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( Box2dData, Box2dDataTypeId, 4 )
IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( Box3dData, Box3dDataTypeId, 6 )
IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( M33fData, M33fDataTypeId, 9 )
IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( M33dData, M33dDataTypeId, 9 )
IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( M44fData, M44fDataTypeId, 16 )
IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( M44dData, M44dDataTypeId, 16 )
IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( QuatfData, QuatfDataTypeId, 4 )
IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( QuatdData, QuatdDataTypeId, 4 )

template<>
void StringData::memoryUsage( Object::MemoryAccumulator &accumulator ) const
{
	Data::memoryUsage( accumulator );
	accumulator.accumulate( &readable(), readable().capacity() );
}

template<>
void TypedData<bool>::save( SaveContext *context ) const
{
	Data::save( context );
	IndexedIOInterfacePtr container = context->rawContainer();
	unsigned char c = readable();
	container->write( "value", c );
}

template<>
void TypedData<bool>::load( LoadContextPtr context )
{
	Data::load( context );
	unsigned char c;
	try
	{
		// optimised format for new files
		IndexedIOInterfacePtr container = context->rawContainer();
		container->read( "value", c );
	}
	catch( ... )
	{
		// backwards compatibility with old files
		unsigned int v = 0;
		IndexedIOInterfacePtr container = context->container( staticTypeName(), v );
		container->read( "value", c );
	}

	writable() = c;
}

template<>
void TypedData<short>::save( SaveContext *context ) const
{
	Data::save( context );
	IndexedIOInterfacePtr container = context->rawContainer();
	int c = readable();
	container->write( "value", c );
}

template<>
void TypedData<short>::load( LoadContextPtr context )
{
	Data::load( context );
	int c;
	try
	{
		// optimised format for new files
		IndexedIOInterfacePtr container = context->rawContainer();
		container->read( "value", c );
	}
	catch( ... )
	{
		// backwards compatibility with old files
		unsigned int v = 0;
		IndexedIOInterfacePtr container = context->container( staticTypeName(), v );
		container->read( "value", c );
	}

	writable() = static_cast<short>( c );
}

template<>
void TypedData<unsigned short>::save( SaveContext *context ) const
{
	Data::save( context );
	IndexedIOInterfacePtr container = context->rawContainer();
	unsigned int c = readable();
	container->write( "value", c );
}

template<>
void TypedData<unsigned short>::load( LoadContextPtr context )
{
	Data::load( context );
	unsigned int c;
	try
	{
		// optimised format for new files
		IndexedIOInterfacePtr container = context->rawContainer();
		container->read( "value", c );
	}
	catch( ... )
	{
		// backwards compatibility with old files
		unsigned int v = 0;
		IndexedIOInterfacePtr container = context->container( staticTypeName(), v );
		container->read( "value", c );
	}

	writable() = static_cast<unsigned short>( c );
}

template class TypedData<bool>;
template class TypedData<float>;
template class TypedData<double>;
template class TypedData<int>;
template class TypedData<unsigned int>;
template class TypedData<char>;
template class TypedData<unsigned char>;
template class TypedData<short>;
template class TypedData<unsigned short>;
template class TypedData<int64_t>;
template class TypedData<uint64_t>;
template class TypedData<std::string>;
template class TypedData<half>;
template class TypedData<Imath::V2i>;
template class TypedData<Imath::V3i>;
template class TypedData<Imath::V2f>;
template class TypedData<Imath::V3f>;
template class TypedData<Imath::V2d>;
template class TypedData<Imath::V3d>;
template class TypedData<Imath::Color3f>;
template class TypedData<Imath::Color4f>;
template class TypedData<Imath::Color3<double> >;
template class TypedData<Imath::Color4<double> >;
template class TypedData<Imath::Box2i>;
template class TypedData<Imath::Box3i>;
template class TypedData<Imath::Box2f>;
template class TypedData<Imath::Box3f>;
template class TypedData<Imath::Box2d>;
template class TypedData<Imath::Box3d>;
template class TypedData<Imath::M33f>;
template class TypedData<Imath::M33d>;
template class TypedData<Imath::M44f>;
template class TypedData<Imath::M44d>;
template class TypedData<Imath::Quatf>;
template class TypedData<Imath::Quatd>;

} // namespace IECore
<commit_msg>Added todo relating to SimpleTypedData True/False tests<commit_after>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2007-2008, 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 Image Engine Design 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.
//
//////////////////////////////////////////////////////////////////////////

/// \todo Simple types should handle True/False tests based on their content. Ex.: IntData(0) should be False, IntData(3) should be True. Types like IntVectorData already handle such tests that way (IntVectorData([]) is False and other values are True).

#include "IECore/SimpleTypedData.h"
#include "IECore/TypedData.inl"

#include <iostream>

namespace IECore
{

LongDataAlias::TypeDescription<IntData> LongDataAlias::m_typeDescription( LongDataTypeId, "LongData" );

#define IE_CORE_DEFINEBASETYPEDDATASPECIALISATION( TNAME, TID )			\
	IE_CORE_DEFINECOMMONTYPEDDATASPECIALISATION( TNAME, TID )			\

#define IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( TNAME, TID, N )		\
	IE_CORE_DEFINECOMMONTYPEDDATASPECIALISATION( TNAME, TID )			\
	IE_CORE_DEFINEBASETYPEDDATAIOSPECIALISATION( TNAME, N )				\

IE_CORE_DEFINEBASETYPEDDATASPECIALISATION( BoolData, BoolDataTypeId )
IE_CORE_DEFINEBASETYPEDDATASPECIALISATION( FloatData, FloatDataTypeId )
IE_CORE_DEFINEBASETYPEDDATASPECIALISATION( DoubleData, DoubleDataTypeId )
IE_CORE_DEFINEBASETYPEDDATASPECIALISATION( IntData, IntDataTypeId )
IE_CORE_DEFINEBASETYPEDDATASPECIALISATION( UIntData, UIntDataTypeId )
IE_CORE_DEFINEBASETYPEDDATASPECIALISATION( CharData, CharDataTypeId )
IE_CORE_DEFINEBASETYPEDDATASPECIALISATION( UCharData, UCharDataTypeId )
IE_CORE_DEFINEBASETYPEDDATASPECIALISATION( HalfData, HalfDataTypeId )
IE_CORE_DEFINEBASETYPEDDATASPECIALISATION( ShortData, ShortDataTypeId )
IE_CORE_DEFINEBASETYPEDDATASPECIALISATION( UShortData, UShortDataTypeId )
IE_CORE_DEFINEBASETYPEDDATASPECIALISATION( Int64Data, Int64DataTypeId )
IE_CORE_DEFINEBASETYPEDDATASPECIALISATION( UInt64Data, UInt64DataTypeId )

IE_CORE_DEFINECOMMONTYPEDDATASPECIALISATION( StringData, StringDataTypeId )
IE_CORE_DEFINETYPEDDATANOBASESIZE( StringData )

IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( V2iData, V2iDataTypeId, 2 )
IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( V3iData, V3iDataTypeId, 3 )
IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( V2fData, V2fDataTypeId, 2 )
IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( V3fData, V3fDataTypeId, 3 )
IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( V2dData, V2dDataTypeId, 2 )
IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( V3dData, V3dDataTypeId, 3 )
IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( Color3fData, Color3fDataTypeId, 3 )
IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( Color4fData, Color4fDataTypeId, 4 )
IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( Color3dData, Color3dDataTypeId, 3 )
IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( Color4dData, Color4dDataTypeId, 4 )
IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( Box2iData, Box2iDataTypeId, 4 )
IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( Box3iData, Box3iDataTypeId, 6 )
IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( Box2fData, Box2fDataTypeId, 4 )
IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( Box3fData, Box3fDataTypeId, 6 )
IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( Box2dData, Box2dDataTypeId, 4 )
IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( Box3dData, Box3dDataTypeId, 6 )
IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( M33fData, M33fDataTypeId, 9 )
IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( M33dData, M33dDataTypeId, 9 )
IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( M44fData, M44fDataTypeId, 16 )
IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( M44dData, M44dDataTypeId, 16 )
IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( QuatfData, QuatfDataTypeId, 4 )
IE_CORE_DEFINEIMATHTYPEDDATASPECIALISATION( QuatdData, QuatdDataTypeId, 4 )

template<>
void StringData::memoryUsage( Object::MemoryAccumulator &accumulator ) const
{
	Data::memoryUsage( accumulator );
	accumulator.accumulate( &readable(), readable().capacity() );
}

template<>
void TypedData<bool>::save( SaveContext *context ) const
{
	Data::save( context );
	IndexedIOInterfacePtr container = context->rawContainer();
	unsigned char c = readable();
	container->write( "value", c );
}

template<>
void TypedData<bool>::load( LoadContextPtr context )
{
	Data::load( context );
	unsigned char c;
	try
	{
		// optimised format for new files
		IndexedIOInterfacePtr container = context->rawContainer();
		container->read( "value", c );
	}
	catch( ... )
	{
		// backwards compatibility with old files
		unsigned int v = 0;
		IndexedIOInterfacePtr container = context->container( staticTypeName(), v );
		container->read( "value", c );
	}

	writable() = c;
}

template<>
void TypedData<short>::save( SaveContext *context ) const
{
	Data::save( context );
	IndexedIOInterfacePtr container = context->rawContainer();
	int c = readable();
	container->write( "value", c );
}

template<>
void TypedData<short>::load( LoadContextPtr context )
{
	Data::load( context );
	int c;
	try
	{
		// optimised format for new files
		IndexedIOInterfacePtr container = context->rawContainer();
		container->read( "value", c );
	}
	catch( ... )
	{
		// backwards compatibility with old files
		unsigned int v = 0;
		IndexedIOInterfacePtr container = context->container( staticTypeName(), v );
		container->read( "value", c );
	}

	writable() = static_cast<short>( c );
}

template<>
void TypedData<unsigned short>::save( SaveContext *context ) const
{
	Data::save( context );
	IndexedIOInterfacePtr container = context->rawContainer();
	unsigned int c = readable();
	container->write( "value", c );
}

template<>
void TypedData<unsigned short>::load( LoadContextPtr context )
{
	Data::load( context );
	unsigned int c;
	try
	{
		// optimised format for new files
		IndexedIOInterfacePtr container = context->rawContainer();
		container->read( "value", c );
	}
	catch( ... )
	{
		// backwards compatibility with old files
		unsigned int v = 0;
		IndexedIOInterfacePtr container = context->container( staticTypeName(), v );
		container->read( "value", c );
	}

	writable() = static_cast<unsigned short>( c );
}

template class TypedData<bool>;
template class TypedData<float>;
template class TypedData<double>;
template class TypedData<int>;
template class TypedData<unsigned int>;
template class TypedData<char>;
template class TypedData<unsigned char>;
template class TypedData<short>;
template class TypedData<unsigned short>;
template class TypedData<int64_t>;
template class TypedData<uint64_t>;
template class TypedData<std::string>;
template class TypedData<half>;
template class TypedData<Imath::V2i>;
template class TypedData<Imath::V3i>;
template class TypedData<Imath::V2f>;
template class TypedData<Imath::V3f>;
template class TypedData<Imath::V2d>;
template class TypedData<Imath::V3d>;
template class TypedData<Imath::Color3f>;
template class TypedData<Imath::Color4f>;
template class TypedData<Imath::Color3<double> >;
template class TypedData<Imath::Color4<double> >;
template class TypedData<Imath::Box2i>;
template class TypedData<Imath::Box3i>;
template class TypedData<Imath::Box2f>;
template class TypedData<Imath::Box3f>;
template class TypedData<Imath::Box2d>;
template class TypedData<Imath::Box3d>;
template class TypedData<Imath::M33f>;
template class TypedData<Imath::M33d>;
template class TypedData<Imath::M44f>;
template class TypedData<Imath::M44d>;
template class TypedData<Imath::Quatf>;
template class TypedData<Imath::Quatd>;

} // namespace IECore
<|endoftext|>


<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. 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.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
 * ITS 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
#if !defined(AIXDEFINITIONS_HEADER_GUARD_1357924680)
#define AIXDEFINITIONS_HEADER_GUARD_1357924680

// ---------------------------------------------------------------------------
//  A define in the build for each project is also used to control whether
//  the export keyword is from the project's viewpoint or the client's.
//  These defines provide the platform specific keywords that they need
//  to do this.
// ---------------------------------------------------------------------------

#define XALAN_PLATFORM_EXPORT
#define XALAN_PLATFORM_IMPORT
#define XALAN_PLATFORM_EXPORT_FUNCTION(T) T XALAN_PLATFORM_EXPORT
#define XALAN_PLATFORM_IMPORT_FUNCTION(T) T XALAN_PLATFORM_IMPORT

#define XALAN_OLD_STYLE_CASTS
#define XALAN_NO_NAMESPACES
#define XALAN_NO_MUTABLE
#define XALAN_SGI_BASED_STL
#define XALAN_NO_MEMBER_TEMPLATES
#define XALAN_AMBIGUOUS_EVEN_IF_NOT_CALLED
#define XALAN_CANNOT_DELETE_CONST
#define XALAN_BOOL_AS_INT
#define XALAN_NO_STD_ALLOCATORS
#define XALAN_NO_SELECTIVE_TEMPLATE_INSTANTIATION
#define XALAN_NO_ALGORITHMS_WITH_BUILTINS
#define XALAN_NO_DEFAULT_TEMPLATE_ARGUMENTS
#define XALAN_NO_COVARIANT_RETURN_TYPE
#define XALAN_LSTRSUPPORT
#define XALAN_AUTO_PTR_REQUIRES_DEFINITION
#define XALAN_NEEDS_EXPLICIT_TEMPLATE_INSTANTIATION
#define XALAN_XALANDOMCHAR_USHORT_MISMATCH
#define XALAN_BIG_ENDIAN
#define XALAN_STLPORT_STL
#define XALAN_TEMPLATE_FUNCTION_NO_DEFAULT_PARAMETERS
#define XALAN_USE_WCHAR_CAST_HACK
#define XALAN_POSIX2_AVAILABLE

#define XALAN_UNALIGNED

// STL Port Definitions
#define __STL_NO_SGI_IOSTREAMS
#include <stl/_config.h>

#endif	// AIXDEFINITIONS_HEADER_GUARD_1357924680
<commit_msg>iostream header cleanup.<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. 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.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
 * ITS 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
#if !defined(AIXDEFINITIONS_HEADER_GUARD_1357924680)
#define AIXDEFINITIONS_HEADER_GUARD_1357924680

// ---------------------------------------------------------------------------
//  A define in the build for each project is also used to control whether
//  the export keyword is from the project's viewpoint or the client's.
//  These defines provide the platform specific keywords that they need
//  to do this.
// ---------------------------------------------------------------------------

#define XALAN_PLATFORM_EXPORT
#define XALAN_PLATFORM_IMPORT
#define XALAN_PLATFORM_EXPORT_FUNCTION(T) T XALAN_PLATFORM_EXPORT
#define XALAN_PLATFORM_IMPORT_FUNCTION(T) T XALAN_PLATFORM_IMPORT

#define XALAN_OLD_STYLE_CASTS
#define XALAN_OLD_STREAMS
#define XALAN_NO_NAMESPACES
#define XALAN_NO_MUTABLE
#define XALAN_SGI_BASED_STL
#define XALAN_NO_MEMBER_TEMPLATES
#define XALAN_AMBIGUOUS_EVEN_IF_NOT_CALLED
#define XALAN_CANNOT_DELETE_CONST
#define XALAN_BOOL_AS_INT
#define XALAN_NO_STD_ALLOCATORS
#define XALAN_NO_SELECTIVE_TEMPLATE_INSTANTIATION
#define XALAN_NO_ALGORITHMS_WITH_BUILTINS
#define XALAN_NO_DEFAULT_TEMPLATE_ARGUMENTS
#define XALAN_NO_COVARIANT_RETURN_TYPE
#define XALAN_LSTRSUPPORT
#define XALAN_AUTO_PTR_REQUIRES_DEFINITION
#define XALAN_NEEDS_EXPLICIT_TEMPLATE_INSTANTIATION
#define XALAN_XALANDOMCHAR_USHORT_MISMATCH
#define XALAN_BIG_ENDIAN
#define XALAN_STLPORT_STL
#define XALAN_TEMPLATE_FUNCTION_NO_DEFAULT_PARAMETERS
#define XALAN_USE_WCHAR_CAST_HACK
#define XALAN_POSIX2_AVAILABLE

#define XALAN_UNALIGNED

// STL Port Definitions
#define __STL_NO_SGI_IOSTREAMS
#include <stl/_config.h>

#endif	// AIXDEFINITIONS_HEADER_GUARD_1357924680
<|endoftext|>


<commit_before>//===--- CodeGenFunction.cpp - Emit LLVM Code from ASTs for a Function ----===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This coordinates the per-function state used while generating code.
//
//===----------------------------------------------------------------------===//

#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/AST/AST.h"
#include "llvm/CallingConv.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/ParamAttrsList.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Support/CFG.h"
using namespace clang;
using namespace CodeGen;

CodeGenFunction::CodeGenFunction(CodeGenModule &cgm)
  : CGM(cgm), Target(CGM.getContext().Target), SwitchInsn(NULL),
    CaseRangeBlock(NULL) {}

ASTContext &CodeGenFunction::getContext() const {
  return CGM.getContext();
}

llvm::BasicBlock *CodeGenFunction::getBasicBlockForLabel(const LabelStmt *S) {
  llvm::BasicBlock *&BB = LabelMap[S];
  if (BB) return BB;

  // Create, but don't insert, the new block.
  return BB = new llvm::BasicBlock(S->getName());
}

llvm::Constant *
CodeGenFunction::GetAddrOfStaticLocalVar(const BlockVarDecl *BVD) {
  return cast<llvm::Constant>(LocalDeclMap[BVD]);
}

const llvm::Type *CodeGenFunction::ConvertType(QualType T) {
  return CGM.getTypes().ConvertType(T);
}

bool CodeGenFunction::hasAggregateLLVMType(QualType T) {
  return !T->isRealType() && !T->isPointerType() && !T->isReferenceType() &&
         !T->isVoidType() && !T->isVectorType() && !T->isFunctionType();
}

void CodeGenFunction::GenerateCode(const FunctionDecl *FD) {
  LLVMIntTy = ConvertType(getContext().IntTy);
  LLVMPointerWidth = static_cast<unsigned>(
    getContext().getTypeSize(getContext().getPointerType(getContext().VoidTy)));

  CurFuncDecl = FD;
  CurFn = cast<llvm::Function>(CGM.GetAddrOfFunctionDecl(FD, true));
  assert(CurFn->isDeclaration() && "Function already has body?");

  // TODO: Set up linkage and many other things.  Note, this is a simple
  // approximation of what we really want.
  if (FD->getAttr<DLLImportAttr>())
    CurFn->setLinkage(llvm::Function::DLLImportLinkage);
  else if (FD->getAttr<DLLExportAttr>())
    CurFn->setLinkage(llvm::Function::DLLExportLinkage);
  else if (FD->getAttr<WeakAttr>() || FD->isInline())
    CurFn->setLinkage(llvm::Function::WeakLinkage);
  else if (FD->getStorageClass() == FunctionDecl::Static)
    CurFn->setLinkage(llvm::Function::InternalLinkage);

  if (FD->getAttr<FastCallAttr>())
    CurFn->setCallingConv(llvm::CallingConv::Fast);

  if (const VisibilityAttr *attr = FD->getAttr<VisibilityAttr>())
    CurFn->setVisibility(attr->getVisibility());
  // FIXME: else handle -fvisibility

  unsigned FuncAttrs = 0;
  if (FD->getAttr<NoThrowAttr>())
    FuncAttrs |= llvm::ParamAttr::NoUnwind;
  if (FD->getAttr<NoReturnAttr>())
    FuncAttrs |= llvm::ParamAttr::NoReturn;

  if (FuncAttrs) {
    llvm::ParamAttrsVector ParamAttrsVec;
    ParamAttrsVec.push_back(llvm::ParamAttrsWithIndex::get(0, FuncAttrs));
    CurFn->setParamAttrs(llvm::ParamAttrsList::get(ParamAttrsVec));
  }

  llvm::BasicBlock *EntryBB = new llvm::BasicBlock("entry", CurFn);

  // Create a marker to make it easy to insert allocas into the entryblock
  // later.  Don't create this with the builder, because we don't want it
  // folded.
  llvm::Value *Undef = llvm::UndefValue::get(llvm::Type::Int32Ty);
  AllocaInsertPt = new llvm::BitCastInst(Undef, llvm::Type::Int32Ty, "allocapt",
                                         EntryBB);

  Builder.SetInsertPoint(EntryBB);

  // Emit allocs for param decls.  Give the LLVM Argument nodes names.
  llvm::Function::arg_iterator AI = CurFn->arg_begin();

  // Name the struct return argument.
  if (hasAggregateLLVMType(FD->getResultType())) {
    AI->setName("agg.result");
    ++AI;
  }

  for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i, ++AI) {
    assert(AI != CurFn->arg_end() && "Argument mismatch!");
    EmitParmDecl(*FD->getParamDecl(i), AI);
  }

  // Emit the function body.
  EmitStmt(FD->getBody());

  // Emit a return for code that falls off the end. If insert point
  // is a dummy block with no predecessors then remove the block itself.
  llvm::BasicBlock *BB = Builder.GetInsertBlock();
  if (isDummyBlock(BB))
    BB->eraseFromParent();
  else {
    // FIXME: if this is C++ main, this should return 0.
    if (CurFn->getReturnType() == llvm::Type::VoidTy)
      Builder.CreateRetVoid();
    else
      Builder.CreateRet(llvm::UndefValue::get(CurFn->getReturnType()));
  }
  assert(BreakContinueStack.empty() &&
         "mismatched push/pop in break/continue stack!");

  // Remove the AllocaInsertPt instruction, which is just a convenience for us.
  AllocaInsertPt->eraseFromParent();
  AllocaInsertPt = 0;

  // Verify that the function is well formed.
  assert(!verifyFunction(*CurFn));
}

/// isDummyBlock - Return true if BB is an empty basic block
/// with no predecessors.
bool CodeGenFunction::isDummyBlock(const llvm::BasicBlock *BB) {
  if (BB->empty() && pred_begin(BB) == pred_end(BB))
    return true;
  return false;
}

/// StartBlock - Start new block named N. If insert block is a dummy block
/// then reuse it.
void CodeGenFunction::StartBlock(const char *N) {
  llvm::BasicBlock *BB = Builder.GetInsertBlock();
  if (!isDummyBlock(BB))
    EmitBlock(new llvm::BasicBlock(N));
  else
    BB->setName(N);
}

/// getCGRecordLayout - Return record layout info.
const CGRecordLayout *CodeGenFunction::getCGRecordLayout(CodeGenTypes &CGT,
                                                         QualType Ty) {
  const RecordType *RTy = Ty->getAsRecordType();
  assert (RTy && "Unexpected type. RecordType expected here.");

  return CGT.getCGRecordLayout(RTy->getDecl());
}

/// WarnUnsupported - Print out a warning that codegen doesn't support the
/// specified stmt yet.
void CodeGenFunction::WarnUnsupported(const Stmt *S, const char *Type) {
  CGM.WarnUnsupported(S, Type);
}

<commit_msg>Update to reflect changes in parameter attribute api.<commit_after>//===--- CodeGenFunction.cpp - Emit LLVM Code from ASTs for a Function ----===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This coordinates the per-function state used while generating code.
//
//===----------------------------------------------------------------------===//

#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/AST/AST.h"
#include "llvm/CallingConv.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Support/CFG.h"
using namespace clang;
using namespace CodeGen;

CodeGenFunction::CodeGenFunction(CodeGenModule &cgm)
  : CGM(cgm), Target(CGM.getContext().Target), SwitchInsn(NULL),
    CaseRangeBlock(NULL) {}

ASTContext &CodeGenFunction::getContext() const {
  return CGM.getContext();
}

llvm::BasicBlock *CodeGenFunction::getBasicBlockForLabel(const LabelStmt *S) {
  llvm::BasicBlock *&BB = LabelMap[S];
  if (BB) return BB;

  // Create, but don't insert, the new block.
  return BB = new llvm::BasicBlock(S->getName());
}

llvm::Constant *
CodeGenFunction::GetAddrOfStaticLocalVar(const BlockVarDecl *BVD) {
  return cast<llvm::Constant>(LocalDeclMap[BVD]);
}

const llvm::Type *CodeGenFunction::ConvertType(QualType T) {
  return CGM.getTypes().ConvertType(T);
}

bool CodeGenFunction::hasAggregateLLVMType(QualType T) {
  return !T->isRealType() && !T->isPointerType() && !T->isReferenceType() &&
         !T->isVoidType() && !T->isVectorType() && !T->isFunctionType();
}

void CodeGenFunction::GenerateCode(const FunctionDecl *FD) {
  LLVMIntTy = ConvertType(getContext().IntTy);
  LLVMPointerWidth = static_cast<unsigned>(
    getContext().getTypeSize(getContext().getPointerType(getContext().VoidTy)));

  CurFuncDecl = FD;
  CurFn = cast<llvm::Function>(CGM.GetAddrOfFunctionDecl(FD, true));
  assert(CurFn->isDeclaration() && "Function already has body?");

  // TODO: Set up linkage and many other things.  Note, this is a simple
  // approximation of what we really want.
  if (FD->getAttr<DLLImportAttr>())
    CurFn->setLinkage(llvm::Function::DLLImportLinkage);
  else if (FD->getAttr<DLLExportAttr>())
    CurFn->setLinkage(llvm::Function::DLLExportLinkage);
  else if (FD->getAttr<WeakAttr>() || FD->isInline())
    CurFn->setLinkage(llvm::Function::WeakLinkage);
  else if (FD->getStorageClass() == FunctionDecl::Static)
    CurFn->setLinkage(llvm::Function::InternalLinkage);

  if (FD->getAttr<FastCallAttr>())
    CurFn->setCallingConv(llvm::CallingConv::Fast);

  if (const VisibilityAttr *attr = FD->getAttr<VisibilityAttr>())
    CurFn->setVisibility(attr->getVisibility());
  // FIXME: else handle -fvisibility

  unsigned FuncAttrs = 0;
  if (FD->getAttr<NoThrowAttr>())
    FuncAttrs |= llvm::ParamAttr::NoUnwind;
  if (FD->getAttr<NoReturnAttr>())
    FuncAttrs |= llvm::ParamAttr::NoReturn;

  if (FuncAttrs) {
    llvm::ParamAttrsWithIndex PAWI =
      llvm::ParamAttrsWithIndex::get(0, FuncAttrs);
    CurFn->setParamAttrs(llvm::PAListPtr::get(&PAWI, 1));
  }

  llvm::BasicBlock *EntryBB = new llvm::BasicBlock("entry", CurFn);

  // Create a marker to make it easy to insert allocas into the entryblock
  // later.  Don't create this with the builder, because we don't want it
  // folded.
  llvm::Value *Undef = llvm::UndefValue::get(llvm::Type::Int32Ty);
  AllocaInsertPt = new llvm::BitCastInst(Undef, llvm::Type::Int32Ty, "allocapt",
                                         EntryBB);

  Builder.SetInsertPoint(EntryBB);

  // Emit allocs for param decls.  Give the LLVM Argument nodes names.
  llvm::Function::arg_iterator AI = CurFn->arg_begin();

  // Name the struct return argument.
  if (hasAggregateLLVMType(FD->getResultType())) {
    AI->setName("agg.result");
    ++AI;
  }

  for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i, ++AI) {
    assert(AI != CurFn->arg_end() && "Argument mismatch!");
    EmitParmDecl(*FD->getParamDecl(i), AI);
  }

  // Emit the function body.
  EmitStmt(FD->getBody());

  // Emit a return for code that falls off the end. If insert point
  // is a dummy block with no predecessors then remove the block itself.
  llvm::BasicBlock *BB = Builder.GetInsertBlock();
  if (isDummyBlock(BB))
    BB->eraseFromParent();
  else {
    // FIXME: if this is C++ main, this should return 0.
    if (CurFn->getReturnType() == llvm::Type::VoidTy)
      Builder.CreateRetVoid();
    else
      Builder.CreateRet(llvm::UndefValue::get(CurFn->getReturnType()));
  }
  assert(BreakContinueStack.empty() &&
         "mismatched push/pop in break/continue stack!");

  // Remove the AllocaInsertPt instruction, which is just a convenience for us.
  AllocaInsertPt->eraseFromParent();
  AllocaInsertPt = 0;

  // Verify that the function is well formed.
  assert(!verifyFunction(*CurFn));
}

/// isDummyBlock - Return true if BB is an empty basic block
/// with no predecessors.
bool CodeGenFunction::isDummyBlock(const llvm::BasicBlock *BB) {
  if (BB->empty() && pred_begin(BB) == pred_end(BB))
    return true;
  return false;
}

/// StartBlock - Start new block named N. If insert block is a dummy block
/// then reuse it.
void CodeGenFunction::StartBlock(const char *N) {
  llvm::BasicBlock *BB = Builder.GetInsertBlock();
  if (!isDummyBlock(BB))
    EmitBlock(new llvm::BasicBlock(N));
  else
    BB->setName(N);
}

/// getCGRecordLayout - Return record layout info.
const CGRecordLayout *CodeGenFunction::getCGRecordLayout(CodeGenTypes &CGT,
                                                         QualType Ty) {
  const RecordType *RTy = Ty->getAsRecordType();
  assert (RTy && "Unexpected type. RecordType expected here.");

  return CGT.getCGRecordLayout(RTy->getDecl());
}

/// WarnUnsupported - Print out a warning that codegen doesn't support the
/// specified stmt yet.
void CodeGenFunction::WarnUnsupported(const Stmt *S, const char *Type) {
  CGM.WarnUnsupported(S, Type);
}

<|endoftext|>


<commit_before>#line 2 "togo/game/gfx/renderer/private.ipp"
/**
@copyright MIT license; see @ref index or the accompanying LICENSE file.
*/

#include <togo/game/config.hpp>
#include <togo/game/gfx/types.hpp>
#include <togo/game/gfx/generator.hpp>
#include <togo/game/gfx/renderer/types.hpp>
#include <togo/game/gfx/renderer/private.hpp>

namespace togo {
namespace game {
namespace gfx {

void renderer::init_base(gfx::Renderer* const renderer) {
	// Register standard generators
	gfx::renderer::register_generator_def(renderer, gfx::generator::clear);
}

#define TOGO_GFX_RENDERER_TEARDOWN_RA_(ra, func_destroy)		\
	if (renderer->ra._num > 0) {								\
		for (auto const& slot : renderer->ra._slots) {			\
			if (slot.id._value != ID_VALUE_NULL) {				\
				renderer::func_destroy(renderer, slot.id);		\
			}													\
		}														\
	}

void renderer::teardown_base(gfx::Renderer* const renderer) {
	TOGO_GFX_RENDERER_TEARDOWN_RA_(_buffers, destroy_buffer);
	TOGO_GFX_RENDERER_TEARDOWN_RA_(_buffer_bindings, destroy_buffer_binding);
	//TOGO_GFX_RENDERER_TEARDOWN_RA_(_textures, destroy_texture);
	//TOGO_GFX_RENDERER_TEARDOWN_RA_(_uniforms, destroy_uniform);
	TOGO_GFX_RENDERER_TEARDOWN_RA_(_shaders, destroy_shader);
	for (auto& pb_name_hash : renderer->_fixed_param_blocks) {
		pb_name_hash = gfx::PB_NAME_NULL;
	}
	renderer->_num_active_draw_param_blocks = 0;
	for (auto& entry : renderer->_generators) {
		if (entry.value.func_destroy) {
			entry.value.func_destroy(entry.value, renderer);
		}
	}
	hash_map::clear(renderer->_generators);
}

void renderer::configure_base(
	gfx::Renderer* const renderer,
	gfx::RenderConfig const& config
) {
	for (auto const& pipe : config.pipes) {
	for (auto const& layer : pipe.layers) {
	for (auto const& gen_unit : layer.layout) {
		TOGO_ASSERTF(
			renderer::find_generator_def(renderer, gen_unit.name_hash),
			"generator unit %08x is not registered",
			gen_unit.name_hash
		);
	}}}
	std::memcpy(&renderer->_config, &config, sizeof(gfx::RenderConfig));
}

} // namespace gfx
} // namespace game
} // namespace togo
<commit_msg>lib/game/gfx/renderer/private: tidy.<commit_after>#line 2 "togo/game/gfx/renderer/private.ipp"
/**
@copyright MIT license; see @ref index or the accompanying LICENSE file.
*/

#include <togo/game/config.hpp>
#include <togo/game/gfx/types.hpp>
#include <togo/game/gfx/generator.hpp>
#include <togo/game/gfx/renderer/types.hpp>
#include <togo/game/gfx/renderer/private.hpp>

namespace togo {
namespace game {
namespace gfx {

void renderer::init_base(gfx::Renderer* const renderer) {
	// Register standard generators
	gfx::renderer::register_generator_def(renderer, gfx::generator::clear);
}

#define TOGO_GFX_RENDERER_TEARDOWN_RA_(ra, func_destroy)		\
	if (renderer->ra._num > 0) {								\
		for (auto const& slot : renderer->ra._slots) {			\
			if (slot.id._value != ID_VALUE_NULL) {				\
				gfx::renderer::func_destroy(renderer, slot.id);	\
			}													\
		}														\
	}

void renderer::teardown_base(gfx::Renderer* const renderer) {
	TOGO_GFX_RENDERER_TEARDOWN_RA_(_buffers, destroy_buffer);
	TOGO_GFX_RENDERER_TEARDOWN_RA_(_buffer_bindings, destroy_buffer_binding);
	//TOGO_GFX_RENDERER_TEARDOWN_RA_(_textures, destroy_texture);
	//TOGO_GFX_RENDERER_TEARDOWN_RA_(_uniforms, destroy_uniform);
	TOGO_GFX_RENDERER_TEARDOWN_RA_(_shaders, destroy_shader);
	for (auto& pb_name_hash : renderer->_fixed_param_blocks) {
		pb_name_hash = gfx::PB_NAME_NULL;
	}
	renderer->_num_active_draw_param_blocks = 0;
	for (auto& entry : renderer->_generators) {
		if (entry.value.func_destroy) {
			entry.value.func_destroy(entry.value, renderer);
		}
	}
	hash_map::clear(renderer->_generators);
}

void renderer::configure_base(
	gfx::Renderer* const renderer,
	gfx::RenderConfig const& config
) {
	for (auto const& pipe : config.pipes) {
	for (auto const& layer : pipe.layers) {
	for (auto const& gen_unit : layer.layout) {
		TOGO_ASSERTF(
			gfx::renderer::find_generator_def(renderer, gen_unit.name_hash),
			"generator unit %08x is not registered",
			gen_unit.name_hash
		);
	}}}
	std::memcpy(&renderer->_config, &config, sizeof(gfx::RenderConfig));
}

} // namespace gfx
} // namespace game
} // namespace togo
<|endoftext|>


<commit_before>// Copyright (C) 2016 Elviss Strazdins
// This file is part of the Ouzel engine.

#define NOMINMAX
#include <windows.h>
#include "WindowWin.h"
#include "core/Engine.h"
#include "utils/Utils.h"

void ouzelMain(const std::vector<std::string>& args);

int WINAPI WinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nCmdShow)
{
    OUZEL_UNUSED(hInstance);
    OUZEL_UNUSED(hPrevInstance);
    OUZEL_UNUSED(lpCmdLine);
    OUZEL_UNUSED(nCmdShow);

    LPWSTR* argList;
    int nArgs;
    int i;

    argList = CommandLineToArgvW(GetCommandLineW(), &nArgs);

    std::vector<std::string> args;

    if (argList)
    {
        for (i = 0; i < nArgs; i++)
        {
            char temporaryCString[256];
            WideCharToMultiByte(CP_UTF8, 0, argList[i], -1, temporaryCString, sizeof(temporaryCString), nullptr, nullptr);

            args.push_back(temporaryCString);
        }

        LocalFree(argList);
    }

    ouzel::setArgs(args);
    ouzelMain(ouzel::getArgs());

    if (!ouzel::sharedEngine)
    {
        return 0;
    }

    std::shared_ptr<ouzel::WindowWin> window = std::static_pointer_cast<ouzel::WindowWin>(ouzel::sharedEngine->getWindow());
    ouzel::sharedEngine->begin();

    MSG msg;

    for (;;)
    {
        std::set<HACCEL> accelerators = window->getAccelerators();

        while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            bool translate = true;

            for (HACCEL accelerator : accelerators)
            {
                if (!TranslateAccelerator(window->getNativeWindow(), accelerator, &msg))
                {
                    translate = false;
                }
            }

            if (translate)
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
        }

        if (msg.message == WM_QUIT)
        {
            break;
        }

        if (!ouzel::sharedEngine->run())
        {
            break;
        }
    }

    ouzel::sharedEngine->end();

    return 0;
}
<commit_msg>Fix accelerator translation<commit_after>// Copyright (C) 2016 Elviss Strazdins
// This file is part of the Ouzel engine.

#define NOMINMAX
#include <windows.h>
#include "WindowWin.h"
#include "core/Engine.h"
#include "utils/Utils.h"

void ouzelMain(const std::vector<std::string>& args);

int WINAPI WinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nCmdShow)
{
    OUZEL_UNUSED(hInstance);
    OUZEL_UNUSED(hPrevInstance);
    OUZEL_UNUSED(lpCmdLine);
    OUZEL_UNUSED(nCmdShow);

    LPWSTR* argList;
    int nArgs;
    int i;

    argList = CommandLineToArgvW(GetCommandLineW(), &nArgs);

    std::vector<std::string> args;

    if (argList)
    {
        for (i = 0; i < nArgs; i++)
        {
            char temporaryCString[256];
            WideCharToMultiByte(CP_UTF8, 0, argList[i], -1, temporaryCString, sizeof(temporaryCString), nullptr, nullptr);

            args.push_back(temporaryCString);
        }

        LocalFree(argList);
    }

    ouzel::setArgs(args);
    ouzelMain(ouzel::getArgs());

    if (!ouzel::sharedEngine)
    {
        return 0;
    }

    std::shared_ptr<ouzel::WindowWin> window = std::static_pointer_cast<ouzel::WindowWin>(ouzel::sharedEngine->getWindow());
    ouzel::sharedEngine->begin();

    MSG msg;

    for (;;)
    {
        std::set<HACCEL> accelerators = window->getAccelerators();

        while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            bool translate = true;

            for (HACCEL accelerator : accelerators)
            {
                if (TranslateAccelerator(window->getNativeWindow(), accelerator, &msg))
                {
                    translate = false;
                }
            }

            if (translate)
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
        }

        if (msg.message == WM_QUIT)
        {
            break;
        }

        if (!ouzel::sharedEngine->run())
        {
            break;
        }
    }

    ouzel::sharedEngine->end();

    return 0;
}
<|endoftext|>


<commit_before>/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
#ident "$Id$"
#ident "Copyright (c) 2007-2012 Tokutek Inc.  All rights reserved."
#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."

#include <toku_stdint.h>

#include "ft.h"
#include "log-internal.h"
#include "rollback-ct-callbacks.h"

static void rollback_unpin_remove_callback(CACHEKEY* cachekey, bool for_checkpoint, void* extra) {
    FT CAST_FROM_VOIDP(h, extra);
    toku_free_blocknum(
        h->blocktable,
        cachekey,
        h,
        for_checkpoint
        );
}

void toku_rollback_log_unpin_and_remove(TOKUTXN txn, ROLLBACK_LOG_NODE log) {
    int r;
    CACHEFILE cf = txn->logger->rollback_cachefile;
    FT CAST_FROM_VOIDP(h, toku_cachefile_get_userdata(cf));
    r = toku_cachetable_unpin_and_remove (cf, log->ct_pair, rollback_unpin_remove_callback, h);
    assert(r == 0);
}

int
toku_find_xid_by_xid (const TXNID &xid, const TXNID &xidfind) {
    if (xid<xidfind) return -1;
    if (xid>xidfind) return +1;
    return 0;
}

void *toku_malloc_in_rollback(ROLLBACK_LOG_NODE log, size_t size) {
    return malloc_in_memarena(log->rollentry_arena, size);
}

void *toku_memdup_in_rollback(ROLLBACK_LOG_NODE log, const void *v, size_t len) {
    void *r=toku_malloc_in_rollback(log, len);
    memcpy(r,v,len);
    return r;
}

static inline PAIR_ATTR make_rollback_pair_attr(long size) {
    PAIR_ATTR result={
     .size = size,
     .nonleaf_size = 0,
     .leaf_size = 0,
     .rollback_size = size,
     .cache_pressure_size = 0,
     .is_valid = true
    };
    return result;
}

PAIR_ATTR
rollback_memory_size(ROLLBACK_LOG_NODE log) {
    size_t size = sizeof(*log);
    if (log->rollentry_arena) {
        size += memarena_total_memory_size(log->rollentry_arena);
    }
    return make_rollback_pair_attr(size);
}

static void toku_rollback_node_save_ct_pair(CACHEKEY UU(key), void *value_data, PAIR p) {
    ROLLBACK_LOG_NODE CAST_FROM_VOIDP(log, value_data);
    log->ct_pair = p;
}

//
// initializes an empty rollback log node
// Does not touch the blocknum or hash, that is the
// responsibility of the caller
//
void rollback_empty_log_init(ROLLBACK_LOG_NODE log) {
    // Having a txnid set to TXNID_NONE is how we determine if the
    // rollback log node is empty or in use.
    log->txnid = TXNID_NONE;

    log->layout_version                = FT_LAYOUT_VERSION;
    log->layout_version_original       = FT_LAYOUT_VERSION;
    log->layout_version_read_from_disk = FT_LAYOUT_VERSION;
    log->dirty = true;
    log->sequence = 0;
    log->previous = make_blocknum(0);
    log->previous_hash = 0;
    log->oldest_logentry = NULL;
    log->newest_logentry = NULL;
    log->rollentry_arena = NULL;
    log->rollentry_resident_bytecount = 0;
}

static void rollback_initialize_for_txn(
    ROLLBACK_LOG_NODE log,
    TOKUTXN txn,
    BLOCKNUM previous,
    uint32_t previous_hash
    )
{
    log->txnid = txn->txnid64;
    log->sequence = txn->roll_info.num_rollback_nodes++;
    log->previous = previous;
    log->previous_hash = previous_hash;
    log->oldest_logentry = NULL;
    log->newest_logentry = NULL;
    log->rollentry_arena = memarena_create();
    log->rollentry_resident_bytecount = 0;

}

void make_rollback_log_empty(ROLLBACK_LOG_NODE log) {
    memarena_close(&log->rollentry_arena);
    rollback_empty_log_init(log);
}

// create and pin a new rollback log node. chain it to the other rollback nodes
// by providing a previous blocknum/ hash and assigning the new rollback log
// node the next sequence number
static void rollback_log_create (
    TOKUTXN txn,
    BLOCKNUM previous,
    uint32_t previous_hash,
    ROLLBACK_LOG_NODE *result
    )
{
    ROLLBACK_LOG_NODE XMALLOC(log);
    rollback_empty_log_init(log);

    CACHEFILE cf = txn->logger->rollback_cachefile;
    FT CAST_FROM_VOIDP(ft, toku_cachefile_get_userdata(cf));
    rollback_initialize_for_txn(log, txn, previous, previous_hash);
    toku_allocate_blocknum(ft->blocktable, &log->blocknum, ft);
    log->hash = toku_cachetable_hash(ft->cf, log->blocknum);
    *result = log;
    toku_cachetable_put(cf, log->blocknum, log->hash,
                       log, rollback_memory_size(log),
                       get_write_callbacks_for_rollback_log(ft),
                       toku_rollback_node_save_ct_pair);
    txn->roll_info.current_rollback = log->blocknum;
    txn->roll_info.current_rollback_hash = log->hash;
}

void toku_rollback_log_unpin(TOKUTXN txn, ROLLBACK_LOG_NODE log) {
    int r;
    CACHEFILE cf = txn->logger->rollback_cachefile;
    r = toku_cachetable_unpin(
        cf,
        log->ct_pair,
        (enum cachetable_dirty)log->dirty,
        rollback_memory_size(log)
        );
    assert(r == 0);
}

//Requires: log is pinned
//          log is current
//After:
//  Maybe there is no current after (if it spilled)
void toku_maybe_spill_rollbacks(TOKUTXN txn, ROLLBACK_LOG_NODE log) {
    if (log->rollentry_resident_bytecount > txn->logger->write_block_size) {
        assert(log->blocknum.b == txn->roll_info.current_rollback.b);
        //spill
        if (!txn_has_spilled_rollback_logs(txn)) {
            //First spilled.  Copy to head.
            txn->roll_info.spilled_rollback_head      = txn->roll_info.current_rollback;
            txn->roll_info.spilled_rollback_head_hash = txn->roll_info.current_rollback_hash;
        }
        //Unconditionally copy to tail.  Old tail does not need to be cached anymore.
        txn->roll_info.spilled_rollback_tail      = txn->roll_info.current_rollback;
        txn->roll_info.spilled_rollback_tail_hash = txn->roll_info.current_rollback_hash;

        txn->roll_info.current_rollback      = ROLLBACK_NONE;
        txn->roll_info.current_rollback_hash = 0;
    }
}

int find_filenum (const FT &h, const FT &hfind);
int find_filenum (const FT &h, const FT &hfind) {
    FILENUM fnum     = toku_cachefile_filenum(h->cf);
    FILENUM fnumfind = toku_cachefile_filenum(hfind->cf);
    if (fnum.fileid<fnumfind.fileid) return -1;
    if (fnum.fileid>fnumfind.fileid) return +1;
    return 0;
}

//Notify a transaction that it has touched a brt.
void toku_txn_maybe_note_ft (TOKUTXN txn, FT ft) {
    toku_txn_lock(txn);
    FT ftv;
    uint32_t idx;
    int r = txn->open_fts.find_zero<FT, find_filenum>(ft, &ftv, &idx);
    if (r == 0) {
        // already there
        assert(ftv == ft);
        goto exit;
    }
    r = txn->open_fts.insert_at(ft, idx);
    assert_zero(r);
    // TODO(leif): if there's anything that locks the reflock and then
    // the txn lock, this may deadlock, because it grabs the reflock.
    toku_ft_add_txn_ref(ft);
exit:
    toku_txn_unlock(txn);
}

// Return the number of bytes that went into the rollback data structure (the uncompressed count if there is compression)
int toku_logger_txn_rollback_raw_count(TOKUTXN txn, uint64_t *raw_count)
{
    toku_txn_lock(txn);
    *raw_count = txn->roll_info.rollentry_raw_count;
    toku_txn_unlock(txn);
    return 0;
}

void toku_maybe_prefetch_previous_rollback_log(TOKUTXN txn, ROLLBACK_LOG_NODE log) {
    //Currently processing 'log'.  Prefetch the next (previous) log node.

    BLOCKNUM name = log->previous;
    int r = 0;
    if (name.b != ROLLBACK_NONE.b) {
        uint32_t hash = log->previous_hash;
        CACHEFILE cf = txn->logger->rollback_cachefile;
        FT CAST_FROM_VOIDP(h, toku_cachefile_get_userdata(cf));
        bool doing_prefetch = false;
        r = toku_cachefile_prefetch(cf, name, hash,
                                    get_write_callbacks_for_rollback_log(h),
                                    toku_rollback_fetch_callback,
                                    toku_rollback_pf_req_callback,
                                    toku_rollback_pf_callback,
                                    h,
                                    &doing_prefetch);
        assert(r == 0);
    }
}

void toku_rollback_verify_contents(ROLLBACK_LOG_NODE log,
        TXNID txnid, uint64_t sequence)
{
    assert(log->txnid == txnid);
    assert(log->sequence == sequence);
}

void toku_get_and_pin_rollback_log(TOKUTXN txn, BLOCKNUM blocknum, uint32_t hash, ROLLBACK_LOG_NODE *log) {
    void * value;
    CACHEFILE cf = txn->logger->rollback_cachefile;
    FT CAST_FROM_VOIDP(h, toku_cachefile_get_userdata(cf));
    int r = toku_cachetable_get_and_pin_with_dep_pairs(cf, blocknum, hash,
                                        &value, NULL,
                                        get_write_callbacks_for_rollback_log(h),
                                        toku_rollback_fetch_callback,
                                        toku_rollback_pf_req_callback,
                                        toku_rollback_pf_callback,
                                        PL_WRITE_CHEAP, // lock_type
                                        h,
                                        0, NULL, NULL
                                        );
    assert(r == 0);
    ROLLBACK_LOG_NODE CAST_FROM_VOIDP(pinned_log, value);
    assert(pinned_log->blocknum.b == blocknum.b);
    assert(pinned_log->hash == hash);
    *log = pinned_log;
}

void toku_get_and_pin_rollback_log_for_new_entry (TOKUTXN txn, ROLLBACK_LOG_NODE *log) {
    ROLLBACK_LOG_NODE pinned_log = NULL;
    invariant(txn->state == TOKUTXN_LIVE || txn->state == TOKUTXN_PREPARING); // hot indexing may call this function for prepared transactions
    if (txn_has_current_rollback_log(txn)) {
        toku_get_and_pin_rollback_log(txn, txn->roll_info.current_rollback, txn->roll_info.current_rollback_hash, &pinned_log);
        toku_rollback_verify_contents(pinned_log, txn->txnid64, txn->roll_info.num_rollback_nodes - 1);
    } else {
        // For each transaction, we try to acquire the first rollback log
        // from the rollback log node cache, so that we avoid
        // putting something new into the cachetable. However,
        // if transaction has spilled rollbacks, that means we
        // have already done a lot of work for this transaction,
        // and subsequent rollback log nodes are created
        // and put into the cachetable. The idea is for
        // transactions that don't do a lot of work to (hopefully)
        // get a rollback log node from a cache, as opposed to
        // taking the more expensive route of creating a new one.
        if (!txn_has_spilled_rollback_logs(txn)) {
            txn->logger->rollback_cache.get_rollback_log_node(txn, &pinned_log);
            if (pinned_log != NULL) {
                rollback_initialize_for_txn(
                    pinned_log,
                    txn,
                    txn->roll_info.spilled_rollback_tail,
                    txn->roll_info.spilled_rollback_tail_hash
                    );
                txn->roll_info.current_rollback = pinned_log->blocknum;
                txn->roll_info.current_rollback_hash = pinned_log->hash;
            }
        }
        if (pinned_log == NULL) {
            rollback_log_create(txn, txn->roll_info.spilled_rollback_tail, txn->roll_info.spilled_rollback_tail_hash, &pinned_log);
        }
    }
    assert(pinned_log->txnid == txn->txnid64);
    assert(pinned_log->blocknum.b != ROLLBACK_NONE.b);
    *log = pinned_log;
}
<commit_msg>closes #5685, dirty the rollback log node when we give it to a transaction after rollback_log_node_cache.get_rollback_log_node<commit_after>/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
#ident "$Id$"
#ident "Copyright (c) 2007-2012 Tokutek Inc.  All rights reserved."
#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."

#include <toku_stdint.h>

#include "ft.h"
#include "log-internal.h"
#include "rollback-ct-callbacks.h"

static void rollback_unpin_remove_callback(CACHEKEY* cachekey, bool for_checkpoint, void* extra) {
    FT CAST_FROM_VOIDP(h, extra);
    toku_free_blocknum(
        h->blocktable,
        cachekey,
        h,
        for_checkpoint
        );
}

void toku_rollback_log_unpin_and_remove(TOKUTXN txn, ROLLBACK_LOG_NODE log) {
    int r;
    CACHEFILE cf = txn->logger->rollback_cachefile;
    FT CAST_FROM_VOIDP(h, toku_cachefile_get_userdata(cf));
    r = toku_cachetable_unpin_and_remove (cf, log->ct_pair, rollback_unpin_remove_callback, h);
    assert(r == 0);
}

int
toku_find_xid_by_xid (const TXNID &xid, const TXNID &xidfind) {
    if (xid<xidfind) return -1;
    if (xid>xidfind) return +1;
    return 0;
}

void *toku_malloc_in_rollback(ROLLBACK_LOG_NODE log, size_t size) {
    return malloc_in_memarena(log->rollentry_arena, size);
}

void *toku_memdup_in_rollback(ROLLBACK_LOG_NODE log, const void *v, size_t len) {
    void *r=toku_malloc_in_rollback(log, len);
    memcpy(r,v,len);
    return r;
}

static inline PAIR_ATTR make_rollback_pair_attr(long size) {
    PAIR_ATTR result={
     .size = size,
     .nonleaf_size = 0,
     .leaf_size = 0,
     .rollback_size = size,
     .cache_pressure_size = 0,
     .is_valid = true
    };
    return result;
}

PAIR_ATTR
rollback_memory_size(ROLLBACK_LOG_NODE log) {
    size_t size = sizeof(*log);
    if (log->rollentry_arena) {
        size += memarena_total_memory_size(log->rollentry_arena);
    }
    return make_rollback_pair_attr(size);
}

static void toku_rollback_node_save_ct_pair(CACHEKEY UU(key), void *value_data, PAIR p) {
    ROLLBACK_LOG_NODE CAST_FROM_VOIDP(log, value_data);
    log->ct_pair = p;
}

//
// initializes an empty rollback log node
// Does not touch the blocknum or hash, that is the
// responsibility of the caller
//
void rollback_empty_log_init(ROLLBACK_LOG_NODE log) {
    // Having a txnid set to TXNID_NONE is how we determine if the
    // rollback log node is empty or in use.
    log->txnid = TXNID_NONE;

    log->layout_version                = FT_LAYOUT_VERSION;
    log->layout_version_original       = FT_LAYOUT_VERSION;
    log->layout_version_read_from_disk = FT_LAYOUT_VERSION;
    log->dirty = true;
    log->sequence = 0;
    log->previous = make_blocknum(0);
    log->previous_hash = 0;
    log->oldest_logentry = NULL;
    log->newest_logentry = NULL;
    log->rollentry_arena = NULL;
    log->rollentry_resident_bytecount = 0;
}

static void rollback_initialize_for_txn(
    ROLLBACK_LOG_NODE log,
    TOKUTXN txn,
    BLOCKNUM previous,
    uint32_t previous_hash
    )
{
    log->txnid = txn->txnid64;
    log->sequence = txn->roll_info.num_rollback_nodes++;
    log->previous = previous;
    log->previous_hash = previous_hash;
    log->oldest_logentry = NULL;
    log->newest_logentry = NULL;
    log->rollentry_arena = memarena_create();
    log->rollentry_resident_bytecount = 0;
    log->dirty = true;
}

void make_rollback_log_empty(ROLLBACK_LOG_NODE log) {
    memarena_close(&log->rollentry_arena);
    rollback_empty_log_init(log);
}

// create and pin a new rollback log node. chain it to the other rollback nodes
// by providing a previous blocknum/ hash and assigning the new rollback log
// node the next sequence number
static void rollback_log_create (
    TOKUTXN txn,
    BLOCKNUM previous,
    uint32_t previous_hash,
    ROLLBACK_LOG_NODE *result
    )
{
    ROLLBACK_LOG_NODE XMALLOC(log);
    rollback_empty_log_init(log);

    CACHEFILE cf = txn->logger->rollback_cachefile;
    FT CAST_FROM_VOIDP(ft, toku_cachefile_get_userdata(cf));
    rollback_initialize_for_txn(log, txn, previous, previous_hash);
    toku_allocate_blocknum(ft->blocktable, &log->blocknum, ft);
    log->hash = toku_cachetable_hash(ft->cf, log->blocknum);
    *result = log;
    toku_cachetable_put(cf, log->blocknum, log->hash,
                       log, rollback_memory_size(log),
                       get_write_callbacks_for_rollback_log(ft),
                       toku_rollback_node_save_ct_pair);
    txn->roll_info.current_rollback = log->blocknum;
    txn->roll_info.current_rollback_hash = log->hash;
}

void toku_rollback_log_unpin(TOKUTXN txn, ROLLBACK_LOG_NODE log) {
    int r;
    CACHEFILE cf = txn->logger->rollback_cachefile;
    r = toku_cachetable_unpin(
        cf,
        log->ct_pair,
        (enum cachetable_dirty)log->dirty,
        rollback_memory_size(log)
        );
    assert(r == 0);
}

//Requires: log is pinned
//          log is current
//After:
//  Maybe there is no current after (if it spilled)
void toku_maybe_spill_rollbacks(TOKUTXN txn, ROLLBACK_LOG_NODE log) {
    if (log->rollentry_resident_bytecount > txn->logger->write_block_size) {
        assert(log->blocknum.b == txn->roll_info.current_rollback.b);
        //spill
        if (!txn_has_spilled_rollback_logs(txn)) {
            //First spilled.  Copy to head.
            txn->roll_info.spilled_rollback_head      = txn->roll_info.current_rollback;
            txn->roll_info.spilled_rollback_head_hash = txn->roll_info.current_rollback_hash;
        }
        //Unconditionally copy to tail.  Old tail does not need to be cached anymore.
        txn->roll_info.spilled_rollback_tail      = txn->roll_info.current_rollback;
        txn->roll_info.spilled_rollback_tail_hash = txn->roll_info.current_rollback_hash;

        txn->roll_info.current_rollback      = ROLLBACK_NONE;
        txn->roll_info.current_rollback_hash = 0;
    }
}

int find_filenum (const FT &h, const FT &hfind);
int find_filenum (const FT &h, const FT &hfind) {
    FILENUM fnum     = toku_cachefile_filenum(h->cf);
    FILENUM fnumfind = toku_cachefile_filenum(hfind->cf);
    if (fnum.fileid<fnumfind.fileid) return -1;
    if (fnum.fileid>fnumfind.fileid) return +1;
    return 0;
}

//Notify a transaction that it has touched a brt.
void toku_txn_maybe_note_ft (TOKUTXN txn, FT ft) {
    toku_txn_lock(txn);
    FT ftv;
    uint32_t idx;
    int r = txn->open_fts.find_zero<FT, find_filenum>(ft, &ftv, &idx);
    if (r == 0) {
        // already there
        assert(ftv == ft);
        goto exit;
    }
    r = txn->open_fts.insert_at(ft, idx);
    assert_zero(r);
    // TODO(leif): if there's anything that locks the reflock and then
    // the txn lock, this may deadlock, because it grabs the reflock.
    toku_ft_add_txn_ref(ft);
exit:
    toku_txn_unlock(txn);
}

// Return the number of bytes that went into the rollback data structure (the uncompressed count if there is compression)
int toku_logger_txn_rollback_raw_count(TOKUTXN txn, uint64_t *raw_count)
{
    toku_txn_lock(txn);
    *raw_count = txn->roll_info.rollentry_raw_count;
    toku_txn_unlock(txn);
    return 0;
}

void toku_maybe_prefetch_previous_rollback_log(TOKUTXN txn, ROLLBACK_LOG_NODE log) {
    //Currently processing 'log'.  Prefetch the next (previous) log node.

    BLOCKNUM name = log->previous;
    int r = 0;
    if (name.b != ROLLBACK_NONE.b) {
        uint32_t hash = log->previous_hash;
        CACHEFILE cf = txn->logger->rollback_cachefile;
        FT CAST_FROM_VOIDP(h, toku_cachefile_get_userdata(cf));
        bool doing_prefetch = false;
        r = toku_cachefile_prefetch(cf, name, hash,
                                    get_write_callbacks_for_rollback_log(h),
                                    toku_rollback_fetch_callback,
                                    toku_rollback_pf_req_callback,
                                    toku_rollback_pf_callback,
                                    h,
                                    &doing_prefetch);
        assert(r == 0);
    }
}

void toku_rollback_verify_contents(ROLLBACK_LOG_NODE log,
        TXNID txnid, uint64_t sequence)
{
    assert(log->txnid == txnid);
    assert(log->sequence == sequence);
}

void toku_get_and_pin_rollback_log(TOKUTXN txn, BLOCKNUM blocknum, uint32_t hash, ROLLBACK_LOG_NODE *log) {
    void * value;
    CACHEFILE cf = txn->logger->rollback_cachefile;
    FT CAST_FROM_VOIDP(h, toku_cachefile_get_userdata(cf));
    int r = toku_cachetable_get_and_pin_with_dep_pairs(cf, blocknum, hash,
                                        &value, NULL,
                                        get_write_callbacks_for_rollback_log(h),
                                        toku_rollback_fetch_callback,
                                        toku_rollback_pf_req_callback,
                                        toku_rollback_pf_callback,
                                        PL_WRITE_CHEAP, // lock_type
                                        h,
                                        0, NULL, NULL
                                        );
    assert(r == 0);
    ROLLBACK_LOG_NODE CAST_FROM_VOIDP(pinned_log, value);
    assert(pinned_log->blocknum.b == blocknum.b);
    assert(pinned_log->hash == hash);
    *log = pinned_log;
}

void toku_get_and_pin_rollback_log_for_new_entry (TOKUTXN txn, ROLLBACK_LOG_NODE *log) {
    ROLLBACK_LOG_NODE pinned_log = NULL;
    invariant(txn->state == TOKUTXN_LIVE || txn->state == TOKUTXN_PREPARING); // hot indexing may call this function for prepared transactions
    if (txn_has_current_rollback_log(txn)) {
        toku_get_and_pin_rollback_log(txn, txn->roll_info.current_rollback, txn->roll_info.current_rollback_hash, &pinned_log);
        toku_rollback_verify_contents(pinned_log, txn->txnid64, txn->roll_info.num_rollback_nodes - 1);
    } else {
        // For each transaction, we try to acquire the first rollback log
        // from the rollback log node cache, so that we avoid
        // putting something new into the cachetable. However,
        // if transaction has spilled rollbacks, that means we
        // have already done a lot of work for this transaction,
        // and subsequent rollback log nodes are created
        // and put into the cachetable. The idea is for
        // transactions that don't do a lot of work to (hopefully)
        // get a rollback log node from a cache, as opposed to
        // taking the more expensive route of creating a new one.
        if (!txn_has_spilled_rollback_logs(txn)) {
            txn->logger->rollback_cache.get_rollback_log_node(txn, &pinned_log);
            if (pinned_log != NULL) {
                rollback_initialize_for_txn(
                    pinned_log,
                    txn,
                    txn->roll_info.spilled_rollback_tail,
                    txn->roll_info.spilled_rollback_tail_hash
                    );
                txn->roll_info.current_rollback = pinned_log->blocknum;
                txn->roll_info.current_rollback_hash = pinned_log->hash;
            }
        }
        if (pinned_log == NULL) {
            rollback_log_create(txn, txn->roll_info.spilled_rollback_tail, txn->roll_info.spilled_rollback_tail_hash, &pinned_log);
        }
    }
    assert(pinned_log->txnid == txn->txnid64);
    assert(pinned_log->blocknum.b != ROLLBACK_NONE.b);
    *log = pinned_log;
}
<|endoftext|>


<commit_before>/*
 * Stack
 *
 */

// version 1: use one stack
class Queue {
public:
    // Push element x to the back of queue.
    void push(int x) {
        stack<int> tmp;
        while (!s.empty()) {
            tmp.push(s.top());
            s.pop();
        }
        s.push(x);
        while (!tmp.empty()) {
            s.push(tmp.top());
            tmp.pop();
        }
    }

    // Removes the element from in front of queue.
    void pop(void) {
        s.pop();
    }

    // Get the front element.
    int peek(void) {
        return s.top();
    }

    // Return whether the queue is empty.
    bool empty(void) {
        return s.empty();
    }

private:
    stack<int> s;
};

// Conclusion:
// stack twice --> reverse and reverse -->queue
//
//

// version 2: use two stacks
class Queue {
public:
    // Push element x to the back of queue.
    void push(int x) {
        _new.push(x);
    }

    void shiftStack() {
        if (_old.empty()) {
            while (!_new.empty()) {
                _old.push(_new.top());
                _new.pop();
            }
        }
    }

    // Removes the element from in front of queue.
    void pop(void) {
        shiftStack();
        if (!_old.empty()) _old.pop();
    }

    // Get the front element.
    int peek(void) {
        shiftStack();
        if (!_old.empty()) return _old.top();
        return 0;
    }

    // Return whether the queue is empty.
    bool empty(void) {
        return _old.empty() && _new.empty();
    }

private:
    stack<int> _old, _new;
};

// Conclusion:
// v1那个解法虽然简单，但是效率不高，因为每次在push的时候，都要翻转两边栈，v2这个方法使用了
// 两个栈_new和_old，其中新进栈的都先缓存在_new中，入股要pop和peek的时候，才将_new中所有元素
// 移到_old中操作，提高了效率。

<commit_msg>Update 232.cpp<commit_after>/*
 * Stack
 *
 */

// version 1: use one stack
class MyQueue {
public:
    /** Initialize your data structure here. */
    MyQueue() {

    }

    /** Push element x to the back of queue. */
    void push(int x) {
        stack<int> tmp;
        while (!s.empty()) {
            tmp.push(s.top());
            s.pop();
        }
        s.push(x);
        while (!tmp.empty()) {
            s.push(tmp.top());
            tmp.pop();
        }
    }

    /** Removes the element from in front of queue and returns that element. */
    int pop() {
        int tmp = s.top();
        s.pop();
        return tmp;
    }

    /** Get the front element. */
    int peek() {
        return s.top();
    }

    /** Returns whether the queue is empty. */
    bool empty() {
        return s.empty();
    }

private:
    stack<int> s;
};

// Conclusion:
// stack twice --> reverse and reverse -->queue
//
//

// version 2: use two stacks
class Queue {
public:
    // Push element x to the back of queue.
    void push(int x) {
        _new.push(x);
    }

    void shiftStack() {
        if (_old.empty()) {
            while (!_new.empty()) {
                _old.push(_new.top());
                _new.pop();
            }
        }
    }

    // Removes the element from in front of queue.
    void pop(void) {
        shiftStack();
        if (!_old.empty()) _old.pop();
    }

    // Get the front element.
    int peek(void) {
        shiftStack();
        if (!_old.empty()) return _old.top();
        return 0;
    }

    // Return whether the queue is empty.
    bool empty(void) {
        return _old.empty() && _new.empty();
    }

private:
    stack<int> _old, _new;
};

// Conclusion:
// v1那个解法虽然简单，但是效率不高，因为每次在push的时候，都要翻转两边栈，v2这个方法使用了
// 两个栈_new和_old，其中新进栈的都先缓存在_new中，入股要pop和peek的时候，才将_new中所有元素
// 移到_old中操作，提高了效率。

<|endoftext|>


<commit_before>// Copyright (c) 2012-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
// SYSCOIN
#include <primitives/transaction.h>
#include <script/standard.h>
#include <test/util/setup_common.h>

#include <stdint.h>

#include <boost/test/unit_test.hpp>

// amounts 0.00000001 .. 0.00100000
#define NUM_MULTIPLES_UNIT 100000

// amounts 0.01 .. 100.00
#define NUM_MULTIPLES_CENT 10000

// amounts 1 .. 10000
#define NUM_MULTIPLES_1SYS 10000

// amounts 50 .. 21000000
#define NUM_MULTIPLES_50SYS 420000

BOOST_FIXTURE_TEST_SUITE(compress_tests, BasicTestingSetup)

bool static TestEncode(uint64_t in) {
    return in == DecompressAmount(CompressAmount(in));
}

bool static TestDecode(uint64_t in) {
    return in == CompressAmount(DecompressAmount(in));
}

bool static TestPair(uint64_t dec, uint64_t enc) {
    return CompressAmount(dec) == enc &&
           DecompressAmount(enc) == dec;
}

BOOST_AUTO_TEST_CASE(compress_amounts)
{
    BOOST_CHECK(TestPair(            0,       0x0));
    BOOST_CHECK(TestPair(            1,       0x1));
    BOOST_CHECK(TestPair(         CENT,       0x7));
    BOOST_CHECK(TestPair(         COIN,       0x9));
    BOOST_CHECK(TestPair(      50*COIN,      0x32));
    BOOST_CHECK(TestPair(21000000*COIN, 0x1406f40));

    for (uint64_t i = 1; i <= NUM_MULTIPLES_UNIT; i++)
        BOOST_CHECK(TestEncode(i));

    for (uint64_t i = 1; i <= NUM_MULTIPLES_CENT; i++)
        BOOST_CHECK(TestEncode(i * CENT));

    for (uint64_t i = 1; i <= NUM_MULTIPLES_1SYS; i++)
        BOOST_CHECK(TestEncode(i * COIN));

    for (uint64_t i = 1; i <= NUM_MULTIPLES_50SYS; i++)
        BOOST_CHECK(TestEncode(i * 50 * COIN));

    for (uint64_t i = 0; i < 100000; i++)
        BOOST_CHECK(TestDecode(i));
}

BOOST_AUTO_TEST_CASE(compress_script_to_ckey_id)
{
    // case CKeyID
    CKey key;
    key.MakeNewKey(true);
    CPubKey pubkey = key.GetPubKey();

    CScript script = CScript() << OP_DUP << OP_HASH160 << ToByteVector(pubkey.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
    BOOST_CHECK_EQUAL(script.size(), 25U);

    std::vector<unsigned char> out;
    bool done = CompressScript(script, out);
    BOOST_CHECK_EQUAL(done, true);

    // Check compressed script
    BOOST_CHECK_EQUAL(out.size(), 21U);
    BOOST_CHECK_EQUAL(out[0], 0x00);
    BOOST_CHECK_EQUAL(memcmp(&out[1], &script[3], 20), 0); // compare the 20 relevant chars of the CKeyId in the script
}

BOOST_AUTO_TEST_CASE(compress_script_to_cscript_id)
{
    // case CScriptID
    CScript script, redeemScript;
    script << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL;
    BOOST_CHECK_EQUAL(script.size(), 23U);

    std::vector<unsigned char> out;
    bool done = CompressScript(script, out);
    BOOST_CHECK_EQUAL(done, true);

    // Check compressed script
    BOOST_CHECK_EQUAL(out.size(), 21U);
    BOOST_CHECK_EQUAL(out[0], 0x01);
    BOOST_CHECK_EQUAL(memcmp(&out[1], &script[2], 20), 0); // compare the 20 relevant chars of the CScriptId in the script
}

BOOST_AUTO_TEST_CASE(compress_script_to_compressed_pubkey_id)
{
    CKey key;
    key.MakeNewKey(true); // case compressed PubKeyID

    CScript script = CScript() << ToByteVector(key.GetPubKey()) << OP_CHECKSIG; // COMPRESSED_PUBLIC_KEY_SIZE (33)
    BOOST_CHECK_EQUAL(script.size(), 35U);

    std::vector<unsigned char> out;
    bool done = CompressScript(script, out);
    BOOST_CHECK_EQUAL(done, true);

    // Check compressed script
    BOOST_CHECK_EQUAL(out.size(), 33U);
    BOOST_CHECK_EQUAL(memcmp(&out[0], &script[1], 1), 0);
    BOOST_CHECK_EQUAL(memcmp(&out[1], &script[2], 32), 0); // compare the 32 chars of the compressed CPubKey
}

BOOST_AUTO_TEST_CASE(compress_script_to_uncompressed_pubkey_id)
{
    CKey key;
    key.MakeNewKey(false); // case uncompressed PubKeyID
    CScript script =  CScript() << ToByteVector(key.GetPubKey()) << OP_CHECKSIG; // PUBLIC_KEY_SIZE (65)
    BOOST_CHECK_EQUAL(script.size(), 67U);                   // 1 char code + 65 char pubkey + OP_CHECKSIG

    std::vector<unsigned char> out;
    bool done = CompressScript(script, out);
    BOOST_CHECK_EQUAL(done, true);

    // Check compressed script
    BOOST_CHECK_EQUAL(out.size(), 33U);
    BOOST_CHECK_EQUAL(memcmp(&out[1], &script[2], 32), 0); // first 32 chars of CPubKey are copied into out[1:]
    BOOST_CHECK_EQUAL(out[0], 0x04 | (script[65] & 0x01)); // least significant bit (lsb) of last char of pubkey is mapped into out[0]
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>add uint64 compress test<commit_after>// Copyright (c) 2012-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
// SYSCOIN
#include <primitives/transaction.h>
#include <script/standard.h>
#include <test/util/setup_common.h>

#include <stdint.h>

#include <boost/test/unit_test.hpp>

// amounts 0.00000001 .. 0.00100000
#define NUM_MULTIPLES_UNIT 100000

// amounts 0.01 .. 100.00
#define NUM_MULTIPLES_CENT 10000

// amounts 1 .. 10000
#define NUM_MULTIPLES_1SYS 10000

// amounts 50 .. 21000000
#define NUM_MULTIPLES_50SYS 420000

BOOST_FIXTURE_TEST_SUITE(compress_tests, BasicTestingSetup)

bool static TestEncode(uint64_t in) {
    return in == DecompressAmount(CompressAmount(in));
}

bool static TestDecode(uint64_t in) {
    return in == CompressAmount(DecompressAmount(in));
}

bool static TestPair(uint64_t dec, uint64_t enc) {
    return CompressAmount(dec) == enc &&
           DecompressAmount(enc) == dec;
}

BOOST_AUTO_TEST_CASE(compress_amounts)
{
    BOOST_CHECK(TestPair(            0,       0x0));
    BOOST_CHECK(TestPair(            1,       0x1));
    BOOST_CHECK(TestPair(         CENT,       0x7));
    BOOST_CHECK(TestPair(         COIN,       0x9));
    BOOST_CHECK(TestPair(      50*COIN,      0x32));
    BOOST_CHECK(TestPair(21000000*COIN, 0x1406f40));
    // SYSCOIN
    BOOST_CHECK(TestPair(std::numeric_limits<uint64_t>::max(), 0x1406f40));

    for (uint64_t i = 1; i <= NUM_MULTIPLES_UNIT; i++)
        BOOST_CHECK(TestEncode(i));

    for (uint64_t i = 1; i <= NUM_MULTIPLES_CENT; i++)
        BOOST_CHECK(TestEncode(i * CENT));

    for (uint64_t i = 1; i <= NUM_MULTIPLES_1SYS; i++)
        BOOST_CHECK(TestEncode(i * COIN));

    for (uint64_t i = 1; i <= NUM_MULTIPLES_50SYS; i++)
        BOOST_CHECK(TestEncode(i * 50 * COIN));

    for (uint64_t i = 0; i < 100000; i++)
        BOOST_CHECK(TestDecode(i));
}

BOOST_AUTO_TEST_CASE(compress_script_to_ckey_id)
{
    // case CKeyID
    CKey key;
    key.MakeNewKey(true);
    CPubKey pubkey = key.GetPubKey();

    CScript script = CScript() << OP_DUP << OP_HASH160 << ToByteVector(pubkey.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
    BOOST_CHECK_EQUAL(script.size(), 25U);

    std::vector<unsigned char> out;
    bool done = CompressScript(script, out);
    BOOST_CHECK_EQUAL(done, true);

    // Check compressed script
    BOOST_CHECK_EQUAL(out.size(), 21U);
    BOOST_CHECK_EQUAL(out[0], 0x00);
    BOOST_CHECK_EQUAL(memcmp(&out[1], &script[3], 20), 0); // compare the 20 relevant chars of the CKeyId in the script
}

BOOST_AUTO_TEST_CASE(compress_script_to_cscript_id)
{
    // case CScriptID
    CScript script, redeemScript;
    script << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL;
    BOOST_CHECK_EQUAL(script.size(), 23U);

    std::vector<unsigned char> out;
    bool done = CompressScript(script, out);
    BOOST_CHECK_EQUAL(done, true);

    // Check compressed script
    BOOST_CHECK_EQUAL(out.size(), 21U);
    BOOST_CHECK_EQUAL(out[0], 0x01);
    BOOST_CHECK_EQUAL(memcmp(&out[1], &script[2], 20), 0); // compare the 20 relevant chars of the CScriptId in the script
}

BOOST_AUTO_TEST_CASE(compress_script_to_compressed_pubkey_id)
{
    CKey key;
    key.MakeNewKey(true); // case compressed PubKeyID

    CScript script = CScript() << ToByteVector(key.GetPubKey()) << OP_CHECKSIG; // COMPRESSED_PUBLIC_KEY_SIZE (33)
    BOOST_CHECK_EQUAL(script.size(), 35U);

    std::vector<unsigned char> out;
    bool done = CompressScript(script, out);
    BOOST_CHECK_EQUAL(done, true);

    // Check compressed script
    BOOST_CHECK_EQUAL(out.size(), 33U);
    BOOST_CHECK_EQUAL(memcmp(&out[0], &script[1], 1), 0);
    BOOST_CHECK_EQUAL(memcmp(&out[1], &script[2], 32), 0); // compare the 32 chars of the compressed CPubKey
}

BOOST_AUTO_TEST_CASE(compress_script_to_uncompressed_pubkey_id)
{
    CKey key;
    key.MakeNewKey(false); // case uncompressed PubKeyID
    CScript script =  CScript() << ToByteVector(key.GetPubKey()) << OP_CHECKSIG; // PUBLIC_KEY_SIZE (65)
    BOOST_CHECK_EQUAL(script.size(), 67U);                   // 1 char code + 65 char pubkey + OP_CHECKSIG

    std::vector<unsigned char> out;
    bool done = CompressScript(script, out);
    BOOST_CHECK_EQUAL(done, true);

    // Check compressed script
    BOOST_CHECK_EQUAL(out.size(), 33U);
    BOOST_CHECK_EQUAL(memcmp(&out[1], &script[2], 32), 0); // first 32 chars of CPubKey are copied into out[1:]
    BOOST_CHECK_EQUAL(out[0], 0x04 | (script[65] & 0x01)); // least significant bit (lsb) of last char of pubkey is mapped into out[0]
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>