<commit_before>//===- EdgeProfiling.cpp - Insert counters for edge profiling -------------===//
//
//                      The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass instruments the specified program with counters for edge profiling.
// Edge profiling can give a reasonable approximation of the hot paths through a
// program, and is used for a wide variety of program transformations.
//
// Note that this implementation is very naive.  We insert a counter for *every*
// edge in the program, instead of using control flow information to prune the
// number of counters inserted.
//
//===----------------------------------------------------------------------===//

#include "ProfilingUtils.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Streams.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Instrumentation.h"
#include <set>
using namespace llvm;

namespace {
  class VISIBILITY_HIDDEN EdgeProfiler : public ModulePass {
    bool runOnModule(Module &M);
  public:
    static char ID; // Pass identification, replacement for typeid
    EdgeProfiler() : ModulePass((intptr_t)&ID) {}
  };

  char EdgeProfiler::ID = 0;
  RegisterPass<EdgeProfiler> X("insert-edge-profiling",
                               "Insert instrumentation for edge profiling");
}

ModulePass *llvm::createEdgeProfilerPass() { return new EdgeProfiler(); }

bool EdgeProfiler::runOnModule(Module &M) {
  Function *Main = M.getFunction("main");
  if (Main == 0) {
    cerr << "WARNING: cannot insert edge profiling into a module"
         << " with no main function!\n";
    return false;  // No main, no instrumentation!
  }

  std::set<BasicBlock*> BlocksToInstrument;
  unsigned NumEdges = 0;
  for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F)
    for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
      // Keep track of which blocks need to be instrumented.  We don't want to
      // instrument blocks that are added as the result of breaking critical
      // edges!
      BlocksToInstrument.insert(BB);
      NumEdges += BB->getTerminator()->getNumSuccessors();
    }

  const Type *ATy = ArrayType::get(Type::Int32Ty, NumEdges);
  GlobalVariable *Counters =
    new GlobalVariable(ATy, false, GlobalValue::InternalLinkage,
                       Constant::getNullValue(ATy), "EdgeProfCounters", &M);

  // Instrument all of the edges...
  unsigned i = 0;
  for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F)
    for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
      if (BlocksToInstrument.count(BB)) {  // Don't instrument inserted blocks
        // Okay, we have to add a counter of each outgoing edge.  If the
        // outgoing edge is not critical don't split it, just insert the counter
        // in the source or destination of the edge.
        TerminatorInst *TI = BB->getTerminator();
        for (unsigned s = 0, e = TI->getNumSuccessors(); s != e; ++s) {
          // If the edge is critical, split it.
          SplitCriticalEdge(TI, s, this);

          // Okay, we are guaranteed that the edge is no longer critical.  If we
          // only have a single successor, insert the counter in this block,
          // otherwise insert it in the successor block.
          if (TI->getNumSuccessors() == 0) {
            // Insert counter at the start of the block
            IncrementCounterInBlock(BB, i++, Counters);
          } else {
            // Insert counter at the start of the block
            IncrementCounterInBlock(TI->getSuccessor(s), i++, Counters);
          }
        }
      }

  // Add the initialization call to main.
  InsertProfilingInitCall(Main, "llvm_start_edge_profiling", Counters);
  return true;
}

<commit_msg>Fix for edge profiling, patch by 'Marc' for PR1857<commit_after>//===- EdgeProfiling.cpp - Insert counters for edge profiling -------------===//
//
//                      The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass instruments the specified program with counters for edge profiling.
// Edge profiling can give a reasonable approximation of the hot paths through a
// program, and is used for a wide variety of program transformations.
//
// Note that this implementation is very naive.  We insert a counter for *every*
// edge in the program, instead of using control flow information to prune the
// number of counters inserted.
//
//===----------------------------------------------------------------------===//

#include "ProfilingUtils.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Streams.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Instrumentation.h"
#include <set>
using namespace llvm;

namespace {
  class VISIBILITY_HIDDEN EdgeProfiler : public ModulePass {
    bool runOnModule(Module &M);
  public:
    static char ID; // Pass identification, replacement for typeid
    EdgeProfiler() : ModulePass((intptr_t)&ID) {}
  };

  char EdgeProfiler::ID = 0;
  RegisterPass<EdgeProfiler> X("insert-edge-profiling",
                               "Insert instrumentation for edge profiling");
}

ModulePass *llvm::createEdgeProfilerPass() { return new EdgeProfiler(); }

bool EdgeProfiler::runOnModule(Module &M) {
  Function *Main = M.getFunction("main");
  if (Main == 0) {
    cerr << "WARNING: cannot insert edge profiling into a module"
         << " with no main function!\n";
    return false;  // No main, no instrumentation!
  }

  std::set<BasicBlock*> BlocksToInstrument;
  unsigned NumEdges = 0;
  for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F)
    for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
      // Keep track of which blocks need to be instrumented.  We don't want to
      // instrument blocks that are added as the result of breaking critical
      // edges!
      BlocksToInstrument.insert(BB);
      NumEdges += BB->getTerminator()->getNumSuccessors();
    }

  const Type *ATy = ArrayType::get(Type::Int32Ty, NumEdges);
  GlobalVariable *Counters =
    new GlobalVariable(ATy, false, GlobalValue::InternalLinkage,
                       Constant::getNullValue(ATy), "EdgeProfCounters", &M);

  // Instrument all of the edges...
  unsigned i = 0;
  for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F)
    for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
      if (BlocksToInstrument.count(BB)) {  // Don't instrument inserted blocks
        // Okay, we have to add a counter of each outgoing edge.  If the
        // outgoing edge is not critical don't split it, just insert the counter
        // in the source or destination of the edge.
        TerminatorInst *TI = BB->getTerminator();
        for (unsigned s = 0, e = TI->getNumSuccessors(); s != e; ++s) {
          // If the edge is critical, split it.
          SplitCriticalEdge(TI, s, this);

          // Okay, we are guaranteed that the edge is no longer critical.  If we
          // only have a single successor, insert the counter in this block,
          // otherwise insert it in the successor block.
          if (TI->getNumSuccessors() == 1) {
            // Insert counter at the start of the block
            IncrementCounterInBlock(BB, i++, Counters);
          } else {
            // Insert counter at the start of the block
            IncrementCounterInBlock(TI->getSuccessor(s), i++, Counters);
          }
        }
      }

  // Add the initialization call to main.
  InsertProfilingInitCall(Main, "llvm_start_edge_profiling", Counters);
  return true;
}

<|endoftext|>


<commit_before>#include "generated/cpp/SQLite3Base.h"
#include "json/JSONIterator.h"
#include "db/DBAdapter.h"
#include "common/RhodesApp.h"

extern "C" {
int rho_db_open(const char* szDBPath, const char* szDBPartition, void** ppDB);
int rho_db_close(void* pDB);
int rho_db_startTransaction(void* pDB);
int rho_db_commitTransaction(void* pDB);
int rho_db_rollbackTransaction(void* pDB);
int rho_db_is_ui_waitfordb(void* pDB);
void rho_db_lock(void* pDB);
void rho_db_unlock(void* pDB);
int  rho_db_is_table_exist(void* pDB, const char* szTableName);
unsigned long rb_c_impl_SQLite3_execute(int argc, unsigned long *argv, void* pDB);
};

#undef DEFAULT_LOGCATEGORY
#define DEFAULT_LOGCATEGORY "SQLite3"

namespace rho {
namespace database {

using namespace rho::apiGenerator;
using namespace rho::common;

class CSQLite3Impl: public CSQLite3Base
{
public:

    virtual void open( const rho::String& dbPath,  const rho::String& dbPartition, rho::apiGenerator::CMethodResult& oResult);
    virtual void close(rho::apiGenerator::CMethodResult& oResult);
    virtual void startTransaction(rho::apiGenerator::CMethodResult& oResult);
    virtual void commitTransaction(rho::apiGenerator::CMethodResult& oResult);
    virtual void rollbackTransaction(rho::apiGenerator::CMethodResult& oResult);
    virtual void lockDb(rho::apiGenerator::CMethodResult& oResult);
    virtual void unlockDb(rho::apiGenerator::CMethodResult& oResult);
	virtual void doImport(const rho::String& zipName, rho::apiGenerator::CMethodResult& oResult);
	virtual void doExport(rho::apiGenerator::CMethodResult& oResult);
    virtual void destroyTables(const rho::Vector<rho::String>& include, const rho::Vector<rho::String>& exclude, rho::apiGenerator::CMethodResult& oResult);
    virtual void isTableExist( const rho::String& tableName, rho::apiGenerator::CMethodResult& oResult);
    virtual void isUiWaitForDb(rho::apiGenerator::CMethodResult& oResult);
	void* getDb() const {return m_pDB;}

private:
	void* m_pDB;

};

void CSQLite3Impl::open( const rho::String& dbPath,  const rho::String& dbPartition, rho::apiGenerator::CMethodResult& oResult)
{
	m_pDB = NULL;
	rho_db_open(dbPath.c_str(), dbPartition.c_str(), &m_pDB);
    //TODO: process errors
}

void CSQLite3Impl::close(rho::apiGenerator::CMethodResult& oResult)
{
	rho_db_close(m_pDB);
    //TODO: process errors
}

void CSQLite3Impl::startTransaction(rho::apiGenerator::CMethodResult& oResult)
{
	rho_db_startTransaction(m_pDB);
    //TODO: process errors
}

void CSQLite3Impl::commitTransaction(rho::apiGenerator::CMethodResult& oResult)
{
	rho_db_commitTransaction(m_pDB);
    //TODO: process errors
}

void CSQLite3Impl::rollbackTransaction(rho::apiGenerator::CMethodResult& oResult)
{
    rho_db_rollbackTransaction(m_pDB);
}

void CSQLite3Impl::lockDb(rho::apiGenerator::CMethodResult& oResult)
{
	rho_db_lock(m_pDB);
}

void CSQLite3Impl::unlockDb(rho::apiGenerator::CMethodResult& oResult)
{
	rho_db_unlock(m_pDB);
}

void CSQLite3Impl::destroyTables(const rho::Vector<rho::String>& include, const rho::Vector<rho::String>& exclude, rho::apiGenerator::CMethodResult& oResult)
{
    rho::db::CDBAdapter& db = *((rho::db::CDBAdapter*)m_pDB);
    db.destroy_tables(include,exclude);
}

void CSQLite3Impl::isTableExist( const rho::String& tableName, rho::apiGenerator::CMethodResult& oResult)
{
	int result;

	result = rho_db_is_table_exist(m_pDB, tableName.c_str());
	oResult.set(result ? true : false);
}

void CSQLite3Impl::isUiWaitForDb( rho::apiGenerator::CMethodResult& oResult)
{
	int result;

	result = rho_db_is_ui_waitfordb(m_pDB);
	oResult.set(result ? true : false);
}

void CSQLite3Impl::doImport(const rho::String& zipName, rho::apiGenerator::CMethodResult& oResult)
{
	rho::db::CDBAdapter& db = *((rho::db::CDBAdapter*)m_pDB);
	bool bRes = db.importDatabase(zipName);
    oResult.set(bRes);
}

void CSQLite3Impl::doExport(rho::apiGenerator::CMethodResult& oResult)
{
	rho::db::CDBAdapter& db = *((rho::db::CDBAdapter*)m_pDB);
    String strRes = db.exportDatabase();
    oResult.set(strRes);
}

////////////////////////////////////////////////////////////////////////

class CSQLite3SingletonImpl: public CSQLite3SingletonBase
{
public:
};

class CSQLite3Factory: public CSQLite3FactoryBase
{
public:
    ~CSQLite3Factory(){}

    ISQLite3Singleton* createModuleSingleton()
    {
        return new CSQLite3SingletonImpl();
    }

    virtual ISQLite3* createModuleByID(const rho::String& strID){ return new CSQLite3Impl(); };
};

}
}

extern "C" void Init_SQLite3()
{
    rho::database::CSQLite3Factory::setInstance( new rho::database::CSQLite3Factory() );

    RHODESAPP().getExtManager().requireRubyFile("Database");

    rho::database::Init_SQLite3_API();
}

extern "C" unsigned long rb_impl_SQLite3_execute(int argc, unsigned long *argv, rho::database::ISQLite3* pObj)
{
    void* pDB =  static_cast<rho::database::CSQLite3Impl*>(pObj)->getDb();
    return rb_c_impl_SQLite3_execute(argc, argv, pDB);
}

rho::String js_SQLite3_execute(rho::json::CJSONArray& argv, const rho::String& strObjID)
{
    //TODO: js_Database_execute
    return "{}";
}
<commit_msg>api: database: support js execute<commit_after>#include "generated/cpp/SQLite3Base.h"
#include "json/JSONIterator.h"
#include "db/DBAdapter.h"
#include "common/RhodesApp.h"
#include "statistic/RhoProfiler.h"
#include "common/StringConverter.h"

extern "C" {
int rho_db_open(const char* szDBPath, const char* szDBPartition, void** ppDB);
int rho_db_close(void* pDB);
int rho_db_startTransaction(void* pDB);
int rho_db_commitTransaction(void* pDB);
int rho_db_rollbackTransaction(void* pDB);
int rho_db_is_ui_waitfordb(void* pDB);
void rho_db_lock(void* pDB);
void rho_db_unlock(void* pDB);
int  rho_db_is_table_exist(void* pDB, const char* szTableName);
unsigned long rb_c_impl_SQLite3_execute(int argc, unsigned long *argv, void* pDB);

void* rho_db_get_handle(void* pDB);
int rho_db_prepare_statement(void* pDB, const char* szSql, int nByte, sqlite3_stmt **ppStmt);

};

#undef DEFAULT_LOGCATEGORY
#define DEFAULT_LOGCATEGORY "SQLite3"

namespace rho {
namespace database {

using namespace rho::apiGenerator;
using namespace rho::common;

class CSQLite3Impl: public CSQLite3Base
{
public:

    virtual void open( const rho::String& dbPath,  const rho::String& dbPartition, rho::apiGenerator::CMethodResult& oResult);
    virtual void close(rho::apiGenerator::CMethodResult& oResult);
    virtual void startTransaction(rho::apiGenerator::CMethodResult& oResult);
    virtual void commitTransaction(rho::apiGenerator::CMethodResult& oResult);
    virtual void rollbackTransaction(rho::apiGenerator::CMethodResult& oResult);
    virtual void lockDb(rho::apiGenerator::CMethodResult& oResult);
    virtual void unlockDb(rho::apiGenerator::CMethodResult& oResult);
	virtual void doImport(const rho::String& zipName, rho::apiGenerator::CMethodResult& oResult);
	virtual void doExport(rho::apiGenerator::CMethodResult& oResult);
    virtual void destroyTables(const rho::Vector<rho::String>& include, const rho::Vector<rho::String>& exclude, rho::apiGenerator::CMethodResult& oResult);
    virtual void isTableExist( const rho::String& tableName, rho::apiGenerator::CMethodResult& oResult);
    virtual void isUiWaitForDb(rho::apiGenerator::CMethodResult& oResult);
	void* getDb() const {return m_pDB;}

private:
	void* m_pDB;

};

void CSQLite3Impl::open( const rho::String& dbPath,  const rho::String& dbPartition, rho::apiGenerator::CMethodResult& oResult)
{
	m_pDB = NULL;
	rho_db_open(dbPath.c_str(), dbPartition.c_str(), &m_pDB);
    //TODO: process errors
}

void CSQLite3Impl::close(rho::apiGenerator::CMethodResult& oResult)
{
	rho_db_close(m_pDB);
    //TODO: process errors
}

void CSQLite3Impl::startTransaction(rho::apiGenerator::CMethodResult& oResult)
{
	rho_db_startTransaction(m_pDB);
    //TODO: process errors
}

void CSQLite3Impl::commitTransaction(rho::apiGenerator::CMethodResult& oResult)
{
	rho_db_commitTransaction(m_pDB);
    //TODO: process errors
}

void CSQLite3Impl::rollbackTransaction(rho::apiGenerator::CMethodResult& oResult)
{
    rho_db_rollbackTransaction(m_pDB);
}

void CSQLite3Impl::lockDb(rho::apiGenerator::CMethodResult& oResult)
{
	rho_db_lock(m_pDB);
}

void CSQLite3Impl::unlockDb(rho::apiGenerator::CMethodResult& oResult)
{
	rho_db_unlock(m_pDB);
}

void CSQLite3Impl::destroyTables(const rho::Vector<rho::String>& include, const rho::Vector<rho::String>& exclude, rho::apiGenerator::CMethodResult& oResult)
{
    rho::db::CDBAdapter& db = *((rho::db::CDBAdapter*)m_pDB);
    db.destroy_tables(include,exclude);
}

void CSQLite3Impl::isTableExist( const rho::String& tableName, rho::apiGenerator::CMethodResult& oResult)
{
	int result;

	result = rho_db_is_table_exist(m_pDB, tableName.c_str());
	oResult.set(result ? true : false);
}

void CSQLite3Impl::isUiWaitForDb( rho::apiGenerator::CMethodResult& oResult)
{
	int result;

	result = rho_db_is_ui_waitfordb(m_pDB);
	oResult.set(result ? true : false);
}

void CSQLite3Impl::doImport(const rho::String& zipName, rho::apiGenerator::CMethodResult& oResult)
{
	rho::db::CDBAdapter& db = *((rho::db::CDBAdapter*)m_pDB);
	bool bRes = db.importDatabase(zipName);
    oResult.set(bRes);
}

void CSQLite3Impl::doExport(rho::apiGenerator::CMethodResult& oResult)
{
	rho::db::CDBAdapter& db = *((rho::db::CDBAdapter*)m_pDB);
    String strRes = db.exportDatabase();
    oResult.set(strRes);
}

////////////////////////////////////////////////////////////////////////

class CSQLite3SingletonImpl: public CSQLite3SingletonBase
{
public:
};

class CSQLite3Factory: public CSQLite3FactoryBase
{
public:
    ~CSQLite3Factory(){}

    ISQLite3Singleton* createModuleSingleton()
    {
        return new CSQLite3SingletonImpl();
    }

    virtual ISQLite3* createModuleByID(const rho::String& strID){ return new CSQLite3Impl(); };
};

}
}

extern "C" void Init_SQLite3()
{
    rho::database::CSQLite3Factory::setInstance( new rho::database::CSQLite3Factory() );

    RHODESAPP().getExtManager().requireRubyFile("Database");

    rho::database::Init_SQLite3_API();
}

extern "C" unsigned long rb_impl_SQLite3_execute(int argc, unsigned long *argv, rho::database::ISQLite3* pObj)
{
    void* pDB =  static_cast<rho::database::CSQLite3Impl*>(pObj)->getDb();
    return rb_c_impl_SQLite3_execute(argc, argv, pDB);
}

using namespace rho;
using namespace rho::common;
using namespace rho::json;

rho::String js_SQLite3_execute(CJSONArray& argv, const rho::String& strObjID)
{
    rho::database::ISQLite3* pObj = rho::database::CSQLite3FactoryBase::getInstance()->getModuleByID(strObjID);
    void* pDB =  static_cast<rho::database::CSQLite3Impl*>(pObj)->getDb();

    sqlite3 * db = NULL;
	void **ppDB = &pDB;
	sqlite3_stmt *statement = NULL;
	const char* sql = NULL;
	Vector< rho::Hashtable<rho::String, rho::String> > arRes;
    rho::apiGenerator::CMethodResult oResult;

	int nRes = 0;
    char * szErrMsg = 0;
    int is_batch = 0;

	db = (sqlite3 *)rho_db_get_handle(*ppDB);
    sql = argv[0].getString();
    is_batch = argv[1].getBoolean();

    RAWTRACE1("db_execute: %s", sql);

    PROF_START_CREATED("SQLITE");
    if ( is_batch )
    {
        PROF_START_CREATED("SQLITE_EXEC");

        rho_db_lock(*ppDB);
        nRes = sqlite3_exec(db, sql,  NULL, NULL, &szErrMsg);
        rho_db_unlock(*ppDB);

        PROF_STOP("SQLITE_EXEC");
    }
    else
    {
        rho_db_lock(*ppDB);
        PROF_START_CREATED("SQLITE_PREPARE");
        nRes = rho_db_prepare_statement(*ppDB, sql, -1, &statement);
        PROF_STOP("SQLITE_PREPARE");
        if ( nRes != SQLITE_OK)
        {
            szErrMsg = (char *)sqlite3_errmsg(db);
            rho_db_unlock(*ppDB);

            oResult.setArgError( String("could not prepare statement: ") + convertToStringA(nRes) + "; Message: " + (szErrMsg?szErrMsg:""));
            return oResult.toJSON();
        }

        if ( argv.getSize() > 2 && argv[2].isArray() )
        {
            int i = 0;
            CJSONArray args( argv[2] );

            for( ; i < args.getSize(); i++ )
            {
                CJSONEntry arg = args[i];
                if ( arg.isNull() )
                {
                    sqlite3_bind_null(statement, i+1);
                    continue;
                }

                if ( arg.isString() )
                    sqlite3_bind_text(statement, i+1, arg.getString(), strlen(arg.getString()), SQLITE_TRANSIENT);
                else if (arg.isFloat())
                    sqlite3_bind_double(statement, i+1, arg.getDouble() );
                else if (arg.isInteger())
                    sqlite3_bind_int64(statement, i+1, arg.getUInt64() );
                else if (arg.isBoolean())
                    sqlite3_bind_int(statement, i+1, arg.getBoolean() ? 1 : 0 );
                else
				{
                    sqlite3_reset(statement);

                    oResult.setArgError( String("Unsupported argument type. Argument number: ") + convertToStringA(i));
                    return oResult.toJSON();
				}
            }
        }

        PROF_START_CREATED("SQLITE_EXEC");
        nRes = sqlite3_step(statement);
        PROF_STOP("SQLITE_EXEC");

	    while( nRes== SQLITE_ROW )
        {
		    int nCount = sqlite3_data_count(statement);
		    int nCol = 0;
            rho::Hashtable<rho::String, rho::String> hashRec;

		    for(;nCol<nCount;nCol++)
            {
			    int nColType = sqlite3_column_type(statement,nCol);
			    const char* szColName = sqlite3_column_name(statement,nCol);
                String colValue;

			    switch(nColType)
                {
				    case SQLITE_NULL:
					    break;
                    case SQLITE_FLOAT:
                    {
                        double dVal = sqlite3_column_double(statement, nCol);
                        colValue = convertToStringA(dVal);
                        break;
                    }
                    case SQLITE_INTEGER:
                    {
                        sqlite_int64 nVal = sqlite3_column_int64(statement, nCol);
                        colValue = convertToStringA(nVal);
                        break;
                    }
				    default:{
                        sqlite3_value * sqlValue = sqlite3_column_value(statement, nCol);
                        int nLen = sqlite3_value_bytes(sqlValue);
                        const char*  szValue = (const char *)sqlite3_value_text(sqlValue);
					    colValue = String(szValue, nLen);
					    break;
				    }
			    }

                hashRec[szColName] = colValue;
		    }

            arRes.addElement( hashRec );

            PROF_START_CREATED("SQLITE_EXEC");
            nRes = sqlite3_step(statement);
            PROF_STOP("SQLITE_EXEC");

	    }

        rho_db_unlock(*ppDB);

    }

    if ( statement )
        sqlite3_reset(statement);

    PROF_STOP("SQLITE");

    if ( nRes != SQLITE_OK && nRes != SQLITE_ROW && nRes != SQLITE_DONE )
    {
        if ( !szErrMsg )
            szErrMsg = (char*)sqlite3_errmsg(db);

        oResult.setError( String("could not execute statement: ") + convertToStringA(nRes) + "; Message: " + (szErrMsg?szErrMsg:""));
        return oResult.toJSON();
    }

    //TODO: set result
    //oResult.set(arRes);

    return oResult.toJSON();
}
<|endoftext|>


<commit_before>// This is free and unencumbered software released into the public domain.
// For more information, please refer to <http://unlicense.org/>

#include "transmissionline/cable.h"

CableComponent::CableComponent() {
  coefficient_expansion_linear_thermal = -999999;
  coefficients_polynomial_creep = std::vector<double>(5, 0);
  coefficients_polynomial_loadstrain = std::vector<double>(5, 0);
  load_limit_polynomial_creep = -999999;
  load_limit_polynomial_loadstrain = -999999;
  modulus_compression_elastic_area = -999999;
  modulus_tension_elastic_area = -999999;
}

CableComponent::~CableComponent() {}

bool CableComponent::Validate(const bool& is_included_warnings,
                              std::list<std::string>* messages_error) const {
  bool is_valid = true;

  // validate coefficient-expansion-thermal-linear
  if (coefficient_expansion_linear_thermal <= -0.005
      || 0.005 < coefficient_expansion_linear_thermal) {

    is_valid = false;
    if (messages_error != nullptr) {
      messages_error->push_back("CABLE COMPONENT - Invalid coefficient of "
                                "thermal expansion");
    }
  }

  // validate coefficients-polynomial-creep
  if (coefficients_polynomial_creep.size() != 5) {
    messages_error->push_back("CABLE COMPONENT - Invalid creep coefficients");
  }

  // validate coefficients-polynomial-loadstrain
  if (coefficients_polynomial_loadstrain.size() != 5) {
    messages_error->push_back("CABLE COMPONENT - Invalid load-strain "
                              "coefficients");
  }

  // validate load-limit-polynomial-creep
  if (load_limit_polynomial_creep < 0) {

    is_valid = false;
    if (messages_error != nullptr) {
      messages_error->push_back("CABLE COMPONENT - Invalid creep polynomial "
                                "limit");
    }
  }

  // validate load-limit-polynomial-loadstrain
  if (load_limit_polynomial_loadstrain < 0) {

    is_valid = false;
    if (messages_error != nullptr) {
      messages_error->push_back("CABLE COMPONENT - Invalid load-strain "
                                "polynomial limit");
    }
  }

  // validate modulus-compression-elastic-area
  if (modulus_compression_elastic_area < 0) {

    is_valid = false;
    if (messages_error != nullptr) {
      messages_error->push_back("CABLE COMPONENT- Invalid compression elastic "
                                "area modulus");
    }
  }

  // validate modulus-tension-elastic-area
  if (modulus_tension_elastic_area < 0) {

    is_valid = false;
    if (messages_error != nullptr) {
      messages_error->push_back("COMPONENT | CABLE - Invalid tension elastic "
                                "area modulus");
    }
  }

  //return validation status
  return is_valid;
}

Cable::Cable() {
  area_electrical = -999999;
  area_physical = -999999;
  diameter = -999999;
  name = "";
  strength_rated = -999999;
  temperature_properties_components = -999999;
  type_construction = "";
  weight_unit = -999999;
}

Cable::~Cable() {}

bool Cable::Validate(const bool& is_included_warnings,
                     std::list<std::string>* messages_error) const {
  bool is_valid = true;

  // validate area-electrical
  if (area_electrical < 0) {

    is_valid = false;
    if (messages_error != nullptr) {
      messages_error->push_back("CABLE - Invalid electrical area");
    }
  }

  // validate area-physical
  if (area_physical < 0) {
    is_valid = false;
    if (messages_error != nullptr) {
      messages_error->push_back("CABLE - Invalid physical area");
    }
  }

  // validate component-core
  component_core.Validate(is_included_warnings, messages_error);

  // validate component-shell
  component_shell.Validate(is_included_warnings, messages_error);

  // validate diameter
  if (diameter <= 0
      || (3 < diameter && is_included_warnings == true)) {

    is_valid = false;
    if (messages_error != nullptr) {
      messages_error->push_back("CABLE - Invalid diameter");
    }
  }

  // validate name
  // nothing to validate

  // validate strength-rated
  if (strength_rated < 0) {

    is_valid = false;
    if (messages_error != nullptr) {
      messages_error->push_back("CABLE - Invalid rated strength");
    }
  }

  // validate temperature-component-properties
  if (temperature_properties_components < 0) {

    is_valid = false;
    if (messages_error != nullptr) {
      messages_error->push_back("CABLE - Invalid component properties "
                                "temperature");
    }
  }

  // validate type-construction
  // nothing to validate

  // validate type-polynomial-active
  if (type_polynomial_active != CablePolynomialType::kCreep
      || type_polynomial_active != CablePolynomialType::kLoadStrain) {

    is_valid = false;
    if (messages_error != nullptr) {
      messages_error->push_back("CABLE - Invalid active polynomial type");
    }
  }

  // validate weight-unit
  if (weight_unit <= 0
      || (10 < weight_unit && is_included_warnings == true)) {

    is_valid = false;
    if (messages_error != nullptr) {
      messages_error->push_back("CABLE - Invalid unit weight");
    }
  }

  // return validation status
  return is_valid;
}
<commit_msg>Fix for Cable validation function when validating active polynomial type.<commit_after>// This is free and unencumbered software released into the public domain.
// For more information, please refer to <http://unlicense.org/>

#include "transmissionline/cable.h"

CableComponent::CableComponent() {
  coefficient_expansion_linear_thermal = -999999;
  coefficients_polynomial_creep = std::vector<double>(5, 0);
  coefficients_polynomial_loadstrain = std::vector<double>(5, 0);
  load_limit_polynomial_creep = -999999;
  load_limit_polynomial_loadstrain = -999999;
  modulus_compression_elastic_area = -999999;
  modulus_tension_elastic_area = -999999;
}

CableComponent::~CableComponent() {}

bool CableComponent::Validate(const bool& is_included_warnings,
                              std::list<std::string>* messages_error) const {
  bool is_valid = true;

  // validate coefficient-expansion-thermal-linear
  if (coefficient_expansion_linear_thermal <= -0.005
      || 0.005 < coefficient_expansion_linear_thermal) {

    is_valid = false;
    if (messages_error != nullptr) {
      messages_error->push_back("CABLE COMPONENT - Invalid coefficient of "
                                "thermal expansion");
    }
  }

  // validate coefficients-polynomial-creep
  if (coefficients_polynomial_creep.size() != 5) {
    messages_error->push_back("CABLE COMPONENT - Invalid creep coefficients");
  }

  // validate coefficients-polynomial-loadstrain
  if (coefficients_polynomial_loadstrain.size() != 5) {
    messages_error->push_back("CABLE COMPONENT - Invalid load-strain "
                              "coefficients");
  }

  // validate load-limit-polynomial-creep
  if (load_limit_polynomial_creep < 0) {

    is_valid = false;
    if (messages_error != nullptr) {
      messages_error->push_back("CABLE COMPONENT - Invalid creep polynomial "
                                "limit");
    }
  }

  // validate load-limit-polynomial-loadstrain
  if (load_limit_polynomial_loadstrain < 0) {

    is_valid = false;
    if (messages_error != nullptr) {
      messages_error->push_back("CABLE COMPONENT - Invalid load-strain "
                                "polynomial limit");
    }
  }

  // validate modulus-compression-elastic-area
  if (modulus_compression_elastic_area < 0) {

    is_valid = false;
    if (messages_error != nullptr) {
      messages_error->push_back("CABLE COMPONENT- Invalid compression elastic "
                                "area modulus");
    }
  }

  // validate modulus-tension-elastic-area
  if (modulus_tension_elastic_area < 0) {

    is_valid = false;
    if (messages_error != nullptr) {
      messages_error->push_back("COMPONENT | CABLE - Invalid tension elastic "
                                "area modulus");
    }
  }

  //return validation status
  return is_valid;
}

Cable::Cable() {
  area_electrical = -999999;
  area_physical = -999999;
  diameter = -999999;
  name = "";
  strength_rated = -999999;
  temperature_properties_components = -999999;
  type_construction = "";
  weight_unit = -999999;
}

Cable::~Cable() {}

bool Cable::Validate(const bool& is_included_warnings,
                     std::list<std::string>* messages_error) const {
  bool is_valid = true;

  // validate area-electrical
  if (area_electrical < 0) {

    is_valid = false;
    if (messages_error != nullptr) {
      messages_error->push_back("CABLE - Invalid electrical area");
    }
  }

  // validate area-physical
  if (area_physical < 0) {
    is_valid = false;
    if (messages_error != nullptr) {
      messages_error->push_back("CABLE - Invalid physical area");
    }
  }

  // validate component-core
  component_core.Validate(is_included_warnings, messages_error);

  // validate component-shell
  component_shell.Validate(is_included_warnings, messages_error);

  // validate diameter
  if (diameter <= 0
      || (3 < diameter && is_included_warnings == true)) {

    is_valid = false;
    if (messages_error != nullptr) {
      messages_error->push_back("CABLE - Invalid diameter");
    }
  }

  // validate name
  // nothing to validate

  // validate strength-rated
  if (strength_rated < 0) {

    is_valid = false;
    if (messages_error != nullptr) {
      messages_error->push_back("CABLE - Invalid rated strength");
    }
  }

  // validate temperature-component-properties
  if (temperature_properties_components < 0) {

    is_valid = false;
    if (messages_error != nullptr) {
      messages_error->push_back("CABLE - Invalid component properties "
                                "temperature");
    }
  }

  // validate type-construction
  // nothing to validate

  // validate type-polynomial-active
  if (type_polynomial_active != CablePolynomialType::kCreep
      && type_polynomial_active != CablePolynomialType::kLoadStrain) {

    is_valid = false;
    if (messages_error != nullptr) {
      messages_error->push_back("CABLE - Invalid active polynomial type");
    }
  }

  // validate weight-unit
  if (weight_unit <= 0
      || (10 < weight_unit && is_included_warnings == true)) {

    is_valid = false;
    if (messages_error != nullptr) {
      messages_error->push_back("CABLE - Invalid unit weight");
    }
  }

  // return validation status
  return is_valid;
}
<|endoftext|>


<commit_before>#include "RndSmoothCircleIC.h"

template<>
InputParameters validParams<RndSmoothCircleIC>()
{
  InputParameters params = validParams<InitialCondition>();
  params.addRequiredParam<Real>("x1", "The x coordinate of the circle center");
  params.addRequiredParam<Real>("y1", "The y coordinate of the circle center");
  params.addParam<Real>("z1", 0.0, "The z coordinate of the circle center");

  params.addRequiredParam<Real>("mx_invalue", "The max variable value inside the circle");
  params.addRequiredParam<Real>("mx_outvalue", "The max variable value outside the circle");
  params.addRequiredParam<Real>("mn_invalue", "The min variable value inside the circle");
  params.addRequiredParam<Real>("mn_outvalue", "The min variable value outside the circle");
  params.addRequiredParam<Real>("radius", "The radius of a circle");

  params.addParam<unsigned int>("seed", 12345, "Seed value for the random number generator");
  return params;
}

RndSmoothCircleIC::RndSmoothCircleIC(const std::string & name,
                               InputParameters parameters)
  :InitialCondition(name, parameters),
   _x1(parameters.get<Real>("x1")),
   _y1(parameters.get<Real>("y1")),
   _z1(parameters.get<Real>("z1")),
   _mx_invalue(parameters.get<Real>("mx_invalue")),
   _mn_invalue(parameters.get<Real>("mn_invalue")),
   _mx_outvalue(parameters.get<Real>("mx_outvalue")),
   _mn_outvalue(parameters.get<Real>("mn_outvalue")),
   _range_invalue(_mx_invalue - _mn_invalue),
   _range_outvalue(_mx_outvalue - _mn_outvalue),
   _radius(parameters.get<Real>("radius")),
   _center(_x1,_y1,_z1)
{
  mooseAssert(_range_invalue > 0.0, "Inside Min > Max for RndSmoothCircleIC!");
  mooseAssert(_range_outvalue > 0.0, "Outside Min > Max for RndSmoothCircleIC!");
  Moose::seed(getParam<unsigned int>("seed"));
}

Real
RndSmoothCircleIC::value(const Point & p)
{
  Real value = 0.0;

  Real rad = 0.0;

  for(unsigned int i=0; i<LIBMESH_DIM; i++)
    rad += (p(i)-_center(i)) * (p(i)-_center(i));

  rad = sqrt(rad);

  //Random number between 0 and 1
  Real rand_num = Moose::rand();

  if (rad <= _radius)
    value = _mn_invalue + rand_num*(_range_invalue);
  else if (rad < 1.5*_radius)
  {
    Real av_invalue = (_mn_invalue + _mx_invalue)/2.0;
    Real av_outvalue = (_mn_outvalue + _mx_outvalue)/2.0;
    value = av_outvalue + (av_invalue-av_outvalue)*(1+cos((rad-_radius)/_radius*2.0*3.14159))/2.0;
  }
  else
    value = _mx_outvalue + rand_num*(_range_outvalue);

  return value;

}

<commit_msg>r3329 dd8cd9ef-2931-0410-98ca-75ad22d19dd1<commit_after>#include "RndSmoothCircleIC.h"

template<>
InputParameters validParams<RndSmoothCircleIC>()
{
  InputParameters params = validParams<InitialCondition>();
  params.addRequiredParam<Real>("x1", "The x coordinate of the circle center");
  params.addRequiredParam<Real>("y1", "The y coordinate of the circle center");
  params.addParam<Real>("z1", 0.0, "The z coordinate of the circle center");

  params.addRequiredParam<Real>("mx_invalue", "The max variable value inside the circle");
  params.addRequiredParam<Real>("mx_outvalue", "The max variable value outside the circle");
  params.addRequiredParam<Real>("mn_invalue", "The min variable value inside the circle");
  params.addRequiredParam<Real>("mn_outvalue", "The min variable value outside the circle");
  params.addRequiredParam<Real>("radius", "The radius of a circle");

  params.addParam<unsigned int>("seed", 12345, "Seed value for the random number generator");
  return params;
}

RndSmoothCircleIC::RndSmoothCircleIC(const std::string & name,
                               InputParameters parameters)
  :InitialCondition(name, parameters),
   _x1(parameters.get<Real>("x1")),
   _y1(parameters.get<Real>("y1")),
   _z1(parameters.get<Real>("z1")),
   _mx_invalue(parameters.get<Real>("mx_invalue")),
   _mn_invalue(parameters.get<Real>("mn_invalue")),
   _mx_outvalue(parameters.get<Real>("mx_outvalue")),
   _mn_outvalue(parameters.get<Real>("mn_outvalue")),
   _range_invalue(_mx_invalue - _mn_invalue),
   _range_outvalue(_mx_outvalue - _mn_outvalue),
   _radius(parameters.get<Real>("radius")),
   _center(_x1,_y1,_z1)
{
  mooseAssert(_range_invalue >= 0.0, "Inside Min > Max for RndSmoothCircleIC!");
  mooseAssert(_range_outvalue >= 0.0, "Outside Min > Max for RndSmoothCircleIC!");
  Moose::seed(getParam<unsigned int>("seed"));
}

Real
RndSmoothCircleIC::value(const Point & p)
{
  Real value = 0.0;

  Real rad = 0.0;

  for(unsigned int i=0; i<LIBMESH_DIM; i++)
    rad += (p(i)-_center(i)) * (p(i)-_center(i));

  rad = sqrt(rad);

  //Random number between 0 and 1
  Real rand_num = Moose::rand();

  if (rad <= _radius)
    value = _mn_invalue + rand_num*(_range_invalue);
  else if (rad < 1.5*_radius)
  {
    Real av_invalue = (_mn_invalue + _mx_invalue)/2.0;
    Real av_outvalue = (_mn_outvalue + _mx_outvalue)/2.0;
    value = av_outvalue + (av_invalue-av_outvalue)*(1+cos((rad-_radius)/_radius*2.0*3.14159))/2.0;
  }
  else
    value = _mx_outvalue + rand_num*(_range_outvalue);

  return value;

}

<|endoftext|>


<commit_before>#include <CQTitleBar.h>

#include <QPainter>
#include <QStylePainter>
#include <QStyleOptionToolButton>

// create title bar
CQTitleBar::
CQTitleBar(Qt::Orientation orient, QWidget *parent) :
 QWidget(parent), title_(), icon_(), orient_(orient), border_(2),
 bgColor_(160,160,160), barColor_(120,120,120), buttons_()
{
  setObjectName("title");
}

// create title bar (swapped args)
CQTitleBar::
CQTitleBar(QWidget *parent, Qt::Orientation orient) :
 QWidget(parent), title_(), icon_(), orient_(orient), border_(2),
 bgColor_(160,160,160), barColor_(120,120,120), buttons_()
{
  setObjectName("title");
}

// set title
void
CQTitleBar::
setTitle(const QString &title)
{
  title_ = title;

  if (isVisible())
    update();
}

// set icon
void
CQTitleBar::
setIcon(const QIcon &icon)
{
  icon_ = icon;

  if (isVisible())
    update();
}

// set orientation
void
CQTitleBar::
setOrientation(Qt::Orientation orient)
{
  orient_ = orient;

  if (isVisible())
    updateLayout();
}

// set border
void
CQTitleBar::
setBorder(int border)
{
  border_ = border;

  if (isVisible())
    updateLayout();
}

// set background color
void
CQTitleBar::
setBackgroundColor(const QColor &color)
{
  bgColor_ = color;

  if (isVisible())
    update();
}

// set title bar line color
void
CQTitleBar::
setBarColor(const QColor &color)
{
  barColor_ = color;

  if (isVisible())
    update();
}

// add icon button
CQTitleBarButton *
CQTitleBar::
addButton(const QIcon &icon)
{
  CQTitleBarButton *button = new CQTitleBarButton;

  button->setIcon(icon);

  addButton(button);

  return button;
}

// add button widget
void
CQTitleBar::
addButton(CQTitleBarButton *button)
{
  button->setParent(this);

  button->setTitleBar(this);

  buttons_.push_back(button);

  updateLayout();
}

// handle show event
void
CQTitleBar::
showEvent(QShowEvent *)
{
  updateLayout();
}

// handle paint event
void
CQTitleBar::
paintEvent(QPaintEvent *)
{
  int b  = border();
  int b1 = std::max(b, 1);

  QPainter p(this);

  QColor bgColor = this->backgroundColor();

  p.fillRect(rect(), bgColor);

  QColor barColor = this->barColor();

  drawTitleBarLines(&p, rect(), barColor);

  QIcon   icon  = this->icon();
  QString title = this->title();

  int x = 0;

  if (orientation() == Qt::Horizontal) {
    if (! icon.isNull()) {
      int ps = height() - 2*b1;

      p.fillRect(QRect(x, 0, ps + 2*b1, height()), bgColor);

      p.drawPixmap(x + 2, 2, icon.pixmap(QSize(ps,ps)));

      x += ps + 2*b1;
    }

    if (! title.isEmpty()) {
      QFontMetrics fm(font());

      int tw = fm.width(title);
      int th = fm.boundingRect(title).height();

      p.fillRect(QRect(x, 0, tw + 8, height()), bgColor);

      p.setPen(palette().color(QPalette::Text));

      p.drawText(x + 2, (height() - th)/2 + fm.ascent(), title);
    }
  }
  else {
    int y = height() - 1;

    if (! icon.isNull()) {
      int ps = width() - 2*b1;

      p.fillRect(QRect(0, y - ps - 2*b1, width(), ps + 2*b1), bgColor);

      p.save();

      p.translate(0, height());
      p.rotate(-90);

      //p.drawPixmap(2, y - ps - 2, icon.pixmap(QSize(ps,ps)));
      p.drawPixmap(x + 2, 2, icon.pixmap(QSize(ps,ps)));

      p.restore();

      y -= ps + 2*b1;
      x += ps + 2*b1;
    }

    if (! title.isEmpty()) {
      QFontMetrics fm(font());

      int tw = fm.width(title);
      int th = fm.boundingRect(title).height();

      p.save();

      p.fillRect(QRect(0, y - tw - 8, width(), tw + 8), bgColor);

      p.setPen(palette().color(QPalette::Text));

      p.translate(0, height());
      p.rotate(-90);

      p.drawText(x + 2, (width() - th)/2 + fm.ascent(), title);

      p.restore();
    }
  }

  int bw = (orientation() == Qt::Horizontal ? height() - 2*b1 : width() - 2*b1);

  int nb = 0;

  for (uint i = 0; i < buttons_.size(); ++i)
    if (buttons_[i]->isVisible())
      ++nb;

  if (orientation() == Qt::Horizontal)
    p.fillRect(QRect(width() - nb*bw, 0, nb*bw, height()), bgColor);
  else
    p.fillRect(QRect(0, 0, width(), nb*bw), bgColor);
}

// handle resize event
void
CQTitleBar::
resizeEvent(QResizeEvent *)
{
  updateLayout();
}

// update layout
void
CQTitleBar::
updateLayout()
{
  if (! isVisible()) return;

  int b  = border();
  int b1 = std::max(b, 1);

  QFontMetrics fm(font());

  if (orientation() == Qt::Horizontal) {
    setFixedHeight(fm.height() + 2*b);
    setMinimumWidth(0); setMaximumWidth(QWIDGETSIZE_MAX);
  }
  else {
    setFixedWidth(fm.height() + 2*b);
    setMinimumHeight(0); setMaximumHeight(QWIDGETSIZE_MAX);
  }

  //------

  int bw = (orientation() == Qt::Horizontal ? height() - 2*b1 : width() - 2*b1);

  int nb = buttons_.size();

  int pos = (orientation() == Qt::Horizontal ? width() - 2 : 2);

  for (int i = nb - 1; i >= 0; --i) {
    CQTitleBarButton *button = buttons_[i];

    if (! button->isVisible())
      continue;

    if (orientation() == Qt::Horizontal) {
      int dh = height() - button->height();

      button->move(pos - bw, dh/2);

      pos -= bw;
    }
    else {
      int dw = width() - button->width();

      button->move(dw/2, pos);

      pos += bw;
    }
  }
}

// draw title lines
void
CQTitleBar::
drawTitleBarLines(QPainter *p, const QRect &r, const QColor &c)
{
  p->setPen(c);

  if (orientation() == Qt::Horizontal) {
    int left  = r.left () + 2;
    int right = r.right() - 2;

    int y = r.center().y() - 3;

    for (int i = 0; i < 4; ++i) {
      int y1 = y + 2*i;

      p->drawLine(left, y1, right, y1);
    }
  }
  else {
    int top    = r.top   () + 2;
    int bottom = r.bottom() - 2;

    int x = r.center().x() - 3;

    for (int i = 0; i < 4; ++i) {
      int x1 = x + 2*i;

      p->drawLine(x1, top, x1, bottom);
    }
  }
}

// check if point inside title (not in button area)
bool
CQTitleBar::
insideTitle(const QPoint &pos) const
{
  int b  = border();
  int b1 = std::max(b, 1);

  int bw = (orientation() == Qt::Horizontal ? height() - 2*b1 : width() - 2*b1);

  int nb = 0;

  for (uint i = 0; i < buttons_.size(); ++i)
    if (buttons_[i]->isVisible())
      ++nb;

  if (orientation() == Qt::Horizontal)
    return (pos.x() < width() - nb*bw - 2*b1);
  else
    return (pos.y() > nb*bw + 2*b1);
}

// return size hint
QSize
CQTitleBar::
sizeHint() const
{
  int b = border();

  QFontMetrics fm(font());

  int h = fm.height() + 2*b;
  int w = 0;

  int nb = 0;

  for (uint i = 0; i < buttons_.size(); ++i)
    if (buttons_[i]->isVisible())
      ++nb;

  w += nb*h;

  if (! icon().isNull()) w += h;

  if (! title().isEmpty())
    w += fm.width(title());

  w = std::max(w, h);

  if (orientation() != Qt::Horizontal)
    std::swap(w, h);

  return QSize(w, h);
}

// return minimum size hint
QSize
CQTitleBar::
minimumSizeHint() const
{
  int b = border();

  QFontMetrics fm(font());

  int w, h;

  if (orientation() == Qt::Horizontal) {
    h = fm.height() + 2*b;
    w = h;
  }
  else {
    w = fm.height() + 2*b;
    h = w;
  }

  return QSize(w, h);
}

//------

// create title button
CQTitleBarButton::
CQTitleBarButton(QWidget *parent) :
 QToolButton(parent), bar_(0)
{
  setObjectName("button");

  setIconSize(QSize(10,10));

  setAutoRaise(true);

  setFocusPolicy(Qt::NoFocus);

  setCursor(Qt::ArrowCursor);
}

// handle draw
void
CQTitleBarButton::
paintEvent(QPaintEvent *)
{
  QStylePainter p(this);

  QStyleOptionToolButton opt;

#if 0
  opt.initFrom(this);

  opt.iconSize = iconSize(); //default value

  opt.icon = icon();

  if (isDown())
    opt.state |= QStyle::State_Sunken;
  else
    opt.state |= QStyle::State_Raised;

  opt.state |= QStyle::State_AutoRaise;

  opt.subControls = QStyle::SC_ToolButton;

  if (isDown())
    opt.activeSubControls = QStyle::SC_ToolButton;
  else
    opt.activeSubControls = QStyle::SC_None;

  opt.features = QStyleOptionToolButton::None;

  opt.toolButtonStyle = Qt::ToolButtonIconOnly;

  opt.pos  = pos();
  opt.font = font();
#else
  initStyleOption(&opt);
#endif

  if (bar_ && bar_->orientation() == Qt::Vertical) {
    p.translate(0, height());
    p.rotate(-90);
  }

  p.drawComplexControl(QStyle::CC_ToolButton, opt);
}
<commit_msg>new files<commit_after>#include <CQTitleBar.h>

#include <QPainter>
#include <QStylePainter>
#include <QStyleOptionToolButton>

// create title bar
CQTitleBar::
CQTitleBar(Qt::Orientation orient, QWidget *parent) :
 QWidget(parent), title_(), icon_(), orient_(orient), border_(2),
 bgColor_(160,160,160), barColor_(120,120,120), buttons_()
{
  setObjectName("title");
}

// create title bar (swapped args)
CQTitleBar::
CQTitleBar(QWidget *parent, Qt::Orientation orient) :
 QWidget(parent), title_(), icon_(), orient_(orient), border_(2),
 bgColor_(160,160,160), barColor_(120,120,120), buttons_()
{
  setObjectName("title");
}

// set title
void
CQTitleBar::
setTitle(const QString &title)
{
  title_ = title;

  if (isVisible())
    update();
}

// set icon
void
CQTitleBar::
setIcon(const QIcon &icon)
{
  icon_ = icon;

  if (isVisible())
    update();
}

// set orientation
void
CQTitleBar::
setOrientation(Qt::Orientation orient)
{
  orient_ = orient;

  if (isVisible())
    updateLayout();
}

// set border
void
CQTitleBar::
setBorder(int border)
{
  border_ = border;

  if (isVisible())
    updateLayout();
}

// set background color
void
CQTitleBar::
setBackgroundColor(const QColor &color)
{
  bgColor_ = color;

  if (isVisible())
    update();
}

// set title bar line color
void
CQTitleBar::
setBarColor(const QColor &color)
{
  barColor_ = color;

  if (isVisible())
    update();
}

// add icon button
CQTitleBarButton *
CQTitleBar::
addButton(const QIcon &icon)
{
  CQTitleBarButton *button = new CQTitleBarButton;

  button->setIcon(icon);

  addButton(button);

  return button;
}

// add button widget
void
CQTitleBar::
addButton(CQTitleBarButton *button)
{
  button->setParent(this);

  button->setTitleBar(this);

  buttons_.push_back(button);

  updateLayout();
}

// handle show event
void
CQTitleBar::
showEvent(QShowEvent *)
{
  updateLayout();
}

// handle paint event
void
CQTitleBar::
paintEvent(QPaintEvent *)
{
  int b  = border();
  int b1 = std::max(b, 1);

  QPainter p(this);

  QColor bgColor = this->backgroundColor();

  p.fillRect(rect(), bgColor);

  QColor barColor = this->barColor();

  drawTitleBarLines(&p, rect(), barColor);

  QIcon   icon  = this->icon();
  QString title = this->title();

  int x = 0;

  if (orientation() == Qt::Horizontal) {
    if (! icon.isNull()) {
      int ps = height() - 2*b1;

      p.fillRect(QRect(x, 0, ps + 2*b1, height()), bgColor);

      p.drawPixmap(x + 2, 2, icon.pixmap(QSize(ps,ps)));

      x += ps + 2*b1;
    }

    if (! title.isEmpty()) {
      QFontMetrics fm(font());

      int tw = fm.width(title);
      int th = fm.boundingRect(title).height();

      p.fillRect(QRect(x, 0, tw + 8, height()), bgColor);

      p.setPen(palette().color(QPalette::Text));

      p.drawText(x + 2, (height() - th)/2 + fm.ascent(), title);
    }
  }
  else {
    int y = height() - 1;

    if (! icon.isNull()) {
      int ps = width() - 2*b1;

      p.fillRect(QRect(0, y - ps - 2*b1, width(), ps + 2*b1), bgColor);

      p.save();

      p.translate(0, height());
      p.rotate(-90);

      //p.drawPixmap(2, y - ps - 2, icon.pixmap(QSize(ps,ps)));
      p.drawPixmap(x + 2, 2, icon.pixmap(QSize(ps,ps)));

      p.restore();

      y -= ps + 2*b1;
      x += ps + 2*b1;
    }

    if (! title.isEmpty()) {
      QFontMetrics fm(font());

      int tw = fm.width(title);
      int th = fm.boundingRect(title).height();

      p.save();

      p.fillRect(QRect(0, y - tw - 8, width(), tw + 8), bgColor);

      p.setPen(palette().color(QPalette::Text));

      p.translate(0, height());
      p.rotate(-90);

      p.drawText(x + 2, (width() - th)/2 + fm.ascent(), title);

      p.restore();
    }
  }

  int bw = (orientation() == Qt::Horizontal ? height() - 2*b1 : width() - 2*b1);

  int nb = 0;

  for (uint i = 0; i < buttons_.size(); ++i)
    if (buttons_[i]->isVisible())
      ++nb;

  if (orientation() == Qt::Horizontal)
    p.fillRect(QRect(width() - nb*bw, 0, nb*bw, height()), bgColor);
  else
    p.fillRect(QRect(0, 0, width(), nb*bw), bgColor);
}

// handle resize event
void
CQTitleBar::
resizeEvent(QResizeEvent *)
{
  updateLayout();
}

// update layout
void
CQTitleBar::
updateLayout()
{
  if (! isVisible()) return;

  int b  = border();
  int b1 = std::max(b, 1);

  QFontMetrics fm(font());

  if (orientation() == Qt::Horizontal) {
    setFixedHeight(fm.height() + 2*b);
    setMinimumWidth(0); setMaximumWidth(QWIDGETSIZE_MAX);
  }
  else {
    setFixedWidth(fm.height() + 2*b);
    setMinimumHeight(0); setMaximumHeight(QWIDGETSIZE_MAX);
  }

  //------

  int bw = (orientation() == Qt::Horizontal ? height() - 2*b1 : width() - 2*b1);

  int nb = int(buttons_.size());

  int pos = (orientation() == Qt::Horizontal ? width() - 2 : 2);

  for (int i = nb - 1; i >= 0; --i) {
    auto *button = buttons_[uint(i)];

    if (! button->isVisible())
      continue;

    if (orientation() == Qt::Horizontal) {
      int dh = height() - button->height();

      button->move(pos - bw, dh/2);

      pos -= bw;
    }
    else {
      int dw = width() - button->width();

      button->move(dw/2, pos);

      pos += bw;
    }
  }
}

// draw title lines
void
CQTitleBar::
drawTitleBarLines(QPainter *p, const QRect &r, const QColor &c)
{
  p->setPen(c);

  if (orientation() == Qt::Horizontal) {
    int left  = r.left () + 2;
    int right = r.right() - 2;

    int y = r.center().y() - 3;

    for (int i = 0; i < 4; ++i) {
      int y1 = y + 2*i;

      p->drawLine(left, y1, right, y1);
    }
  }
  else {
    int top    = r.top   () + 2;
    int bottom = r.bottom() - 2;

    int x = r.center().x() - 3;

    for (int i = 0; i < 4; ++i) {
      int x1 = x + 2*i;

      p->drawLine(x1, top, x1, bottom);
    }
  }
}

// check if point inside title (not in button area)
bool
CQTitleBar::
insideTitle(const QPoint &pos) const
{
  int b  = border();
  int b1 = std::max(b, 1);

  int bw = (orientation() == Qt::Horizontal ? height() - 2*b1 : width() - 2*b1);

  int nb = 0;

  for (uint i = 0; i < buttons_.size(); ++i)
    if (buttons_[i]->isVisible())
      ++nb;

  if (orientation() == Qt::Horizontal)
    return (pos.x() < width() - nb*bw - 2*b1);
  else
    return (pos.y() > nb*bw + 2*b1);
}

// return size hint
QSize
CQTitleBar::
sizeHint() const
{
  int b = border();

  QFontMetrics fm(font());

  int h = fm.height() + 2*b;
  int w = 0;

  int nb = 0;

  for (uint i = 0; i < buttons_.size(); ++i)
    if (buttons_[i]->isVisible())
      ++nb;

  w += nb*h;

  if (! icon().isNull()) w += h;

  if (! title().isEmpty())
    w += fm.width(title());

  w = std::max(w, h);

  if (orientation() != Qt::Horizontal)
    std::swap(w, h);

  return QSize(w, h);
}

// return minimum size hint
QSize
CQTitleBar::
minimumSizeHint() const
{
  int b = border();

  QFontMetrics fm(font());

  int w, h;

  if (orientation() == Qt::Horizontal) {
    h = fm.height() + 2*b;
    w = h;
  }
  else {
    w = fm.height() + 2*b;
    h = w;
  }

  return QSize(w, h);
}

//------

// create title button
CQTitleBarButton::
CQTitleBarButton(QWidget *parent) :
 QToolButton(parent), bar_(0)
{
  setObjectName("button");

  setIconSize(QSize(10,10));

  setAutoRaise(true);

  setFocusPolicy(Qt::NoFocus);

  setCursor(Qt::ArrowCursor);
}

// handle draw
void
CQTitleBarButton::
paintEvent(QPaintEvent *)
{
  QStylePainter p(this);

  QStyleOptionToolButton opt;

#if 0
  opt.initFrom(this);

  opt.iconSize = iconSize(); //default value

  opt.icon = icon();

  if (isDown())
    opt.state |= QStyle::State_Sunken;
  else
    opt.state |= QStyle::State_Raised;

  opt.state |= QStyle::State_AutoRaise;

  opt.subControls = QStyle::SC_ToolButton;

  if (isDown())
    opt.activeSubControls = QStyle::SC_ToolButton;
  else
    opt.activeSubControls = QStyle::SC_None;

  opt.features = QStyleOptionToolButton::None;

  opt.toolButtonStyle = Qt::ToolButtonIconOnly;

  opt.pos  = pos();
  opt.font = font();
#else
  initStyleOption(&opt);
#endif

  if (bar_ && bar_->orientation() == Qt::Vertical) {
    p.translate(0, height());
    p.rotate(-90);
  }

  p.drawComplexControl(QStyle::CC_ToolButton, opt);
}
<|endoftext|>


<commit_before>#include"../header/thread/CSemaphore.hpp"
#include<atomic>
#include<condition_variable>
#include<mutex>
using namespace std;

namespace nThread
{
	class CSemaphore::Impl
	{
		atomic<CSemaphore::size_type> count_;
		condition_variable cv_;
		mutex mut_;
	public:
		Impl(CSemaphore::size_type);
		inline CSemaphore::size_type count() const noexcept
		{
			return count_;
		}
		void signal();
		void wait();
	};

	CSemaphore::Impl::Impl(const CSemaphore::size_type count)
		:count_{count}{}

	void CSemaphore::Impl::signal()
	{
		if(!count_++)
		{
			lock_guard<mutex> lock{mut_};
			cv_.notify_all();
		}
	}

	void CSemaphore::Impl::wait()
	{
		unique_lock<mutex> lock{mut_};
		cv_.wait(lock,[this]() noexcept{return count();});
		--count_;
	}

	CSemaphore::CSemaphore()
		:CSemaphore{0}{}

	CSemaphore::CSemaphore(const CSemaphore::size_type count)
		:impl_{count}{}

	CSemaphore::size_type CSemaphore::count() const noexcept
	{
		return impl_.get().count();
	}

	void CSemaphore::signal()
	{
		impl_.get().signal();
	}

	void CSemaphore::wait()
	{
		impl_.get().wait();
	}

	CSemaphore::~CSemaphore(){}

	class CReaders_Writers_Problem::Impl
	{
		atomic<CSemaphore::size_type> count_;
		CSemaphore use_,wait_,writing_;
	public:
		Impl();
		void readBegin();
		void readEnd();
		void writeBegin();
		inline void writeEnd()
		{
			use_.signal();
		}
	};

	CReaders_Writers_Problem::Impl::Impl()
		:count_{0},use_{1},wait_{1},writing_{1}{}

	void CReaders_Writers_Problem::Impl::readBegin()
	{
		wait_.wait();
		writing_.wait();	//must
		if(++count_==1)
			use_.wait();
		wait_.signal();
		writing_.signal();	//can this line put prior to wait_.signal()?
	}

	void CReaders_Writers_Problem::Impl::readEnd()
	{
		//writing_.wait();	//atomic is enough, I think
		if(!--count_)
			use_.signal();
		//writing_.signal();	//atomic is enough, I think
	}

	void CReaders_Writers_Problem::Impl::writeBegin()
	{
		wait_.wait();
		use_.wait();
		wait_.signal();
	}

	CReaders_Writers_Problem::CReaders_Writers_Problem(){}

	void CReaders_Writers_Problem::readBegin()
	{
		impl_.get().readBegin();
	}

	void CReaders_Writers_Problem::readEnd()
	{
		impl_.get().readEnd();
	}

	void CReaders_Writers_Problem::writeBegin()
	{
		impl_.get().writeBegin();
	}

	void CReaders_Writers_Problem::writeEnd()
	{
		impl_.get().writeEnd();
	}

	CReaders_Writers_Problem::~CReaders_Writers_Problem(){}
}<commit_msg>use =default<commit_after>#include"../header/thread/CSemaphore.hpp"
#include<atomic>
#include<condition_variable>
#include<mutex>
using namespace std;

namespace nThread
{
	class CSemaphore::Impl
	{
		atomic<CSemaphore::size_type> count_;
		condition_variable cv_;
		mutex mut_;
	public:
		Impl(CSemaphore::size_type);
		inline CSemaphore::size_type count() const noexcept
		{
			return count_;
		}
		void signal();
		void wait();
	};

	CSemaphore::Impl::Impl(const CSemaphore::size_type count)
		:count_{count}{}

	void CSemaphore::Impl::signal()
	{
		if(!count_++)
		{
			lock_guard<mutex> lock{mut_};
			cv_.notify_all();
		}
	}

	void CSemaphore::Impl::wait()
	{
		unique_lock<mutex> lock{mut_};
		cv_.wait(lock,[this]() noexcept{return count();});
		--count_;
	}

	CSemaphore::CSemaphore()
		:CSemaphore{0}{}

	CSemaphore::CSemaphore(const CSemaphore::size_type count)
		:impl_{count}{}

	CSemaphore::size_type CSemaphore::count() const noexcept
	{
		return impl_.get().count();
	}

	void CSemaphore::signal()
	{
		impl_.get().signal();
	}

	void CSemaphore::wait()
	{
		impl_.get().wait();
	}

	CSemaphore::~CSemaphore()=default;

	class CReaders_Writers_Problem::Impl
	{
		atomic<CSemaphore::size_type> count_;
		CSemaphore use_,wait_,writing_;
	public:
		Impl();
		void readBegin();
		void readEnd();
		void writeBegin();
		inline void writeEnd()
		{
			use_.signal();
		}
	};

	CReaders_Writers_Problem::Impl::Impl()
		:count_{0},use_{1},wait_{1},writing_{1}{}

	void CReaders_Writers_Problem::Impl::readBegin()
	{
		wait_.wait();
		writing_.wait();	//must
		if(++count_==1)
			use_.wait();
		wait_.signal();
		writing_.signal();	//can this line put prior to wait_.signal()?
	}

	void CReaders_Writers_Problem::Impl::readEnd()
	{
		//writing_.wait();	//atomic is enough, I think
		if(!--count_)
			use_.signal();
		//writing_.signal();	//atomic is enough, I think
	}

	void CReaders_Writers_Problem::Impl::writeBegin()
	{
		wait_.wait();
		use_.wait();
		wait_.signal();
	}

	CReaders_Writers_Problem::CReaders_Writers_Problem()=default;

	void CReaders_Writers_Problem::readBegin()
	{
		impl_.get().readBegin();
	}

	void CReaders_Writers_Problem::readEnd()
	{
		impl_.get().readEnd();
	}

	void CReaders_Writers_Problem::writeBegin()
	{
		impl_.get().writeBegin();
	}

	void CReaders_Writers_Problem::writeEnd()
	{
		impl_.get().writeEnd();
	}

	CReaders_Writers_Problem::~CReaders_Writers_Problem()=default;
}<|endoftext|>


<commit_before>#include "types.h"
#include "multiboot.hh"
#include "kernel.hh"
#include "spinlock.h"
#include "kalloc.hh"
#include "cpu.hh"
#include "amd64.h"
#include "hwvm.hh"
#include "condvar.h"
#include "proc.hh"
#include "apic.hh"
#include "codex.hh"
#include "mfs.hh"

void initpic(void);
void initextpic(void);
void inituart(void);
void inituartcons(void);
void initcga(void);
void initconsole(void);
void initpg(void);
void cleanuppg(void);
void inittls(struct cpu *);
void initnmi(void);
void initcodex(void);
void inittrap(void);
void initseg(struct cpu *);
void initphysmem(paddr mbaddr);
void initpercpu(void);
void initkalloc(void);
void initz(void);
void initrcu(void);
void initproc(void);
void initinode(void);
void initdisk(void);
void inituser(void);
void initsamp(void);
void inite1000(void);
void initpci(void);
void initnet(void);
void initsched(void);
void initlockstat(void);
void initwq(void);
void initidle(void);
void initcpprt(void);
void initfutex(void);
void initcmdline(void);
void initdistref(void);
void initrefcache(void);
void initacpitables(void);
void initnuma(void);
void initcpus(void);
void initlapic(void);
void initiommu(void);
void initacpi(void);
void initwd(void);
void initdev(void);
void idleloop(void);

#define IO_RTC  0x70

static std::atomic<int> bstate;
static cpuid_t bcpuid;

void
mpboot(void)
{
  initseg(&cpus[bcpuid]);
  inittls(&cpus[bcpuid]);       // Requires initseg
  initpg();

  // Call per-CPU static initializers.  This is the per-CPU equivalent
  // of the init_array calls in cmain.
  extern void (*__percpuinit_array_start[])(size_t);
  extern void (*__percpuinit_array_end[])(size_t);
  for (size_t i = 0; i < __percpuinit_array_end - __percpuinit_array_start; i++)
      (*__percpuinit_array_start[i])(bcpuid);

  initlapic();
  initsamp();
  initidle();
  initnmi();
  initwd();                     // Requires initnmi
  bstate.store(1);
  idleloop();
}

static void
warmreset(u32 addr)
{
  volatile u16 *wrv;

  // "The BSP must initialize CMOS shutdown code to 0AH
  // and the warm reset vector (DWORD based at 40:67) to point at
  // the AP startup code prior to the [universal startup algorithm]."
  outb(IO_RTC, 0xF);  // offset 0xF is shutdown code
  outb(IO_RTC+1, 0x0A);
  wrv = (u16*)p2v(0x40<<4 | 0x67);  // Warm reset vector
  wrv[0] = 0;
  wrv[1] = addr >> 4;
}

static void
rstrreset(void)
{
  volatile u16 *wrv;

  // Paranoid: set warm reset code and vector back to defaults
  outb(IO_RTC, 0xF);
  outb(IO_RTC+1, 0);
  wrv = (u16*)p2v(0x40<<4 | 0x67);
  wrv[0] = 0;
  wrv[1] = 0;
}

static void
bootothers(void)
{
  extern u8 _bootother_start[];
  extern u64 _bootother_size;
  extern void (*apstart)(void);
  char *stack;
  u8 *code;

  // Write bootstrap code to unused memory at 0x7000.
  // The linker has placed the image of bootother.S in
  // _binary_bootother_start.
  code = (u8*) p2v(0x7000);
  memmove(code, _bootother_start, _bootother_size);

  for (int i = 0; i < ncpu; ++i) {
    if(i == myid())  // We've started already.
      continue;
    struct cpu *c = &cpus[i];

    warmreset(v2p(code));

    // Tell bootother.S what stack to use and the address of apstart;
    // it expects to find these two addresses stored just before
    // its first instruction.
    stack = (char*) ksalloc(slab_stack);
    *(u32*)(code-4) = (u32)v2p(&apstart);
    *(u64*)(code-12) = (u64)stack + KSTACKSIZE;
    // bootother.S sets this to 0x0a55face early on
    *(u32*)(code-64) = 0;

    bstate.store(0);
    bcpuid = c->id;
    lapic->start_ap(c, v2p(code));
#if CODEX
    codex_magic_action_run_thread_create(c->id);
#endif
    // Wait for cpu to finish mpmain()
    while(bstate.load() == 0)
      ;
    rstrreset();
  }
}

void
cmain(u64 mbmagic, u64 mbaddr)
{
  extern u64 cpuhz;

  // Make cpus[0] work.  CPU 0's percpu data is pre-allocated directly
  // in the image.  *cpu and such won't work until we inittls.
  percpu_offsets[0] = __percpu_start;

  inituart();
  initphysmem(mbaddr);
  initpg();                // Requires initphysmem
  inithz();        // CPU Hz, microdelay
  initseg(&cpus[0]);
  inittls(&cpus[0]);       // Requires initseg

  initacpitables();        // Requires initpg, inittls
  initlapic();             // Requires initpg
  initnuma();              // Requires initacpitables, initlapic
  initpercpu();            // Requires initnuma
  initcpus();              // Requires initnuma, initpercpu,
                           // suggests initacpitables

  initpic();       // interrupt controller
  initiommu();             // Requires initlapic
  initextpic();            // Requires initpic
  // Interrupt routing is now configured

  inituartcons();          // Requires interrupt routing
  initcga();

  // Some global constructors require mycpu()->id (via myid()) which
  // we setup in inittls.  (Note that gcc 4.7 eliminated the .ctors
  // section entirely, but gcc has supported .init_array for some
  // time.)  Note that this will implicitly initialize CPU 0's per-CPU
  // objects as well.
  extern void (*__init_array_start[])(int, char **, char **);
  extern void (*__init_array_end[])(int, char **, char **);
  for (size_t i = 0; i < __init_array_end - __init_array_start; i++)
      (*__init_array_start[i])(0, nullptr, nullptr);

  inittrap();
  initcmdline();
  initkalloc();
  initwq();        // (after kalloc)
  initz();         // (after wq)
  initproc();      // process table
  initsched();     // scheduler run queues
  initidle();
  initgc();        // gc epochs and threads
  initdistref();   // distref collector thread
  initrefcache();  // Requires initsched
  initdisk();      // disk
  initinode();     // inode cache
  initconsole();
  initfutex();
  initsamp();
  initlockstat();
  initacpi();              // Requires initacpitables, initkalloc?
  inite1000();             // Before initpci
  initpci();               // Suggests initacpi
  initnet();
  initdev();               // Misc /dev nodes

  if (VERBOSE)
    cprintf("ncpu %d %lu MHz\n", ncpu, cpuhz / 1000000);

  inituser();      // first user process
  initnmi();

  // XXX hack until mnodes can load from disk
  extern void mfsload();
  mfsload();

#if CODEX
  initcodex();
#endif
  bootothers();    // start other processors
  cleanuppg();             // Requires bootothers
  initcpprt();
  initwd();                // Requires initnmi

  idleloop();

  panic("Unreachable");
}

void
halt(void)
{
  acpi_power_off();

  for (;;);
}
<commit_msg>another codex hint<commit_after>#include "types.h"
#include "multiboot.hh"
#include "kernel.hh"
#include "spinlock.h"
#include "kalloc.hh"
#include "cpu.hh"
#include "amd64.h"
#include "hwvm.hh"
#include "condvar.h"
#include "proc.hh"
#include "apic.hh"
#include "codex.hh"
#include "mfs.hh"

void initpic(void);
void initextpic(void);
void inituart(void);
void inituartcons(void);
void initcga(void);
void initconsole(void);
void initpg(void);
void cleanuppg(void);
void inittls(struct cpu *);
void initnmi(void);
void initcodex(void);
void inittrap(void);
void initseg(struct cpu *);
void initphysmem(paddr mbaddr);
void initpercpu(void);
void initkalloc(void);
void initz(void);
void initrcu(void);
void initproc(void);
void initinode(void);
void initdisk(void);
void inituser(void);
void initsamp(void);
void inite1000(void);
void initpci(void);
void initnet(void);
void initsched(void);
void initlockstat(void);
void initwq(void);
void initidle(void);
void initcpprt(void);
void initfutex(void);
void initcmdline(void);
void initdistref(void);
void initrefcache(void);
void initacpitables(void);
void initnuma(void);
void initcpus(void);
void initlapic(void);
void initiommu(void);
void initacpi(void);
void initwd(void);
void initdev(void);
void idleloop(void);

#define IO_RTC  0x70

static std::atomic<int> bstate;
static cpuid_t bcpuid;

void
mpboot(void)
{
  initseg(&cpus[bcpuid]);
  inittls(&cpus[bcpuid]);       // Requires initseg
  initpg();

  // Call per-CPU static initializers.  This is the per-CPU equivalent
  // of the init_array calls in cmain.
  extern void (*__percpuinit_array_start[])(size_t);
  extern void (*__percpuinit_array_end[])(size_t);
  for (size_t i = 0; i < __percpuinit_array_end - __percpuinit_array_start; i++)
      (*__percpuinit_array_start[i])(bcpuid);

  initlapic();
  initsamp();
  initidle();
  initnmi();
  initwd();                     // Requires initnmi
  bstate.store(1);
  idleloop();
}

static void
warmreset(u32 addr)
{
  volatile u16 *wrv;

  // "The BSP must initialize CMOS shutdown code to 0AH
  // and the warm reset vector (DWORD based at 40:67) to point at
  // the AP startup code prior to the [universal startup algorithm]."
  outb(IO_RTC, 0xF);  // offset 0xF is shutdown code
  outb(IO_RTC+1, 0x0A);
  wrv = (u16*)p2v(0x40<<4 | 0x67);  // Warm reset vector
  wrv[0] = 0;
  wrv[1] = addr >> 4;
}

static void
rstrreset(void)
{
  volatile u16 *wrv;

  // Paranoid: set warm reset code and vector back to defaults
  outb(IO_RTC, 0xF);
  outb(IO_RTC+1, 0);
  wrv = (u16*)p2v(0x40<<4 | 0x67);
  wrv[0] = 0;
  wrv[1] = 0;
}

static void
bootothers(void)
{
  extern u8 _bootother_start[];
  extern u64 _bootother_size;
  extern void (*apstart)(void);
  char *stack;
  u8 *code;

  // Write bootstrap code to unused memory at 0x7000.
  // The linker has placed the image of bootother.S in
  // _binary_bootother_start.
  code = (u8*) p2v(0x7000);
  memmove(code, _bootother_start, _bootother_size);

  for (int i = 0; i < ncpu; ++i) {
    if(i == myid())  // We've started already.
      continue;
    struct cpu *c = &cpus[i];

    warmreset(v2p(code));

    // Tell bootother.S what stack to use and the address of apstart;
    // it expects to find these two addresses stored just before
    // its first instruction.
    stack = (char*) ksalloc(slab_stack);
    *(u32*)(code-4) = (u32)v2p(&apstart);
    *(u64*)(code-12) = (u64)stack + KSTACKSIZE;
    // bootother.S sets this to 0x0a55face early on
    *(u32*)(code-64) = 0;

    bstate.store(0);
    bcpuid = c->id;
    lapic->start_ap(c, v2p(code));
#if CODEX
    codex_magic_action_run_thread_create(c->id);
#endif
    // Wait for cpu to finish mpmain()
    while(bstate.load() == 0)
      nop_pause();
    rstrreset();
  }
}

void
cmain(u64 mbmagic, u64 mbaddr)
{
  extern u64 cpuhz;

  // Make cpus[0] work.  CPU 0's percpu data is pre-allocated directly
  // in the image.  *cpu and such won't work until we inittls.
  percpu_offsets[0] = __percpu_start;

  inituart();
  initphysmem(mbaddr);
  initpg();                // Requires initphysmem
  inithz();        // CPU Hz, microdelay
  initseg(&cpus[0]);
  inittls(&cpus[0]);       // Requires initseg

  initacpitables();        // Requires initpg, inittls
  initlapic();             // Requires initpg
  initnuma();              // Requires initacpitables, initlapic
  initpercpu();            // Requires initnuma
  initcpus();              // Requires initnuma, initpercpu,
                           // suggests initacpitables

  initpic();       // interrupt controller
  initiommu();             // Requires initlapic
  initextpic();            // Requires initpic
  // Interrupt routing is now configured

  inituartcons();          // Requires interrupt routing
  initcga();

  // Some global constructors require mycpu()->id (via myid()) which
  // we setup in inittls.  (Note that gcc 4.7 eliminated the .ctors
  // section entirely, but gcc has supported .init_array for some
  // time.)  Note that this will implicitly initialize CPU 0's per-CPU
  // objects as well.
  extern void (*__init_array_start[])(int, char **, char **);
  extern void (*__init_array_end[])(int, char **, char **);
  for (size_t i = 0; i < __init_array_end - __init_array_start; i++)
      (*__init_array_start[i])(0, nullptr, nullptr);

  inittrap();
  initcmdline();
  initkalloc();
  initwq();        // (after kalloc)
  initz();         // (after wq)
  initproc();      // process table
  initsched();     // scheduler run queues
  initidle();
  initgc();        // gc epochs and threads
  initdistref();   // distref collector thread
  initrefcache();  // Requires initsched
  initdisk();      // disk
  initinode();     // inode cache
  initconsole();
  initfutex();
  initsamp();
  initlockstat();
  initacpi();              // Requires initacpitables, initkalloc?
  inite1000();             // Before initpci
  initpci();               // Suggests initacpi
  initnet();
  initdev();               // Misc /dev nodes

  if (VERBOSE)
    cprintf("ncpu %d %lu MHz\n", ncpu, cpuhz / 1000000);

  inituser();      // first user process
  initnmi();

  // XXX hack until mnodes can load from disk
  extern void mfsload();
  mfsload();

#if CODEX
  initcodex();
#endif
  bootothers();    // start other processors
  cleanuppg();             // Requires bootothers
  initcpprt();
  initwd();                // Requires initnmi

  idleloop();

  panic("Unreachable");
}

void
halt(void)
{
  acpi_power_off();

  for (;;);
}
<|endoftext|>


<commit_before>#ifdef __TEST__
#include "ArrayTest.h"

ArrayTest::ArrayTest( ) :
    allocator( Rumia::Allocator( ) ),
    arr( Rumia::Array<int>( allocator ) ),
    objArr( Rumia::Array<SomeClass>( allocator ) )
{
}

ArrayTest::~ArrayTest( )
{
}

void ArrayTest::SetUp( )
{
    arr.PushBack( 1 );
    arr.PushBack( 2 );
    arr.PushBack( 3 );
    arr.PushBack( 4 );
}

void ArrayTest::TearDown( )
{
    arr.Clear( );
    objArr.Clear( );
}

TEST_F( ArrayTest, Reserve )
{
    EXPECT_EQ( arr.GetCapacity( ), 4 );
    arr.Reserve( 8 );
    EXPECT_EQ( arr.GetCapacity( ), 8 );
    // arr.Reserve( 4 ); // it going to make assertion
}

TEST_F( ArrayTest, Resize )
{
    EXPECT_EQ( arr.GetSize( ), 4 );
    arr.Resize( 5 );
    EXPECT_EQ( arr.GetSize( ), 5 );
    arr.Resize( 4 );
    EXPECT_EQ( arr.GetSize( ), 4 );
    arr.Resize( 5, 999 );
    EXPECT_EQ( arr.GetSize( ), 5 );
    EXPECT_EQ( arr.At( 4 ), 999 );
}

TEST_F( ArrayTest, PushBack )
{
    EXPECT_EQ( arr.At( 0 ), 1 );
    EXPECT_EQ( arr.At( 1 ), 2 );
    EXPECT_EQ( arr.At( 2 ), 3 );
    EXPECT_EQ( arr.At( 3 ), 4 );
    EXPECT_EQ( arr.GetCapacity( ), 4 );
    EXPECT_EQ( arr.GetSize( ), 4 );
    arr.PushBack( 5 );
    EXPECT_EQ( arr.At( arr.GetSize( ) - 1 ), 5 );
    EXPECT_EQ( arr.GetCapacity( ), 8 );
    EXPECT_FALSE( arr.GetCapacity( ) == arr.GetSize( ) );
}

TEST_F( ArrayTest, PopBack )
{
    EXPECT_EQ( arr.PopBack( ), 4 );
    EXPECT_EQ( arr.GetSize( ), 3 );
    EXPECT_EQ( arr.PopBack( ), 3);
    EXPECT_EQ( arr.GetSize( ), 2 );
    EXPECT_EQ( arr.PopBack( ), 2 );
    EXPECT_EQ( arr.GetSize( ), 1 );
    EXPECT_EQ( arr.PopBack( ), 1 );
    EXPECT_EQ( arr.GetSize( ), 0 );
}

TEST_F( ArrayTest, Emplace )
{
    arr.Emplace( 5 );
    EXPECT_EQ( arr.GetSize( ), 5 );
    EXPECT_EQ( arr.GetCapacity( ), 8 );
    arr.Emplace( 6 );
    EXPECT_EQ( arr.GetSize( ), 6 );
    EXPECT_EQ( arr.At( arr.GetSize( ) - 1 ), 6 );
}

TEST_F( ArrayTest, Insert )
{
    arr.Insert( 0, -1 );
    EXPECT_EQ( arr.At( 0 ), -1 );
    EXPECT_EQ( arr.GetSize( ), 5 );
    EXPECT_EQ( arr.GetCapacity( ), 8 );
    arr.Insert( arr.GetSize( ) - 1, 1001 );
    EXPECT_EQ( arr.At( ( arr.GetSize( ) - 2 ) ), 1001 );
}

TEST_F( ArrayTest, IsEmpty )
{
    EXPECT_TRUE( !arr.IsEmpty( ) );
    arr.PopBack( );
    arr.PopBack( );
    arr.PopBack( );
    arr.PopBack( );
    EXPECT_TRUE( arr.IsEmpty( ) );
}

TEST_F( ArrayTest, IsFull )
{
    EXPECT_TRUE( arr.IsFull( ) );
    arr.PopBack( );
    EXPECT_FALSE( arr.IsFull( ) );
    arr.PushBack( 4 );
    arr.PushBack( -1 );
    EXPECT_FALSE( arr.IsFull( ) );
}

TEST_F( ArrayTest, Clear )
{
    arr.Clear( false );
    EXPECT_TRUE( arr.IsEmpty( ) );
    arr.Clear( true );
    EXPECT_EQ( arr.GetCapacity( ), 0 );
}

TEST_F( ArrayTest, Copy )
{
    Rumia::Array<int> copyConstructorObj{ arr };
    EXPECT_EQ( copyConstructorObj.PopBack( ), 4 );
    EXPECT_EQ( copyConstructorObj.PopBack( ), 3 );
    EXPECT_EQ( copyConstructorObj.PopBack( ), 2 );
    EXPECT_EQ( copyConstructorObj.PopBack( ), 1 );
    copyConstructorObj.PushBack( 999 );
    // arr and copyConstructorObj is not a same object!
    EXPECT_EQ( arr.PopBack( ), 4);

    Rumia::Array<int> anotherCopy{ allocator };
    anotherCopy = arr;
    EXPECT_EQ( anotherCopy.PopBack( ), 3 );
    EXPECT_EQ( anotherCopy.PopBack( ), 2 );
    EXPECT_EQ( anotherCopy.PopBack( ), 1 );
    EXPECT_TRUE( anotherCopy.IsEmpty( ) );
}

TEST_F( ArrayTest, Move )
{
    Rumia::Array<int> movedObj( std::move( arr ) );
    EXPECT_TRUE( arr.IsEmpty( ) );
    EXPECT_EQ( movedObj.PopBack( ), 4 );
    EXPECT_EQ( movedObj.PopBack( ), 3 );

    Rumia::Array<int> anotherMovedObj{ allocator };
    EXPECT_TRUE( anotherMovedObj.IsEmpty( ) );
    anotherMovedObj = std::move( movedObj );
    EXPECT_FALSE( anotherMovedObj.IsEmpty( ) );
    EXPECT_TRUE( movedObj.IsEmpty( ) );
    EXPECT_EQ( anotherMovedObj.PopBack( ), 2 );
    EXPECT_EQ( anotherMovedObj.PopBack( ), 1 );
}

TEST_F( ArrayTest, ObjectMove )
{
    SomeClass obj{ 30 };
    objArr.PushBack( obj );
    EXPECT_EQ( objArr.PopBack( ).m_data, 30 );
    EXPECT_EQ( obj.m_data, 30 );
    objArr.PushBack( std::move( obj ) );
    EXPECT_EQ( objArr.PopBack( ).m_data, 30 );
    EXPECT_EQ( obj.m_data, -1 );
}

TEST_F( ArrayTest, IndexOf )
{
    EXPECT_EQ( arr.IndexOf( 1 ), 0 );
    EXPECT_EQ( arr.IndexOf( 2 ), 1 );
    EXPECT_EQ( arr.IndexOf( 3 ), 2 );
    EXPECT_EQ( arr.IndexOf( 4 ), 3 );
    EXPECT_EQ( arr.IndexOf( 9999 ), arr.GetSize( ) );
}

TEST_F( ArrayTest, EraseAt )
{
    arr.EraseAt( 1 );
    EXPECT_EQ( arr.GetSize( ), 3 );
    EXPECT_EQ( arr.At( 1 ), 3 );
    EXPECT_EQ( arr.At( 2 ), 4 );
}

TEST_F( ArrayTest, Erase )
{
    arr.Erase( 2 );
    EXPECT_EQ( arr.GetSize( ), 3 );
    EXPECT_EQ( arr.At( 1 ), 3 );
    EXPECT_EQ( arr.At( 2 ), 4 );
    EXPECT_EQ( arr.IndexOf( 2 ), arr.GetSize( ) );
    arr.Erase( 999 );
    EXPECT_EQ( arr.GetSize( ), 3 );

    arr.Clear( );
    arr.PushBack( 1 );
    arr.PushBack( 2 );
    arr.Erase( arr.begin( ) );
    EXPECT_EQ( 2, arr.At( 0 ) );
}

TEST_F( ArrayTest, FindIf )
{
    arr.Clear( );
    arr.PushBack( 1 );
    arr.PushBack( 2 );
    arr.PushBack( 3 );

    int FoundData = ( *arr.FindIf( [ ]( int Data )->bool { return ( Data == 2 ); } ) );
    EXPECT_EQ( FoundData, 2 );
}

TEST_F( ArrayTest, ConstItr )
{
    arr.Clear( );
    arr.PushBack( 1 );
    arr.PushBack( 2 );
    arr.PushBack( 3 );

    int Counter = 1;
    for ( auto itr = arr.cbegin( ); itr != arr.cend( ); ++itr )
    {
        EXPECT_EQ( ( *itr ), Counter );
        ++Counter;
    }
}

TEST_F( ArrayTest, Shrink )
{
    arr.Clear( );
    arr.PushBack( 1 ); // Capacity 2
    arr.PushBack( 2 );
    arr.PushBack( 3 ); // Capacity 4
    arr.PushBack( 4 );
    arr.PushBack( 5 ); // Capacity 8

    EXPECT_EQ( arr.GetCapacity( ), 8 );
    arr.Shrink( );
    EXPECT_EQ( arr.GetCapacity( ), 5 );
    EXPECT_EQ( arr[ 4 ], 5 );
}

#endif<commit_msg>Added erase itr in loop test case<commit_after>#ifdef __TEST__
#include "ArrayTest.h"

ArrayTest::ArrayTest( ) :
    allocator( Rumia::Allocator( ) ),
    arr( Rumia::Array<int>( allocator ) ),
    objArr( Rumia::Array<SomeClass>( allocator ) )
{
}

ArrayTest::~ArrayTest( )
{
}

void ArrayTest::SetUp( )
{
    arr.PushBack( 1 );
    arr.PushBack( 2 );
    arr.PushBack( 3 );
    arr.PushBack( 4 );
}

void ArrayTest::TearDown( )
{
    arr.Clear( );
    objArr.Clear( );
}

TEST_F( ArrayTest, Reserve )
{
    EXPECT_EQ( arr.GetCapacity( ), 4 );
    arr.Reserve( 8 );
    EXPECT_EQ( arr.GetCapacity( ), 8 );
    // arr.Reserve( 4 ); // it going to make assertion
}

TEST_F( ArrayTest, Resize )
{
    EXPECT_EQ( arr.GetSize( ), 4 );
    arr.Resize( 5 );
    EXPECT_EQ( arr.GetSize( ), 5 );
    arr.Resize( 4 );
    EXPECT_EQ( arr.GetSize( ), 4 );
    arr.Resize( 5, 999 );
    EXPECT_EQ( arr.GetSize( ), 5 );
    EXPECT_EQ( arr.At( 4 ), 999 );
}

TEST_F( ArrayTest, PushBack )
{
    EXPECT_EQ( arr.At( 0 ), 1 );
    EXPECT_EQ( arr.At( 1 ), 2 );
    EXPECT_EQ( arr.At( 2 ), 3 );
    EXPECT_EQ( arr.At( 3 ), 4 );
    EXPECT_EQ( arr.GetCapacity( ), 4 );
    EXPECT_EQ( arr.GetSize( ), 4 );
    arr.PushBack( 5 );
    EXPECT_EQ( arr.At( arr.GetSize( ) - 1 ), 5 );
    EXPECT_EQ( arr.GetCapacity( ), 8 );
    EXPECT_FALSE( arr.GetCapacity( ) == arr.GetSize( ) );
}

TEST_F( ArrayTest, PopBack )
{
    EXPECT_EQ( arr.PopBack( ), 4 );
    EXPECT_EQ( arr.GetSize( ), 3 );
    EXPECT_EQ( arr.PopBack( ), 3);
    EXPECT_EQ( arr.GetSize( ), 2 );
    EXPECT_EQ( arr.PopBack( ), 2 );
    EXPECT_EQ( arr.GetSize( ), 1 );
    EXPECT_EQ( arr.PopBack( ), 1 );
    EXPECT_EQ( arr.GetSize( ), 0 );
}

TEST_F( ArrayTest, Emplace )
{
    arr.Emplace( 5 );
    EXPECT_EQ( arr.GetSize( ), 5 );
    EXPECT_EQ( arr.GetCapacity( ), 8 );
    arr.Emplace( 6 );
    EXPECT_EQ( arr.GetSize( ), 6 );
    EXPECT_EQ( arr.At( arr.GetSize( ) - 1 ), 6 );
}

TEST_F( ArrayTest, Insert )
{
    arr.Insert( 0, -1 );
    EXPECT_EQ( arr.At( 0 ), -1 );
    EXPECT_EQ( arr.GetSize( ), 5 );
    EXPECT_EQ( arr.GetCapacity( ), 8 );
    arr.Insert( arr.GetSize( ) - 1, 1001 );
    EXPECT_EQ( arr.At( ( arr.GetSize( ) - 2 ) ), 1001 );
}

TEST_F( ArrayTest, IsEmpty )
{
    EXPECT_TRUE( !arr.IsEmpty( ) );
    arr.PopBack( );
    arr.PopBack( );
    arr.PopBack( );
    arr.PopBack( );
    EXPECT_TRUE( arr.IsEmpty( ) );
}

TEST_F( ArrayTest, IsFull )
{
    EXPECT_TRUE( arr.IsFull( ) );
    arr.PopBack( );
    EXPECT_FALSE( arr.IsFull( ) );
    arr.PushBack( 4 );
    arr.PushBack( -1 );
    EXPECT_FALSE( arr.IsFull( ) );
}

TEST_F( ArrayTest, Clear )
{
    arr.Clear( false );
    EXPECT_TRUE( arr.IsEmpty( ) );
    arr.Clear( true );
    EXPECT_EQ( arr.GetCapacity( ), 0 );
}

TEST_F( ArrayTest, Copy )
{
    Rumia::Array<int> copyConstructorObj{ arr };
    EXPECT_EQ( copyConstructorObj.PopBack( ), 4 );
    EXPECT_EQ( copyConstructorObj.PopBack( ), 3 );
    EXPECT_EQ( copyConstructorObj.PopBack( ), 2 );
    EXPECT_EQ( copyConstructorObj.PopBack( ), 1 );
    copyConstructorObj.PushBack( 999 );
    // arr and copyConstructorObj is not a same object!
    EXPECT_EQ( arr.PopBack( ), 4);

    Rumia::Array<int> anotherCopy{ allocator };
    anotherCopy = arr;
    EXPECT_EQ( anotherCopy.PopBack( ), 3 );
    EXPECT_EQ( anotherCopy.PopBack( ), 2 );
    EXPECT_EQ( anotherCopy.PopBack( ), 1 );
    EXPECT_TRUE( anotherCopy.IsEmpty( ) );
}

TEST_F( ArrayTest, Move )
{
    Rumia::Array<int> movedObj( std::move( arr ) );
    EXPECT_TRUE( arr.IsEmpty( ) );
    EXPECT_EQ( movedObj.PopBack( ), 4 );
    EXPECT_EQ( movedObj.PopBack( ), 3 );

    Rumia::Array<int> anotherMovedObj{ allocator };
    EXPECT_TRUE( anotherMovedObj.IsEmpty( ) );
    anotherMovedObj = std::move( movedObj );
    EXPECT_FALSE( anotherMovedObj.IsEmpty( ) );
    EXPECT_TRUE( movedObj.IsEmpty( ) );
    EXPECT_EQ( anotherMovedObj.PopBack( ), 2 );
    EXPECT_EQ( anotherMovedObj.PopBack( ), 1 );
}

TEST_F( ArrayTest, ObjectMove )
{
    SomeClass obj{ 30 };
    objArr.PushBack( obj );
    EXPECT_EQ( objArr.PopBack( ).m_data, 30 );
    EXPECT_EQ( obj.m_data, 30 );
    objArr.PushBack( std::move( obj ) );
    EXPECT_EQ( objArr.PopBack( ).m_data, 30 );
    EXPECT_EQ( obj.m_data, -1 );
}

TEST_F( ArrayTest, IndexOf )
{
    EXPECT_EQ( arr.IndexOf( 1 ), 0 );
    EXPECT_EQ( arr.IndexOf( 2 ), 1 );
    EXPECT_EQ( arr.IndexOf( 3 ), 2 );
    EXPECT_EQ( arr.IndexOf( 4 ), 3 );
    EXPECT_EQ( arr.IndexOf( 9999 ), arr.GetSize( ) );
}

TEST_F( ArrayTest, EraseAt )
{
    arr.EraseAt( 1 );
    EXPECT_EQ( arr.GetSize( ), 3 );
    EXPECT_EQ( arr.At( 1 ), 3 );
    EXPECT_EQ( arr.At( 2 ), 4 );
}

TEST_F( ArrayTest, Erase )
{
    arr.Erase( 2 );
    EXPECT_EQ( arr.GetSize( ), 3 );
    EXPECT_EQ( arr.At( 1 ), 3 );
    EXPECT_EQ( arr.At( 2 ), 4 );
    EXPECT_EQ( arr.IndexOf( 2 ), arr.GetSize( ) );
    arr.Erase( 999 );
    EXPECT_EQ( arr.GetSize( ), 3 );

    arr.Clear( );
    arr.PushBack( 1 );
    arr.PushBack( 2 );
    arr.Erase( arr.begin( ) );
    EXPECT_EQ( 2, arr.At( 0 ) );

    arr.Clear( );
    arr.PushBack( 3 );
    arr.PushBack( 2 );
    arr.PushBack( 1 );

    for ( auto itr = arr.begin( ); itr != arr.end( ); ++itr )
    {
        if ( ( *itr ) == 2 )
        {
            arr.Erase( itr );
        }
    }

    EXPECT_EQ( 1, arr[ 1 ] );
    EXPECT_EQ( 3, ( *arr.begin( ) ) );
}

TEST_F( ArrayTest, FindIf )
{
    arr.Clear( );
    arr.PushBack( 1 );
    arr.PushBack( 2 );
    arr.PushBack( 3 );

    int FoundData = ( *arr.FindIf( [ ]( int Data )->bool { return ( Data == 2 ); } ) );
    EXPECT_EQ( FoundData, 2 );
}

TEST_F( ArrayTest, ConstItr )
{
    arr.Clear( );
    arr.PushBack( 1 );
    arr.PushBack( 2 );
    arr.PushBack( 3 );

    int Counter = 1;
    for ( auto itr = arr.cbegin( ); itr != arr.cend( ); ++itr )
    {
        EXPECT_EQ( ( *itr ), Counter );
        ++Counter;
    }
}

TEST_F( ArrayTest, Shrink )
{
    arr.Clear( );
    arr.PushBack( 1 ); // Capacity 2
    arr.PushBack( 2 );
    arr.PushBack( 3 ); // Capacity 4
    arr.PushBack( 4 );
    arr.PushBack( 5 ); // Capacity 8

    EXPECT_EQ( arr.GetCapacity( ), 8 );
    arr.Shrink( );
    EXPECT_EQ( arr.GetCapacity( ), 5 );
    EXPECT_EQ( arr[ 4 ], 5 );
}

#endif<|endoftext|>