<commit_before>/*
 The MIT License (MIT)

 Copyright (c) [2016] [BTC.COM]

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
*/
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <err.h>
#include <errno.h>
#include <unistd.h>

#include <iostream>

#include <boost/interprocess/sync/file_lock.hpp>
#include <glog/logging.h>
#include <libconfig.h++>

#include "zmq.hpp"

#include "Utils.h"
#include "ShareLogParser.h"

using namespace std;
using namespace libconfig;

std::shared_ptr<ShareLogParserServer> gShareLogParserServer = nullptr;

void handler(int sig) {
  if (gShareLogParserServer) {
    gShareLogParserServer->stop();
  }
}

void usage() {
  fprintf(stderr, "Usage:\n\tslparser -c \"slparser.cfg\" -l \"log_dir\"\n");
  fprintf(stderr, "\tslparser -c \"slparser.cfg\" -l \"log_dir2\" -d \"20160830\"\n");
  fprintf(stderr, "\tslparser -c \"slparser.cfg\" -l \"log_dir3\" -d \"20160830\" -u \"puid(0: dump all, >0: someone's)\"\n");
}

std::shared_ptr<ShareLogDumper> newShareLogDumper(const string &chainType, const string &dataDir,
                                                  time_t timestamp, const std::set<int32_t> &uids)
{
  if (chainType == "BTC") {
    return std::make_shared<ShareLogDumperBitcoin>(chainType.c_str(), dataDir, timestamp, uids);
  }
  else if (chainType == "ETH") {
    return std::make_shared<ShareLogDumperEth>(chainType.c_str(), dataDir, timestamp, uids);
  }
  else if (chainType == "BTM") {
    return std::make_shared<ShareLogDumperBytom>(chainType.c_str(), dataDir, timestamp, uids);
  }
  else {
    LOG(FATAL) << "newShareLogDumper: unknown chain type " << chainType;
    return nullptr;
  }
}

std::shared_ptr<ShareLogParser> newShareLogParser(const string &chainType, const string &dataDir,
                                                  time_t timestamp, const MysqlConnectInfo &poolDBInfo,
                                                  const int dupShareTrackingHeight)
{
  if (chainType == "BTC") {
    return std::make_shared<ShareLogParserBitcoin>(chainType.c_str(), dataDir, timestamp, poolDBInfo, nullptr);
  }
  else if (chainType == "ETH") {
    return std::make_shared<ShareLogParserEth>(chainType.c_str(), dataDir, timestamp, poolDBInfo,
                                               std::make_shared<DuplicateShareCheckerEth>(dupShareTrackingHeight));
  }
  else if (chainType == "BTM") {
    return std::make_shared<ShareLogParserBytom>(chainType.c_str(), dataDir, timestamp, poolDBInfo,
                                               std::make_shared<DuplicateShareCheckerBytom>(dupShareTrackingHeight));
  }
  else {
    LOG(FATAL) << "newShareLogParser: unknown chain type " << chainType;
    return nullptr;
  }
}

std::shared_ptr<ShareLogParserServer> newShareLogParserServer(const string &chainType, const string &dataDir,
                                                        const string &httpdHost, unsigned short httpdPort,
                                                        const MysqlConnectInfo &poolDBInfo,
                                                        const uint32_t kFlushDBInterval,
                                                        const int dupShareTrackingHeight)
{
  if (chainType == "BTC") {
    return std::make_shared<ShareLogParserServerBitcoin>(chainType.c_str(), dataDir,
                                                         httpdHost, httpdPort,
                                                         poolDBInfo, kFlushDBInterval, nullptr);
  }
  else if (chainType == "ETH") {
    return std::make_shared<ShareLogParserServerEth>(chainType.c_str(), dataDir,
                                                     httpdHost, httpdPort,
                                                     poolDBInfo, kFlushDBInterval,
                                                     std::make_shared<DuplicateShareCheckerEth>(dupShareTrackingHeight));
  }
  else if (chainType == "ETH") {
    return std::make_shared<ShareLogParserServerBytom>(chainType.c_str(), dataDir,
                                                     httpdHost, httpdPort,
                                                     poolDBInfo, kFlushDBInterval,
                                                     std::make_shared<DuplicateShareCheckerBytom>(dupShareTrackingHeight));
  }
  else {
    LOG(FATAL) << "newShareLogParserServer: unknown chain type " << chainType;
    return nullptr;
  }
}

int main(int argc, char **argv) {
  char *optLogDir = NULL;
  char *optConf   = NULL;
  int32_t optDate = 0;
  int32_t optPUID = -1;  // pool user id
  int c;

  if (argc <= 1) {
    usage();
    return 1;
  }
  while ((c = getopt(argc, argv, "c:l:d:u:h")) != -1) {
    switch (c) {
      case 'c':
        optConf = optarg;
        break;
      case 'l':
        optLogDir = optarg;
        break;
      case 'd':
        optDate = atoi(optarg);
        break;
      case 'u':
        optPUID = atoi(optarg);
        break;
      case 'h': default:
        usage();
        exit(0);
    }
  }

  // Initialize Google's logging library.
  google::InitGoogleLogging(argv[0]);
  FLAGS_log_dir         = string(optLogDir);
  // Log messages at a level >= this flag are automatically sent to
  // stderr in addition to log files.
  FLAGS_stderrthreshold = 3;    // 3: FATAL
  FLAGS_max_log_size    = 100;  // max log file size 100 MB
  FLAGS_logbuflevel     = -1;   // don't buffer logs
  FLAGS_stop_logging_if_full_disk = true;

  // Read the file. If there is an error, report it and exit.
  libconfig::Config cfg;
  try
  {
    cfg.readFile(optConf);
  } catch(const FileIOException &fioex) {
    std::cerr << "I/O error while reading file." << std::endl;
    return(EXIT_FAILURE);
  } catch(const ParseException &pex) {
    std::cerr << "Parse error at " << pex.getFile() << ":" << pex.getLine()
    << " - " << pex.getError() << std::endl;
    return(EXIT_FAILURE);
  }

  try {
    // check if we are using testnet3
    bool isTestnet3 = false;
    cfg.lookupValue("testnet", isTestnet3);
    if (isTestnet3) {
      SelectParams(CBaseChainParams::TESTNET);
      LOG(WARNING) << "using bitcoin testnet3";
    } else {
      SelectParams(CBaseChainParams::MAIN);
    }

    // DB info
    MysqlConnectInfo *poolDBInfo = nullptr;
    {
      int32_t poolDBPort = 3306;
      cfg.lookupValue("pooldb.port", poolDBPort);
      poolDBInfo = new MysqlConnectInfo(cfg.lookup("pooldb.host"), poolDBPort,
                                        cfg.lookup("pooldb.username"),
                                        cfg.lookup("pooldb.password"),
                                        cfg.lookup("pooldb.dbname"));
    }

    // chain type
    string chainType = cfg.lookup("sharelog.chain_type");
    // Track duplicate shares within N blocks.
    int32_t dupShareTrackingHeight = 3;
    cfg.lookupValue("dup_share_checker.tracking_height_number", dupShareTrackingHeight);

    //////////////////////////////////////////////////////////////////////////////
    //  dump shares to stdout
    //////////////////////////////////////////////////////////////////////////////
    if (optDate != 0 && optPUID != -1) {
      const string tsStr = Strings::Format("%04d-%02d-%02d 00:00:00",
                                          optDate/10000,
                                          optDate/100 % 100, optDate % 100);
      const time_t ts = str2time(tsStr.c_str(), "%F %T");
      std::set<int32_t> uids;
      if (optPUID > 0)
      uids.insert(optPUID);

      std::shared_ptr<ShareLogDumper> sldumper = newShareLogDumper(chainType, cfg.lookup("sharelog.data_dir"), ts, uids);
      sldumper->dump2stdout();

      google::ShutdownGoogleLogging();
      return 0;
    }

    //////////////////////////////////////////////////////////////////////////////
    //  re-run someday's share bin log
    //////////////////////////////////////////////////////////////////////////////
    if (optDate != 0) {
      const string tsStr = Strings::Format("%04d-%02d-%02d 00:00:00",
                                          optDate/10000,
                                          optDate/100 % 100, optDate % 100);
      const time_t ts = str2time(tsStr.c_str(), "%F %T");

      std::shared_ptr<ShareLogParser> slparser = newShareLogParser(chainType,
                                                             cfg.lookup("sharelog.data_dir"),
                                                             ts, *poolDBInfo,
                                                             dupShareTrackingHeight);
      do {
        if (slparser->init() == false) {
          LOG(ERROR) << "init failure";
          break;
        }
        if (!slparser->processUnchangedShareLog()) {
          LOG(ERROR) << "processUnchangedShareLog fail";
          break;
        }
        if (!slparser->flushToDB()) {
          LOG(ERROR) << "processUnchangedShareLog fail";
          break;
        }
      } while (0);

      google::ShutdownGoogleLogging();
      return 0;
    }

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

    // lock cfg file:
    //    you can't run more than one process with the same config file
    boost::interprocess::file_lock pidFileLock(optConf);
    if (pidFileLock.try_lock() == false) {
      LOG(FATAL) << "lock cfg file fail";
      return(EXIT_FAILURE);
    }

    signal(SIGTERM, handler);
    signal(SIGINT,  handler);

    int32_t port = 8081;
    cfg.lookupValue("slparserhttpd.port", port);
    uint32_t kFlushDBInterval = 20;
    cfg.lookupValue("slparserhttpd.flush_db_interval", kFlushDBInterval);
    gShareLogParserServer = newShareLogParserServer(chainType,
                                                 cfg.lookup("sharelog.data_dir"),
                                                 cfg.lookup("slparserhttpd.ip"),
                                                 port, *poolDBInfo,
                                                 kFlushDBInterval,
                                                 dupShareTrackingHeight);
    gShareLogParserServer->run();
  }
  catch (std::exception & e) {
    LOG(FATAL) << "exception: " << e.what();
    return 1;
  }

  google::ShutdownGoogleLogging();
  return 0;
}
<commit_msg>fix bug ShareLogParser creation for Bytom<commit_after>/*
 The MIT License (MIT)

 Copyright (c) [2016] [BTC.COM]

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
*/
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <err.h>
#include <errno.h>
#include <unistd.h>

#include <iostream>

#include <boost/interprocess/sync/file_lock.hpp>
#include <glog/logging.h>
#include <libconfig.h++>

#include "zmq.hpp"

#include "Utils.h"
#include "ShareLogParser.h"

using namespace std;
using namespace libconfig;

std::shared_ptr<ShareLogParserServer> gShareLogParserServer = nullptr;

void handler(int sig) {
  if (gShareLogParserServer) {
    gShareLogParserServer->stop();
  }
}

void usage() {
  fprintf(stderr, "Usage:\n\tslparser -c \"slparser.cfg\" -l \"log_dir\"\n");
  fprintf(stderr, "\tslparser -c \"slparser.cfg\" -l \"log_dir2\" -d \"20160830\"\n");
  fprintf(stderr, "\tslparser -c \"slparser.cfg\" -l \"log_dir3\" -d \"20160830\" -u \"puid(0: dump all, >0: someone's)\"\n");
}

std::shared_ptr<ShareLogDumper> newShareLogDumper(const string &chainType, const string &dataDir,
                                                  time_t timestamp, const std::set<int32_t> &uids)
{
  if (chainType == "BTC") {
    return std::make_shared<ShareLogDumperBitcoin>(chainType.c_str(), dataDir, timestamp, uids);
  }
  else if (chainType == "ETH") {
    return std::make_shared<ShareLogDumperEth>(chainType.c_str(), dataDir, timestamp, uids);
  }
  else if (chainType == "BTM") {
    return std::make_shared<ShareLogDumperBytom>(chainType.c_str(), dataDir, timestamp, uids);
  }
  else {
    LOG(FATAL) << "newShareLogDumper: unknown chain type " << chainType;
    return nullptr;
  }
}

std::shared_ptr<ShareLogParser> newShareLogParser(const string &chainType, const string &dataDir,
                                                  time_t timestamp, const MysqlConnectInfo &poolDBInfo,
                                                  const int dupShareTrackingHeight)
{
  if (chainType == "BTC") {
    return std::make_shared<ShareLogParserBitcoin>(chainType.c_str(), dataDir, timestamp, poolDBInfo, nullptr);
  }
  else if (chainType == "ETH") {
    return std::make_shared<ShareLogParserEth>(chainType.c_str(), dataDir, timestamp, poolDBInfo,
                                               std::make_shared<DuplicateShareCheckerEth>(dupShareTrackingHeight));
  }
  else if (chainType == "BTM") {
    return std::make_shared<ShareLogParserBytom>(chainType.c_str(), dataDir, timestamp, poolDBInfo,
                                               std::make_shared<DuplicateShareCheckerBytom>(dupShareTrackingHeight));
  }
  else {
    LOG(FATAL) << "newShareLogParser: unknown chain type " << chainType;
    return nullptr;
  }
}

std::shared_ptr<ShareLogParserServer> newShareLogParserServer(const string &chainType, const string &dataDir,
                                                        const string &httpdHost, unsigned short httpdPort,
                                                        const MysqlConnectInfo &poolDBInfo,
                                                        const uint32_t kFlushDBInterval,
                                                        const int dupShareTrackingHeight)
{
  if (chainType == "BTC") {
    return std::make_shared<ShareLogParserServerBitcoin>(chainType.c_str(), dataDir,
                                                         httpdHost, httpdPort,
                                                         poolDBInfo, kFlushDBInterval, nullptr);
  }
  else if (chainType == "ETH") {
    return std::make_shared<ShareLogParserServerEth>(chainType.c_str(), dataDir,
                                                     httpdHost, httpdPort,
                                                     poolDBInfo, kFlushDBInterval,
                                                     std::make_shared<DuplicateShareCheckerEth>(dupShareTrackingHeight));
  }
  else if (chainType == "BTM") {
    return std::make_shared<ShareLogParserServerBytom>(chainType.c_str(), dataDir,
                                                     httpdHost, httpdPort,
                                                     poolDBInfo, kFlushDBInterval,
                                                     std::make_shared<DuplicateShareCheckerBytom>(dupShareTrackingHeight));
  }
  else {
    LOG(FATAL) << "newShareLogParserServer: unknown chain type " << chainType;
    return nullptr;
  }
}

int main(int argc, char **argv) {
  char *optLogDir = NULL;
  char *optConf   = NULL;
  int32_t optDate = 0;
  int32_t optPUID = -1;  // pool user id
  int c;

  if (argc <= 1) {
    usage();
    return 1;
  }
  while ((c = getopt(argc, argv, "c:l:d:u:h")) != -1) {
    switch (c) {
      case 'c':
        optConf = optarg;
        break;
      case 'l':
        optLogDir = optarg;
        break;
      case 'd':
        optDate = atoi(optarg);
        break;
      case 'u':
        optPUID = atoi(optarg);
        break;
      case 'h': default:
        usage();
        exit(0);
    }
  }

  // Initialize Google's logging library.
  google::InitGoogleLogging(argv[0]);
  FLAGS_log_dir         = string(optLogDir);
  // Log messages at a level >= this flag are automatically sent to
  // stderr in addition to log files.
  FLAGS_stderrthreshold = 3;    // 3: FATAL
  FLAGS_max_log_size    = 100;  // max log file size 100 MB
  FLAGS_logbuflevel     = -1;   // don't buffer logs
  FLAGS_stop_logging_if_full_disk = true;

  // Read the file. If there is an error, report it and exit.
  libconfig::Config cfg;
  try
  {
    cfg.readFile(optConf);
  } catch(const FileIOException &fioex) {
    std::cerr << "I/O error while reading file." << std::endl;
    return(EXIT_FAILURE);
  } catch(const ParseException &pex) {
    std::cerr << "Parse error at " << pex.getFile() << ":" << pex.getLine()
    << " - " << pex.getError() << std::endl;
    return(EXIT_FAILURE);
  }

  try {
    // check if we are using testnet3
    bool isTestnet3 = false;
    cfg.lookupValue("testnet", isTestnet3);
    if (isTestnet3) {
      SelectParams(CBaseChainParams::TESTNET);
      LOG(WARNING) << "using bitcoin testnet3";
    } else {
      SelectParams(CBaseChainParams::MAIN);
    }

    // DB info
    MysqlConnectInfo *poolDBInfo = nullptr;
    {
      int32_t poolDBPort = 3306;
      cfg.lookupValue("pooldb.port", poolDBPort);
      poolDBInfo = new MysqlConnectInfo(cfg.lookup("pooldb.host"), poolDBPort,
                                        cfg.lookup("pooldb.username"),
                                        cfg.lookup("pooldb.password"),
                                        cfg.lookup("pooldb.dbname"));
    }

    // chain type
    string chainType = cfg.lookup("sharelog.chain_type");
    // Track duplicate shares within N blocks.
    int32_t dupShareTrackingHeight = 3;
    cfg.lookupValue("dup_share_checker.tracking_height_number", dupShareTrackingHeight);

    //////////////////////////////////////////////////////////////////////////////
    //  dump shares to stdout
    //////////////////////////////////////////////////////////////////////////////
    if (optDate != 0 && optPUID != -1) {
      const string tsStr = Strings::Format("%04d-%02d-%02d 00:00:00",
                                          optDate/10000,
                                          optDate/100 % 100, optDate % 100);
      const time_t ts = str2time(tsStr.c_str(), "%F %T");
      std::set<int32_t> uids;
      if (optPUID > 0)
      uids.insert(optPUID);

      std::shared_ptr<ShareLogDumper> sldumper = newShareLogDumper(chainType, cfg.lookup("sharelog.data_dir"), ts, uids);
      sldumper->dump2stdout();

      google::ShutdownGoogleLogging();
      return 0;
    }

    //////////////////////////////////////////////////////////////////////////////
    //  re-run someday's share bin log
    //////////////////////////////////////////////////////////////////////////////
    if (optDate != 0) {
      const string tsStr = Strings::Format("%04d-%02d-%02d 00:00:00",
                                          optDate/10000,
                                          optDate/100 % 100, optDate % 100);
      const time_t ts = str2time(tsStr.c_str(), "%F %T");

      std::shared_ptr<ShareLogParser> slparser = newShareLogParser(chainType,
                                                             cfg.lookup("sharelog.data_dir"),
                                                             ts, *poolDBInfo,
                                                             dupShareTrackingHeight);
      do {
        if (slparser->init() == false) {
          LOG(ERROR) << "init failure";
          break;
        }
        if (!slparser->processUnchangedShareLog()) {
          LOG(ERROR) << "processUnchangedShareLog fail";
          break;
        }
        if (!slparser->flushToDB()) {
          LOG(ERROR) << "processUnchangedShareLog fail";
          break;
        }
      } while (0);

      google::ShutdownGoogleLogging();
      return 0;
    }

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

    // lock cfg file:
    //    you can't run more than one process with the same config file
    boost::interprocess::file_lock pidFileLock(optConf);
    if (pidFileLock.try_lock() == false) {
      LOG(FATAL) << "lock cfg file fail";
      return(EXIT_FAILURE);
    }

    signal(SIGTERM, handler);
    signal(SIGINT,  handler);

    int32_t port = 8081;
    cfg.lookupValue("slparserhttpd.port", port);
    uint32_t kFlushDBInterval = 20;
    cfg.lookupValue("slparserhttpd.flush_db_interval", kFlushDBInterval);
    gShareLogParserServer = newShareLogParserServer(chainType,
                                                 cfg.lookup("sharelog.data_dir"),
                                                 cfg.lookup("slparserhttpd.ip"),
                                                 port, *poolDBInfo,
                                                 kFlushDBInterval,
                                                 dupShareTrackingHeight);
    gShareLogParserServer->run();
  }
  catch (std::exception & e) {
    LOG(FATAL) << "exception: " << e.what();
    return 1;
  }

  google::ShutdownGoogleLogging();
  return 0;
}
<|endoftext|>


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

#include <string>
#include <sstream>
#include <cctype>
#include <algorithm>
#include <json/reader.h>
#include <json/writer.h>
#include <huctx.h>
#include <sbreturn.h>
#include <husha1.h>
#include <husha2.h>
#include <hugse56.h>

#include "gsecrypto.hpp"
#include "gsecryptojs.hpp"
#include "util/util.hpp"

class GSECryptoJS;

namespace webworks {

GSECrypto::GSECrypto(GSECryptoJS *owner) {
	parent = owner;

	sbCtx = NULL;

	try {
		int error = hu_GlobalCtxCreateDefault(&sbCtx);
		if (error != SB_SUCCESS) {
			throw "Failed to create global context";
		}

		error = hu_RegisterSbg56(sbCtx);
		if (error != SB_SUCCESS) {
			throw "Failed to register sbg 5.6";
		}

		error = hu_InitSbg56(sbCtx);
		if (error != SB_SUCCESS) {
			throw "Failed to init sbg 5.6";
		}
	} catch (const char * message) {
		lastError = message;
	}
}

GSECrypto::~GSECrypto() {
	if (sbCtx != NULL) {
		hu_GlobalCtxDestroy(&sbCtx);
		sbCtx = NULL;
	}
}

class DataTracker {
public:
	DataTracker() :
			data(0), dataLen(0) {
	}
	;
	virtual ~DataTracker() {
		cleanUp();
	}
	void cleanUp() {
		if (data != NULL) {
			delete[] data;
			data = NULL;
			dataLen = 0;
		}
	}
	void setData(std::string in) {
		cleanUp();
		dataLen = in.length();
		data = new unsigned char[dataLen + 1];
		strcpy((char*) data, in.data());
	}
	unsigned char * data;
	size_t dataLen;
};

// Take in input and return a value
std::string GSECrypto::hash(const std::string& inputString) {
	DataTracker data;
	std::string toReturn;

	try {

		Json::Value args;
		Json::Reader reader;
		if (!reader.parse(inputString, args, 0)) {
			throw "Input is not decodable Json";
		}

		if (args.isMember("hex")) {
			gsecrypto::util::fromHex(args["hex"].asString(), data.data, data.dataLen);
		} else if (args.isMember("b64")) {
			gsecrypto::util::fromB64(args["b64"].asString(), data.data, data.dataLen);
		} else if (args.isMember("raw")) {
			data.setData(args["raw"].asString());
		} else {
			throw "Input must have one of hex,b64,raw";
		}

		std::string alg = args.get("alg", "SHA1").asString();
		std::transform(alg.begin(), alg.end(), alg.begin(), tolower);

		size_t digestLen = 0;

		int (*algFunc)(size_t, sb_YieldCtx, size_t, const unsigned char *,
				unsigned char *, sb_GlobalCtx) = NULL;

		if (alg == "sha1") {
			digestLen = SB_SHA1_DIGEST_LEN;
			algFunc = hu_SHA1Msg;
		} else if (alg == "sha224") {
			digestLen = SB_SHA224_DIGEST_LEN;
			algFunc = hu_SHA224Msg;
		} else if (alg == "sha256") {
			digestLen = SB_SHA256_DIGEST_LEN;
			algFunc = hu_SHA256Msg;
		} else if (alg == "sha384") {
			digestLen = SB_SHA384_DIGEST_LEN;
			algFunc = hu_SHA384Msg;
		} else if (alg == "sha512") {
			digestLen = SB_SHA512_DIGEST_LEN;
			algFunc = hu_SHA512Msg;
		} else {
			throw "Unknown SHA operation";
		}

		lastMessage = "";
		std::stringstream tmp;
		tmp << "dataLength: " << data.dataLen << " data: ";
		for (size_t i = 0; i < data.dataLen; ++i) {
			tmp << data.data[i];
		}
		tmp << "\n";
		tmp << "Input: " << inputString;
		lastMessage = tmp.str();

		unsigned char digest[digestLen];
		for (size_t i = 0; i < digestLen; ++i) {
			digest[i] = i;
		}
		if (SB_SUCCESS
				!= algFunc(digestLen, NULL, data.dataLen, data.data, digest,
						sbCtx)) {
			throw "Could not call hash function";
		}

		toReturn = toString(digest, digestLen);
	} catch (const char * error) {
		Json::Value errorJ;
		Json::FastWriter writer;
		errorJ["error"] = error;
		return writer.write(errorJ);
	}

	return toReturn;
}

std::string GSECrypto::toString(unsigned char * data, size_t dataLen) {
	Json::Value toReturn;
	Json::FastWriter writer;
	toReturn["hex"] = gsecrypto::util::toHex(data, dataLen);
	toReturn["b64"] = gsecrypto::util::toB64(data, dataLen);
	if (lastMessage.length() != 0) {
		toReturn["lastMessage"] = lastMessage;
		lastMessage = "";
	}

	return writer.write(toReturn);
}

} /* namespace webworks */
<commit_msg>Added code to ignore - in the alg name<commit_after>/*
 * Copyright 2013 Research In Motion Limited.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <string>
#include <sstream>
#include <cctype>
#include <algorithm>
#include <json/reader.h>
#include <json/writer.h>
#include <huctx.h>
#include <sbreturn.h>
#include <husha1.h>
#include <husha2.h>
#include <hugse56.h>

#include "gsecrypto.hpp"
#include "gsecryptojs.hpp"
#include "util/util.hpp"

class GSECryptoJS;

namespace webworks {

GSECrypto::GSECrypto(GSECryptoJS *owner) {
	parent = owner;

	sbCtx = NULL;

	try {
		int error = hu_GlobalCtxCreateDefault(&sbCtx);
		if (error != SB_SUCCESS) {
			throw "Failed to create global context";
		}

		error = hu_RegisterSbg56(sbCtx);
		if (error != SB_SUCCESS) {
			throw "Failed to register sbg 5.6";
		}

		error = hu_InitSbg56(sbCtx);
		if (error != SB_SUCCESS) {
			throw "Failed to init sbg 5.6";
		}
	} catch (const char * message) {
		lastError = message;
	}
}

GSECrypto::~GSECrypto() {
	if (sbCtx != NULL) {
		hu_GlobalCtxDestroy(&sbCtx);
		sbCtx = NULL;
	}
}

class DataTracker {
public:
	DataTracker() :
			data(0), dataLen(0) {
	}
	;
	virtual ~DataTracker() {
		cleanUp();
 	}
	void cleanUp() {
		if (data != NULL) {
			delete[] data;
			data = NULL;
			dataLen = 0;
		}
	}
	void setData(std::string in) {
		cleanUp();
		dataLen = in.length();
		data = new unsigned char[dataLen + 1];
		strcpy((char*) data, in.data());
	}
	unsigned char * data;
	size_t dataLen;
};

// Take in input and return a value
std::string GSECrypto::hash(const std::string& inputString) {
	DataTracker data;
	std::string toReturn;

	try {

		Json::Value args;
		Json::Reader reader;
		if (!reader.parse(inputString, args, 0)) {
			throw "Input is not decodable Json";
		}

		if (args.isMember("hex")) {
			gsecrypto::util::fromHex(args["hex"].asString(), data.data, data.dataLen);
		} else if (args.isMember("b64")) {
			gsecrypto::util::fromB64(args["b64"].asString(), data.data, data.dataLen);
		} else if (args.isMember("raw")) {
			data.setData(args["raw"].asString());
		} else {
			throw "Input must have one of hex,b64,raw";
		}

		std::string alg = args.get("alg", "SHA1").asString();
		std::transform(alg.begin(), alg.end(), alg.begin(), tolower);
		alg.erase(std::remove(alg.begin(), alg.end(), '-'), alg.end());

		size_t digestLen = 0;

		int (*algFunc)(size_t, sb_YieldCtx, size_t, const unsigned char *,
				unsigned char *, sb_GlobalCtx) = NULL;

		if (alg == "sha1") {
			digestLen = SB_SHA1_DIGEST_LEN;
			algFunc = hu_SHA1Msg;
		} else if (alg == "sha224") {
			digestLen = SB_SHA224_DIGEST_LEN;
			algFunc = hu_SHA224Msg;
		} else if (alg == "sha256") {
			digestLen = SB_SHA256_DIGEST_LEN;
			algFunc = hu_SHA256Msg;
		} else if (alg == "sha384") {
			digestLen = SB_SHA384_DIGEST_LEN;
			algFunc = hu_SHA384Msg;
		} else if (alg == "sha512") {
			digestLen = SB_SHA512_DIGEST_LEN;
			algFunc = hu_SHA512Msg;
		} else {
			throw "Unknown SHA operation";
		}

		lastMessage = "";
		std::stringstream tmp;
		tmp << "dataLength: " << data.dataLen << " data: ";
		for (size_t i = 0; i < data.dataLen; ++i) {
			tmp << data.data[i];
		}
		tmp << "\n";
		tmp << "Input: " << inputString;
		lastMessage = tmp.str();

		unsigned char digest[digestLen];
		for (size_t i = 0; i < digestLen; ++i) {
			digest[i] = i;
		}
		if (SB_SUCCESS
				!= algFunc(digestLen, NULL, data.dataLen, data.data, digest,
						sbCtx)) {
			throw "Could not call hash function";
		}

		toReturn = toString(digest, digestLen);
	} catch (const char * error) {
		Json::Value errorJ;
		Json::FastWriter writer;
		errorJ["error"] = error;
		return writer.write(errorJ);
	}

	return toReturn;
}

std::string GSECrypto::toString(unsigned char * data, size_t dataLen) {
	Json::Value toReturn;
	Json::FastWriter writer;
	toReturn["hex"] = gsecrypto::util::toHex(data, dataLen);
	toReturn["b64"] = gsecrypto::util::toB64(data, dataLen);
	if (lastMessage.length() != 0) {
		toReturn["lastMessage"] = lastMessage;
		lastMessage = "";
	}

	return writer.write(toReturn);
}

} /* namespace webworks */
<|endoftext|>


<commit_before>//  Copyright [2014] <lgb (LiuGuangBao)>
//=====================================================================================
//
//      Filename:  cmdRemove.cpp
//
//   Description:  删除命令
//
//       Version:  1.0
//       Created:  2014年12月25日 10时44分35秒
//      Revision:  none
//      Compiler:  gcc
//
//        Author:  lgb (LiuGuangBao), easyeagel@gmx.com
//  Organization:  ezbty.org
//
//=====================================================================================
//

#include"option.hpp"
#include"fileset.hpp"

namespace ezsh
{

namespace bf=boost::filesystem;

class CmdRemove:public CmdBaseT<CmdRemove, FileSetCmdBase<>>
{
    typedef CmdBaseT<CmdRemove, FileSetCmdBase> BaseThis;
public:
    CmdRemove()
        :BaseThis("remove - remove file or dir")
    {
        opt_.add_options()
            ("force,f", "ignore nonexistent files and arguments")
        ;
    }

    static const char* nameGet()
    {
        return "remove";
    }

    MainReturn doit() override
    {
        const auto& vm=mapGet();
        auto& files=fileGet();

        files.init(vm);

        const bool force=vm.count("force") ? true : false;
        for(const auto& file: files.setGet())
        {
            if(!file.isExist())
            {
                if(force)
                    continue;
                stdErr() << file.total << ": not exist" << std::endl;
                continue;
            }

            boost::system::error_code ec;
            if(!file.isDir())
            {
                bf::remove(file.total, ec);
                if(ec && !force)
                    stdErr() << file.total << ": " << ec.message() << std::endl;
                continue;
            }

            if(files.isRecursive())
            {
                bf::remove_all(file.total, ec);
                if(ec && !force)
                    stdErr() << file.total << ": " << ec.message() << std::endl;
                continue;
            }

            bf::remove(file.total, ec);
            if(ec && !force)
                stdErr() << file.total << ": " << ec.message() << std::endl;
        }

        return MainReturn::eGood;
    }

};

namespace
{
static CmdRegisterT<CmdRemove> gsRegister;
}

}

<commit_msg>在扫描的过程中删除文件是危险的<commit_after>//  Copyright [2014] <lgb (LiuGuangBao)>
//=====================================================================================
//
//      Filename:  cmdRemove.cpp
//
//   Description:  删除命令
//
//       Version:  1.0
//       Created:  2014年12月25日 10时44分35秒
//      Revision:  none
//      Compiler:  gcc
//
//        Author:  lgb (LiuGuangBao), easyeagel@gmx.com
//  Organization:  ezbty.org
//
//=====================================================================================
//

#include"option.hpp"
#include"fileset.hpp"

namespace ezsh
{

namespace bf=boost::filesystem;

class CmdRemove:public CmdBaseT<CmdRemove, FileSetCmdBase<>>
{
    typedef CmdBaseT<CmdRemove, FileSetCmdBase> BaseThis;
public:
    CmdRemove()
        :BaseThis("remove - remove file or dir")
    {
        opt_.add_options()
            ("force,f", "ignore nonexistent files and arguments")
        ;
    }

    static const char* nameGet()
    {
        return "remove";
    }

    MainReturn doit() override
    {
        auto& files=fileGet();
        const auto& vm=mapGet();

        files.init(vm);
        files.scan();
        const bool force=vm.count("force") ? true : false;
        for(const auto& file: files.setGet())
            fileRemove(file, force);
        return MainReturn::eGood;
    }

private:
    void fileRemove(const FileUnit& file, bool force)
    {
        if(!file.isExist())
        {
            if(!force)
                stdErr() << file.total << ": not exist" << std::endl;
            return;
        }

        boost::system::error_code ec;
        if(!file.isDir())
        {
            bf::remove(file.total, ec);
            if(ec && !force)
                stdErr() << file.total << ": " << ec.message() << std::endl;
            return;
        }

        if(fileGet().isRecursive())
        {
            bf::remove_all(file.total, ec);
            if(ec && !force)
                stdErr() << file.total << ": " << ec.message() << std::endl;
            return;
        }

        bf::remove(file.total, ec);
        if(ec && !force)
            stdErr() << file.total << ": " << ec.message() << std::endl;
    }
};

namespace
{
static CmdRegisterT<CmdRemove> gsRegister;
}

}

<|endoftext|>


<commit_before>/***************************************************************************
 *   Copyright (C) 2014 by Marcin Ziemiński <zieminn@gmail.com>            *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2.1 of the License, or   *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
 ***************************************************************************/

#include "otr-message.h"

namespace OTR
{
    Message::Message()
        : dir(MessageDirection::TO_PEER)
    {
        message << Tp::MessagePart() << Tp::MessagePart();
        setType(Tp::ChannelTextMessageTypeNormal);
    }

    Message::Message(const Tp::MessagePartList &message)
        : dir(MessageDirection::TO_PEER),
        message(message)
    {
        while(this->message.size() < 2) {
            this->message << Tp::MessagePart();
        }
        if(!this->message[0].contains(QLatin1String("message-type"))) {
            setType(Tp::ChannelTextMessageTypeNormal);
        }
    }

    const Tp::MessagePartList& Message::parts() const
    {
        return message;
    }

    QString Message::text() const
    {
        auto it = message[1].find(QLatin1String("content"));
        if(it == message[1].end()) {
            return QLatin1String("");
        } else {
            return it->variant().toString();
        }
    }

    void Message::setText(const QString &text, const QString &contentType)
    {
        message[1].insert(QLatin1String("content-type"),
                QDBusVariant(contentType));
        message[1].insert(QLatin1String("content"), QDBusVariant(text));
    }

    QString Message::contentType() const
    {
        auto it = message[1].find(QLatin1String("content-type"));
        if(it == message[1].end()) {
            return QLatin1String("");
        } else {
            return it->variant().toString();
        }
    }

    void Message::setType(Tp::ChannelTextMessageType msgType)
    {
        message[0].insert(QLatin1String("message-type"), QDBusVariant(msgType));
    }

    Tp::ChannelTextMessageType Message::type() const
    {
        return static_cast<Tp::ChannelTextMessageType>(message[0][QLatin1String("message-type")].variant().toUInt(nullptr));
    }

    bool Message::isOTRmessage() const
    {
        return otrl_proto_message_type(text().toLocal8Bit()) != OTRL_MSGTYPE_NOTOTR;
    }

    MessageDirection Message::direction() const
    {
        return dir;
    }

    void Message::setDirection(MessageDirection direction)
    {
        dir = direction;
    }

    bool Message::isOTRevent() const
    {
        return message[0].contains(QLatin1String("otr-message-event"));
    }

    void Message::setOTRevent(OtrlMessageEvent msgEvent)
    {
        message[0].insert(QLatin1String("otr-message-event"), QDBusVariant(static_cast<uint>(msgEvent)));
    }

    OtrlMessageEvent Message::getOTRevent() const
    {
        return static_cast<OtrlMessageEvent>(message[0][QLatin1String("otr-message-event")].variant().toUInt(nullptr));
    }

    void Message::setOTRheader(const QString &header, const QString &text)
    {
        message[0].insert(header, QDBusVariant(text));
    }

    QString Message::getOTRheader(const QString &header)
    {
        auto it = message[0].find(header);
        if(it == message[0].end()) {
            return QLatin1String("");
        } else {
            return it->variant().toString();
        }
    }

    void Message::setTimestamp(qint64 timestamp)
    {
        message[0].insert(QLatin1String("message-sent"), QDBusVariant(timestamp));
    }

    qint64 Message::getTimestamp() const
    {
        auto it = message[0].find(QLatin1String("message-sent"));
        if(it == message[0].end()) {
            return 0;
        } else {
            return it->variant().toLongLong(NULL);
        }
    }

    void Message::setSenderId(const QString &senderId)
    {
        message[0].insert(QLatin1String("message-sender-id"), QDBusVariant(senderId));
    }

    QString Message::getSenderId() const
    {
        auto it = message[0].find(QLatin1String("message-sender-id"));
        if(it == message[0].end()) {
            return QLatin1String("");
        } else {
            return it->variant().toString();
        }
    }

    void Message::setSender(uint sender)
    {
        message[0].insert(QLatin1String("message-sender"), QDBusVariant(sender));
    }

    uint Message::getSender() const
    {
        auto it = message[0].find(QLatin1String("message-sender"));
        if(it == message[0].end()) {
            return 0;
        } else {
            return it->variant().toUInt(NULL);
        }
    }

    void Message::setToken(const QString &token)
    {
        message[0].insert(QLatin1String("message-token"), QDBusVariant(token));
    }

    QString Message::getToken() const
    {
        auto it = message[0].find(QLatin1String("message-sender"));
        if(it == message[0].end()) {
            return QLatin1String("");
        } else {
            return it->variant().toString();
        }
    }

} /* namespace OTR */
<commit_msg>Return default OtrlMessageEvent in the Message<commit_after>/***************************************************************************
 *   Copyright (C) 2014 by Marcin Ziemiński <zieminn@gmail.com>            *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2.1 of the License, or   *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
 ***************************************************************************/

#include "otr-message.h"

namespace OTR
{
    Message::Message()
        : dir(MessageDirection::TO_PEER)
    {
        message << Tp::MessagePart() << Tp::MessagePart();
        setType(Tp::ChannelTextMessageTypeNormal);
    }

    Message::Message(const Tp::MessagePartList &message)
        : dir(MessageDirection::TO_PEER),
        message(message)
    {
        while(this->message.size() < 2) {
            this->message << Tp::MessagePart();
        }
        if(!this->message[0].contains(QLatin1String("message-type"))) {
            setType(Tp::ChannelTextMessageTypeNormal);
        }
    }

    const Tp::MessagePartList& Message::parts() const
    {
        return message;
    }

    QString Message::text() const
    {
        auto it = message[1].find(QLatin1String("content"));
        if(it == message[1].end()) {
            return QLatin1String("");
        } else {
            return it->variant().toString();
        }
    }

    void Message::setText(const QString &text, const QString &contentType)
    {
        message[1].insert(QLatin1String("content-type"),
                QDBusVariant(contentType));
        message[1].insert(QLatin1String("content"), QDBusVariant(text));
    }

    QString Message::contentType() const
    {
        auto it = message[1].find(QLatin1String("content-type"));
        if(it == message[1].end()) {
            return QLatin1String("");
        } else {
            return it->variant().toString();
        }
    }

    void Message::setType(Tp::ChannelTextMessageType msgType)
    {
        message[0].insert(QLatin1String("message-type"), QDBusVariant(msgType));
    }

    Tp::ChannelTextMessageType Message::type() const
    {
        return static_cast<Tp::ChannelTextMessageType>(message[0][QLatin1String("message-type")].variant().toUInt(nullptr));
    }

    bool Message::isOTRmessage() const
    {
        return otrl_proto_message_type(text().toLocal8Bit()) != OTRL_MSGTYPE_NOTOTR;
    }

    MessageDirection Message::direction() const
    {
        return dir;
    }

    void Message::setDirection(MessageDirection direction)
    {
        dir = direction;
    }

    bool Message::isOTRevent() const
    {
        return message[0].contains(QLatin1String("otr-message-event"));
    }

    void Message::setOTRevent(OtrlMessageEvent msgEvent)
    {
        message[0].insert(QLatin1String("otr-message-event"), QDBusVariant(static_cast<uint>(msgEvent)));
    }

    OtrlMessageEvent Message::getOTRevent() const
    {
        if(isOTRevent()) {
            return static_cast<OtrlMessageEvent>(message[0][QLatin1String("otr-message-event")].variant().toUInt(nullptr));
        } else {
            return OTRL_MSGEVENT_NONE;
        }
    }

    void Message::setOTRheader(const QString &header, const QString &text)
    {
        message[0].insert(header, QDBusVariant(text));
    }

    QString Message::getOTRheader(const QString &header)
    {
        auto it = message[0].find(header);
        if(it == message[0].end()) {
            return QLatin1String("");
        } else {
            return it->variant().toString();
        }
    }

    void Message::setTimestamp(qint64 timestamp)
    {
        message[0].insert(QLatin1String("message-sent"), QDBusVariant(timestamp));
    }

    qint64 Message::getTimestamp() const
    {
        auto it = message[0].find(QLatin1String("message-sent"));
        if(it == message[0].end()) {
            return 0;
        } else {
            return it->variant().toLongLong(NULL);
        }
    }

    void Message::setSenderId(const QString &senderId)
    {
        message[0].insert(QLatin1String("message-sender-id"), QDBusVariant(senderId));
    }

    QString Message::getSenderId() const
    {
        auto it = message[0].find(QLatin1String("message-sender-id"));
        if(it == message[0].end()) {
            return QLatin1String("");
        } else {
            return it->variant().toString();
        }
    }

    void Message::setSender(uint sender)
    {
        message[0].insert(QLatin1String("message-sender"), QDBusVariant(sender));
    }

    uint Message::getSender() const
    {
        auto it = message[0].find(QLatin1String("message-sender"));
        if(it == message[0].end()) {
            return 0;
        } else {
            return it->variant().toUInt(NULL);
        }
    }

    void Message::setToken(const QString &token)
    {
        message[0].insert(QLatin1String("message-token"), QDBusVariant(token));
    }

    QString Message::getToken() const
    {
        auto it = message[0].find(QLatin1String("message-sender"));
        if(it == message[0].end()) {
            return QLatin1String("");
        } else {
            return it->variant().toString();
        }
    }

} /* namespace OTR */
<|endoftext|>


<commit_before>// Time:  O(logn)
// Space: O(1)

class Solution {
public:
    int findMin(vector<int>& nums) {
        int left = 0, right = nums.size() - 1;

        // Find min left s.t. nums[left] < nums[left'].
        while (left < right && nums[left] >= nums[right]) {
            int mid = left + (right - left) / 2;
            if (nums[mid] < nums[left]) {
                right = mid;
            } else {
                left = mid + 1;
            }
        }

        return nums[left];

    }
};
<commit_msg>Update find-minimum-in-rotated-sorted-array.cpp<commit_after>// Time:  O(logn)
// Space: O(1)

class Solution {
public:
    int findMin(vector<int>& nums) {
        int left = 0, right = nums.size() - 1;

        // Find min left s.t. nums[left] < nums[left'].
        while (left < right && nums[left] >= nums[right]) {
            int mid = left + (right - left) / 2;
            if (nums[mid] < nums[left]) {
                right = mid;
            } else {
                left = mid + 1;
            }
        }

        return nums[left];
    }
};
<|endoftext|>


<commit_before>#define BOOST_TEST_MODULE "Number_of_Islands_test"
#include <boost/test/included/unit_test.hpp>

#include "test_common.hpp"
#include "read_test_case.hpp"
#include "solution.hpp"

#include <boost/range/irange.hpp>
#include <prettyprint.hpp>

template<> const pretty_print::delimiters_values<char> pretty_print::delimiters<std::vector<std::vector<char>>, char>::values = { "||\n ", " :\n ", " \n||" };

BOOST_DATA_TEST_CASE(
        test1,
        (make_tests(&read_input, &read_output)),
        // ^ bdata::make( { 1, 2, 3, 5, 8, 13, 21, 35, 56 } ),
        island_map, expected)
{
    auto filepaths = get_all_test_filepaths();
    for (const auto& f : filepaths) {
        cout << f << '\n';
    }
    cout << "island map is " << island_map << '\n';
    Solution sol;
    int actual = sol.numIslands(island_map);
    BOOST_CHECK_EQUAL(actual, expected);
}

//BOOST_AUTO_TEST_CASE(FailTest) {
//    BOOST_FAIL("");
//}
<commit_msg>Number of Islands with test implemented<commit_after>#define BOOST_TEST_MODULE "Number_of_Islands_test"
#include <boost/test/included/unit_test.hpp>

#include "test_common.hpp"
#include "read_test_case.hpp"
#include "solution.hpp"

#include <boost/range/irange.hpp>
#include <prettyprint.hpp>

template<> const pretty_print::delimiters_values<char> pretty_print::delimiters<std::vector<std::vector<char>>, char>::values = { "||\n ", " :\n ", " \n||" };

BOOST_DATA_TEST_CASE(
        test1,
        (make_tests(&read_input, &read_output)),
        // ^ bdata::make( { 1, 2, 3, 5, 8, 13, 21, 35, 56 } ),
        island_map, expected)
{
    // auto filepaths = get_all_test_filepaths();
    // for (const auto& f : filepaths) {
    //     cout << f << '\n';
    // }
    // cout << "island map is " << island_map << '\n';
    Solution sol;
    int actual = sol.numIslands(island_map);
    BOOST_CHECK_EQUAL(actual, expected);
}
<|endoftext|>


<commit_before>#include <stdlib.h>
#include <iostream>

using namespace std;

//Global Variables
const double pi = 3.14159;
//Classes
class railroad_car{
	public:
		//Default constructor
		railroad_car(){}
		//Functions
		virtual void display_name(){}
		virtual void display_capacity(){}
};

class box{
	public:
		//Default constructor
		box(){}
		//Argument-bearing constructor
		box(double h, double w, double l){
			height = h; width = w; length = l;
		}
		//Functions
		double volume(){return height*width*length; }
		//Variables
		double height, width, length;
};

class box_car : public railroad_car, protected box{
	public:
		//Default constructor
		box_car() : box(10.5,9.5,40.0) {}
		virtual void display_height(){cout << height << endl;}
		virtual void display_name(){cout << "box_car";}
		virtual void display_capacity(){cout << volume();}
};
int main(){
	box_car example;
	//cout << example.height<< endl; DOES NOT WORK
	example.display_height();
	box b;
	cout << b.height << endl; //Does work, however since box has no default constructor, return random number
	return 0;
}

<commit_msg>Update S9_Protected_classes.cpp<commit_after>#include <stdlib.h>
#include <iostream>

using namespace std;

//Global Variables
const double pi = 3.14159;
//Classes
class railroad_car{
	public:
		//Default constructor
		railroad_car(){}
		//Functions
		virtual void display_name(){}
		virtual void display_capacity(){}
};

class box{
	public:
		//Default constructor
		box(){}
		//Argument-bearing constructor
		box(double h, double w, double l){
			height = h; width = w; length = l;
		}
		//Functions
		double volume(){return height*width*length; }
		//Variables
		double height, width, length;
};

//Box car class that inherits railraod_car as well as protected box
class box_car : public railroad_car, protected box{
	public:
		//Default constructor
		box_car() : box(10.5,9.5,40.0) {}
		virtual void display_height(){cout << height << endl;}
		virtual void display_name(){cout << "box_car";}
		virtual void display_capacity(){cout << volume();}
};
int main(){
	//A box car
	box_car example;
	//Showing how a protected inheritance limits the classes access

	//cout << example.height<< endl; DOES NOT WORK

	example.display_height();
	box b;
	cout << b.height << endl; //Does work, however since box has no default constructor, return random number
	return 0;
}

<|endoftext|>


<commit_before>/**
 * @file
 *      exercise_03_15.cpp
 * @author
 *      Henrik Samuelsson, henrik.samuelsson(at)gmail.com
 */
#include <iostream>
#include <string>
#include <vector>

using std::cin;
using std::string;
using std::vector;

int main() {
    vector<string> ivec;
    string temp;

    while (cin >> temp) {
        ivec.push_back(temp);
    }

    return 0;
}
<commit_msg>Better variable name.<commit_after>/**
 * @file
 *      exercise_03_15.cpp
 * @author
 *      Henrik Samuelsson, henrik.samuelsson(at)gmail.com
 */
#include <iostream>
#include <string>
#include <vector>

using std::cin;
using std::string;
using std::vector;

int main() {
    vector<string> s_vec;
    string temp;

    while (cin >> temp) {
        s_vec.push_back(temp);
    }

    return 0;
}
<|endoftext|>


<commit_before>/*

    Copyright Eli Dupree and Isaac Dupree, 2011, 2012

    This file is part of Lasercake.

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

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

    You should have received a copy of the GNU General Public License
    along with Lasercake.  If not, see <http://www.gnu.org/licenses/>.

*/

#ifndef LASERCAKE_BORROWED_BITSET_HPP__
#define LASERCAKE_BORROWED_BITSET_HPP__

#include <list>
#include <stack>
#include <boost/utility.hpp>
#include <boost/dynamic_bitset.hpp>

#include "../utils.hpp"
#if 0 && !LASERCAKE_NO_THREADS
#include <boost/thread/thread.hpp>
#endif

typedef uint64_t bit_index_type;

namespace borrowed_bitset_impl {

// Noncopying singly linked list that owns its members unless you pop them.
template<typename T>
struct liststack_node : boost::noncopyable {
  liststack_node* next;
  T here;

  liststack_node() : next(nullptr), here() {}
  template<typename Arg>
  explicit liststack_node(Arg const& arg, liststack_node* next = nullptr)
   : next(next), here(arg) {}
  ~liststack_node() { delete next; }
};

template<typename T>
struct liststack : boost::noncopyable {
  typedef borrowed_bitset_impl::liststack_node<T> liststack_node;
  liststack_node* next;

  liststack() : next(nullptr) {}
  explicit liststack(liststack_node* next) : next(next) {}
  ~liststack() { delete next; }

  liststack_node* pop() {
    liststack_node* result = next;
    next = result->next;
    // for clarity:
    result->next = nullptr;
    return result;
  }
  void push(liststack_node* add) {
    add->next = next;
    next = add;
  }
  bool empty() {
    return next == nullptr;
  }
};

struct zeroable_bitset {
  // until this implementation becomes profile-measurable, it's good enough.
  bit_index_type num_bits;
  boost::dynamic_bitset<> bits;
  std::vector<bit_index_type> bits_to_clear;

  zeroable_bitset(bit_index_type num_bits)
   : num_bits(num_bits), bits(num_bits), bits_to_clear() {}
};

typedef liststack<zeroable_bitset> zeroable_bitset_list;
// node/iterator/such
typedef liststack_node<zeroable_bitset> zeroable_bitset_node;

static const size_t array_of_bitset_lists_len = 40;
static const size_t bit_to_min_size_exponent = 6;
// if we track 4-8byteses individually, this exponent would be smaller.
static const size_t bit_exponent_below_which_its_worth_tracking_bits_individually = 8;

// array of array_of_bitset_lists_len sizes, from 2**bit_to_min_size_exponent bits up.
typedef zeroable_bitset_list* zeroable_bitset_array;

extern thread_local zeroable_bitset_array array_of_bitset_lists;

inline
void delete_array_of_bitset_lists() { delete[] array_of_bitset_lists; }

inline
zeroable_bitset_array get_this_thread_array_of_bitset_lists() {
  if(array_of_bitset_lists == nullptr) {
    array_of_bitset_lists = new zeroable_bitset_list[array_of_bitset_lists_len];
    #if 0 && !LASERCAKE_NO_THREADS
    // No Boost.Thread for now; fewer deps.
    // Currently, the borrowed_bitset won't leak memory in Lasercake
    // because we only create a small, finite number of threads.
    // We'll use some better solution if that changes (TODO).
      try {
        // (note, if we use forcible thread cancelation, this won't run)
        // Also, donating them to another thread might be more useful
        // than deleting them.
        boost::this_thread::at_thread_exit(delete_array_of_bitset_lists);
      }
      catch(...) {
        delete array_of_bitset_lists;
        array_of_bitset_lists = nullptr;
        throw;
      }
    #endif
  }
  return array_of_bitset_lists;
};

inline size_t which_bitset_index_is_size(bit_index_type num_bits) {
  if(num_bits == 0) return 0;
  const bit_index_type max_bit_index = num_bits - 1;
  const bit_index_type max_8byte_index = max_bit_index >> bit_to_min_size_exponent;
  caller_error_if(max_8byte_index != size_t(max_8byte_index), "More bits requested than your architecture can handle!");
  const size_t which_bitset_size_index = num_bits_in_integer_that_are_not_leading_zeroes(max_8byte_index);
  caller_error_if(which_bitset_size_index >= array_of_bitset_lists_len, "More bits requested than we support!");
  return which_bitset_size_index;
}

inline bit_index_type how_many_bits_at_bitset_index(size_t bitset_index) {
  return bit_index_type(1) << (bitset_index + bit_to_min_size_exponent);
}

inline
zeroable_bitset_node* borrow_bitset(bit_index_type num_bits_desired) {
  zeroable_bitset_array array_of_bitset_lists = get_this_thread_array_of_bitset_lists();
  const size_t which_bitset_size_index = which_bitset_index_is_size(num_bits_desired);
  const bit_index_type actual_bits = how_many_bits_at_bitset_index(which_bitset_size_index);
  assert(actual_bits >= num_bits_desired);
  assert(actual_bits < num_bits_desired*2 || actual_bits == (1<<bit_to_min_size_exponent));
  zeroable_bitset_list& result_list = array_of_bitset_lists[which_bitset_size_index];
  if(!result_list.empty()) {
    zeroable_bitset_node* result = result_list.pop();
    assert(result->here.num_bits == actual_bits);
    return result;
  }
  else {
    return new zeroable_bitset_node(actual_bits);
  }
}

inline void return_bitset(zeroable_bitset_node* node) BOOST_NOEXCEPT {
  zeroable_bitset_array array_of_bitset_lists;
  try {
    array_of_bitset_lists = get_this_thread_array_of_bitset_lists();
  }
  catch(std::exception const&) {
    // This function is called from destructors so it must be nothrow.
    // In particular, this may happen if the destructor is called in a different
    // thread than the constructor was (std::bad_alloc or similar).
    delete node;
    return;
  }
  const size_t which_bitset_size_index = which_bitset_index_is_size(node->here.num_bits);
  array_of_bitset_lists[which_bitset_size_index].push(node);
}

// borrowed_bitset(n) borrows an array of zero bits of size n (rounded
// up to something), and when destructed it restores the zeroes and returns
// that array.  (There's a dynamically allocated pool of arrays of zeroes
// waiting to be borrowed; if none are available, borrowed_bitset allocates
// a new one, which it will return to the pool when destructed.)
//
// If there aren't too many borrowed_bitsets at once and program runs for
// a while, borrowed_bitset() effectively has O(1) construction, and
// destruction time <= the number of operations performed on it (so no worse
// than a constant factor). This is pretty good for something this much
// faster at uniquing than an unordered_set<uint>.
class borrowed_bitset : boost::noncopyable {
public:
  explicit borrowed_bitset(bit_index_type num_bits_desired) : bs_(borrow_bitset(num_bits_desired)) {}
  borrowed_bitset() : bs_(nullptr) {} //default-constructing invalid bitsets is okay
  borrowed_bitset(borrowed_bitset&& other) { bs_ = other.bs_; other.bs_ = nullptr; }
  bool test(bit_index_type which)const {
    caller_correct_if(which < size(), "borrowed_bitset bounds overflow");
    return bs_->here.bits.test(which);
  }
  bool set(bit_index_type which) {
    bool was_already_set = test(which);
    if(!was_already_set && tracking_bits_individually_()) {
      bs_->here.bits_to_clear.push_back(which);
    }
    bs_->here.bits.set(which);
    return was_already_set;
  }
  bit_index_type size()const {
    // Implementation detail: this number might be greater than the number
    // requested by the constructor.  We could store the requested number,
    // but is it important to?
    return bs_->here.num_bits;
  }
  ~borrowed_bitset() {
    if(!bs_) return;
    if(tracking_bits_individually_()) {
      for(bit_index_type which : bs_->here.bits_to_clear) {
        bs_->here.bits.reset(which);
      }
    }
    else {
      bs_->here.bits.reset();
    }
    bs_->here.bits_to_clear.clear();
    return_bitset(bs_);
  }
private:
  bool tracking_bits_individually_() const {
    return bs_->here.bits_to_clear.size()
         < (bs_->here.num_bits >> bit_exponent_below_which_its_worth_tracking_bits_individually);
  }
  zeroable_bitset_node* bs_;
};

// If you know ahead of time that you're going to set most of the bits,
// this will give a small constant-factor speed improvement over
// borrowed_bitset.
class borrowed_bitset_that_always_clears_using_memset : boost::noncopyable {
public:
  explicit borrowed_bitset_that_always_clears_using_memset(bit_index_type num_bits_desired)
   : bs_(borrow_bitset(num_bits_desired)) {}
  borrowed_bitset_that_always_clears_using_memset()
   : bs_(nullptr) {} //default-constructing invalid bitsets is okay
  borrowed_bitset_that_always_clears_using_memset(borrowed_bitset_that_always_clears_using_memset&& other)
    { bs_ = other.bs_; other.bs_ = nullptr; }
  bool test(bit_index_type which)const {
    caller_correct_if(which < size(), "borrowed_bitset bounds overflow");
    return bs_->here.bits.test(which);
  }
  bool set(bit_index_type which) {
    bool was_already_set = test(which);
    bs_->here.bits.set(which);
    return was_already_set;
  }
  bit_index_type size()const {
    // Implementation detail: this number might be greater than the number
    // requested by the constructor.  We could store the requested number,
    // but is it important to?
    return bs_->here.num_bits;
  }
  ~borrowed_bitset_that_always_clears_using_memset() {
    if(!bs_) return;
    bs_->here.bits.reset();
    return_bitset(bs_);
  }
private:
  zeroable_bitset_node* bs_;
};

}

using borrowed_bitset_impl::borrowed_bitset;
using borrowed_bitset_impl::borrowed_bitset_that_always_clears_using_memset;

#endif

<commit_msg>replace borrowed_bitset's use of dynamic_bitset with custom bitbuffer<commit_after>/*

    Copyright Eli Dupree and Isaac Dupree, 2011, 2012

    This file is part of Lasercake.

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

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

    You should have received a copy of the GNU General Public License
    along with Lasercake.  If not, see <http://www.gnu.org/licenses/>.

*/

#ifndef LASERCAKE_BORROWED_BITSET_HPP__
#define LASERCAKE_BORROWED_BITSET_HPP__

#include <list>
#include <stack>
#include <boost/utility.hpp>
#include <cstring> // for memset

#include "../utils.hpp"
#if 0 && !LASERCAKE_NO_THREADS
#include <boost/thread/thread.hpp>
#endif

typedef uint64_t bit_index_type;

namespace borrowed_bitset_impl {

// Noncopying singly linked list that owns its members unless you pop them.
template<typename T>
struct liststack_node : boost::noncopyable {
  liststack_node* next;
  T here;

  liststack_node() : next(nullptr), here() {}
  template<typename Arg>
  explicit liststack_node(Arg const& arg, liststack_node* next = nullptr)
   : next(next), here(arg) {}
  ~liststack_node() { delete next; }
};

template<typename T>
struct liststack : boost::noncopyable {
  typedef borrowed_bitset_impl::liststack_node<T> liststack_node;
  liststack_node* next;

  liststack() : next(nullptr) {}
  explicit liststack(liststack_node* next) : next(next) {}
  ~liststack() { delete next; }

  liststack_node* pop() {
    liststack_node* result = next;
    next = result->next;
    // for clarity:
    result->next = nullptr;
    return result;
  }
  void push(liststack_node* add) {
    add->next = next;
    next = add;
  }
  bool empty() {
    return next == nullptr;
  }
};

// reminiscent of boost::dynamic_bitset
// should Block be a union instead?
// There is no checking for invalid indexes.
// In fact, after construction, it doesn't even *know* how large it is.
// It's for the other parts of the code to keep track of which parts of that
// they want to.
//
// For bitset operations, on x86_64,
// uint32_t appeared a bit faster than uint64_t as block-size for this.
template <typename Block = uint32_t>
struct bitbuffer : boost::noncopyable {
  typedef Block block_type;
  typedef ::bit_index_type bit_index_type;
  typedef size_t block_index_type;
  typedef int32_t block_width_type;
  static const block_width_type bits_per_block = std::numeric_limits<Block>::digits;
  block_type* buffer;
  bitbuffer() : buffer(nullptr) {}
  bitbuffer(bitbuffer&& other) {
    buffer = other.buffer;
    other.buffer = nullptr;
  }
  bitbuffer& operator=(bitbuffer&& other) {
    buffer = other.buffer;
    other.buffer = nullptr;
  }

  void new_zeroed_buffer_with_num_blocks(block_index_type num_blocks) {
    buffer = new block_type[num_blocks];
    reset_block_range(0, num_blocks);
  }
  void delete_buffer() {
    if(buffer) {delete[] buffer;}
    buffer = nullptr;
  }
  ~bitbuffer() {
    delete_buffer();
  }

  void reset_block_range(block_index_type begin, block_index_type count) {
    memset(buffer + begin, 0, count * sizeof(block_type));
  }

  void set_bit(bit_index_type pos) {
    buffer[block_index(pos)] |= bit_mask(pos);
  }
  void reset_bit(bit_index_type pos) {
    buffer[block_index(pos)] &= ~bit_mask(pos);
  }
  void set_bit(bit_index_type pos, bool val) {
    buffer[block_index(pos)] |= bit_mask_if(pos, val);
    buffer[block_index(pos)] &= ~bit_mask_if(pos, !val);
  }
  void flip_bit(bit_index_type pos) {
    buffer[block_index(pos)] ^= bit_mask(pos);
  }
  bool test_bit(bit_index_type pos)const {
    return bool(buffer[block_index(pos)] & bit_mask(pos));
  }

  void set_block(block_index_type pos, block_type val) {
    buffer[pos] = val;
  }
  void get_block(block_index_type pos)const {
    return buffer[pos];
  }

  static block_index_type block_index(bit_index_type pos) {
    return pos / bits_per_block;

  }
  static block_width_type bit_index(bit_index_type pos) {
    return static_cast<block_width_type>(pos % bits_per_block);
  }
  static block_type bit_mask(bit_index_type pos) {
    return block_type(1) << bit_index(pos);
  }
  static block_type bit_mask_if(bit_index_type pos, bool val) {
    return block_type(val) << bit_index(pos);
  }
};

struct zeroable_bitset {
  typedef bitbuffer<> bitbuffer_type;
  bit_index_type num_bits;
  bitbuffer_type bits;
  std::vector<bit_index_type> bits_to_clear;

  zeroable_bitset(bit_index_type num_bits) : num_bits(num_bits) {
     bits.new_zeroed_buffer_with_num_blocks(num_blocks_allocated());
  }
  size_t num_blocks_allocated()const {
    // Divide rounding up.
    return (num_bits + (bitbuffer_type::bits_per_block - 1)) / bitbuffer_type::bits_per_block;
  }
};

typedef liststack<zeroable_bitset> zeroable_bitset_list;
// node/iterator/such
typedef liststack_node<zeroable_bitset> zeroable_bitset_node;

static const size_t array_of_bitset_lists_len = 40;
static const size_t bit_to_min_size_exponent = 6;
// if we track 4-8byteses individually, this exponent would be smaller.
static const size_t bit_exponent_below_which_its_worth_tracking_bits_individually = 8;

// array of array_of_bitset_lists_len sizes, from 2**bit_to_min_size_exponent bits up.
typedef zeroable_bitset_list* zeroable_bitset_array;

extern thread_local zeroable_bitset_array array_of_bitset_lists;

inline
void delete_array_of_bitset_lists() { delete[] array_of_bitset_lists; }

inline
zeroable_bitset_array get_this_thread_array_of_bitset_lists() {
  if(array_of_bitset_lists == nullptr) {
    array_of_bitset_lists = new zeroable_bitset_list[array_of_bitset_lists_len];
    #if 0 && !LASERCAKE_NO_THREADS
    // No Boost.Thread for now; fewer deps.
    // Currently, the borrowed_bitset won't leak memory in Lasercake
    // because we only create a small, finite number of threads.
    // We'll use some better solution if that changes (TODO).
      try {
        // (note, if we use forcible thread cancelation, this won't run)
        // Also, donating them to another thread might be more useful
        // than deleting them.
        boost::this_thread::at_thread_exit(delete_array_of_bitset_lists);
      }
      catch(...) {
        delete array_of_bitset_lists;
        array_of_bitset_lists = nullptr;
        throw;
      }
    #endif
  }
  return array_of_bitset_lists;
};

inline size_t which_bitset_index_is_size(bit_index_type num_bits) {
  if(num_bits == 0) return 0;
  const bit_index_type max_bit_index = num_bits - 1;
  const bit_index_type max_8byte_index = max_bit_index >> bit_to_min_size_exponent;
  caller_error_if(max_8byte_index != size_t(max_8byte_index), "More bits requested than your architecture can handle!");
  const size_t which_bitset_size_index = num_bits_in_integer_that_are_not_leading_zeroes(max_8byte_index);
  caller_error_if(which_bitset_size_index >= array_of_bitset_lists_len, "More bits requested than we support!");
  return which_bitset_size_index;
}

inline bit_index_type how_many_bits_at_bitset_index(size_t bitset_index) {
  return bit_index_type(1) << (bitset_index + bit_to_min_size_exponent);
}

inline
zeroable_bitset_node* borrow_bitset(bit_index_type num_bits_desired) {
  zeroable_bitset_array array_of_bitset_lists = get_this_thread_array_of_bitset_lists();
  const size_t which_bitset_size_index = which_bitset_index_is_size(num_bits_desired);
  const bit_index_type actual_bits = how_many_bits_at_bitset_index(which_bitset_size_index);
  assert(actual_bits >= num_bits_desired);
  assert(actual_bits < num_bits_desired*2 || actual_bits == (1<<bit_to_min_size_exponent));
  zeroable_bitset_list& result_list = array_of_bitset_lists[which_bitset_size_index];
  if(!result_list.empty()) {
    zeroable_bitset_node* result = result_list.pop();
    assert(result->here.num_bits == actual_bits);
    return result;
  }
  else {
    return new zeroable_bitset_node(actual_bits);
  }
}

inline void return_bitset(zeroable_bitset_node* node) BOOST_NOEXCEPT {
  zeroable_bitset_array array_of_bitset_lists;
  try {
    array_of_bitset_lists = get_this_thread_array_of_bitset_lists();
  }
  catch(std::exception const&) {
    // This function is called from destructors so it must be nothrow.
    // In particular, this may happen if the destructor is called in a different
    // thread than the constructor was (std::bad_alloc or similar).
    delete node;
    return;
  }
  const size_t which_bitset_size_index = which_bitset_index_is_size(node->here.num_bits);
  array_of_bitset_lists[which_bitset_size_index].push(node);
}

// borrowed_bitset(n) borrows an array of zero bits of size n (rounded
// up to something), and when destructed it restores the zeroes and returns
// that array.  (There's a dynamically allocated pool of arrays of zeroes
// waiting to be borrowed; if none are available, borrowed_bitset allocates
// a new one, which it will return to the pool when destructed.)
//
// If there aren't too many borrowed_bitsets at once and program runs for
// a while, borrowed_bitset() effectively has O(1) construction, and
// destruction time <= the number of operations performed on it (so no worse
// than a constant factor). This is pretty good for something this much
// faster at uniquing than an unordered_set<uint>.
class borrowed_bitset : boost::noncopyable {
public:
  explicit borrowed_bitset(bit_index_type num_bits_desired) : bs_(borrow_bitset(num_bits_desired)) {}
  borrowed_bitset() : bs_(nullptr) {} //default-constructing invalid bitsets is okay
  borrowed_bitset(borrowed_bitset&& other) { bs_ = other.bs_; other.bs_ = nullptr; }
  bool test(bit_index_type which)const {
    caller_correct_if(which < size(), "borrowed_bitset bounds overflow");
    return bs_->here.bits.test_bit(which);
  }
  bool set(bit_index_type which) {
    bool was_already_set = test(which);
    if(!was_already_set && tracking_bits_individually_()) {
      bs_->here.bits_to_clear.push_back(which);
    }
    bs_->here.bits.set_bit(which);
    return was_already_set;
  }
  bit_index_type size()const {
    // Implementation detail: this number might be greater than the number
    // requested by the constructor.  We could store the requested number,
    // but is it important to?
    return bs_->here.num_bits;
  }
  ~borrowed_bitset() {
    if(!bs_) return;
    if(tracking_bits_individually_()) {
      for(bit_index_type which : bs_->here.bits_to_clear) {
        bs_->here.bits.reset_bit(which);
      }
    }
    else {
      // TODO optimization: store size of *this* buffer and only clear *that*.
      bs_->here.bits.reset_block_range(0, bs_->here.num_blocks_allocated());
    }
    bs_->here.bits_to_clear.clear();
    return_bitset(bs_);
  }
private:
  bool tracking_bits_individually_() const {
    return bs_->here.bits_to_clear.size()
         < (bs_->here.num_bits >> bit_exponent_below_which_its_worth_tracking_bits_individually);
  }
  zeroable_bitset_node* bs_;
};

// If you know ahead of time that you're going to set most of the bits,
// this will give a small constant-factor speed improvement over
// borrowed_bitset.
class borrowed_bitset_that_always_clears_using_memset : boost::noncopyable {
public:
  explicit borrowed_bitset_that_always_clears_using_memset(bit_index_type num_bits_desired)
   : bs_(borrow_bitset(num_bits_desired)) {}
  borrowed_bitset_that_always_clears_using_memset()
   : bs_(nullptr) {} //default-constructing invalid bitsets is okay
  borrowed_bitset_that_always_clears_using_memset(borrowed_bitset_that_always_clears_using_memset&& other)
    { bs_ = other.bs_; other.bs_ = nullptr; }
  bool test(bit_index_type which)const {
    caller_correct_if(which < size(), "borrowed_bitset bounds overflow");
    return bs_->here.bits.test_bit(which);
  }
  bool set(bit_index_type which) {
    bool was_already_set = test(which);
    bs_->here.bits.set_bit(which);
    return was_already_set;
  }
  bit_index_type size()const {
    // Implementation detail: this number might be greater than the number
    // requested by the constructor.  We could store the requested number,
    // but is it important to?
    return bs_->here.num_bits;
  }
  ~borrowed_bitset_that_always_clears_using_memset() {
    if(!bs_) return;
    bs_->here.bits.reset_block_range(0, bs_->here.num_blocks_allocated());
    return_bitset(bs_);
  }
private:
  zeroable_bitset_node* bs_;
};

}

using borrowed_bitset_impl::borrowed_bitset;
using borrowed_bitset_impl::borrowed_bitset_that_always_clears_using_memset;

#endif

<|endoftext|>


<commit_before>// Copyright (c) 2011-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.

#include <policy/fees.h>
#include <policy/policy.h>
#include <txmempool.h>
#include <uint256.h>
#include <util/time.h>

#include <test/util/setup_common.h>

#include <boost/test/unit_test.hpp>

BOOST_FIXTURE_TEST_SUITE(policyestimator_tests, BasicTestingSetup)

BOOST_AUTO_TEST_CASE(BlockPolicyEstimates)
{
    CBlockPolicyEstimator feeEst;
    CTxMemPool mpool(&feeEst);
    LOCK2(cs_main, mpool.cs);
    TestMemPoolEntryHelper entry;
    CAmount basefee(2000);
    CAmount deltaFee(100);
    std::vector<CAmount> feeV;

    // Populate vectors of increasing fees
    for (int j = 0; j < 10; j++) {
        feeV.push_back(basefee * (j+1));
    }

    // Store the hashes of transactions that have been
    // added to the mempool by their associate fee
    // txHashes[j] is populated with transactions either of
    // fee = basefee * (j+1)
    std::vector<uint256> txHashes[10];

    // Create a transaction template
    CScript garbage;
    for (unsigned int i = 0; i < 128; i++)
        garbage.push_back('X');
    CMutableTransaction tx;
    tx.vin.resize(1);
    tx.vin[0].scriptSig = garbage;
    tx.vout.resize(1);
    tx.vout[0].nValue=0LL;
    CFeeRate baseRate(basefee, GetVirtualTransactionSize(CTransaction(tx)));

    // Create a fake block
    std::vector<CTransactionRef> block;
    int blocknum = 0;

    // Loop through 200 blocks
    // At a decay .9952 and 4 fee transactions per block
    // This makes the tx count about 2.5 per bucket, well above the 0.1 threshold
    while (blocknum < 200) {
        for (int j = 0; j < 10; j++) { // For each fee
            for (int k = 0; k < 4; k++) { // add 4 fee txs
                tx.vin[0].prevout.n = 10000*blocknum+100*j+k; // make transaction unique
                uint256 hash = tx.GetHash();
                mpool.addUnchecked(entry.Fee(feeV[j]).Time(GetTime()).Height(blocknum).FromTx(tx));
                txHashes[j].push_back(hash);
            }
        }
        //Create blocks where higher fee txs are included more often
        for (int h = 0; h <= blocknum%10; h++) {
            // 10/10 blocks add highest fee transactions
            // 9/10 blocks add 2nd highest and so on until ...
            // 1/10 blocks add lowest fee transactions
            while (txHashes[9-h].size()) {
                CTransactionRef ptx = mpool.get(txHashes[9-h].back());
                if (ptx)
                    block.push_back(ptx);
                txHashes[9-h].pop_back();
            }
        }
        mpool.removeForBlock(block, ++blocknum);
        block.clear();
        // Check after just a few txs that combining buckets works as expected
        if (blocknum == 3) {
            // At this point we should need to combine 3 buckets to get enough data points
            // So estimateFee(1) should fail and estimateFee(2) should return somewhere around
            // 9*baserate.  estimateFee(2) %'s are 100,100,90 = average 97%
            BOOST_CHECK(feeEst.estimateFee(1) == CFeeRate(0));
            BOOST_CHECK(feeEst.estimateFee(2).GetFeePerK() < 9*baseRate.GetFeePerK() + deltaFee);
            BOOST_CHECK(feeEst.estimateFee(2).GetFeePerK() > 9*baseRate.GetFeePerK() - deltaFee);
        }
    }

    std::vector<CAmount> origFeeEst;
    // Highest feerate is 10*baseRate and gets in all blocks,
    // second highest feerate is 9*baseRate and gets in 9/10 blocks = 90%,
    // third highest feerate is 8*base rate, and gets in 8/10 blocks = 80%,
    // so estimateFee(1) would return 10*baseRate but is hardcoded to return failure
    // Second highest feerate has 100% chance of being included by 2 blocks,
    // so estimateFee(2) should return 9*baseRate etc...
    for (int i = 1; i < 10;i++) {
        origFeeEst.push_back(feeEst.estimateFee(i).GetFeePerK());
        if (i > 2) { // Fee estimates should be monotonically decreasing
            BOOST_CHECK(origFeeEst[i-1] <= origFeeEst[i-2]);
        }
        int mult = 11-i;
        if (i % 2 == 0) { //At scale 2, test logic is only correct for even targets
            BOOST_CHECK(origFeeEst[i-1] < mult*baseRate.GetFeePerK() + deltaFee);
            BOOST_CHECK(origFeeEst[i-1] > mult*baseRate.GetFeePerK() - deltaFee);
        }
    }
    // Fill out rest of the original estimates
    for (int i = 10; i <= 48; i++) {
        origFeeEst.push_back(feeEst.estimateFee(i).GetFeePerK());
    }

    // Mine 50 more blocks with no transactions happening, estimates shouldn't change
    // We haven't decayed the moving average enough so we still have enough data points in every bucket
    while (blocknum < 250)
        mpool.removeForBlock(block, ++blocknum);

    BOOST_CHECK(feeEst.estimateFee(1) == CFeeRate(0));
    for (int i = 2; i < 10;i++) {
        BOOST_CHECK(feeEst.estimateFee(i).GetFeePerK() < origFeeEst[i-1] + deltaFee);
        BOOST_CHECK(feeEst.estimateFee(i).GetFeePerK() > origFeeEst[i-1] - deltaFee);
    }

    // Mine 15 more blocks with lots of transactions happening and not getting mined
    // Estimates should go up
    while (blocknum < 265) {
        for (int j = 0; j < 10; j++) { // For each fee multiple
            for (int k = 0; k < 4; k++) { // add 4 fee txs
                tx.vin[0].prevout.n = 10000*blocknum+100*j+k;
                uint256 hash = tx.GetHash();
                mpool.addUnchecked(entry.Fee(feeV[j]).Time(GetTime()).Height(blocknum).FromTx(tx));
                txHashes[j].push_back(hash);
            }
        }
        mpool.removeForBlock(block, ++blocknum);
    }

    for (int i = 1; i < 10;i++) {
        BOOST_CHECK(feeEst.estimateFee(i) == CFeeRate(0) || feeEst.estimateFee(i).GetFeePerK() > origFeeEst[i-1] - deltaFee);
    }

    // Mine all those transactions
    // Estimates should still not be below original
    for (int j = 0; j < 10; j++) {
        while(txHashes[j].size()) {
            CTransactionRef ptx = mpool.get(txHashes[j].back());
            if (ptx)
                block.push_back(ptx);
            txHashes[j].pop_back();
        }
    }
    mpool.removeForBlock(block, 266);
    block.clear();
    BOOST_CHECK(feeEst.estimateFee(1) == CFeeRate(0));
    for (int i = 2; i < 10;i++) {
        BOOST_CHECK(feeEst.estimateFee(i) == CFeeRate(0) || feeEst.estimateFee(i).GetFeePerK() > origFeeEst[i-1] - deltaFee);
    }

    // Mine 400 more blocks where everything is mined every block
    // Estimates should be below original estimates
    while (blocknum < 665) {
        for (int j = 0; j < 10; j++) { // For each fee multiple
            for (int k = 0; k < 4; k++) { // add 4 fee txs
                tx.vin[0].prevout.n = 10000*blocknum+100*j+k;
                uint256 hash = tx.GetHash();
                mpool.addUnchecked(entry.Fee(feeV[j]).Time(GetTime()).Height(blocknum).FromTx(tx));
                CTransactionRef ptx = mpool.get(hash);
                if (ptx)
                    block.push_back(ptx);

            }
        }
        mpool.removeForBlock(block, ++blocknum);
        block.clear();
    }
    BOOST_CHECK(feeEst.estimateFee(1) == CFeeRate(0));
    for (int i = 2; i < 9; i++) { // At 9, the original estimate was already at the bottom (b/c scale = 2)
        BOOST_CHECK(feeEst.estimateFee(i).GetFeePerK() < origFeeEst[i-1] - deltaFee);
    }
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>test/policyestimator: Use ChainTestingSetup's CTxMemPool<commit_after>// Copyright (c) 2011-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.

#include <policy/fees.h>
#include <policy/policy.h>
#include <txmempool.h>
#include <uint256.h>
#include <util/time.h>

#include <test/util/setup_common.h>

#include <boost/test/unit_test.hpp>

BOOST_FIXTURE_TEST_SUITE(policyestimator_tests, ChainTestingSetup)

BOOST_AUTO_TEST_CASE(BlockPolicyEstimates)
{
    CBlockPolicyEstimator& feeEst = *Assert(m_node.fee_estimator);
    CTxMemPool& mpool = *Assert(m_node.mempool);
    LOCK2(cs_main, mpool.cs);
    TestMemPoolEntryHelper entry;
    CAmount basefee(2000);
    CAmount deltaFee(100);
    std::vector<CAmount> feeV;

    // Populate vectors of increasing fees
    for (int j = 0; j < 10; j++) {
        feeV.push_back(basefee * (j+1));
    }

    // Store the hashes of transactions that have been
    // added to the mempool by their associate fee
    // txHashes[j] is populated with transactions either of
    // fee = basefee * (j+1)
    std::vector<uint256> txHashes[10];

    // Create a transaction template
    CScript garbage;
    for (unsigned int i = 0; i < 128; i++)
        garbage.push_back('X');
    CMutableTransaction tx;
    tx.vin.resize(1);
    tx.vin[0].scriptSig = garbage;
    tx.vout.resize(1);
    tx.vout[0].nValue=0LL;
    CFeeRate baseRate(basefee, GetVirtualTransactionSize(CTransaction(tx)));

    // Create a fake block
    std::vector<CTransactionRef> block;
    int blocknum = 0;

    // Loop through 200 blocks
    // At a decay .9952 and 4 fee transactions per block
    // This makes the tx count about 2.5 per bucket, well above the 0.1 threshold
    while (blocknum < 200) {
        for (int j = 0; j < 10; j++) { // For each fee
            for (int k = 0; k < 4; k++) { // add 4 fee txs
                tx.vin[0].prevout.n = 10000*blocknum+100*j+k; // make transaction unique
                uint256 hash = tx.GetHash();
                mpool.addUnchecked(entry.Fee(feeV[j]).Time(GetTime()).Height(blocknum).FromTx(tx));
                txHashes[j].push_back(hash);
            }
        }
        //Create blocks where higher fee txs are included more often
        for (int h = 0; h <= blocknum%10; h++) {
            // 10/10 blocks add highest fee transactions
            // 9/10 blocks add 2nd highest and so on until ...
            // 1/10 blocks add lowest fee transactions
            while (txHashes[9-h].size()) {
                CTransactionRef ptx = mpool.get(txHashes[9-h].back());
                if (ptx)
                    block.push_back(ptx);
                txHashes[9-h].pop_back();
            }
        }
        mpool.removeForBlock(block, ++blocknum);
        block.clear();
        // Check after just a few txs that combining buckets works as expected
        if (blocknum == 3) {
            // At this point we should need to combine 3 buckets to get enough data points
            // So estimateFee(1) should fail and estimateFee(2) should return somewhere around
            // 9*baserate.  estimateFee(2) %'s are 100,100,90 = average 97%
            BOOST_CHECK(feeEst.estimateFee(1) == CFeeRate(0));
            BOOST_CHECK(feeEst.estimateFee(2).GetFeePerK() < 9*baseRate.GetFeePerK() + deltaFee);
            BOOST_CHECK(feeEst.estimateFee(2).GetFeePerK() > 9*baseRate.GetFeePerK() - deltaFee);
        }
    }

    std::vector<CAmount> origFeeEst;
    // Highest feerate is 10*baseRate and gets in all blocks,
    // second highest feerate is 9*baseRate and gets in 9/10 blocks = 90%,
    // third highest feerate is 8*base rate, and gets in 8/10 blocks = 80%,
    // so estimateFee(1) would return 10*baseRate but is hardcoded to return failure
    // Second highest feerate has 100% chance of being included by 2 blocks,
    // so estimateFee(2) should return 9*baseRate etc...
    for (int i = 1; i < 10;i++) {
        origFeeEst.push_back(feeEst.estimateFee(i).GetFeePerK());
        if (i > 2) { // Fee estimates should be monotonically decreasing
            BOOST_CHECK(origFeeEst[i-1] <= origFeeEst[i-2]);
        }
        int mult = 11-i;
        if (i % 2 == 0) { //At scale 2, test logic is only correct for even targets
            BOOST_CHECK(origFeeEst[i-1] < mult*baseRate.GetFeePerK() + deltaFee);
            BOOST_CHECK(origFeeEst[i-1] > mult*baseRate.GetFeePerK() - deltaFee);
        }
    }
    // Fill out rest of the original estimates
    for (int i = 10; i <= 48; i++) {
        origFeeEst.push_back(feeEst.estimateFee(i).GetFeePerK());
    }

    // Mine 50 more blocks with no transactions happening, estimates shouldn't change
    // We haven't decayed the moving average enough so we still have enough data points in every bucket
    while (blocknum < 250)
        mpool.removeForBlock(block, ++blocknum);

    BOOST_CHECK(feeEst.estimateFee(1) == CFeeRate(0));
    for (int i = 2; i < 10;i++) {
        BOOST_CHECK(feeEst.estimateFee(i).GetFeePerK() < origFeeEst[i-1] + deltaFee);
        BOOST_CHECK(feeEst.estimateFee(i).GetFeePerK() > origFeeEst[i-1] - deltaFee);
    }

    // Mine 15 more blocks with lots of transactions happening and not getting mined
    // Estimates should go up
    while (blocknum < 265) {
        for (int j = 0; j < 10; j++) { // For each fee multiple
            for (int k = 0; k < 4; k++) { // add 4 fee txs
                tx.vin[0].prevout.n = 10000*blocknum+100*j+k;
                uint256 hash = tx.GetHash();
                mpool.addUnchecked(entry.Fee(feeV[j]).Time(GetTime()).Height(blocknum).FromTx(tx));
                txHashes[j].push_back(hash);
            }
        }
        mpool.removeForBlock(block, ++blocknum);
    }

    for (int i = 1; i < 10;i++) {
        BOOST_CHECK(feeEst.estimateFee(i) == CFeeRate(0) || feeEst.estimateFee(i).GetFeePerK() > origFeeEst[i-1] - deltaFee);
    }

    // Mine all those transactions
    // Estimates should still not be below original
    for (int j = 0; j < 10; j++) {
        while(txHashes[j].size()) {
            CTransactionRef ptx = mpool.get(txHashes[j].back());
            if (ptx)
                block.push_back(ptx);
            txHashes[j].pop_back();
        }
    }
    mpool.removeForBlock(block, 266);
    block.clear();
    BOOST_CHECK(feeEst.estimateFee(1) == CFeeRate(0));
    for (int i = 2; i < 10;i++) {
        BOOST_CHECK(feeEst.estimateFee(i) == CFeeRate(0) || feeEst.estimateFee(i).GetFeePerK() > origFeeEst[i-1] - deltaFee);
    }

    // Mine 400 more blocks where everything is mined every block
    // Estimates should be below original estimates
    while (blocknum < 665) {
        for (int j = 0; j < 10; j++) { // For each fee multiple
            for (int k = 0; k < 4; k++) { // add 4 fee txs
                tx.vin[0].prevout.n = 10000*blocknum+100*j+k;
                uint256 hash = tx.GetHash();
                mpool.addUnchecked(entry.Fee(feeV[j]).Time(GetTime()).Height(blocknum).FromTx(tx));
                CTransactionRef ptx = mpool.get(hash);
                if (ptx)
                    block.push_back(ptx);

            }
        }
        mpool.removeForBlock(block, ++blocknum);
        block.clear();
    }
    BOOST_CHECK(feeEst.estimateFee(1) == CFeeRate(0));
    for (int i = 2; i < 9; i++) { // At 9, the original estimate was already at the bottom (b/c scale = 2)
        BOOST_CHECK(feeEst.estimateFee(i).GetFeePerK() < origFeeEst[i-1] - deltaFee);
    }
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>