<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include <QtCore/QVariant>
#include <QtGui/QMainWindow>

#include <coreplugin/icore.h>

#include "progressmanager_p.h"

// for windows progress bar
#ifndef __GNUC__
#    include <shobjidl.h>
#endif

// Windows 7 SDK required
#ifdef __ITaskbarList3_INTERFACE_DEFINED__

namespace {
    int total = 0;
    ITaskbarList3* pITask = 0;
}

void Core::Internal::ProgressManagerPrivate::init()
{
    CoInitialize(NULL);
    HRESULT hRes = CoCreateInstance(CLSID_TaskbarList,
                                    NULL,CLSCTX_INPROC_SERVER,
                                    IID_ITaskbarList3,(LPVOID*) &pITask);
     if (FAILED(hRes))
     {
         pITask = 0;
         CoUninitialize();
         return;
     }

     pITask->HrInit();
     return;
}

void Core::Internal::ProgressManagerPrivate::cleanup()
{
    if (pITask) {
    pITask->Release();
    pITask = NULL;
    CoUninitialize();
    }
}

void Core::Internal::ProgressManagerPrivate::setApplicationLabel(const QString &text)
{
    Q_UNUSED(text)
}

void Core::Internal::ProgressManagerPrivate::setApplicationProgressRange(int min, int max)
{
    total = max-min;
}

void Core::Internal::ProgressManagerPrivate::setApplicationProgressValue(int value)
{
    if (pITask) {
        WId winId = Core::ICore::instance()->mainWindow()->winId();
        pITask->SetProgressValue(winId, value, total);
    }
}

void Core::Internal::ProgressManagerPrivate::setApplicationProgressVisible(bool visible)
{
    if (!pITask)
        return;

    WId winId = Core::ICore::instance()->mainWindow()->winId();
    if (visible)
        pITask->SetProgressState(winId, TBPF_NORMAL);
    else
        pITask->SetProgressState(winId, TBPF_NOPROGRESS);
}

#else

void Core::Internal::ProgressManagerPrivate::init()
{
}

void Core::Internal::ProgressManagerPrivate::cleanup()
{
}

void Core::Internal::ProgressManagerPrivate::setApplicationLabel(const QString &text)
{
    Q_UNUSED(text)
}

void Core::Internal::ProgressManagerPrivate::setApplicationProgressRange(int min, int max)
{
    Q_UNUSED(min)
    Q_UNUSED(max)
}

void Core::Internal::ProgressManagerPrivate::setApplicationProgressValue(int value)
{
    Q_UNUSED(value)
}

void Core::Internal::ProgressManagerPrivate::setApplicationProgressVisible(bool visible)
{
    Q_UNUSED(visible)
}

#endif // __ITaskbarList2_INTERFACE_DEFINED__
<commit_msg>Show errors in overlay icon on Windows 7.<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include <QtCore/QVariant>
#include <QtGui/QMainWindow>
#include <QtGui/QFont>
#include <QtGui/QFontMetrics>
#include <QtGui/QPixmap>
#include <QtGui/QPainter>
#include <QtGui/QLabel>

#include <coreplugin/icore.h>

#include "progressmanager_p.h"

// for windows progress bar
#ifndef __GNUC__
#    include <shobjidl.h>
#endif

// Windows 7 SDK required
#ifdef __ITaskbarList3_INTERFACE_DEFINED__

namespace {
    int total = 0;
    ITaskbarList3* pITask = 0;
}

void Core::Internal::ProgressManagerPrivate::init()
{
    CoInitialize(NULL);
    HRESULT hRes = CoCreateInstance(CLSID_TaskbarList,
                                    NULL,CLSCTX_INPROC_SERVER,
                                    IID_ITaskbarList3,(LPVOID*) &pITask);
     if (FAILED(hRes))
     {
         pITask = 0;
         CoUninitialize();
         return;
     }

     pITask->HrInit();
     return;
}

void Core::Internal::ProgressManagerPrivate::cleanup()
{
    if (pITask) {
    pITask->Release();
    pITask = NULL;
    CoUninitialize();
    }
}

void Core::Internal::ProgressManagerPrivate::setApplicationLabel(const QString &text)
{
    if (!pITask)
        return;

    WId winId = Core::ICore::instance()->mainWindow()->winId();
    if (text.isNull()) {
        pITask->SetOverlayIcon(winId, NULL, NULL);
    } else {
        QPixmap pix = QPixmap(":/projectexplorer/images/compile_error.png");
        QPainter p(&pix);
        p.setPen(Qt::white);
        QFont font = p.font();
        font.setPointSize(font.pointSize()-2);
        p.setFont(font);
        p.drawText(QRect(QPoint(0,0), pix.size()), Qt::AlignHCenter|Qt::AlignCenter, text);
        pITask->SetOverlayIcon(winId, pix.toWinHICON(), text.utf16());
    }
}

void Core::Internal::ProgressManagerPrivate::setApplicationProgressRange(int min, int max)
{
    total = max-min;
}

void Core::Internal::ProgressManagerPrivate::setApplicationProgressValue(int value)
{
    if (pITask) {
        WId winId = Core::ICore::instance()->mainWindow()->winId();
        pITask->SetProgressValue(winId, value, total);
    }
}

void Core::Internal::ProgressManagerPrivate::setApplicationProgressVisible(bool visible)
{
    if (!pITask)
        return;

    WId winId = Core::ICore::instance()->mainWindow()->winId();
    if (visible)
        pITask->SetProgressState(winId, TBPF_NORMAL);
    else
        pITask->SetProgressState(winId, TBPF_NOPROGRESS);
}

#else

void Core::Internal::ProgressManagerPrivate::init()
{
}

void Core::Internal::ProgressManagerPrivate::cleanup()
{
}

void Core::Internal::ProgressManagerPrivate::setApplicationLabel(const QString &text)
{
    Q_UNUSED(text)
}

void Core::Internal::ProgressManagerPrivate::setApplicationProgressRange(int min, int max)
{
    Q_UNUSED(min)
    Q_UNUSED(max)
}

void Core::Internal::ProgressManagerPrivate::setApplicationProgressValue(int value)
{
    Q_UNUSED(value)
}

void Core::Internal::ProgressManagerPrivate::setApplicationProgressVisible(bool visible)
{
    Q_UNUSED(visible)
}

#endif // __ITaskbarList2_INTERFACE_DEFINED__
<|endoftext|>


<commit_before>#include "derivations.hh"
#include "globals.hh"
#include "shared.hh"
#include "store-api.hh"
#include <sys/utsname.h>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <mach-o/loader.h>
#include <mach-o/swap.h>

using namespace nix;

typedef std::map<string, std::set<string>> SetMap;

static auto cacheDir = Path{};

Path resolveCacheFile(const Path & lib) {
    Path lib2 = Path(lib);
    std::replace(lib2.begin(), lib2.end(), '/', '%');
    return cacheDir + "/" + lib2;
}

std::set<string> readCacheFile(const Path & file) {
    return tokenizeString<set<string>>(readFile(file), "\n");
}

void writeCacheFile(const Path & file, std::set<string> & deps) {
    std::ofstream fp;
    fp.open(file);
    for (auto & d : deps) {
        fp << d << "\n";
    }
    fp.close();
}

std::string find_dylib_name(FILE *obj_file, struct load_command cmd) {
  fpos_t pos;
  fgetpos(obj_file, &pos);
  struct dylib_command dylc;
  dylc.cmd = cmd.cmd;
  dylc.cmdsize = cmd.cmdsize;
  fread(&dylc.dylib, sizeof(struct dylib), 1, obj_file);

  char *dylib_name = (char*)calloc(cmd.cmdsize, sizeof(char));
  fseek(obj_file,
      // offset is calculated from the beginning of the load command, which is two
      // uint32_t's backwards
      dylc.dylib.name.offset - (sizeof(uint32_t) * 2) + pos,
      SEEK_SET);
  fread(dylib_name, sizeof(char), cmd.cmdsize, obj_file);
  fseek(obj_file, pos, SEEK_SET);
  return std::string(dylib_name);
}

bool seek_mach64_blob(FILE *obj_file, enum NXByteOrder end) {
  struct fat_header head;
  fread(&head, sizeof(struct fat_header), 1, obj_file);
  swap_fat_header(&head, end);
  for(uint32_t narches = 0; narches < head.nfat_arch; narches++) {
    struct fat_arch arch;
    fread(&arch, sizeof(struct fat_arch), 1, obj_file);
    swap_fat_arch(&arch, 1, end);
    if(arch.cputype == CPU_TYPE_X86_64) {
      fseek(obj_file, arch.offset, SEEK_SET);
      return true;
    }
  }
  return false;
}

std::set<std::string> runResolver(const Path & filename) {
  FILE *obj_file = fopen(filename.c_str(), "rb");
  uint32_t magic;
  fread(&magic, sizeof(uint32_t), 1, obj_file);
  fseek(obj_file, 0, SEEK_SET);
  enum NXByteOrder endianness;
  if(magic == 0xBEBAFECA) {
    endianness = NX_BigEndian;
    if(!seek_mach64_blob(obj_file, endianness)) {
      std::cerr << "Could not find any mach64 blobs in file " << filename << ", continuing..." << std::endl;
      return std::set<string>();
    }
  }
  struct mach_header_64 header;
  fread(&header, sizeof(struct mach_header_64), 1, obj_file);
  if(!(header.magic == MH_MAGIC_64 || header.magic == MH_CIGAM_64)) {
    std::cerr << "Not a mach-o object file: " << filename << std::endl;
    return std::set<string>();
  }
  std::set<string> libs;
  for(uint32_t i = 0; i < header.ncmds; i++) {
    struct load_command cmd;
    fread(&cmd.cmd, sizeof(uint32_t), 1, obj_file);
    fread(&cmd.cmdsize, sizeof(uint32_t), 1, obj_file);
    switch(cmd.cmd) {
      case LC_LOAD_DYLIB:
      case LC_LOAD_UPWARD_DYLIB:
      case LC_REEXPORT_DYLIB:
        libs.insert(find_dylib_name(obj_file, cmd));
        break;
    }
    fseek(obj_file, cmd.cmdsize - (sizeof(uint32_t) * 2), SEEK_CUR);
  }
  fclose(obj_file);
  libs.erase(filename);
  return libs;
}

bool isSymlink(const Path & path) {
  struct stat st;
  if(lstat(path.c_str(), &st))
      throw SysError(format("getting attributes of path ‘%1%’") % path);

  return S_ISLNK(st.st_mode);
}

Path resolveSymlink(const Path & path) {
    char buf[PATH_MAX];
    ssize_t len = readlink(path.c_str(), buf, sizeof(buf) - 1);
    if(len != -1) {
      buf[len] = 0;
      return Path(buf);
    } else {
      throw SysError(format("readlink('%1%')") % path);
    }
}

std::set<string> resolve_tree(const Path & path, PathSet & deps) {
  std::set<string> results;
  if(deps.find(path) != deps.end()) {
    return std::set<string>();
  }
  deps.insert(path);
  for (auto & lib : runResolver(path)) {
    results.insert(lib);
    for (auto & p : resolve_tree(lib, deps)) {
      results.insert(p);
    }
  }
  return results;
}

std::set<string> get_path(const Path & path) {
  Path cacheFile = resolveCacheFile(path);
  if(pathExists(cacheFile)) {
    return readCacheFile(cacheFile);
  }

  std::set<string> deps;
  std::set<string> paths;
  paths.insert(path);

  Path next_path = Path(path);
  while(isSymlink(next_path)) {
    next_path = resolveSymlink(next_path);
    paths.insert(next_path);
  }

  for(auto & t : resolve_tree(next_path, deps)) {
    paths.insert(t);
  }

  writeCacheFile(cacheFile, paths);

  return paths;
}

int main(int argc, char ** argv) {
    return handleExceptions(argv[0], [&]() {
        initNix();

        struct utsname _uname;

        uname(&_uname);

        cacheDir = (format("%1%/dependency-maps/%2%-%3%-%4%")
            % settings.nixStateDir
            % _uname.machine
            % _uname.sysname
            % _uname.release).str();

        auto store = openStore();

        auto drv = store->derivationFromPath(Path(argv[1]));
        Strings impurePaths = tokenizeString<Strings>(get(drv.env, "__impureHostDeps"));

        std::set<string> all_paths;

        for (auto & path : impurePaths) {
            for(auto & p : get_path(path)) {
              all_paths.insert(p);
            }
        }

        std::cout << "extra-chroot-dirs" << std::endl;
        for(auto & path : all_paths) {
          std::cout << path << std::endl;
        }
        std::cout << std::endl;
    });
}
<commit_msg>code review comments<commit_after>#include "derivations.hh"
#include "globals.hh"
#include "shared.hh"
#include "store-api.hh"
#include <sys/utsname.h>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <mach-o/loader.h>
#include <mach-o/swap.h>

using namespace nix;

static auto cacheDir = Path{};

Path resolveCacheFile(Path lib) {
    std::replace(lib.begin(), lib.end(), '/', '%');
    return cacheDir + "/" + lib;
}

std::set<string> readCacheFile(const Path & file) {
    return tokenizeString<set<string>>(readFile(file), "\n");
}

void writeCacheFile(const Path & file, std::set<string> & deps) {
    std::ofstream fp;
    fp.open(file);
    for (auto & d : deps) {
        fp << d << "\n";
    }
    fp.close();
}

std::string findDylibName(FILE *obj_file, struct load_command cmd) {
    fpos_t pos;
    fgetpos(obj_file, &pos);
    struct dylib_command dylc;
    dylc.cmd = cmd.cmd;
    dylc.cmdsize = cmd.cmdsize;
    fread(&dylc.dylib, sizeof(struct dylib), 1, obj_file);

    char *dylib_name = (char*)calloc(cmd.cmdsize, sizeof(char));
    fseek(obj_file,
            // offset is calculated from the beginning of the load command, which is two
            // uint32_t's backwards
            dylc.dylib.name.offset - (sizeof(uint32_t) * 2) + pos,
            SEEK_SET);
    fread(dylib_name, sizeof(char), cmd.cmdsize, obj_file);
    fseek(obj_file, pos, SEEK_SET);
    return std::string(dylib_name);
}

bool seekMach64Blob(FILE *obj_file, enum NXByteOrder end) {
    struct fat_header head;
    fread(&head, sizeof(struct fat_header), 1, obj_file);
    swap_fat_header(&head, end);
    for(uint32_t narches = 0; narches < head.nfat_arch; narches++) {
        struct fat_arch arch;
        fread(&arch, sizeof(struct fat_arch), 1, obj_file);
        swap_fat_arch(&arch, 1, end);
        if(arch.cputype == CPU_TYPE_X86_64) {
            fseek(obj_file, arch.offset, SEEK_SET);
            return true;
        }
    }
    return false;
}

std::set<std::string> runResolver(const Path & filename) {
    FILE *obj_file = fopen(filename.c_str(), "rb");
    uint32_t magic;
    fread(&magic, sizeof(uint32_t), 1, obj_file);
    fseek(obj_file, 0, SEEK_SET);
    enum NXByteOrder endianness;
    if(magic == 0xBEBAFECA) {
        endianness = NX_BigEndian;
        if(!seekMach64Blob(obj_file, endianness)) {
            std::cerr << "Could not find any mach64 blobs in file " << filename << ", continuing..." << std::endl;
            return std::set<string>();
        }
    }
    struct mach_header_64 header;
    fread(&header, sizeof(struct mach_header_64), 1, obj_file);
    if(!(header.magic == MH_MAGIC_64 || header.magic == MH_CIGAM_64)) {
        std::cerr << "Not a mach-o object file: " << filename << std::endl;
        return std::set<string>();
    }
    std::set<string> libs;
    for(uint32_t i = 0; i < header.ncmds; i++) {
        struct load_command cmd;
        fread(&cmd.cmd, sizeof(cmd.cmd), 1, obj_file);
        fread(&cmd.cmdsize, sizeof(cmd.cmdsize), 1, obj_file);
        switch(cmd.cmd) {
            case LC_LOAD_DYLIB:
            case LC_LOAD_UPWARD_DYLIB:
            case LC_REEXPORT_DYLIB:
                libs.insert(findDylibName(obj_file, cmd));
                break;
        }
        fseek(obj_file, cmd.cmdsize - (sizeof(uint32_t) * 2), SEEK_CUR);
    }
    fclose(obj_file);
    libs.erase(filename);
    return libs;
}

bool isSymlink(const Path & path) {
    struct stat st;
    if(lstat(path.c_str(), &st))
        throw SysError(format("getting attributes of path ‘%1%’") % path);

    return S_ISLNK(st.st_mode);
}

Path resolveSymlink(const Path & path) {
    char buf[PATH_MAX];
    ssize_t len = readlink(path.c_str(), buf, sizeof(buf) - 1);
    if(len != -1) {
        buf[len] = 0;
        return Path(buf);
    } else {
        throw SysError(format("readlink('%1%')") % path);
    }
}

std::set<string> resolveTree(const Path & path, PathSet & deps) {
    std::set<string> results;
    if(deps.find(path) != deps.end()) {
        return std::set<string>();
    }
    deps.insert(path);
    for (auto & lib : runResolver(path)) {
        results.insert(lib);
        for (auto & p : resolveTree(lib, deps)) {
            results.insert(p);
        }
    }
    return results;
}

std::set<string> getPath(const Path & path) {
    Path cacheFile = resolveCacheFile(path);
    if(pathExists(cacheFile)) {
        return readCacheFile(cacheFile);
    }

    std::set<string> deps;
    std::set<string> paths;
    paths.insert(path);

    Path next_path = Path(path);
    while(isSymlink(next_path)) {
        next_path = resolveSymlink(next_path);
        paths.insert(next_path);
    }

    for(auto & t : resolveTree(next_path, deps)) {
        paths.insert(t);
    }

    writeCacheFile(cacheFile, paths);

    return paths;
}

int main(int argc, char ** argv) {
    return handleExceptions(argv[0], [&]() {
            initNix();

            struct utsname _uname;

            uname(&_uname);

            cacheDir = (format("%1%/dependency-maps/%2%-%3%-%4%")
                    % settings.nixStateDir
                    % _uname.machine
                    % _uname.sysname
                    % _uname.release).str();

            auto store = openStore();

            auto drv = store->derivationFromPath(Path(argv[1]));
            Strings impurePaths = tokenizeString<Strings>(get(drv.env, "__impureHostDeps"));

            std::set<string> all_paths;

            for (auto & path : impurePaths) {
                for(auto & p : getPath(path)) {
                    all_paths.insert(p);
                }
            }

            std::cout << "extra-chroot-dirs" << std::endl;
            for(auto & path : all_paths) {
                std::cout << path << std::endl;
            }
            std::cout << std::endl;
    });
}
<|endoftext|>


<commit_before>#include "output.h"
#include "buffer_pool.h"
#include "compress.h"
#include "cso.h"

namespace maxcso {

// TODO: Tune, less may be better.
static const size_t QUEUE_SIZE = 128;

Output::Output(uv_loop_t *loop, const Task &task)
	: loop_(loop), flags_(task.flags), state_(STATE_INIT), srcSize_(-1), index_(nullptr) {
	for (size_t i = 0; i < QUEUE_SIZE; ++i) {
		freeSectors_.push_back(new Sector(task.flags));
	}
}

Output::~Output() {
	for (Sector *sector : freeSectors_) {
		delete sector;
	}
	for (auto pair : pendingSectors_) {
		delete pair.second;
	}
	freeSectors_.clear();
	pendingSectors_.clear();

	delete [] index_;
	index_ = nullptr;
}

void Output::SetFile(uv_file file, int64_t srcSize) {
	file_ = file;
	srcSize_ = srcSize;
	srcPos_ = 0;

	const uint32_t sectors = static_cast<uint32_t>(srcSize >> SECTOR_SHIFT);
	// Start after the header and index, which we'll fill in later.
	index_ = new uint32_t[sectors + 1];
	// Start after the end of the index data and header.
	dstPos_ = sizeof(CSOHeader) + (sectors + 1) * sizeof(uint32_t);

	// TODO: We might be able to optimize shift better by running through the data.
	// That would require either a second pass or keeping the entire result in RAM.
	// For now, just take worst case (all blocks stored uncompressed.)
	int64_t worstSize = dstPos_ + srcSize;
	shift_ = 0;
	for (int i = 62; i >= 31; --i) {
		int64_t max = 1LL << i;
		if (worstSize >= max) {
			// This means we need i + 1 bits to store the position.
			// We have to shift enough off to fit into 31.
			shift_ = i + 1 - 31;
			break;
		}
	}

	// If the shift is above 11, the padding could make it need more space.
	// But that would be > 4 TB anyway, so let's not worry about it.
	align_ = 1 << shift_;
	Align(dstPos_);

	state_ |= STATE_HAS_FILE;
}

int32_t Output::Align(int64_t &pos) {
	uint32_t off = static_cast<uint32_t>(pos % align_);
	if (off != 0) {
		pos += align_ - off;
		return align_ - off;
	}
	return 0;
}

void Output::Enqueue(int64_t pos, uint8_t *buffer) {
	Sector *sector = freeSectors_.back();
	freeSectors_.pop_back();

	// We might not compress all blocks.
	const bool tryCompress = ShouldCompress(pos, buffer);

	// Sector takes ownership of buffer either way.
	if (tryCompress) {
		sector->Process(loop_, pos, buffer, [this, sector](bool status, const char *reason) {
			HandleReadySector(sector);
		});
	} else {
		sector->Reserve(pos, buffer);
		HandleReadySector(sector);
	}
}

void Output::HandleReadySector(Sector *sector) {
	if (sector != nullptr) {
		if (srcPos_ != sector->Pos()) {
			// We're not there yet in the file stream.  Queue this, get to it later.
			pendingSectors_[sector->Pos()] = sector;
			return;
		}
	} else {
		// If no sector was provided, we're looking at the first in the queue.
		if (pendingSectors_.empty()) {
			return;
		}
		sector = pendingSectors_.begin()->second;
		if (srcPos_ != sector->Pos()) {
			return;
		}

		// Remove it from the queue, and then run with it.
		pendingSectors_.erase(pendingSectors_.begin());
	}

	// Check for any sectors that immediately follow the one we're writing.
	// We'll just write them all together.
	std::vector<Sector *> sectors;
	sectors.push_back(sector);
	// TODO: Try other numbers.
	static const size_t MAX_BUFS = 8;
	int64_t nextPos = srcPos_ + SECTOR_SIZE;
	auto it = pendingSectors_.find(nextPos);
	while (it != pendingSectors_.end()) {
		sectors.push_back(it->second);
		pendingSectors_.erase(it);
		nextPos += SECTOR_SIZE;
		it = pendingSectors_.find(nextPos);

		// Don't do more than 4 at a time.
		if (sectors.size() >= MAX_BUFS) {
			break;
		}
	}

	int64_t dstPos = dstPos_;
	uv_buf_t bufs[MAX_BUFS * 2];
	unsigned int nbufs = 0;
	static char padding[2048] = {0};
	for (size_t i = 0; i < sectors.size(); ++i) {
		bufs[nbufs++] = uv_buf_init(reinterpret_cast<char *>(sectors[i]->BestBuffer()), sectors[i]->BestSize());

		// Update the index.
		const int32_t s = static_cast<int32_t>(sectors[i]->Pos() >> SECTOR_SHIFT);
		index_[s] = static_cast<int32_t>(dstPos >> shift_);
		if (!sectors[i]->Compressed()) {
			index_[s] |= CSO_INDEX_UNCOMPRESSED;
		}

		dstPos += sectors[i]->BestSize();
		int32_t padSize = Align(dstPos);
		if (padSize != 0) {
			// We need uv to write the padding out as well.
			bufs[nbufs++] = uv_buf_init(padding, padSize);
		}
	}

	// If we're working on the last sectors, then the index is ready to write.
	if (nextPos == srcSize_) {
		// Update the final index entry.
		const int32_t s = static_cast<int32_t>(srcSize_ >> SECTOR_SHIFT);
		index_[s] = static_cast<int32_t>(dstPos >> shift_);

		state_ |= STATE_INDEX_READY;
		Flush();
	}

	const int64_t totalWrite = dstPos - dstPos_;
	uv_.fs_write(loop_, sector->WriteReq(), file_, bufs, nbufs, dstPos_, [this, sectors, nextPos, totalWrite](uv_fs_t *req) {
		for (Sector *sector : sectors) {
			sector->Release();
			freeSectors_.push_back(sector);
		}

		if (req->result != totalWrite) {
			finish_(false, "Data could not be written to output file");
			uv_fs_req_cleanup(req);
			return;
		}
		uv_fs_req_cleanup(req);

		srcPos_ = nextPos;
		dstPos_ += totalWrite;

		progress_(srcPos_, srcSize_, dstPos_);

		if (nextPos == srcSize_) {
			state_ |= STATE_DATA_WRITTEN;
			CheckFinish();
		} else {
			// Check if there's more data to write out.
			HandleReadySector(nullptr);
		}
	});
}

bool Output::ShouldCompress(int64_t pos, uint8_t *buffer) {
	if (flags_ & TASKFLAG_FORCE_ALL) {
		return true;
	}

	if (pos == 16 * SECTOR_SIZE) {
		// This is the volume descriptor.
		// TODO: Could read it in and map all the directory structures.
		// Would just need to keep  a list, assuming they are sequential, we'd get most of them.
		// TODO: This doesn't really seem to help anyone.  Rethink.
		//return false;
	}
	// TODO
	return true;
}

bool Output::QueueFull() {
	return freeSectors_.empty();
}

void Output::OnProgress(OutputCallback callback) {
	progress_ = callback;
}

void Output::OnFinish(OutputFinishCallback callback) {
	finish_ = callback;
}

void Output::Flush() {
	if (!(state_ & STATE_INDEX_READY)) {
		finish_(false, "Flush called before index finalized");
		return;
	}

	CSOHeader *header = new CSOHeader;
	memcpy(header->magic, CSO_MAGIC, sizeof(header->magic));
	header->header_size = sizeof(CSOHeader);
	header->uncompressed_size = srcSize_;
	header->sector_size = SECTOR_SIZE;
	header->version = 1;
	header->index_shift = shift_;
	header->unused[0] = 0;
	header->unused[1] = 0;

	const uint32_t sectors = static_cast<uint32_t>(srcSize_ >> SECTOR_SHIFT);

	uv_buf_t bufs[2];
	bufs[0] = uv_buf_init(reinterpret_cast<char *>(header), sizeof(CSOHeader));
	bufs[1] = uv_buf_init(reinterpret_cast<char *>(index_), (sectors + 1) * sizeof(uint32_t));
	const size_t totalBytes = sizeof(CSOHeader) + (sectors + 1) * sizeof(uint32_t);
	uv_.fs_write(loop_, &flush_, file_, bufs, 2, 0, [this, header, totalBytes](uv_fs_t *req) {
		if (req->result != totalBytes) {
			finish_(false, "Unable to write header data");
		} else {
			state_ |= STATE_INDEX_WRITTEN;
			CheckFinish();
		}
		uv_fs_req_cleanup(req);
		delete header;
	});
}

void Output::CheckFinish() {
	if ((state_ & STATE_INDEX_WRITTEN) && (state_ & STATE_DATA_WRITTEN)) {
		finish_(true, nullptr);
	}
}

};
<commit_msg>Use a reduced queue size for less mem usage.<commit_after>#include "output.h"
#include "buffer_pool.h"
#include "compress.h"
#include "cso.h"

namespace maxcso {

// TODO: Tune, less may be better.
static const size_t QUEUE_SIZE = 32;

Output::Output(uv_loop_t *loop, const Task &task)
	: loop_(loop), flags_(task.flags), state_(STATE_INIT), srcSize_(-1), index_(nullptr) {
	for (size_t i = 0; i < QUEUE_SIZE; ++i) {
		freeSectors_.push_back(new Sector(task.flags));
	}
}

Output::~Output() {
	for (Sector *sector : freeSectors_) {
		delete sector;
	}
	for (auto pair : pendingSectors_) {
		delete pair.second;
	}
	freeSectors_.clear();
	pendingSectors_.clear();

	delete [] index_;
	index_ = nullptr;
}

void Output::SetFile(uv_file file, int64_t srcSize) {
	file_ = file;
	srcSize_ = srcSize;
	srcPos_ = 0;

	const uint32_t sectors = static_cast<uint32_t>(srcSize >> SECTOR_SHIFT);
	// Start after the header and index, which we'll fill in later.
	index_ = new uint32_t[sectors + 1];
	// Start after the end of the index data and header.
	dstPos_ = sizeof(CSOHeader) + (sectors + 1) * sizeof(uint32_t);

	// TODO: We might be able to optimize shift better by running through the data.
	// That would require either a second pass or keeping the entire result in RAM.
	// For now, just take worst case (all blocks stored uncompressed.)
	int64_t worstSize = dstPos_ + srcSize;
	shift_ = 0;
	for (int i = 62; i >= 31; --i) {
		int64_t max = 1LL << i;
		if (worstSize >= max) {
			// This means we need i + 1 bits to store the position.
			// We have to shift enough off to fit into 31.
			shift_ = i + 1 - 31;
			break;
		}
	}

	// If the shift is above 11, the padding could make it need more space.
	// But that would be > 4 TB anyway, so let's not worry about it.
	align_ = 1 << shift_;
	Align(dstPos_);

	state_ |= STATE_HAS_FILE;
}

int32_t Output::Align(int64_t &pos) {
	uint32_t off = static_cast<uint32_t>(pos % align_);
	if (off != 0) {
		pos += align_ - off;
		return align_ - off;
	}
	return 0;
}

void Output::Enqueue(int64_t pos, uint8_t *buffer) {
	Sector *sector = freeSectors_.back();
	freeSectors_.pop_back();

	// We might not compress all blocks.
	const bool tryCompress = ShouldCompress(pos, buffer);

	// Sector takes ownership of buffer either way.
	if (tryCompress) {
		sector->Process(loop_, pos, buffer, [this, sector](bool status, const char *reason) {
			HandleReadySector(sector);
		});
	} else {
		sector->Reserve(pos, buffer);
		HandleReadySector(sector);
	}
}

void Output::HandleReadySector(Sector *sector) {
	if (sector != nullptr) {
		if (srcPos_ != sector->Pos()) {
			// We're not there yet in the file stream.  Queue this, get to it later.
			pendingSectors_[sector->Pos()] = sector;
			return;
		}
	} else {
		// If no sector was provided, we're looking at the first in the queue.
		if (pendingSectors_.empty()) {
			return;
		}
		sector = pendingSectors_.begin()->second;
		if (srcPos_ != sector->Pos()) {
			return;
		}

		// Remove it from the queue, and then run with it.
		pendingSectors_.erase(pendingSectors_.begin());
	}

	// Check for any sectors that immediately follow the one we're writing.
	// We'll just write them all together.
	std::vector<Sector *> sectors;
	sectors.push_back(sector);
	// TODO: Try other numbers.
	static const size_t MAX_BUFS = 8;
	int64_t nextPos = srcPos_ + SECTOR_SIZE;
	auto it = pendingSectors_.find(nextPos);
	while (it != pendingSectors_.end()) {
		sectors.push_back(it->second);
		pendingSectors_.erase(it);
		nextPos += SECTOR_SIZE;
		it = pendingSectors_.find(nextPos);

		// Don't do more than 4 at a time.
		if (sectors.size() >= MAX_BUFS) {
			break;
		}
	}

	int64_t dstPos = dstPos_;
	uv_buf_t bufs[MAX_BUFS * 2];
	unsigned int nbufs = 0;
	static char padding[2048] = {0};
	for (size_t i = 0; i < sectors.size(); ++i) {
		bufs[nbufs++] = uv_buf_init(reinterpret_cast<char *>(sectors[i]->BestBuffer()), sectors[i]->BestSize());

		// Update the index.
		const int32_t s = static_cast<int32_t>(sectors[i]->Pos() >> SECTOR_SHIFT);
		index_[s] = static_cast<int32_t>(dstPos >> shift_);
		if (!sectors[i]->Compressed()) {
			index_[s] |= CSO_INDEX_UNCOMPRESSED;
		}

		dstPos += sectors[i]->BestSize();
		int32_t padSize = Align(dstPos);
		if (padSize != 0) {
			// We need uv to write the padding out as well.
			bufs[nbufs++] = uv_buf_init(padding, padSize);
		}
	}

	// If we're working on the last sectors, then the index is ready to write.
	if (nextPos == srcSize_) {
		// Update the final index entry.
		const int32_t s = static_cast<int32_t>(srcSize_ >> SECTOR_SHIFT);
		index_[s] = static_cast<int32_t>(dstPos >> shift_);

		state_ |= STATE_INDEX_READY;
		Flush();
	}

	const int64_t totalWrite = dstPos - dstPos_;
	uv_.fs_write(loop_, sector->WriteReq(), file_, bufs, nbufs, dstPos_, [this, sectors, nextPos, totalWrite](uv_fs_t *req) {
		for (Sector *sector : sectors) {
			sector->Release();
			freeSectors_.push_back(sector);
		}

		if (req->result != totalWrite) {
			finish_(false, "Data could not be written to output file");
			uv_fs_req_cleanup(req);
			return;
		}
		uv_fs_req_cleanup(req);

		srcPos_ = nextPos;
		dstPos_ += totalWrite;

		progress_(srcPos_, srcSize_, dstPos_);

		if (nextPos == srcSize_) {
			state_ |= STATE_DATA_WRITTEN;
			CheckFinish();
		} else {
			// Check if there's more data to write out.
			HandleReadySector(nullptr);
		}
	});
}

bool Output::ShouldCompress(int64_t pos, uint8_t *buffer) {
	if (flags_ & TASKFLAG_FORCE_ALL) {
		return true;
	}

	if (pos == 16 * SECTOR_SIZE) {
		// This is the volume descriptor.
		// TODO: Could read it in and map all the directory structures.
		// Would just need to keep  a list, assuming they are sequential, we'd get most of them.
		// TODO: This doesn't really seem to help anyone.  Rethink.
		//return false;
	}
	// TODO
	return true;
}

bool Output::QueueFull() {
	return freeSectors_.empty();
}

void Output::OnProgress(OutputCallback callback) {
	progress_ = callback;
}

void Output::OnFinish(OutputFinishCallback callback) {
	finish_ = callback;
}

void Output::Flush() {
	if (!(state_ & STATE_INDEX_READY)) {
		finish_(false, "Flush called before index finalized");
		return;
	}

	CSOHeader *header = new CSOHeader;
	memcpy(header->magic, CSO_MAGIC, sizeof(header->magic));
	header->header_size = sizeof(CSOHeader);
	header->uncompressed_size = srcSize_;
	header->sector_size = SECTOR_SIZE;
	header->version = 1;
	header->index_shift = shift_;
	header->unused[0] = 0;
	header->unused[1] = 0;

	const uint32_t sectors = static_cast<uint32_t>(srcSize_ >> SECTOR_SHIFT);

	uv_buf_t bufs[2];
	bufs[0] = uv_buf_init(reinterpret_cast<char *>(header), sizeof(CSOHeader));
	bufs[1] = uv_buf_init(reinterpret_cast<char *>(index_), (sectors + 1) * sizeof(uint32_t));
	const size_t totalBytes = sizeof(CSOHeader) + (sectors + 1) * sizeof(uint32_t);
	uv_.fs_write(loop_, &flush_, file_, bufs, 2, 0, [this, header, totalBytes](uv_fs_t *req) {
		if (req->result != totalBytes) {
			finish_(false, "Unable to write header data");
		} else {
			state_ |= STATE_INDEX_WRITTEN;
			CheckFinish();
		}
		uv_fs_req_cleanup(req);
		delete header;
	});
}

void Output::CheckFinish() {
	if ((state_ & STATE_INDEX_WRITTEN) && (state_ & STATE_DATA_WRITTEN)) {
		finish_(true, nullptr);
	}
}

};
<|endoftext|>


<commit_before>#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

#include "common_struct.h"
#include "common_constant.h"
#include "version.h"

extern int press_rate;
extern double press_interval;
extern host_info host;
extern int press_time;

//如何使用本工具
void usage( const char* tool_name )
{
	fprintf( stderr, "usage:  %s\n", tool_name );
	fprintf( stderr, "        -r [or --rate] N                 [REQUIRED] specify the press rate (unit: query per second).\n" );
	fprintf( stderr, "        -t [or --time] N                 [REQUIRED] test time (unit: second). \n" );
	fprintf( stderr, "        -h [or --host] XXX.XXX.XXX.XXX   target host ip. The default host ip is 127.0.0.1 .\n" );
	fprintf( stderr, "        -p [or --port] N                 port number. The default port number is 80.\n" );
	fprintf( stderr, "        -u [or --uri ] /index.html       uri of the request.\n" );
	exit( 1 );
}

//打印读取的参数信息
void print_info( void )
{
	fprintf( stdout, "\n" );
	fprintf( stdout, "This is %s (last updated on %s), an HTTP benchmarking tool.\n", VERSION, LAST_UPDATE );
	fprintf( stdout, "Copyright © 2014 %s. Email: %s\n\n", AUTHOR, CONTACT );
	fprintf( stdout, "Test Information\n" );
	fprintf( stdout, "    Host       : %s\n", host.host_ip );
	fprintf( stdout, "    Port       : %d\n", host.port );
	fprintf( stdout, "    URI        : %s\n", host.uri );
	fprintf( stdout, "    Target QPS : %-6d%-11s\n", press_rate, "[#/second]" );
	fprintf( stdout, "    Test Time  : %-6d%-11s\n", press_time, "[second]" );
	fprintf( stdout, "\n" );
	return;
}

void check_setting( void )
{
	if( press_rate <= 0 || press_rate > MAX_RATE )
	{
		fprintf( stderr, "The press rate is illegal. The request rate should be between 1 and %d RPS.\n", MAX_RATE );
		exit( 1 );
	}

	if( press_time <= 0 || press_time > MAX_TIME )
	{
		fprintf( stderr, "The press time is too long! The test time should be between 1 and %d seconds.\n", MAX_TIME );
		exit( 1 );
	}

	return ;
}

void statistics_calculation( final_statistics *overall_stat, const request_data test_data[], const int press_number )
{
	unsigned int min_connect_time = UINT_MAX;
	unsigned int max_connect_time = 0;
	double avg_connect_time = 0.0;

	unsigned int min_response_time = UINT_MAX;
	unsigned int max_response_time = 0;
	double avg_response_time = 0.0;

	unsigned int min_request_time = UINT_MAX;
	unsigned int max_request_time = 0;
	double avg_request_time = 0;

	int connect_count = 0; //实时统计请求连接的成功数
	int response_count = 0; //实时统计成功收到回复的连接数
	for( int i = 0; i < press_number; i++ )
	{
		if( test_data[i].is_connected == 1 )
		{ //如果该请求连接成功
			connect_count++;
			if( test_data[i].connect_time > max_connect_time )
			{
				max_connect_time = test_data[i].connect_time;
			}
			if ( test_data[i].connect_time < min_connect_time )
			{
				min_connect_time = test_data[i].connect_time;
			}
			avg_connect_time = 1.0 * ( connect_count - 1 ) / connect_count * avg_connect_time + 1.0 / connect_count * test_data[i].connect_time;
		}

		if( test_data[i].is_replied == 1 && test_data[i].is_connected == 1 )
		{ //如果该请求连接成功，发送出去后也成功收到回复
			response_count++;
			overall_stat->total_byte += test_data[i].byte_transfered;

			int response_time_elapsed = test_data[i].recv_finish_time - test_data[i].start_send_time;
			if( response_time_elapsed > max_response_time )
			{
				max_response_time = response_time_elapsed;
			}
			if( response_time_elapsed < min_response_time )
			{
				min_response_time = response_time_elapsed;
			}
			avg_response_time = 1.0 * ( response_count - 1 ) / response_count * avg_response_time + 1.0 / response_count * response_time_elapsed;

			if( test_data[i].recv_finish_time > max_request_time )
			{
				max_request_time = test_data[i].recv_finish_time;
			}
			if( test_data[i].recv_finish_time < min_request_time )
			{
				min_request_time = test_data[i].recv_finish_time;
			}
			avg_request_time = 1.0 * ( response_count - 1 ) / response_count * avg_request_time + 1.0 / response_count * test_data[i].recv_finish_time;
		}

		if( test_data[i].is_replied != 1 && test_data[i].is_connected == 1 )
		{
			overall_stat->response_fail_count++;
		}
	}

	overall_stat->avg_connect_time = (unsigned int)avg_connect_time;
	overall_stat->min_connect_time = min_connect_time;
	overall_stat->max_connect_time = max_connect_time;

	overall_stat->avg_response_time = (unsigned int)avg_response_time;
	overall_stat->min_response_time = min_response_time;
	overall_stat->max_response_time = max_response_time;

	overall_stat->avg_request_time = (unsigned int)avg_request_time;
	overall_stat->min_request_time = min_request_time;
	overall_stat->max_request_time = max_request_time;

	overall_stat->connect_fail_count = press_number - connect_count;

	overall_stat->total_fail_count = overall_stat->response_fail_count + overall_stat->connect_fail_count;
	overall_stat->total_request = press_number;
	overall_stat->fail_percent = 1.0 * overall_stat->total_fail_count / overall_stat->total_request;
}

void print_statistics( final_statistics *overall_stat )
{
	fprintf( stdout, "    TCP Connect Fail Count:   %-9d%-8s\n", overall_stat->connect_fail_count, "[#]" );
	fprintf( stdout, "    HTTP Response Fail Count: %-9d%-8s\n", overall_stat->response_fail_count, "[#]" );
	fprintf( stdout, "    Overall Fail Count:       %-9d%-8s\n", overall_stat->total_fail_count, "[#]" );
	fprintf( stdout, "    Total Request Number:     %-9d%-8s\n", overall_stat->total_request, "[#]" );
	fprintf( stdout, "    Fail Percent:             %.3f%%\n", 100*(overall_stat->fail_percent) );
	fprintf( stdout, "    Total Bytes Transferred:  %-9lu%-8s\n", overall_stat->total_byte, "[Bytes]" );
	fprintf( stdout, "\n" );
	fprintf( stdout, "Request Time [unit: us]\n" );
	fprintf( stdout, "                             min         max         avg\n" );
	fprintf( stdout, "    TCP Connect Time:  %9u%12u%12u\n", overall_stat->min_connect_time,
		overall_stat->max_connect_time, overall_stat->avg_connect_time );

	fprintf( stdout, "    HTTP Response Time:%9u%12u%12u\n", overall_stat->min_response_time,
		overall_stat->max_response_time, overall_stat->avg_response_time );

	fprintf( stdout, "    Total Request Time:%9u%12u%12u\n", overall_stat->min_request_time,
		overall_stat->max_request_time, overall_stat->avg_request_time );
	fprintf( stdout, "\n" );

	return ;
}
<commit_msg>Update output.cpp<commit_after>#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

#include "common_struct.h"
#include "common_constant.h"
#include "version.h"

extern int press_rate;
extern double press_interval;
extern int press_time;

//如何使用本工具
void usage( const char* tool_name )
{
	fprintf( stderr, "Usage: %s\n", tool_name );
	fprintf( stderr, "       -r [--rate] M                                  press rate (unit: query per second).\n" );
	fprintf( stderr, "       -t [--time] N                                  test time (unit: second). \n" );
	fprintf( stderr, "       -u [--url ] http://XX.XXX.XXX.XX:80/index.html request url, default port number 80.\n" );
	exit( 1 );
}

//打印读取的参数信息
void print_info( parameters_set *parameters )
{
	fprintf( stdout, "\n" );
	fprintf( stdout, "This is %s (last updated on %s), an HTTP benchmarking tool.\n", VERSION, LAST_UPDATE );
	fprintf( stdout, "Copyright © 2014 %s. Email: %s\n\n", AUTHOR, CONTACT );
	fprintf( stdout, "Test Information\n" );
	if( parameters->url_number == 1 )
	{
		fprintf( stdout, "    Host       : %s\n", parameters->host[0]->host_ip );
		fprintf( stdout, "    Port       : %d\n", parameters->host[0]->port );
		fprintf( stdout, "    URI        : %s\n", parameters->host[0]->uri );
	}
	fprintf( stdout, "    Target RPS : %-6d%-11s\n", press_rate, "[#/second]" );
	fprintf( stdout, "    Test Time  : %-6d%-11s\n", press_time, "[second]" );
	fprintf( stdout, "\n" );
	return;
}

void check_setting( void )
{
	if( press_rate <= 0 || press_rate > MAX_RATE )
	{
		fprintf( stderr, "The press rate is illegal. The request rate should be between 1 and %d RPS.\n", MAX_RATE );
		exit( 1 );
	}

	if( press_time <= 0 || press_time > MAX_TIME )
	{
		fprintf( stderr, "The press time is too long! The test time should be between 1 and %d seconds.\n", MAX_TIME );
		exit( 1 );
	}

	return ;
}

void check_connect_ontime( const int press_number, const test_connect_ontime *tco )
{
	if( press_number < 100 )
	{
		return ;
	}
	int temptime_us = (tco->test_end).tv_usec - (tco->test_start).tv_usec;
	int temptime_s = (tco->test_end).tv_sec - (tco->test_start).tv_sec;
	if ( temptime_us < 0 )
	{
		temptime_s--;
		temptime_us += 1000000;
	}
	int actual_rps = (int)( press_number / (temptime_s + temptime_us / 1000000.0) );
	double err = actual_rps*1.0 / press_rate -1;
	if( err > 0.05 || err < -0.05)
	{
		fprintf( stderr, "ATTENTION: The actual RPS did NOT reach your Target RPS %d [#/second].\n", press_rate );
		fprintf( stderr, "           Actually, %d requests were sent out within %d.%d seconds.\n", press_number, temptime_s, (temptime_us/1000) );
		fprintf( stderr, "           Therefore, the actual RPS is about %d [#/second].\n", actual_rps);
		fprintf( stderr, "\n");
	}else
	{
		fprintf( stdout, "The actual RPS is %d, which is exactly equal to your settings.\n", press_rate );
		fprintf( stdout, "Please refer to the test results as follows: \n" );
		fprintf( stdout, "\n");
	}

	return;
}

void statistics_calculation( final_statistics *overall_stat, const request_data test_data[], const int press_number )
{
	unsigned int min_connect_time = UINT_MAX;
	unsigned int max_connect_time = 0;
	double avg_connect_time = 0.0;

	unsigned int min_response_time = UINT_MAX;
	unsigned int max_response_time = 0;
	double avg_response_time = 0.0;

	unsigned int min_request_time = UINT_MAX;
	unsigned int max_request_time = 0;
	double avg_request_time = 0;

	int connect_count = 0; //实时统计请求连接的成功数
	int response_count = 0; //实时统计成功收到回复的连接数
	for( int i = 0; i < press_number; i++ )
	{
		if( test_data[i].is_connected == 1 )
		{ //如果该请求连接成功
			connect_count++;
			if( test_data[i].connect_time > max_connect_time )
			{
				max_connect_time = test_data[i].connect_time;
			}
			if ( test_data[i].connect_time < min_connect_time )
			{
				min_connect_time = test_data[i].connect_time;
			}
			avg_connect_time = 1.0 * ( connect_count - 1 ) / connect_count * avg_connect_time + 1.0 / connect_count * test_data[i].connect_time;
		}

		if( test_data[i].is_replied == 1 && test_data[i].is_connected == 1 )
		{ //如果该请求连接成功，发送出去后也成功收到回复
			response_count++;
			overall_stat->total_byte += test_data[i].byte_transfered;

			int response_time_elapsed = test_data[i].recv_finish_time - test_data[i].start_send_time;
			if( response_time_elapsed > max_response_time )
			{
				max_response_time = response_time_elapsed;
			}
			if( response_time_elapsed < min_response_time )
			{
				min_response_time = response_time_elapsed;
			}
			avg_response_time = 1.0 * ( response_count - 1 ) / response_count * avg_response_time + 1.0 / response_count * response_time_elapsed;

			if( test_data[i].recv_finish_time > max_request_time )
			{
				max_request_time = test_data[i].recv_finish_time;
			}
			if( test_data[i].recv_finish_time < min_request_time )
			{
				min_request_time = test_data[i].recv_finish_time;
			}
			avg_request_time = 1.0 * ( response_count - 1 ) / response_count * avg_request_time + 1.0 / response_count * test_data[i].recv_finish_time;
		}

		if( test_data[i].is_replied != 1 && test_data[i].is_connected == 1 )
		{
			overall_stat->response_fail_count++;
		}
	}

	overall_stat->avg_connect_time = (unsigned int)avg_connect_time;
	overall_stat->min_connect_time = min_connect_time;
	overall_stat->max_connect_time = max_connect_time;

	overall_stat->avg_response_time = (unsigned int)avg_response_time;
	overall_stat->min_response_time = min_response_time;
	overall_stat->max_response_time = max_response_time;

	overall_stat->avg_request_time = (unsigned int)avg_request_time;
	overall_stat->min_request_time = min_request_time;
	overall_stat->max_request_time = max_request_time;

	overall_stat->connect_fail_count = press_number - connect_count;

	overall_stat->total_fail_count = overall_stat->response_fail_count + overall_stat->connect_fail_count;
	overall_stat->total_request = press_number;
	overall_stat->fail_percent = 1.0 * overall_stat->total_fail_count / overall_stat->total_request;
}

void print_statistics( final_statistics *overall_stat )
{
	fprintf( stdout, "    TCP Connect Fail Count:   %-9d%-8s\n", overall_stat->connect_fail_count, "[#]" );
	fprintf( stdout, "    HTTP Response Fail Count: %-9d%-8s\n", overall_stat->response_fail_count, "[#]" );
	fprintf( stdout, "    Overall Fail Count:       %-9d%-8s\n", overall_stat->total_fail_count, "[#]" );
	fprintf( stdout, "    Total Request Number:     %-9d%-8s\n", overall_stat->total_request, "[#]" );
	fprintf( stdout, "    Fail Percent:             %.3lf%%\n", 100*(overall_stat->fail_percent) );
	fprintf( stdout, "    Total Bytes Transferred:  %-9lu%-8s\n", overall_stat->total_byte, "[Bytes]" );
	fprintf( stdout, "\n" );
	fprintf( stdout, "Request Time [unit: us]\n" );
	fprintf( stdout, "                             min         max         avg\n" );
	fprintf( stdout, "    TCP Connect Time:  %9u%12u%12u\n", overall_stat->min_connect_time,
		overall_stat->max_connect_time, overall_stat->avg_connect_time );

	fprintf( stdout, "    HTTP Response Time:%9u%12u%12u\n", overall_stat->min_response_time,
		overall_stat->max_response_time, overall_stat->avg_response_time );

	fprintf( stdout, "    Total Request Time:%9u%12u%12u\n", overall_stat->min_request_time,
		overall_stat->max_request_time, overall_stat->avg_request_time );
	fprintf( stdout, "\n" );

	return ;
}
<|endoftext|>


<commit_before>/*
 FILNAMN: 		NetClient.cc
 PROGRAMMERARE:	hanel742, eriek984, jened502, tobgr602, niker917, davha227
 SKAPAD DATUM:	2013-11-19
 BESKRIVNING:
 */

#include "NetClient.h"
#include "../gui/gui.h"

using namespace std;

NetClient::NetClient(QString username, QString inAddress, Gui* myGui, QObject *parent) : QObject(parent){

    guiPointer = myGui;
    name=username;
    address=inAddress;
    compare += 0x1F;
    breaker +=0x1E;
}

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

void NetClient::start(){
    TcpSocket = new QTcpSocket(this);

    connect(TcpSocket,SIGNAL(connected()),this,SLOT(connected()));
    connect(TcpSocket,SIGNAL(disconnected()),this,SLOT(disconnected()));
    connect(TcpSocket,SIGNAL(readyRead()),this,SLOT(readyRead()));

    QHostInfo info = QHostInfo::fromName(address);

    if (info.addresses().size() == 0){
        guiPointer->noConnection();
    }
    else{
        TcpSocket->connectToHost(info.addresses().at(0),quint16(40001));
        if(!TcpSocket->waitForConnected(1000)){
            guiPointer->noConnection();
        }
    }
}

//------Slots---------

void NetClient::connected(){
    QByteArray array = "/initiate";
    array += 0x1F; //unit separator
    array += name;
    array += breaker;

    TcpSocket->write(array);
    TcpSocket->waitForBytesWritten(1000);
}

void NetClient::disconnected(){
    guiPointer->disconnectedFromServer();

}

// --------readyRead------------------

void NetClient::readyRead(){

    QString inData = "";

    if( not(incompleteCommand.isEmpty())){
        inData = incompleteCommand;
        cout << "old command exists" << endl;
        incompleteCommand = "";
    }
    QByteArray Data = TcpSocket->readAll();

    QString commandName = "";
    inData += Data;
    QString rest = "";
    int n = inData.indexOf(breaker);
    int i;
    int p = 0;

    if(inData.indexOf(breaker) == -1 ){
        cout << "breaker missing " << endl;
        incompleteCommand = inData;
        return;
    }

    do {

        rest = inData.mid(n+1);
        inData = inData.left(n);
        i = inData.indexOf(compare);
        cout << p << endl;
        commandName = inData.left(i);

        p = p + 1;
        inData = inData.mid(i+1);

        QString temp = inData;
        string stdInData = temp.toStdString();

        // Check which command that's supposed to run
        if (commandName == "/reinitiate") {
            guiPointer->userNameTaken();
            break;
        }

        else if ( commandName == "/userAccepted") {
            guiPointer->connected();
        }

        else if (commandName == "/history") {
            handleHistory(inData);
        }

        else if (commandName == "/oldHistory") {
            handleOldHistory(inData);
        }

        else if (commandName == "/message") {
            handleMessage(inData);
        }

        else if ( commandName == "/requestStruct") {
            handleRequestStruct();
        }

        else if ( commandName == "/structure" ) {
            handleStructure(inData);
        }

        else {

            //throw logic_error("Unknown command: " + commandName.toStdString());
            //release version
            cout << "Unknown command: " << endl;
            inData = "";
            commandName = "";
            incompleteCommand = "";
            return;
        }

        inData = rest;
        n = inData.indexOf(breaker);
        commandName = "";

    }while (n != -1 );
}

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

void NetClient::sendMessage(QString from, QString to, QString message){
    QByteArray array = "/message";
    array += 0x1F; //unit separator
    array += from;
    array += 0x1F;
    array += to;
    array += 0x1F;
    array += message;
    array += breaker;

    TcpSocket->write(array);
    TcpSocket->waitForBytesWritten(1000);
}

void NetClient::setName(QString inName) {
    name=inName;
}

void NetClient::getStruct(){
    QByteArray array = "/structure";
    array += 0x1E;

    TcpSocket->write(array);
    TcpSocket->waitForBytesWritten(1000);
}

//--------------------------------------------
//Helpfunctions

void NetClient::handleRequestStruct(){
    QByteArray array = "/structure";
    array += compare;
    array += breaker;

    TcpSocket->write(array);
    TcpSocket->waitForBytesWritten(1000);
}

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

void NetClient::handleMessage(QString inData){

    int i;
    // Get from
    i = inData.indexOf(compare);
    QString from = inData.left(i);
    inData = inData.mid(i+1);

    // Get to
    i = inData.indexOf(compare);
    QString to = inData.left(i);
    inData = inData.mid(i+1);

    // Get message
    i = inData.indexOf(compare);
    QString contents = inData.left(i);
    inData = inData.mid(i+1);

    // Get time
    QString dateTime = inData;

    //Send message to Gui
    guiPointer->receiveMessage(from, to, contents, dateTime);

}

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

void NetClient::handleHistory(QString inData){
    QVector<QString> history;
    int i = inData.indexOf(compare);
    while(i != -1 ){

        // Get from
        i = inData.indexOf(compare);
        QString from = inData.left(i);
        inData = inData.mid(i+1);
        history.push_back(from);

        // Get to
        i = inData.indexOf(compare);
        QString to = inData.left(i);
        inData = inData.mid(i+1);
        history.push_back(to);

        // Get message
        i = inData.indexOf(compare);
        QString contents = inData.left(i);
        inData = inData.mid(i+1);
        history.push_back(contents);

        //Get time
        i = inData.indexOf(compare);
        QString time = inData.left(i);
        inData = inData.mid(i+1);
        history.push_back(time);
    }
    guiPointer->receiveHistory(history);
}

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

void NetClient::handleOldHistory(QString inData){
    QVector<QString> history;
    int i = inData.indexOf(compare);
    while(i != -1 ){

        // Get from
        i = inData.indexOf(compare);
        QString from = inData.left(i);
        inData = inData.mid(i+1);
        history.push_back(from);

        // Get to
        i = inData.indexOf(compare);
        QString to = inData.left(i);
        inData = inData.mid(i+1);
        history.push_back(to);

        // Get message
        i = inData.indexOf(compare);
        QString contents = inData.left(i);
        inData = inData.mid(i+1);
        history.push_back(contents);

        //Get time
        i = inData.indexOf(compare);
        QString time = inData.left(i);
        inData = inData.mid(i+1);
        history.push_back(time);
    }
    guiPointer->receiveOldHistory(history);
}

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

void NetClient::handleStructure(QString inData){
    QVector<QString> output;
    int i = inData.indexOf(compare);

    while(i  != -1){
        //Create vector output, containing room content structure
        QString data = inData.left(i);
        inData = inData.mid(i+1);
        output.push_back(data);

        i = inData.indexOf(compare);
    }

    output.push_back(inData);

    guiPointer->updateStruct(output);

}

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

void NetClient::getHistory(unsigned int daysBack) {
    QString temp;
    string daysBackString = to_string(daysBack);

    temp = QString::fromStdString(daysBackString);

    QByteArray array = "/oldHistory";
    array += compare; //unit separator
    array += temp;
    array += breaker;

    TcpSocket->write(array);
    TcpSocket->waitForBytesWritten(1000);
}

<commit_msg>Removed couts<commit_after>/*
 FILNAMN: 		NetClient.cc
 PROGRAMMERARE:	hanel742, eriek984, jened502, tobgr602, niker917, davha227
 SKAPAD DATUM:	2013-11-19
 BESKRIVNING:
 */

#include "NetClient.h"
#include "../gui/gui.h"

using namespace std;

NetClient::NetClient(QString username, QString inAddress, Gui* myGui, QObject *parent) : QObject(parent){

    guiPointer = myGui;
    name=username;
    address=inAddress;
    compare += 0x1F;
    breaker +=0x1E;
}

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

void NetClient::start(){
    TcpSocket = new QTcpSocket(this);

    connect(TcpSocket,SIGNAL(connected()),this,SLOT(connected()));
    connect(TcpSocket,SIGNAL(disconnected()),this,SLOT(disconnected()));
    connect(TcpSocket,SIGNAL(readyRead()),this,SLOT(readyRead()));

    QHostInfo info = QHostInfo::fromName(address);

    if (info.addresses().size() == 0){
        guiPointer->noConnection();
    }
    else{
        TcpSocket->connectToHost(info.addresses().at(0),quint16(40001));
        if(!TcpSocket->waitForConnected(1000)){
            guiPointer->noConnection();
        }
    }
}

//------Slots---------

void NetClient::connected(){
    QByteArray array = "/initiate";
    array += 0x1F; //unit separator
    array += name;
    array += breaker;

    TcpSocket->write(array);
    TcpSocket->waitForBytesWritten(1000);
}

void NetClient::disconnected(){
    guiPointer->disconnectedFromServer();

}

// --------readyRead------------------

void NetClient::readyRead(){

    QString inData = "";

    if( not(incompleteCommand.isEmpty())){
        inData = incompleteCommand;
        incompleteCommand = "";
    }
    QByteArray Data = TcpSocket->readAll();

    QString commandName = "";
    inData += Data;
    QString rest = "";
    int n = inData.indexOf(breaker);
    int i;

    if(inData.indexOf(breaker) == -1 ){
        incompleteCommand = inData;
        return;
    }

    do {

        rest = inData.mid(n+1);
        inData = inData.left(n);
        i = inData.indexOf(compare);
        commandName = inData.left(i);

        p = p + 1;
        inData = inData.mid(i+1);

        QString temp = inData;
        string stdInData = temp.toStdString();

        // Check which command that's supposed to run
        if (commandName == "/reinitiate") {
            guiPointer->userNameTaken();
            break;
        }

        else if ( commandName == "/userAccepted") {
            guiPointer->connected();
        }

        else if (commandName == "/history") {
            handleHistory(inData);
        }

        else if (commandName == "/oldHistory") {
            handleOldHistory(inData);
        }

        else if (commandName == "/message") {
            handleMessage(inData);
        }

        else if ( commandName == "/requestStruct") {
            handleRequestStruct();
        }

        else if ( commandName == "/structure" ) {
            handleStructure(inData);
        }

        else {

            //throw logic_error("Unknown command: " + commandName.toStdString());
            //release version
            cout << "Unknown command: " << endl;
            inData = "";
            commandName = "";
            incompleteCommand = "";
            return;
        }

        inData = rest;
        n = inData.indexOf(breaker);
        commandName = "";

    }while (n != -1 );
}

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

void NetClient::sendMessage(QString from, QString to, QString message){
    QByteArray array = "/message";
    array += 0x1F; //unit separator
    array += from;
    array += 0x1F;
    array += to;
    array += 0x1F;
    array += message;
    array += breaker;

    TcpSocket->write(array);
    TcpSocket->waitForBytesWritten(1000);
}

void NetClient::setName(QString inName) {
    name=inName;
}

void NetClient::getStruct(){
    QByteArray array = "/structure";
    array += 0x1E;

    TcpSocket->write(array);
    TcpSocket->waitForBytesWritten(1000);
}

//--------------------------------------------
//Helpfunctions

void NetClient::handleRequestStruct(){
    QByteArray array = "/structure";
    array += compare;
    array += breaker;

    TcpSocket->write(array);
    TcpSocket->waitForBytesWritten(1000);
}

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

void NetClient::handleMessage(QString inData){

    int i;
    // Get from
    i = inData.indexOf(compare);
    QString from = inData.left(i);
    inData = inData.mid(i+1);

    // Get to
    i = inData.indexOf(compare);
    QString to = inData.left(i);
    inData = inData.mid(i+1);

    // Get message
    i = inData.indexOf(compare);
    QString contents = inData.left(i);
    inData = inData.mid(i+1);

    // Get time
    QString dateTime = inData;

    //Send message to Gui
    guiPointer->receiveMessage(from, to, contents, dateTime);

}

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

void NetClient::handleHistory(QString inData){
    QVector<QString> history;
    int i = inData.indexOf(compare);
    while(i != -1 ){

        // Get from
        i = inData.indexOf(compare);
        QString from = inData.left(i);
        inData = inData.mid(i+1);
        history.push_back(from);

        // Get to
        i = inData.indexOf(compare);
        QString to = inData.left(i);
        inData = inData.mid(i+1);
        history.push_back(to);

        // Get message
        i = inData.indexOf(compare);
        QString contents = inData.left(i);
        inData = inData.mid(i+1);
        history.push_back(contents);

        //Get time
        i = inData.indexOf(compare);
        QString time = inData.left(i);
        inData = inData.mid(i+1);
        history.push_back(time);
    }
    guiPointer->receiveHistory(history);
}

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

void NetClient::handleOldHistory(QString inData){
    QVector<QString> history;
    int i = inData.indexOf(compare);
    while(i != -1 ){

        // Get from
        i = inData.indexOf(compare);
        QString from = inData.left(i);
        inData = inData.mid(i+1);
        history.push_back(from);

        // Get to
        i = inData.indexOf(compare);
        QString to = inData.left(i);
        inData = inData.mid(i+1);
        history.push_back(to);

        // Get message
        i = inData.indexOf(compare);
        QString contents = inData.left(i);
        inData = inData.mid(i+1);
        history.push_back(contents);

        //Get time
        i = inData.indexOf(compare);
        QString time = inData.left(i);
        inData = inData.mid(i+1);
        history.push_back(time);
    }
    guiPointer->receiveOldHistory(history);
}

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

void NetClient::handleStructure(QString inData){
    QVector<QString> output;
    int i = inData.indexOf(compare);

    while(i  != -1){
        //Create vector output, containing room content structure
        QString data = inData.left(i);
        inData = inData.mid(i+1);
        output.push_back(data);

        i = inData.indexOf(compare);
    }

    output.push_back(inData);

    guiPointer->updateStruct(output);

}

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

void NetClient::getHistory(unsigned int daysBack) {
    QString temp;
    string daysBackString = to_string(daysBack);

    temp = QString::fromStdString(daysBackString);

    QByteArray array = "/oldHistory";
    array += compare; //unit separator
    array += temp;
    array += breaker;

    TcpSocket->write(array);
    TcpSocket->waitForBytesWritten(1000);
}

<|endoftext|>


<commit_before>#include "nin10kit.hpp"

#include <wx/filedlg.h>
#include <wx/msgdlg.h>

#include "nin10kitviewer.hpp"

#include "exporter.hpp"
#include "imageutil.hpp"
#include "logger.hpp"

static inline long GetSelectedIndex(wxListCtrl* listControl)
{
    long itemIndex = -1;
    for (;;)
    {
        itemIndex = listControl->GetNextItem(itemIndex, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
        if (itemIndex == -1) break;
        return itemIndex;
    }
    return itemIndex;
}

Nin10KitFrame::Nin10KitFrame() : Nin10KitGUI(NULL), imageList(new wxImageList(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT))
{
    imagesList->SetImageList(imageList.get(), wxIMAGE_LIST_NORMAL);
}

Nin10KitFrame::~Nin10KitFrame()
{

}

void Nin10KitFrame::OnLoadImages(wxCommandEvent& event)
{
    EventLog l(__func__);
    std::unique_ptr<wxFileDialog> filedlg(new wxFileDialog(this, _("Open Images"), "", "", wxFileSelectorDefaultWildcardStr,
                                                           wxFD_FILE_MUST_EXIST | wxFD_CHANGE_DIR | wxFD_MULTIPLE | wxFD_PREVIEW | wxFD_OPEN));
    if (filedlg->ShowModal() == wxID_CANCEL)
    {
        WarnLog("No images given");
        return;
    }

    wxArrayString files;
    filedlg->GetPaths(files);

    for (const auto& wxFile : files)
    {
        std::string file = wxFile.ToStdString();
        InfoLog("Got file: %s", file.c_str());
        if (images.find(file) != images.end())
        {
            WarnLog("File %s already loaded ignoring", file.c_str());
            continue;
        }
        filenames.push_back(file);
        images.emplace(file, file);
        const ImageInfo& info = images.at(file);
        imageList->Add(info.GetThumbnail());
        long index = imagesList->GetItemCount();
        imagesList->InsertItem(index, info.GetName(), index);
    }
}

void Nin10KitFrame::OnImageSelected(wxListEvent& event)
{
    EventLog l(__func__);
    //Ignoring event.GetSelection as it is always 0.
    long index = GetSelectedIndex(imagesList);
    if (index == -1)
    {
        WarnLog("No item selected ignoring");
        return;
    }

    const std::string& filename = filenames[index];
    const ImageInfo& info = images.at(filename);
    InfoLog("Selected %d %s %s", index, filename.c_str(), info.GetName().c_str());

    imageFilename->SetValue(filename);
    imageName->SetValue(info.GetName());
    imageWidth->SetValue(info.GetWidth());
    imageHeight->SetValue(info.GetHeight());
    imageAnimated->SetValue(info.IsAnimated());
}

void Nin10KitFrame::OnDeleteAllImages(wxCommandEvent& event)
{
    EventLog l(__func__);
    InfoLog("Delete all items");
    imagesList->DeleteAllItems();
    imageList->RemoveAll();
    filenames.clear();
    images.clear();
}

void Nin10KitFrame::OnUpdateCurrentImage(wxCommandEvent& event)
{
    EventLog l(__func__);
    long item = GetSelectedIndex(imagesList);
    if (item == -1)
    {
        WarnLog("No item selected ignoring");
        return;
    }

    const std::string& filename = filenames[item];
    ImageInfo& info = images.at(filename);
    InfoLog("Updating %ld %s %s", item, filename.c_str(), info.GetName().c_str());

    info.SetName(imageName->GetValue().ToStdString());
    info.SetWidth(imageWidth->GetValue());
    info.SetHeight(imageHeight->GetValue());
    InfoLog("Updated %ld %s %s", item, filename.c_str(), info.GetName().c_str());
    imagesList->SetItemText(item, info.GetName());
    imagesList->Refresh();
}

void Nin10KitFrame::OnDeleteCurrentImage(wxCommandEvent& event)
{
    EventLog l(__func__);
    long item = GetSelectedIndex(imagesList);
    if (item == -1)
    {
        WarnLog("No item selected ignoring");
        return;
    }

    imagesList->DeleteItem(item);
    imageList->Remove(item);
    InfoLog("Updating %ld %s %s", item, filenames[item].c_str(), images.at(filenames[item]).GetName().c_str());
    images.erase(filenames[item]);
    filenames.erase(filenames.begin() + item);
}

void Nin10KitFrame::OnExport(wxCommandEvent& event)
{
    EventLog l(__func__);
    if (filenames.empty())
    {
        WarnLog("No images loaded not exporting");
        return;
    }
    std::string filename = wxSaveFileSelector(_("Export Images"), "", "", this).ToStdString();
    if (filename.empty())
    {
        WarnLog("Filename empty not saving");
        return;
    }

    InfoLog("Saving exported file to %s", filename.c_str());
    DoExport(mode->GetSelection(), filename, filenames, images);
}

void Nin10KitFrame::OnView(wxCommandEvent& event)
{
    EventLog l(__func__);
    if (images.empty())
    {
        WarnLog("No images given.");
        return;
    }

    if (!viewer)
        viewer = new Nin10KitViewerFrame();

    viewer->Connect(wxEVT_CLOSE_WINDOW, wxCloseEventHandler(Nin10KitFrame::OnCloseView), NULL, this);
    if (!viewer->Set(mode->GetSelection(), images))
    {
        viewer->Close(true);
        delete viewer;
        viewer = NULL;
        return;
    }
    viewer->Show(true);
}

void Nin10KitFrame::OnCloseView(wxCloseEvent& event)
{
    EventLog l(__func__);
    if (viewer)
        viewer = NULL;
    event.Skip();
}

void Nin10KitFrame::OnEditor(wxCommandEvent& event)
{
    EventLog l(__func__);
    wxMessageBox(_("Unfortunately this part of the program isn't implemented yet\n"
                   "This is a planned feature to have a bitmap/palette/tilemap editor\n"), _("Coming soon"));
}
<commit_msg>Fix for issue #8, Added a prompt if the files already existed<commit_after>#include "nin10kit.hpp"

#include <wx/filedlg.h>
#include <wx/msgdlg.h>

#include "nin10kitviewer.hpp"

#include "exporter.hpp"
#include "imageutil.hpp"
#include "logger.hpp"

static inline long GetSelectedIndex(wxListCtrl* listControl)
{
    long itemIndex = -1;
    for (;;)
    {
        itemIndex = listControl->GetNextItem(itemIndex, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
        if (itemIndex == -1) break;
        return itemIndex;
    }
    return itemIndex;
}

Nin10KitFrame::Nin10KitFrame() : Nin10KitGUI(NULL), imageList(new wxImageList(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT))
{
    imagesList->SetImageList(imageList.get(), wxIMAGE_LIST_NORMAL);
}

Nin10KitFrame::~Nin10KitFrame()
{

}

void Nin10KitFrame::OnLoadImages(wxCommandEvent& event)
{
    EventLog l(__func__);
    std::unique_ptr<wxFileDialog> filedlg(new wxFileDialog(this, _("Open Images"), "", "", wxFileSelectorDefaultWildcardStr,
                                                           wxFD_FILE_MUST_EXIST | wxFD_CHANGE_DIR | wxFD_MULTIPLE | wxFD_PREVIEW | wxFD_OPEN));
    if (filedlg->ShowModal() == wxID_CANCEL)
    {
        WarnLog("No images given");
        return;
    }

    wxArrayString files;
    filedlg->GetPaths(files);

    for (const auto& wxFile : files)
    {
        std::string file = wxFile.ToStdString();
        InfoLog("Got file: %s", file.c_str());
        if (images.find(file) != images.end())
        {
            WarnLog("File %s already loaded ignoring", file.c_str());
            continue;
        }
        filenames.push_back(file);
        images.emplace(file, file);
        const ImageInfo& info = images.at(file);
        imageList->Add(info.GetThumbnail());
        long index = imagesList->GetItemCount();
        imagesList->InsertItem(index, info.GetName(), index);
    }
}

void Nin10KitFrame::OnImageSelected(wxListEvent& event)
{
    EventLog l(__func__);
    //Ignoring event.GetSelection as it is always 0.
    long index = GetSelectedIndex(imagesList);
    if (index == -1)
    {
        WarnLog("No item selected ignoring");
        return;
    }

    const std::string& filename = filenames[index];
    const ImageInfo& info = images.at(filename);
    InfoLog("Selected %d %s %s", index, filename.c_str(), info.GetName().c_str());

    imageFilename->SetValue(filename);
    imageName->SetValue(info.GetName());
    imageWidth->SetValue(info.GetWidth());
    imageHeight->SetValue(info.GetHeight());
    imageAnimated->SetValue(info.IsAnimated());
}

void Nin10KitFrame::OnDeleteAllImages(wxCommandEvent& event)
{
    EventLog l(__func__);
    InfoLog("Delete all items");
    imagesList->DeleteAllItems();
    imageList->RemoveAll();
    filenames.clear();
    images.clear();
}

void Nin10KitFrame::OnUpdateCurrentImage(wxCommandEvent& event)
{
    EventLog l(__func__);
    long item = GetSelectedIndex(imagesList);
    if (item == -1)
    {
        WarnLog("No item selected ignoring");
        return;
    }

    const std::string& filename = filenames[item];
    ImageInfo& info = images.at(filename);
    InfoLog("Updating %ld %s %s", item, filename.c_str(), info.GetName().c_str());

    info.SetName(imageName->GetValue().ToStdString());
    info.SetWidth(imageWidth->GetValue());
    info.SetHeight(imageHeight->GetValue());
    InfoLog("Updated %ld %s %s", item, filename.c_str(), info.GetName().c_str());
    imagesList->SetItemText(item, info.GetName());
    imagesList->Refresh();
}

void Nin10KitFrame::OnDeleteCurrentImage(wxCommandEvent& event)
{
    EventLog l(__func__);
    long item = GetSelectedIndex(imagesList);
    if (item == -1)
    {
        WarnLog("No item selected ignoring");
        return;
    }

    imagesList->DeleteItem(item);
    imageList->Remove(item);
    InfoLog("Updating %ld %s %s", item, filenames[item].c_str(), images.at(filenames[item]).GetName().c_str());
    images.erase(filenames[item]);
    filenames.erase(filenames.begin() + item);
}

void Nin10KitFrame::OnExport(wxCommandEvent& event)
{
    EventLog l(__func__);
    if (filenames.empty())
    {
        WarnLog("No images loaded not exporting");
        return;
    }

    std::string filename;
    bool save_ok;
    do
    {
        save_ok = true;
        filename = wxSaveFileSelector(_("Export Images"), "", "", this).ToStdString();
        if (filename.empty())
        {
            WarnLog("Filename empty not saving.");
            return;
        }
        if (wxFile::Exists(filename + ".c") || wxFileExists(filename + ".h"))
        {
            int ans = wxMessageBox(wxString::Format(_("Ok to overwrite %s(.c|.h)?"), filename), _("Confirm"), wxYES_NO | wxCANCEL, this);
            if (ans == wxNO) save_ok = false;
            if (ans == wxCANCEL) return;
        }
    } while (!save_ok);

    InfoLog("Saving exported file to %s", filename.c_str());
    DoExport(mode->GetSelection(), filename, filenames, images);
}

void Nin10KitFrame::OnView(wxCommandEvent& event)
{
    EventLog l(__func__);
    if (images.empty())
    {
        WarnLog("No images given.");
        return;
    }

    if (!viewer)
        viewer = new Nin10KitViewerFrame();

    viewer->Connect(wxEVT_CLOSE_WINDOW, wxCloseEventHandler(Nin10KitFrame::OnCloseView), NULL, this);
    if (!viewer->Set(mode->GetSelection(), images))
    {
        viewer->Close(true);
        delete viewer;
        viewer = NULL;
        return;
    }
    viewer->Show(true);
}

void Nin10KitFrame::OnCloseView(wxCloseEvent& event)
{
    EventLog l(__func__);
    if (viewer)
        viewer = NULL;
    event.Skip();
}

void Nin10KitFrame::OnEditor(wxCommandEvent& event)
{
    EventLog l(__func__);
    wxMessageBox(_("Unfortunately this part of the program isn't implemented yet\n"
                   "This is a planned feature to have a bitmap/palette/tilemap editor\n"), _("Coming soon"));
}
<|endoftext|>


<commit_before>/******************************************************************************
*   Copyright (C) 2010 by Robert Tolliver                                     *
*   Robb.Tolli@gmail.com                                                      *
*                                                                             *
*   This file is part of Birthstone.                                          *
*                                                                             *
*   Birthstone 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.                                        *
*                                                                             *
*   Birthstone 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 Birthstone.  If not, see <http://www.gnu.org/licenses/>.       *
*                                                                             *
******************************************************************************/
#include <iostream>
#include <cstdlib>
#include "parser.h"

Parser::Parser(std::istream &input) : mLexer(input), mToken(NONE) {}

bool Parser::error(std::string msg)
{
	std::cerr << mLexer.getLine() << msg << std::endl;
	exit(1);
}

Token Parser::code()
{
	while (token.getType !=  Sym::END)
		block() || ifCond() || whileLoop() || read() || print () || stmt();
}

bool Parser::print()
{
	// TODO: bool Parser::print()
}

bool Parser::read()
{
	// TODO: bool Parser::read()
}

bool Parser::ifCond()
{
	// TODO: bool Parser::ifCond()
}

bool Parser::elifCond()
{
	// TODO: bool Parser::elifCond()
}

bool Parser::elseCond()
{
	// TODO: bool Parser::elseCond()
}

bool Parser::whileLoop()
{
	// TODO: bool Parser::whileLoop()
}

bool Parser::block()
{
	// TODO: bool Parser::block()
};
bool Parser::stmt()
{
	// TODO: bool Parser::stmt()
}

bool Parser::asgnmt()
{
	// TODO: bool Parser::asgnmt()
}

bool Parser::orOp()
{
	// TODO: bool Parser::orOp()
}

bool Parser::andOp()
{
	// TODO: bool Parser::andOp()
}

bool Parser::comp()
{
	// TODO: bool Parser::comp()
}

bool Parser::expr()
{
	// TODO: bool Parser::expr()
}

bool Parser::term()
{
	// TODO: bool Parser::term()
}

bool Parser::factor()
{
	// TODO: bool Parser::factor()
}
<commit_msg>minor fix<commit_after>/******************************************************************************
*   Copyright (C) 2010 by Robert Tolliver                                     *
*   Robb.Tolli@gmail.com                                                      *
*                                                                             *
*   This file is part of Birthstone.                                          *
*                                                                             *
*   Birthstone 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.                                        *
*                                                                             *
*   Birthstone 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 Birthstone.  If not, see <http://www.gnu.org/licenses/>.       *
*                                                                             *
******************************************************************************/
#include <iostream>
#include <cstdlib>
#include "parser.h"

Parser::Parser(std::istream &input) : mLexer(input), mToken(NONE) {}

bool Parser::error(std::string msg)
{
	std::cerr << mLexer.getLine() << msg << std::endl;
	exit(1);
}

Token Parser::code()
{
	while (token.getType() !=  Sym::END)
		block() || ifCond() || whileLoop() || read() || print() || stmt();
}

bool Parser::print()
{
	// TODO: bool Parser::print()
}

bool Parser::read()
{
	// TODO: bool Parser::read()
}

bool Parser::ifCond()
{
	// TODO: bool Parser::ifCond()
}

bool Parser::elifCond()
{
	// TODO: bool Parser::elifCond()
}

bool Parser::elseCond()
{
	// TODO: bool Parser::elseCond()
}

bool Parser::whileLoop()
{
	// TODO: bool Parser::whileLoop()
}

bool Parser::block()
{
	// TODO: bool Parser::block()
};
bool Parser::stmt()
{
	// TODO: bool Parser::stmt()
}

bool Parser::asgnmt()
{
	// TODO: bool Parser::asgnmt()
}

bool Parser::orOp()
{
	// TODO: bool Parser::orOp()
}

bool Parser::andOp()
{
	// TODO: bool Parser::andOp()
}

bool Parser::comp()
{
	// TODO: bool Parser::comp()
}

bool Parser::expr()
{
	// TODO: bool Parser::expr()
}

bool Parser::term()
{
	// TODO: bool Parser::term()
}

bool Parser::factor()
{
	// TODO: bool Parser::factor()
}
<|endoftext|>


<commit_before>#include "parser.hpp"

//////////////
// Includes //
#include <istream>
#include <string>
#include <vector>

#include "json.hpp"

//////////
// Code //

// Checking if a given string is whitespace.
bool isWhitespace(char c) {
    switch (c) {
    case ' ':
    case '\t':
    case '\r':
    case '\n':
        return true;
    default:
        break;
    }

    return false;
}

// Checking if a character is a quote.
bool isQuote(char c) {
    return c == '"' || c == '\'';
}

// Stripping the whitespace out of a string.
std::string stripWhitespace(const std::string& str) {
    std::string ret;

    for (auto it = str.begin(); it != str.end(); it++)
        if (!isWhitespace(*it))
            ret.push_back(*it);

    return ret;
}

// Trying to specifically parse out a JSON object.
JValue parseJSONObject(const std::string& str) {
    return JValue();
}

// Trying to specifically parse out a JSON array.
JValue parseJSONArray(const std::string& str) {
    return JValue();
}

// Trying to specifically parse out a JSON number.
JValue parseJSONNumber(const std::string& str) {
    try {
        return JValue(stod(str));
    } catch (const std::invalid_argument& ia) {
        return JValue();
    }
}

// Trying to specifically parse out a JSON string.
JValue parseJSONString(const std::string& str) {
    if (isQuote(*str.begin()) && isQuote(*(str.end() - 1))) {
        bool ok = false;
        std::string accum;

        for (auto it = str.begin() + 1; it != str.end() - 1; it++) {
            if (!ok && isQuote(*it))
                return JValue();
            else if ((*it) == '\\')
                ok = true;
            else
                ok = false;

            accum.push_back(*it);
        }

        return JValue(accum);
    }

    return JValue();
}

// Trying to specifically parse out a JSON boolean.
JValue parseJSONBool(const std::string& str) {
    if (str.compare("true") == 0)
        return JValue(true);
    else if (str.compare("false") == 0)
        return JValue(false);
    else
        return JValue();
}

// Parsing out a block of JSON from a string.
JValue parseJSON(const std::string& str) {
    std::vector<JValue (*)(const std::string&)> fns;
    fns.push_back(&parseJSONObject);
    fns.push_back(&parseJSONArray);
    fns.push_back(&parseJSONNumber);
    fns.push_back(&parseJSONString);
    fns.push_back(&parseJSONBool);

    JValue val;
    for (auto it = fns.begin(); it != fns.end(); it++) {
        val = (*it)(str);
        if (!val.isNull())
            return val;
    }

    return JValue();
}

// Parsing out a block of JSON from an istream.
JValue parseJSON(std::istream& stream) {
    std::string line, all;

    while (!stream.eof()) {
        std::getline(stream, line);
        all += line;
    }

    return parseJSON(all);
}
<commit_msg>Added array parsing (sorta)<commit_after>#include "parser.hpp"

//////////////
// Includes //
#include <istream>
#include <string>
#include <vector>
#include <tuple>

#include "json.hpp"

//////////
// Code //

// Checking if a given string is whitespace.
bool isWhitespace(char c) {
    switch (c) {
    case ' ':
    case '\t':
    case '\r':
    case '\n':
        return true;
    default:
        break;
    }

    return false;
}

// Returns the strings before and after a delimiter character.
std::tuple<std::string, std::string> untilChar(const std::string& str, char delim) {
    int n;
    for (n = 0; n < str.size(); n++)
        if (str[n] == delim)
            break;

    if (n + 1 >= str.size())
        return std::make_tuple(str, "");
    return std::make_tuple(str.substr(0, n), str.substr(n + 1, str.size() - 1));
}

// Checking if a character is a quote.
bool isQuote(char c) {
    return c == '"' || c == '\'';
}

// Stripping the whitespace out of a string.
std::string stripWhitespace(const std::string& str) {
    std::string ret;

    for (auto it = str.begin(); it != str.end(); it++)
        if (!isWhitespace(*it))
            ret.push_back(*it);

    return ret;
}

// Trying to specifically parse out a JSON object.
JValue parseJSONObject(const std::string& str) {
    return JValue();
}

// Trying to specifically parse out a JSON array.
JValue parseJSONArray(const std::string& str) {
    if (str[0] == '[' && str[str.size() - 1] == ']') {
        std::string useStr = str.substr(1, str.size() - 2);
        if (useStr.compare("") == 0)
            return JValue();

        std::vector<JValue> jValues;
        std::tuple<std::string, std::string> tup;
        for (tup = untilChar(useStr, ','); std::get<0>(tup).compare("") != 0; tup = untilChar(std::get<1>(tup), ','))
            jValues.push_back(parseJSON(std::get<0>(tup)));

        return JValue(jValues);
    }

    return JValue();
}

// Trying to specifically parse out a JSON number.
JValue parseJSONNumber(const std::string& str) {
    try {
        return JValue(stod(str));
    } catch (const std::invalid_argument& ia) {
        return JValue();
    }
}

// Trying to specifically parse out a JSON string.
JValue parseJSONString(const std::string& str) {
    if (isQuote(*str.begin()) && isQuote(*(str.end() - 1))) {
        bool ok = false;
        std::string accum;

        for (auto it = str.begin() + 1; it != str.end() - 1; it++) {
            if (!ok && isQuote(*it))
                return JValue();
            else if ((*it) == '\\')
                ok = true;
            else
                ok = false;

            accum.push_back(*it);
        }

        return JValue(accum);
    }

    return JValue();
}

// Trying to specifically parse out a JSON boolean.
JValue parseJSONBool(const std::string& str) {
    if (str.compare("true") == 0)
        return JValue(true);
    else if (str.compare("false") == 0)
        return JValue(false);
    else
        return JValue();
}

// Parsing out a block of JSON from a string.
JValue parseJSON(const std::string& str) {
    std::vector<JValue (*)(const std::string&)> fns;
    fns.push_back(&parseJSONObject);
    fns.push_back(&parseJSONArray);
    fns.push_back(&parseJSONNumber);
    fns.push_back(&parseJSONString);
    fns.push_back(&parseJSONBool);

    JValue val;
    for (auto it = fns.begin(); it != fns.end(); it++) {
        val = (*it)(str);
        if (!val.isNull())
            return val;
    }

    return JValue();
}

// Parsing out a block of JSON from an istream.
JValue parseJSON(std::istream& stream) {
    std::string line, all;

    while (!stream.eof()) {
        std::getline(stream, line);
        all += line;
    }

    return parseJSON(all);
}
<|endoftext|>