<commit_before>//
//  FileUtils.hpp
//  cppcommon
//
//  Created by Sean Grimes on 12/7/15.
//  Copyright © 2015 Sean Grimes. All rights reserved.
//

#pragma once

#include <string>
#include <fstream>
#include <vector>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/file.h>
#include <fcntl.h>
#include <dirent.h>
#include <cstring>
#include <unistd.h>
#include <mutex>
#include <fstream>
#include "StrUtils.hpp"

/**
    \brief Utility functions related to the file system
    \author Sean Grimes, spg63@cs.drexel.edu
    \date 12-7-15
*/
namespace FileUtils{
    inline std::string readFullFile(const std::string &filename);
    inline std::vector<std::string> readLineByLine(const std::string &filename);
    inline size_t lineCount(const std::string &filename);
    inline std::vector<std::string> getFilesInDir(const std::string &dirpath, const std::string &ext = "");
    inline std::vector<std::string> getDirsInDir(const std::string &path);
    inline bool makeDir(const std::string &dirpath);
    inline bool isFile(const std::string &filepath);
    inline bool isDir(const std::string &dirpath);
    inline bool isExc(const std::string &filepath);
    inline bool fexists(const std::string &filepath);
    inline bool dexists(const std::string &dirpath);
    inline bool deleteFile(const std::string &filepath);
    inline bool deleteDir(const std::string &dirpath);
    inline bool moveFile(const std::string &curpath, const std::string &newpath);
    inline bool moveDir(const std::string &curpath, const std::string &newpath);
    inline bool copyFile(const std::string &curpath, const std::string &newpath);
    inline bool copyDir(const std::string &curpath, const std::string &newpath);
    inline double fileSize(const std::string &filepath, const std::string &order = "b");
    inline std::vector<std::vector<std::string>> csvToMatrix(const std::string &filename);
    inline void appendToFile(const std::string &filepath, const std::string &msg);
}

/**
    \brief Read full file into a single string
    \details Will read a full file, all content, into a single string
    @param fileName File name if file is in cwd, else path to file
    @return The full file as a string
*/
std::string FileUtils::readFullFile(const std::string &fileName){
    std::ifstream ifs(fileName, std::ios::in | std::ios::binary | std::ios::ate);
    if(!ifs.is_open())
        throw std::runtime_error("Couldn't open " + fileName);

    std::ifstream::pos_type f_size = ifs.tellg();
    ifs.seekg(0, std::ios::beg);

    std::vector<char> bytes(f_size);
    ifs.read(&bytes[0], f_size);

    return std::string(&bytes[0], f_size);
}

/**
    \brief Read file into vector<string> of lines
    \details Will read the full file then proceed to split it into a vector<string> of lines
    @param fileName File name if file is in cwd, else path to file
    @return A vector of strings which represent the lines of the file
*/
std::vector<std::string> FileUtils::readLineByLine(const std::string &fileName){
    std::string line;
    std::ifstream in(fileName);
    if(!in.is_open())
        throw std::runtime_error("Couldn't open " + fileName);

    std::vector<std::string> vec;
    vec.reserve(lineCount(fileName));

    while(std::getline(in, line))
        vec.push_back(line);

    vec.shrink_to_fit();
    return vec;
}

/**
    \brief Returns number of lines in a file
    \details This code comes almost letter for letter from the "wc" utility, I am not the author and
    after a brief search I can't find the author on the GNU source website
    @param fileName File name if file is in cwd, else path to file
    @return Number of lines in the file
*/
size_t FileUtils::lineCount(const std::string &fileName){
    const char *fname = fileName.c_str();
    static const auto BUF_SIZE = 16*1024;
    int fd = open(fname, O_RDONLY);
    if(fd == -1){
        throw std::runtime_error("Couldn't open " + std::string(fname));
    }

    char buf[BUF_SIZE + 1];
    size_t lines = 0;

    while(size_t bytes_read = read(fd, buf, BUF_SIZE)){
        if(bytes_read == (size_t) -1)
            throw std::runtime_error("Read Failure" + std::string(fname));

        if(!bytes_read)
            break;

        for(char *p = buf; (p = (char *) memchr(p, '\n', (buf + bytes_read) - p)); ++p)
                ++lines;
    }
    close(fd);
    return lines;
}

/**
    \brief Get a list of files in directory
    @param dirPath Path to the directory in question
    @param ext Optional file extension, will only return files meeting passed file extension
    @return A vector of strings representing the files in the directory
*/
std::vector<std::string> FileUtils::getFilesInDir(const std::string &dirPath, const std::string &ext){
        std::vector<std::string> files;

    DIR *dir;
    struct dirent *ent;

    if((dir = opendir(dirPath.c_str())) == NULL)
        throw std::runtime_error("Couldn't open " + dirPath);

    // print all the files and directories within directory
    while ((ent = readdir(dir)) != NULL) {
        if(isFile(std::string(dirPath + "/" + ent->d_name))){
            // Only add files with the requested file extension
            if(ext != ""){
                // Note: This can easily be fooled
                std::string f_name(ent->d_name);
                if(StrUtils::endsWithString(f_name, ext))
                    files.push_back(f_name);
            }
            // Don't care what the file extension is
            else
                files.emplace_back(ent->d_name);
        }
    }
    closedir(dir);

    return files;
}

/**
    \brief Get a list of directories in directory
    @param path Path to the directory in question
    @return A vector of strings representing the directories in the directory
*/
std::vector<std::string> FileUtils::getDirsInDir(const std::string &path){
    std::vector<std::string> dirs;
    DIR *dir;
    struct dirent *ent;

    if((dir = opendir(path.c_str())) == NULL)
        throw std::runtime_error("Couldn't open " + path);

    while((ent = readdir(dir)) != NULL){
        if(isDir(std::string(path + "/" + ent->d_name)))
            dirs.emplace_back(ent->d_name);
    }

    return dirs;
}

/*
 * The next 3 functions *ONLY* tell you if something you know exists is a file, dir, has exec
 * permissions. They should not be used to test if something exists
 */

/**
    \brief Determine if resource at path is a file
    @param path Path to the resource
    @return True if the resource is a file, false otherwise
*/
bool FileUtils::isFile(const std::string &path){
    struct stat buffer;
    stat(path.c_str(), &buffer);
    return fexists(path) && S_ISREG(buffer.st_mode);
}

/**
    \brief Determine if resource at path is a directory
    @param path Path to the resource
    @return True if the resource is a directory, false otherwise
*/
bool FileUtils::isDir(const std::string &path){
    struct stat buffer;
    stat(path.c_str(), &buffer);
    return S_ISDIR(buffer.st_mode);
}

/**
    \brief Determine if resource at path is executable
    @param path Path to the resource
    @return True if the resource is executable, false otherwise
*/
bool FileUtils::isExc(const std::string& path){
    struct stat buffer;
    return (stat(path.c_str(), &buffer) == 0 && buffer.st_mode & S_IXUSR);
}

/**
    \brief Wrapper to create a directory
    @param path The path to where the directory should be created
    @return True if the directory is created successfully
*/
bool FileUtils::makeDir(const std::string &path){
    if(isDir(path))
        return true;

    // NOTE: I have no idea why flushing the stream is required, however without this flush only the root
    // directory is created when creating multiple directories on macOS Sierra 10.12.3 (and possibly other
    // systems)
    std::cout << std::flush;
    mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IRWXO);
    return isDir(path);
}

/**
    \brief Determine if a file exists
    @param path Path to the file in question
    @return True if file exists, false otherwise
*/
bool FileUtils::fexists(const std::string &path){
    struct stat buffer;
    return (stat(path.c_str(), &buffer) == 0 && S_ISREG(buffer.st_mode));
}

/**
 \brief Determine if a directory exists
 @param path Path to the directory in question
 @return True if directory exists, false otherwise
*/
bool FileUtils::dexists(const std::string &path){
    struct stat buffer;
    return (stat(path.c_str(), &buffer) == 0 && S_ISDIR(buffer.st_mode));
}

/**
    \brief Delete a file
    @param filepath The path to the file
    @return True if the file does not exist at the end of the function
*/
bool FileUtils::deleteFile(const std::string &filepath){
    if(!fexists(filepath))
        return true;

    std::remove(filepath.c_str());

    return !fexists(filepath);
}

/**
    \brief Delete a directory and contents
    @param dirpath The path to the directory
    @return True if the directory does not exist at the end of the function
*/
bool FileUtils::deleteDir(const std::string &dirpath){
#warning not implemented
    if(!dexists(dirpath))
        return true;
    return false;
}

/**
    \brief Move a file
    @param curpath The current path to the file
    @param newpath Where to move the file
    @return True if the file is successfully moved
*/
bool FileUtils::moveFile(const std::string &curpath, const std::string &newpath){
    if(!fexists(curpath) || !isFile(curpath))
        return false;

    std::rename(curpath.c_str(), newpath.c_str());

    return !fexists(curpath) && fexists(newpath);
}

/**
    \brief Move a directory
    @param curpath The current path to the directory
    @param newpath Where to move the file
    @return True if the directory is successfully moved
*/
bool FileUtils::moveDir(const std::string &curpath, const std::string &newpath){
#warning not implemented
    if(!dexists(curpath) || !isDir(curpath))
        return false;

    return false;

}

/**
    \brief Copy a file
    @param curpath The current path to the file
    @param newpath Where to copy the file
    @return True if file is successfully copied
*/
bool FileUtils::copyFile(const std::string &curpath, const std::string &newpath){
    if(!fexists(curpath) || !isFile(curpath))
        return false;

    {
        std::ifstream src(curpath, std::ios::binary);
        std::ofstream dst(newpath, std::ios::binary);
        dst << src.rdbuf();
    }

    return fexists(curpath) && fexists(newpath);
}

/**
    \brief Copy a directory
    @param curpath The current path to the directory
    @param newpath Where to copy the directory
    @return True if directory is successfully copied
*/
bool FileUtils::copyDir(const std::string &curpath, const std::string &newpath){
    if(!dexists(curpath) || !isDir(curpath))
        return false;

    DIR *dir;
    struct dirent *ent;

    if((dir = opendir(curpath.c_str())) == NULL)
        throw std::runtime_error("Couldn't open " + curpath);

    // Step 1, create the directory at the new path
    if(!makeDir(newpath))
        throw std::runtime_error("Failed to create " + newpath);

    std::string this_dir_dot(".");
    std::string previous_dir_dot("..");

    while((ent = readdir(dir)) != NULL){
        std::string it(ent->d_name);
        // Don't want to do anything if we're on a dot
        if(this_dir_dot == it || previous_dir_dot == it)
            continue;
        std::string cur_item(curpath + "/" + it);
        std::string new_item(newpath + "/" + it);

        if(isFile(cur_item))
            copyFile(cur_item, new_item);
        // Make the recursive call
        else if(isDir(cur_item))
            copyDir(cur_item, new_item);
        else
            throw std::runtime_error("Not sure what else we could have here...");
    }
    return dexists(newpath);
}

/**
    \brief Return size of file
    \details Optional second parameter to select the return value\n
    bytes = "b"\n
    kilobytes = "kb"\n
    megabytes = "mb"\n
    gigabytes = "gb"
    @param filepath The path to the file
    @return The file size if the file exists in bytes (or in specified value, if used)
    \note This function returns a double, unlike standard size functions, to allow for partial
    values when getting size back in KB, MB, or GB
*/
double FileUtils::fileSize(const std::string &filepath, const std::string &order){
    if(!fexists(filepath))
        throw std::runtime_error("Cannot find " + filepath);
    double sz;
    {
        std::ifstream f(filepath, std::ifstream::ate | std::ifstream::binary);
        sz = static_cast<double>(f.tellg());
    }

    if("kb" == order)
        return sz / 1000;
    else if("mb" == order)
        return sz / 1000000;
    else if("gb" == order)
        return sz / 1000000000;
    else
        return sz;
}

/**
    \brief Parse a csv file into a 2D vector
    \details The function parses a csv, reading the file line by line then splitting each line on
    the commas, returning a 2D vector representing the rows/cols of the csv...i.e. a matrix.
    @param fileName File name if file is in cwd, else path to file
    @return A vector<vector<string>> that represents rows/column of the csv file
*/
std::vector<std::vector<std::string>> FileUtils::csvToMatrix(const std::string& fileName){
    auto file_lines = readLineByLine(fileName);
    std::vector<std::vector<std::string>> matrix;
    for(auto &&line : file_lines)
        matrix.emplace_back(StrUtils::parseOnCharDelim(line, ','));
    return matrix;
}

/**
    \brief Wrapper to append text to a file
    @param fileName File name if file is in cwd, else path to file
    @param msg The text to append to the file
*/
void FileUtils::appendToFile(const std::string &fileName, const std::string &msg){
    std::ofstream out(fileName, std::ofstream::app);
    out << msg << "\n";
}
<commit_msg>deleteDir testing<commit_after>//
//  FileUtils.hpp
//  cppcommon
//
//  Created by Sean Grimes on 12/7/15.
//  Copyright © 2015 Sean Grimes. All rights reserved.
//

#pragma once

#include <string>
#include <fstream>
#include <vector>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/file.h>
#include <fcntl.h>
#include <dirent.h>
#include <cstring>
#include <unistd.h>
#include <mutex>
#include <fstream>
#include "StrUtils.hpp"

/**
    \brief Utility functions related to the file system
    \author Sean Grimes, spg63@cs.drexel.edu
    \date 12-7-15
*/
namespace FileUtils{
    inline std::string readFullFile(const std::string &filename);
    inline std::vector<std::string> readLineByLine(const std::string &filename);
    inline size_t lineCount(const std::string &filename);
    inline std::vector<std::string> getFilesInDir(const std::string &dirpath, const std::string &ext = "");
    inline std::vector<std::string> getDirsInDir(const std::string &path);
    inline bool makeDir(const std::string &dirpath);
    inline bool isFile(const std::string &filepath);
    inline bool isDir(const std::string &dirpath);
    inline bool isExc(const std::string &filepath);
    inline bool fexists(const std::string &filepath);
    inline bool dexists(const std::string &dirpath);
    inline bool deleteFile(const std::string &filepath);
    inline bool deleteDir(const std::string &dirpath);
    inline bool moveFile(const std::string &curpath, const std::string &newpath);
    inline bool moveDir(const std::string &curpath, const std::string &newpath);
    inline bool copyFile(const std::string &curpath, const std::string &newpath);
    inline bool copyDir(const std::string &curpath, const std::string &newpath);
    inline double fileSize(const std::string &filepath, const std::string &order = "b");
    inline std::vector<std::vector<std::string>> csvToMatrix(const std::string &filename);
    inline void appendToFile(const std::string &filepath, const std::string &msg);

    const std::string THIS_DIR_DOT{"."};
    const std::string PREV_DIR_DOT{".."};
}

/**
    \brief Read full file into a single string
    \details Will read a full file, all content, into a single string
    @param fileName File name if file is in cwd, else path to file
    @return The full file as a string
*/
std::string FileUtils::readFullFile(const std::string &fileName){
    std::ifstream ifs(fileName, std::ios::in | std::ios::binary | std::ios::ate);
    if(!ifs.is_open())
        throw std::runtime_error("Couldn't open " + fileName);

    std::ifstream::pos_type f_size = ifs.tellg();
    ifs.seekg(0, std::ios::beg);

    std::vector<char> bytes(f_size);
    ifs.read(&bytes[0], f_size);

    return std::string(&bytes[0], f_size);
}

/**
    \brief Read file into vector<string> of lines
    \details Will read the full file then proceed to split it into a vector<string> of lines
    @param fileName File name if file is in cwd, else path to file
    @return A vector of strings which represent the lines of the file
*/
std::vector<std::string> FileUtils::readLineByLine(const std::string &fileName){
    std::string line;
    std::ifstream in(fileName);
    if(!in.is_open())
        throw std::runtime_error("Couldn't open " + fileName);

    std::vector<std::string> vec;
    vec.reserve(lineCount(fileName));

    while(std::getline(in, line))
        vec.push_back(line);

    vec.shrink_to_fit();
    return vec;
}

/**
    \brief Returns number of lines in a file
    \details This code comes almost letter for letter from the "wc" utility, I am not the author and
    after a brief search I can't find the author on the GNU source website
    @param fileName File name if file is in cwd, else path to file
    @return Number of lines in the file
*/
size_t FileUtils::lineCount(const std::string &fileName){
    const char *fname = fileName.c_str();
    static const auto BUF_SIZE = 16*1024;
    int fd = open(fname, O_RDONLY);
    if(fd == -1)
        throw std::runtime_error("Couldn't open " + std::string(fname));

    char buf[BUF_SIZE + 1];
    size_t lines = 0;

    while(size_t bytes_read = read(fd, buf, BUF_SIZE)){
        if(bytes_read == (size_t) -1)
            throw std::runtime_error("Read Failure" + std::string(fname));

        if(!bytes_read)
            break;

        for(char *p = buf; (p = (char *) memchr(p, '\n', (buf + bytes_read) - p)); ++p)
                ++lines;
    }
    close(fd);
    return lines;
}

/**
    \brief Get a list of files in directory
    @param dirPath Path to the directory in question
    @param ext Optional file extension, will only return files meeting passed file extension
    @return A vector of strings representing the files in the directory
*/
std::vector<std::string> FileUtils::getFilesInDir(const std::string &dirPath, const std::string &ext){
        std::vector<std::string> files;

    DIR *dir;
    struct dirent *ent;

    if((dir = opendir(dirPath.c_str())) == NULL)
        throw std::runtime_error("Couldn't open " + dirPath);

    // print all the files and directories within directory
    while ((ent = readdir(dir)) != NULL) {
        if(isFile(std::string(dirPath + "/" + ent->d_name))){
            // Only add files with the requested file extension
            if(ext != ""){
                // Note: This can easily be fooled
                std::string f_name(ent->d_name);
                if(StrUtils::endsWithString(f_name, ext))
                    files.push_back(f_name);
            }
            // Don't care what the file extension is
            else
                files.emplace_back(ent->d_name);
        }
    }
    closedir(dir);

    return files;
}

/**
    \brief Get a list of directories in directory
    @param path Path to the directory in question
    @return A vector of strings representing the directories in the directory
*/
std::vector<std::string> FileUtils::getDirsInDir(const std::string &path){
    std::vector<std::string> dirs;
    DIR *dir;
    struct dirent *ent;

    if((dir = opendir(path.c_str())) == NULL)
        throw std::runtime_error("Couldn't open " + path);

    while((ent = readdir(dir)) != NULL){
        if(isDir(std::string(path + "/" + ent->d_name)))
            dirs.emplace_back(ent->d_name);
    }

    return dirs;
}

/*
 * The next 3 functions *ONLY* tell you if something you know exists is a file, dir, has exec
 * permissions. They should not be used to test if something exists
 */

/**
    \brief Determine if resource at path is a file
    @param path Path to the resource
    @return True if the resource is a file, false otherwise
*/
bool FileUtils::isFile(const std::string &path){
    struct stat buffer;
    stat(path.c_str(), &buffer);
    return fexists(path) && S_ISREG(buffer.st_mode);
}

/**
    \brief Determine if resource at path is a directory
    @param path Path to the resource
    @return True if the resource is a directory, false otherwise
*/
bool FileUtils::isDir(const std::string &path){
    struct stat buffer;
    stat(path.c_str(), &buffer);
    return S_ISDIR(buffer.st_mode);
}

/**
    \brief Determine if resource at path is executable
    @param path Path to the resource
    @return True if the resource is executable, false otherwise
*/
bool FileUtils::isExc(const std::string& path){
    struct stat buffer;
    return (stat(path.c_str(), &buffer) == 0 && buffer.st_mode & S_IXUSR);
}

/**
    \brief Wrapper to create a directory
    @param path The path to where the directory should be created
    @return True if the directory is created successfully
*/
bool FileUtils::makeDir(const std::string &path){
    if(isDir(path))
        return true;

    // NOTE: I have no idea why flushing the stream is required, however without this flush only the root
    // directory is created when creating multiple directories on macOS Sierra 10.12.3 (and possibly other
    // systems)
    std::cout << std::flush;
    mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IRWXO);
    return dexists(path) && isDir(path);
}

/**
    \brief Determine if a file exists
    @param path Path to the file in question
    @return True if file exists, false otherwise
*/
bool FileUtils::fexists(const std::string &path){
    struct stat buffer;
    return (stat(path.c_str(), &buffer) == 0 && S_ISREG(buffer.st_mode));
}

/**
 \brief Determine if a directory exists
 @param path Path to the directory in question
 @return True if directory exists, false otherwise
*/
bool FileUtils::dexists(const std::string &path){
    struct stat buffer;
    return (stat(path.c_str(), &buffer) == 0 && S_ISDIR(buffer.st_mode));
}

/**
    \brief Delete a file
    @param filepath The path to the file
    @return True if the file does not exist at the end of the function
*/
bool FileUtils::deleteFile(const std::string &filepath){
    if(!fexists(filepath))
        return true;

    std::remove(filepath.c_str());

    return !fexists(filepath);
}

/**
    \brief Delete a directory and contents
    @param dirpath The path to the directory
    @return True if the directory does not exist at the end of the function
*/
bool FileUtils::deleteDir(const std::string &dirpath){
    if(!dexists(dirpath))
        return true;

    DIR *dir;
    struct dirent *ent;

    if((dir = opendir(dirpath.c_str())) == NULL)
        throw std::runtime_error("Couldn't open " + dirpath + " for deletion");

    while((ent = readdir(dir)) != NULL){
        std::string it(ent->d_name);

        if(THIS_DIR_DOT == it || PREV_DIR_DOT == it)
            continue;

        std::string relative_it(dirpath + "/" + it);

        if(isFile(relative_it))
            std::remove(relative_it.c_str());
        else if(isDir(relative_it))
            deleteDir(relative_it);
        else
            throw std::runtime_error("Not sure what else we could have here...");
    }

    return !dexists(dirpath);
}

/**
    \brief Move a file
    @param curpath The current path to the file
    @param newpath Where to move the file
    @return True if the file is successfully moved
*/
bool FileUtils::moveFile(const std::string &curpath, const std::string &newpath){
    if(!fexists(curpath) || !isFile(curpath))
        return false;

    std::rename(curpath.c_str(), newpath.c_str());

    return !fexists(curpath) && fexists(newpath);
}

/**
    \brief Move a directory
    @param curpath The current path to the directory
    @param newpath Where to move the file
    @return True if the directory is successfully moved
*/
bool FileUtils::moveDir(const std::string &curpath, const std::string &newpath){
    if(!dexists(curpath) || !isDir(curpath))
        return false;

    DIR *dir;
    struct dirent *ent;

    if((dir = opendir(curpath.c_str())) == NULL)
        throw std::runtime_error("Couldn't open " + curpath);

    if(!makeDir(newpath))
        throw std::runtime_error("Failed to create " + newpath);

    while((ent = readdir(dir)) != NULL){
        std::string it(ent->d_name);

        if(THIS_DIR_DOT == it || PREV_DIR_DOT == it)
            continue;

        std::string cur_item(curpath + "/" + it);
        std::string new_item(newpath + "/" + it);

        if(isFile(cur_item))
            moveFile(cur_item, new_item);
        else if(isDir(cur_item))
            moveDir(cur_item, new_item);
        else
            throw std::runtime_error("Not sure what else we could have here...");
    }

    return dexists(newpath);
}

/**
    \brief Copy a file
    @param curpath The current path to the file
    @param newpath Where to copy the file
    @return True if file is successfully copied
*/
bool FileUtils::copyFile(const std::string &curpath, const std::string &newpath){
    if(!fexists(curpath) || !isFile(curpath))
        return false;

    {
        std::ifstream src(curpath, std::ios::binary);
        std::ofstream dst(newpath, std::ios::binary);
        dst << src.rdbuf();
    }

    return fexists(curpath) && fexists(newpath);
}

/**
    \brief Copy a directory
    @param curpath The current path to the directory
    @param newpath Where to copy the directory
    @return True if directory is successfully copied
*/
bool FileUtils::copyDir(const std::string &curpath, const std::string &newpath){
    if(!dexists(curpath) || !isDir(curpath))
        return false;

    DIR *dir;
    struct dirent *ent;

    if((dir = opendir(curpath.c_str())) == NULL)
        throw std::runtime_error("Couldn't open " + curpath);

    // Step 1, create the directory at the new path
    if(!makeDir(newpath))
        throw std::runtime_error("Failed to create " + newpath);

    while((ent = readdir(dir)) != NULL){
        std::string it(ent->d_name);
        // Don't want to do anything if we're on a dot
        if(THIS_DIR_DOT == it || PREV_DIR_DOT == it)
            continue;
        std::string cur_item(curpath + "/" + it);
        std::string new_item(newpath + "/" + it);

        if(isFile(cur_item))
            copyFile(cur_item, new_item);
        // Make the recursive call
        else if(isDir(cur_item))
            copyDir(cur_item, new_item);
        else
            throw std::runtime_error("Not sure what else we could have here...");
    }
    return dexists(newpath);
}

/**
    \brief Return size of file
    \details Optional second parameter to select the return value\n
    bytes = "b"\n
    kilobytes = "kb"\n
    megabytes = "mb"\n
    gigabytes = "gb"
    @param filepath The path to the file
    @return The file size if the file exists in bytes (or in specified value, if used)
    \note This function returns a double, unlike standard size functions, to allow for partial
    values when getting size back in KB, MB, or GB
*/
double FileUtils::fileSize(const std::string &filepath, const std::string &order){
    if(!fexists(filepath))
        throw std::runtime_error("Cannot find " + filepath);
    double sz;
    {
        std::ifstream f(filepath, std::ifstream::ate | std::ifstream::binary);
        sz = static_cast<double>(f.tellg());
    }

    if("kb" == order)
        return sz / 1000;
    else if("mb" == order)
        return sz / 1000000;
    else if("gb" == order)
        return sz / 1000000000;
    else
        return sz;
}

/**
    \brief Parse a csv file into a 2D vector
    \details The function parses a csv, reading the file line by line then splitting each line on
    the commas, returning a 2D vector representing the rows/cols of the csv...i.e. a matrix.
    @param fileName File name if file is in cwd, else path to file
    @return A vector<vector<string>> that represents rows/column of the csv file
*/
std::vector<std::vector<std::string>> FileUtils::csvToMatrix(const std::string& fileName){
    auto file_lines = readLineByLine(fileName);
    std::vector<std::vector<std::string>> matrix;
    for(auto &&line : file_lines)
        matrix.emplace_back(StrUtils::parseOnCharDelim(line, ','));
    return matrix;
}

/**
    \brief Wrapper to append text to a file
    @param fileName File name if file is in cwd, else path to file
    @param msg The text to append to the file
*/
void FileUtils::appendToFile(const std::string &fileName, const std::string &msg){
    std::ofstream out(fileName, std::ofstream::app);
    out << msg << "\n";
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015, Cryptonomex, Inc.
 * All rights reserved.
 *
 * This source code is provided for evaluation in private test networks only, until September 8, 2015. After this date, this license expires and
 * the code may not be used, modified or distributed for any purpose. Redistribution and use in source and binary forms, with or without modification,
 * are permitted until September 8, 2015, provided that the following conditions are met:
 *
 * 1. The code and/or derivative works are used only for private test networks consisting of no more than 10 P2P nodes.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <graphene/market_history/market_history_plugin.hpp>

#include <graphene/chain/account_evaluator.hpp>
#include <graphene/chain/account_object.hpp>
#include <graphene/chain/config.hpp>
#include <graphene/chain/database.hpp>
#include <graphene/chain/evaluator.hpp>
#include <graphene/chain/operation_history_object.hpp>
#include <graphene/chain/transaction_evaluation_state.hpp>
#include <graphene/chain/protocol/fee_schedule.hpp>

#include <fc/thread/thread.hpp>
#include <fc/smart_ref_impl.hpp>

namespace graphene { namespace market_history {

namespace detail
{

class market_history_plugin_impl
{
   public:
      market_history_plugin_impl(market_history_plugin& _plugin)
      :_self( _plugin ) {}
      virtual ~market_history_plugin_impl();

      /** this method is called as a callback after a block is applied
       * and will process/index all operations that were applied in the block.
       */
      void update_market_histories( const signed_block& b );

      graphene::chain::database& database()
      {
         return _self.database();
      }

      market_history_plugin&     _self;
      flat_set<uint32_t>         _tracked_buckets;
      uint32_t                   _maximum_history_per_bucket_size = 1000;
};

struct operation_process_fill_order
{
   market_history_plugin&    _plugin;
   fc::time_point_sec        _now;

   operation_process_fill_order( market_history_plugin& mhp, fc::time_point_sec n )
   :_plugin(mhp),_now(n) {}

   typedef void result_type;

   /** do nothing for other operation types */
   template<typename T>
   void operator()( const T& )const{}

   void operator()( const fill_order_operation& o )const
   {
      ilog( "processing ${o}", ("o",o) );
      const auto& buckets = _plugin.tracked_buckets();
      auto& db         = _plugin.database();
      const auto& bucket_idx = db.get_index_type<bucket_index>();

      auto max_history = _plugin.max_history();
      for( auto bucket : buckets )
      {
          auto cutoff      = (fc::time_point() + fc::seconds( bucket * max_history));

          bucket_key key;
          key.base    = o.pays.asset_id;
          key.quote   = o.receives.asset_id;

          /** for every matched order there are two fill order operations created, one for
           * each side.  We can filter the duplicates by only considering the fill operations where
           * the base > quote
           */
          if( key.base > key.quote )
          {
             ilog( "     skipping because base > quote" );
             continue;
          }

          price trade_price = o.pays / o.receives;

          key.seconds = bucket;
          key.open    = fc::time_point() + fc::seconds((_now.sec_since_epoch() / key.seconds) * key.seconds);

          const auto& by_key_idx = bucket_idx.indices().get<by_key>();
          auto itr = by_key_idx.find( key );
          if( itr == by_key_idx.end() )
          { // create new bucket
            const auto& obj = db.create<bucket_object>( [&]( bucket_object& b ){
                 b.key = key;
                 b.quote_volume += trade_price.quote.amount;
                 b.base_volume += trade_price.base.amount;
                 b.open_base = trade_price.base.amount;
                 b.open_quote = trade_price.quote.amount;
                 b.close_base = trade_price.base.amount;
                 b.close_quote = trade_price.quote.amount;
                 b.high_base = b.close_base;
                 b.high_quote = b.close_quote;
                 b.low_base = b.close_base;
                 b.low_quote = b.close_quote;
            });
            wlog( "    creating bucket ${b}", ("b",obj) );
          }
          else
          { // update existing bucket
             wlog( "    before updating bucket ${b}", ("b",*itr) );
             db.modify( *itr, [&]( bucket_object& b ){
                  b.base_volume += trade_price.base.amount;
                  b.quote_volume += trade_price.quote.amount;
                  b.close_base = trade_price.base.amount;
                  b.close_quote = trade_price.quote.amount;
                  if( b.high() < trade_price )
                  {
                      b.high_base = b.close_base;
                      b.high_quote = b.close_quote;
                  }
                  if( b.low() > trade_price )
                  {
                      b.low_base = b.close_base;
                      b.low_quote = b.close_quote;
                  }
             });
             wlog( "    after bucket bucket ${b}", ("b",*itr) );
          }

          if( max_history != 0  )
          {
             key.open = fc::time_point_sec();
             auto itr = by_key_idx.lower_bound( key );

             while( itr != by_key_idx.end() &&
                    itr->key.base == key.base &&
                    itr->key.quote == key.quote &&
                    itr->key.seconds == bucket &&
                    itr->key.open < cutoff )
             {
                elog( "    removing old bucket ${b}", ("b", *itr) );
                auto old_itr = itr;
                ++itr;
                db.remove( *old_itr );
             }
          }
      }
   }
};

market_history_plugin_impl::~market_history_plugin_impl()
{}

void market_history_plugin_impl::update_market_histories( const signed_block& b )
{
   if( _maximum_history_per_bucket_size == 0 ) return;
   if( _tracked_buckets.size() == 0 ) return;

   graphene::chain::database& db = database();
   const vector<operation_history_object>& hist = db.get_applied_operations();
   for( auto op : hist )
      op.op.visit( operation_process_fill_order( _self, b.timestamp ) );
}

} // end namespace detail

market_history_plugin::market_history_plugin() :
   my( new detail::market_history_plugin_impl(*this) )
{
}

market_history_plugin::~market_history_plugin()
{
}

std::string market_history_plugin::plugin_name()const
{
   return "market_history";
}

void market_history_plugin::plugin_set_program_options(
   boost::program_options::options_description& cli,
   boost::program_options::options_description& cfg
   )
{
   cli.add_options()
         ("bucket-size", boost::program_options::value<std::vector<uint32_t>>()->composing()->multitoken(),
           "Track market history by grouping orders into buckets of equal size measured in seconds, may specify more than one bucket size")
         ("history-per-size", boost::program_options::value<uint32_t>()->default_value(1000),
           "How far back in time to track history for each bucket size, measured in the number of buckets (default: 1000)")
         ;
   cfg.add(cli);
}

void market_history_plugin::plugin_initialize(const boost::program_options::variables_map& options)
{ try {
   database().applied_block.connect( [&]( const signed_block& b){ my->update_market_histories(b); } );
   database().add_index< primary_index< bucket_index  > >();

   if( options.count( "bucket-size" ) )
   {
      const std::vector<uint32_t>& buckets = options["bucket-size"].as<std::vector<uint32_t>>();
      for( auto o : buckets ) my->_tracked_buckets.insert(o);
   }
   if( options.count( "history-per-size" ) )
      my->_maximum_history_per_bucket_size = options["history-per-size"].as<uint32_t>();
} FC_CAPTURE_AND_RETHROW() }

void market_history_plugin::plugin_startup()
{
}

const flat_set<uint32_t>& market_history_plugin::tracked_buckets() const
{
   return my->_tracked_buckets;
}

uint32_t market_history_plugin::max_history()const
{
   return my->_maximum_history_per_bucket_size;
}

} }
<commit_msg>Fix #203 - market history plugin config supports multiple buckets<commit_after>/*
 * Copyright (c) 2015, Cryptonomex, Inc.
 * All rights reserved.
 *
 * This source code is provided for evaluation in private test networks only, until September 8, 2015. After this date, this license expires and
 * the code may not be used, modified or distributed for any purpose. Redistribution and use in source and binary forms, with or without modification,
 * are permitted until September 8, 2015, provided that the following conditions are met:
 *
 * 1. The code and/or derivative works are used only for private test networks consisting of no more than 10 P2P nodes.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <graphene/market_history/market_history_plugin.hpp>

#include <graphene/chain/account_evaluator.hpp>
#include <graphene/chain/account_object.hpp>
#include <graphene/chain/config.hpp>
#include <graphene/chain/database.hpp>
#include <graphene/chain/evaluator.hpp>
#include <graphene/chain/operation_history_object.hpp>
#include <graphene/chain/transaction_evaluation_state.hpp>
#include <graphene/chain/protocol/fee_schedule.hpp>

#include <fc/thread/thread.hpp>
#include <fc/smart_ref_impl.hpp>

namespace graphene { namespace market_history {

namespace detail
{

class market_history_plugin_impl
{
   public:
      market_history_plugin_impl(market_history_plugin& _plugin)
      :_self( _plugin ) {}
      virtual ~market_history_plugin_impl();

      /** this method is called as a callback after a block is applied
       * and will process/index all operations that were applied in the block.
       */
      void update_market_histories( const signed_block& b );

      graphene::chain::database& database()
      {
         return _self.database();
      }

      market_history_plugin&     _self;
      flat_set<uint32_t>         _tracked_buckets;
      uint32_t                   _maximum_history_per_bucket_size = 1000;
};

struct operation_process_fill_order
{
   market_history_plugin&    _plugin;
   fc::time_point_sec        _now;

   operation_process_fill_order( market_history_plugin& mhp, fc::time_point_sec n )
   :_plugin(mhp),_now(n) {}

   typedef void result_type;

   /** do nothing for other operation types */
   template<typename T>
   void operator()( const T& )const{}

   void operator()( const fill_order_operation& o )const
   {
      ilog( "processing ${o}", ("o",o) );
      const auto& buckets = _plugin.tracked_buckets();
      auto& db         = _plugin.database();
      const auto& bucket_idx = db.get_index_type<bucket_index>();

      auto max_history = _plugin.max_history();
      for( auto bucket : buckets )
      {
          auto cutoff      = (fc::time_point() + fc::seconds( bucket * max_history));

          bucket_key key;
          key.base    = o.pays.asset_id;
          key.quote   = o.receives.asset_id;

          /** for every matched order there are two fill order operations created, one for
           * each side.  We can filter the duplicates by only considering the fill operations where
           * the base > quote
           */
          if( key.base > key.quote )
          {
             ilog( "     skipping because base > quote" );
             continue;
          }

          price trade_price = o.pays / o.receives;

          key.seconds = bucket;
          key.open    = fc::time_point() + fc::seconds((_now.sec_since_epoch() / key.seconds) * key.seconds);

          const auto& by_key_idx = bucket_idx.indices().get<by_key>();
          auto itr = by_key_idx.find( key );
          if( itr == by_key_idx.end() )
          { // create new bucket
            const auto& obj = db.create<bucket_object>( [&]( bucket_object& b ){
                 b.key = key;
                 b.quote_volume += trade_price.quote.amount;
                 b.base_volume += trade_price.base.amount;
                 b.open_base = trade_price.base.amount;
                 b.open_quote = trade_price.quote.amount;
                 b.close_base = trade_price.base.amount;
                 b.close_quote = trade_price.quote.amount;
                 b.high_base = b.close_base;
                 b.high_quote = b.close_quote;
                 b.low_base = b.close_base;
                 b.low_quote = b.close_quote;
            });
            wlog( "    creating bucket ${b}", ("b",obj) );
          }
          else
          { // update existing bucket
             wlog( "    before updating bucket ${b}", ("b",*itr) );
             db.modify( *itr, [&]( bucket_object& b ){
                  b.base_volume += trade_price.base.amount;
                  b.quote_volume += trade_price.quote.amount;
                  b.close_base = trade_price.base.amount;
                  b.close_quote = trade_price.quote.amount;
                  if( b.high() < trade_price )
                  {
                      b.high_base = b.close_base;
                      b.high_quote = b.close_quote;
                  }
                  if( b.low() > trade_price )
                  {
                      b.low_base = b.close_base;
                      b.low_quote = b.close_quote;
                  }
             });
             wlog( "    after bucket bucket ${b}", ("b",*itr) );
          }

          if( max_history != 0  )
          {
             key.open = fc::time_point_sec();
             auto itr = by_key_idx.lower_bound( key );

             while( itr != by_key_idx.end() &&
                    itr->key.base == key.base &&
                    itr->key.quote == key.quote &&
                    itr->key.seconds == bucket &&
                    itr->key.open < cutoff )
             {
                elog( "    removing old bucket ${b}", ("b", *itr) );
                auto old_itr = itr;
                ++itr;
                db.remove( *old_itr );
             }
          }
      }
   }
};

market_history_plugin_impl::~market_history_plugin_impl()
{}

void market_history_plugin_impl::update_market_histories( const signed_block& b )
{
   if( _maximum_history_per_bucket_size == 0 ) return;
   if( _tracked_buckets.size() == 0 ) return;

   graphene::chain::database& db = database();
   const vector<operation_history_object>& hist = db.get_applied_operations();
   for( auto op : hist )
      op.op.visit( operation_process_fill_order( _self, b.timestamp ) );
}

} // end namespace detail

market_history_plugin::market_history_plugin() :
   my( new detail::market_history_plugin_impl(*this) )
{
}

market_history_plugin::~market_history_plugin()
{
}

std::string market_history_plugin::plugin_name()const
{
   return "market_history";
}

void market_history_plugin::plugin_set_program_options(
   boost::program_options::options_description& cli,
   boost::program_options::options_description& cfg
   )
{
   cli.add_options()
         ("bucket-size", boost::program_options::value<string>()->default_value("[15,60,300,3600,86400]"),
           "Track market history by grouping orders into buckets of equal size measured in seconds specified as a JSON array of numbers")
         ("history-per-size", boost::program_options::value<uint32_t>()->default_value(1000),
           "How far back in time to track history for each bucket size, measured in the number of buckets (default: 1000)")
         ;
   cfg.add(cli);
}

void market_history_plugin::plugin_initialize(const boost::program_options::variables_map& options)
{ try {
   database().applied_block.connect( [&]( const signed_block& b){ my->update_market_histories(b); } );
   database().add_index< primary_index< bucket_index  > >();

   if( options.count( "bucket-size" ) )
   {
      const std::string& buckets = options["bucket-size"].as<string>();
      my->_tracked_buckets = fc::json::from_string(buckets).as<flat_set<uint32_t>>();
   }
   if( options.count( "history-per-size" ) )
      my->_maximum_history_per_bucket_size = options["history-per-size"].as<uint32_t>();
} FC_CAPTURE_AND_RETHROW() }

void market_history_plugin::plugin_startup()
{
}

const flat_set<uint32_t>& market_history_plugin::tracked_buckets() const
{
   return my->_tracked_buckets;
}

uint32_t market_history_plugin::max_history()const
{
   return my->_maximum_history_per_bucket_size;
}

} }
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: GraphicViewShellBase.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 06:59:09 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include "GraphicViewShellBase.hxx"

#include "ViewTabBar.hxx"
#ifndef SD_RESID_HXX
#include "sdresid.hxx"
#endif
#ifndef SD_GRAPHIC_DOC_SHELL_HXX
#include "GraphicDocShell.hxx"
#endif
#include "strings.hrc"
#include "app.hrc"

#ifndef _SFXREQUEST_HXX
#include <sfx2/request.hxx>
#endif

namespace sd {

class DrawDocShell;

TYPEINIT1(GraphicViewShellBase, ViewShellBase);

// We have to expand the SFX_IMPL_VIEWFACTORY macro to call LateInit() after a
// new GraphicViewShellBase object has been constructed.

/*
SFX_IMPL_VIEWFACTORY(GraphicViewShellBase, SdResId(STR_DEFAULTVIEW))
{
    SFX_VIEW_REGISTRATION(GraphicDocShell);
}
*/
SfxViewFactory* GraphicViewShellBase::pFactory;
SfxViewShell* __EXPORT GraphicViewShellBase::CreateInstance (
    SfxViewFrame *pFrame, SfxViewShell *pOldView)
{
    GraphicViewShellBase* pBase = new GraphicViewShellBase(pFrame, pOldView);
    pBase->LateInit();
    return pBase;
}
void GraphicViewShellBase::RegisterFactory( USHORT nPrio )
{
    pFactory = new SfxViewFactory(
        &CreateInstance,&InitFactory,nPrio,SdResId(STR_DEFAULTVIEW));
    InitFactory();
}
void GraphicViewShellBase::InitFactory()
{
    SFX_VIEW_REGISTRATION(GraphicDocShell);
}

GraphicViewShellBase::GraphicViewShellBase (
    SfxViewFrame* pFrame,
    SfxViewShell* pOldShell)
    : ViewShellBase (pFrame, pOldShell, ViewShell::ST_DRAW)
{
}

void GraphicViewShellBase::LateInit (void)
{
    ViewShellBase::LateInit();
    // Turn the ViewTabBar off again.  It is not needed for Draw.
    mpViewTabBar.reset();
}

GraphicViewShellBase::~GraphicViewShellBase (void)
{
}

void GraphicViewShellBase::Execute (SfxRequest& rRequest)
{
    USHORT nSlotId = rRequest.GetSlot();

    switch (nSlotId)
    {
        case SID_TASK_PANE:
            // Since there is no tool panel in Draw we ignore this call.
            rRequest.Cancel();
            break;

        default:
            // The remaining requests are forwarded to out base class.
            ViewShellBase::Execute (rRequest);
            break;
    }

}

} // end of namespace sd

<commit_msg>INTEGRATION: CWS viewswitch (1.5.72); FILE MERGED 2006/02/09 12:27:57 af 1.5.72.2: #i57552# Ignoring some more slots to prevent view switching. 2006/02/02 09:58:41 af 1.5.72.1: #i61191# Removed LateInit(). Added CreateViewTabBar().<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: GraphicViewShellBase.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: obo $ $Date: 2006-03-21 17:37:04 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include "GraphicViewShellBase.hxx"

#include "ViewTabBar.hxx"
#ifndef SD_RESID_HXX
#include "sdresid.hxx"
#endif
#ifndef SD_GRAPHIC_DOC_SHELL_HXX
#include "GraphicDocShell.hxx"
#endif
#include "strings.hrc"
#include "app.hrc"

#ifndef _SFXREQUEST_HXX
#include <sfx2/request.hxx>
#endif

namespace sd {

class DrawDocShell;

TYPEINIT1(GraphicViewShellBase, ViewShellBase);

// We have to expand the SFX_IMPL_VIEWFACTORY macro to call LateInit() after a
// new GraphicViewShellBase object has been constructed.

/*
SFX_IMPL_VIEWFACTORY(GraphicViewShellBase, SdResId(STR_DEFAULTVIEW))
{
    SFX_VIEW_REGISTRATION(GraphicDocShell);
}
*/
SfxViewFactory* GraphicViewShellBase::pFactory;
SfxViewShell* __EXPORT GraphicViewShellBase::CreateInstance (
    SfxViewFrame *pFrame, SfxViewShell *pOldView)
{
    GraphicViewShellBase* pBase = new GraphicViewShellBase(pFrame, pOldView);
    pBase->LateInit();
    return pBase;
}
void GraphicViewShellBase::RegisterFactory( USHORT nPrio )
{
    pFactory = new SfxViewFactory(
        &CreateInstance,&InitFactory,nPrio,SdResId(STR_DEFAULTVIEW));
    InitFactory();
}
void GraphicViewShellBase::InitFactory()
{
    SFX_VIEW_REGISTRATION(GraphicDocShell);
}

GraphicViewShellBase::GraphicViewShellBase (
    SfxViewFrame* pFrame,
    SfxViewShell* pOldShell)
    : ViewShellBase (pFrame, pOldShell, ViewShell::ST_DRAW)
{
}

ViewTabBar* GraphicViewShellBase::CreateViewTabBar (void)
{
    // The ViewTabBar is not supported.
    return NULL;
}

GraphicViewShellBase::~GraphicViewShellBase (void)
{
}

void GraphicViewShellBase::Execute (SfxRequest& rRequest)
{
    USHORT nSlotId = rRequest.GetSlot();

    switch (nSlotId)
    {
        case SID_LEFT_PANE_IMPRESS:
        case SID_RIGHT_PANE:
        case SID_NOTES_WINDOW:
        case SID_SLIDE_SORTER_MULTI_PANE_GUI:
        case SID_DIAMODE:
        case SID_OUTLINEMODE:
        case SID_NOTESMODE:
        case SID_HANDOUTMODE:
        case SID_TASK_PANE:
            // Prevent some Impress-only slots from being executed.
            rRequest.Cancel();
            break;

        case SID_SWITCH_SHELL:
        case SID_LEFT_PANE_DRAW:
        default:
            // The remaining requests are forwarded to out base class.
            ViewShellBase::Execute (rRequest);
            break;
    }

}

} // end of namespace sd

<|endoftext|>


<commit_before>
/*

Copyright (c) 2007, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include <boost/bind.hpp>
#include "libtorrent/invariant_check.hpp"
#include "libtorrent/connection_queue.hpp"

namespace libtorrent
{

	connection_queue::connection_queue(io_service& ios): m_next_ticket(0)
		, m_num_connecting(0)
		, m_half_open_limit(0)
		, m_timer(ios)
#ifndef NDEBUG
		, m_in_timeout_function(false)
#endif
	{
#ifdef TORRENT_CONNECTION_LOGGING
		m_log.open("connection_queue.log");
#endif
	}

	int connection_queue::free_slots() const
	{
		mutex_t::scoped_lock l(m_mutex);
		return m_half_open_limit == 0 ? std::numeric_limits<int>::max()
			: m_half_open_limit - m_queue.size();
	}

	void connection_queue::enqueue(boost::function<void(int)> const& on_connect
		, boost::function<void()> const& on_timeout
		, time_duration timeout, int priority)
	{
		mutex_t::scoped_lock l(m_mutex);

		INVARIANT_CHECK;

		TORRENT_ASSERT(priority >= 0);
		TORRENT_ASSERT(priority < 2);

		entry* e = 0;

		switch (priority)
		{
			case 0:
				m_queue.push_back(entry());
				e = &m_queue.back();
				break;
			case 1:
				m_queue.push_front(entry());
				e = &m_queue.front();
				break;
		}

		e->priority = priority;
		e->on_connect = on_connect;
		e->on_timeout = on_timeout;
		e->ticket = m_next_ticket;
		e->timeout = timeout;
		++m_next_ticket;
		try_connect();
	}

	void connection_queue::done(int ticket)
	{
		mutex_t::scoped_lock l(m_mutex);

		INVARIANT_CHECK;

		std::list<entry>::iterator i = std::find_if(m_queue.begin()
			, m_queue.end(), boost::bind(&entry::ticket, _1) == ticket);
		if (i == m_queue.end())
		{
			// this might not be here in case on_timeout calls remove
			return;
		}
		if (i->connecting) --m_num_connecting;
		m_queue.erase(i);
		try_connect();
	}

	void connection_queue::close()
	{
		asio::error_code ec;
		m_timer.cancel(ec);
	}

	void connection_queue::limit(int limit)
	{
		TORRENT_ASSERT(limit >= 0);
		m_half_open_limit = limit;
	}

	int connection_queue::limit() const
	{ return m_half_open_limit; }

#ifndef NDEBUG

	void connection_queue::check_invariant() const
	{
		int num_connecting = 0;
		for (std::list<entry>::const_iterator i = m_queue.begin();
			i != m_queue.end(); ++i)
		{
			if (i->connecting) ++num_connecting;
		}
		TORRENT_ASSERT(num_connecting == m_num_connecting);
	}

#endif

	void connection_queue::try_connect()
	{
		INVARIANT_CHECK;

#ifdef TORRENT_CONNECTION_LOGGING
		m_log << log_time() << " " << free_slots() << std::endl;
#endif

		if (m_num_connecting >= m_half_open_limit
			&& m_half_open_limit > 0) return;

		if (m_queue.empty())
		{
			asio::error_code ec;
			m_timer.cancel(ec);
			return;
		}

		std::list<entry>::iterator i = std::find_if(m_queue.begin()
			, m_queue.end(), boost::bind(&entry::connecting, _1) == false);
		while (i != m_queue.end())
		{
			TORRENT_ASSERT(i->connecting == false);
			ptime expire = time_now() + i->timeout;
			if (m_num_connecting == 0)
			{
				asio::error_code ec;
				m_timer.expires_at(expire, ec);
				m_timer.async_wait(boost::bind(&connection_queue::on_timeout, this, _1));
			}
			i->connecting = true;
			++m_num_connecting;
			i->expires = expire;

			INVARIANT_CHECK;

			entry& ent = *i;
			++i;
#ifndef BOOST_NO_EXCEPTIONS
			try {
#endif
				ent.on_connect(ent.ticket);
#ifndef BOOST_NO_EXCEPTIONS
			} catch (std::exception&) {}
#endif

#ifdef TORRENT_CONNECTION_LOGGING
			m_log << log_time() << " " << free_slots() << std::endl;
#endif

			if (m_num_connecting >= m_half_open_limit
				&& m_half_open_limit > 0) break;
			i = std::find_if(i, m_queue.end(), boost::bind(&entry::connecting, _1) == false);
		}
	}

#ifndef NDEBUG
	struct function_guard
	{
		function_guard(bool& v): val(v) { TORRENT_ASSERT(!val); val = true; }
		~function_guard() { val = false; }

		bool& val;
	};
#endif

	void connection_queue::on_timeout(asio::error_code const& e)
	{
		mutex_t::scoped_lock l(m_mutex);

		INVARIANT_CHECK;
#ifndef NDEBUG
		function_guard guard_(m_in_timeout_function);
#endif

		TORRENT_ASSERT(!e || e == asio::error::operation_aborted);
		if (e) return;

		ptime next_expire = max_time();
		ptime now = time_now();
		std::list<entry> timed_out;
		for (std::list<entry>::iterator i = m_queue.begin();
			!m_queue.empty() && i != m_queue.end();)
		{
			if (i->connecting && i->expires < now)
			{
				std::list<entry>::iterator j = i;
				++i;
				timed_out.splice(timed_out.end(), m_queue, j, i);
				--m_num_connecting;
				continue;
			}
			if (i->expires < next_expire)
				next_expire = i->expires;
			++i;
		}

		// we don't want to call the timeout callback while we're locked
		// since that is a recepie for dead-locks
		l.unlock();

		for (std::list<entry>::iterator i = timed_out.begin()
			, end(timed_out.end()); i != end; ++i)
		{
			try { i->on_timeout(); } catch (std::exception&) {}
		}

		l.lock();

		if (next_expire < max_time())
		{
			asio::error_code ec;
			m_timer.expires_at(next_expire, ec);
			m_timer.async_wait(boost::bind(&connection_queue::on_timeout, this, _1));
		}
		try_connect();
	}

}

<commit_msg>msvc fix<commit_after>
/*

Copyright (c) 2007, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include <boost/bind.hpp>
#include "libtorrent/invariant_check.hpp"
#include "libtorrent/connection_queue.hpp"

namespace libtorrent
{

	connection_queue::connection_queue(io_service& ios): m_next_ticket(0)
		, m_num_connecting(0)
		, m_half_open_limit(0)
		, m_timer(ios)
#ifndef NDEBUG
		, m_in_timeout_function(false)
#endif
	{
#ifdef TORRENT_CONNECTION_LOGGING
		m_log.open("connection_queue.log");
#endif
	}

	int connection_queue::free_slots() const
	{
		mutex_t::scoped_lock l(m_mutex);
		return m_half_open_limit == 0 ? (std::numeric_limits<int>::max)()
			: m_half_open_limit - m_queue.size();
	}

	void connection_queue::enqueue(boost::function<void(int)> const& on_connect
		, boost::function<void()> const& on_timeout
		, time_duration timeout, int priority)
	{
		mutex_t::scoped_lock l(m_mutex);

		INVARIANT_CHECK;

		TORRENT_ASSERT(priority >= 0);
		TORRENT_ASSERT(priority < 2);

		entry* e = 0;

		switch (priority)
		{
			case 0:
				m_queue.push_back(entry());
				e = &m_queue.back();
				break;
			case 1:
				m_queue.push_front(entry());
				e = &m_queue.front();
				break;
		}

		e->priority = priority;
		e->on_connect = on_connect;
		e->on_timeout = on_timeout;
		e->ticket = m_next_ticket;
		e->timeout = timeout;
		++m_next_ticket;
		try_connect();
	}

	void connection_queue::done(int ticket)
	{
		mutex_t::scoped_lock l(m_mutex);

		INVARIANT_CHECK;

		std::list<entry>::iterator i = std::find_if(m_queue.begin()
			, m_queue.end(), boost::bind(&entry::ticket, _1) == ticket);
		if (i == m_queue.end())
		{
			// this might not be here in case on_timeout calls remove
			return;
		}
		if (i->connecting) --m_num_connecting;
		m_queue.erase(i);
		try_connect();
	}

	void connection_queue::close()
	{
		asio::error_code ec;
		m_timer.cancel(ec);
	}

	void connection_queue::limit(int limit)
	{
		TORRENT_ASSERT(limit >= 0);
		m_half_open_limit = limit;
	}

	int connection_queue::limit() const
	{ return m_half_open_limit; }

#ifndef NDEBUG

	void connection_queue::check_invariant() const
	{
		int num_connecting = 0;
		for (std::list<entry>::const_iterator i = m_queue.begin();
			i != m_queue.end(); ++i)
		{
			if (i->connecting) ++num_connecting;
		}
		TORRENT_ASSERT(num_connecting == m_num_connecting);
	}

#endif

	void connection_queue::try_connect()
	{
		INVARIANT_CHECK;

#ifdef TORRENT_CONNECTION_LOGGING
		m_log << log_time() << " " << free_slots() << std::endl;
#endif

		if (m_num_connecting >= m_half_open_limit
			&& m_half_open_limit > 0) return;

		if (m_queue.empty())
		{
			asio::error_code ec;
			m_timer.cancel(ec);
			return;
		}

		std::list<entry>::iterator i = std::find_if(m_queue.begin()
			, m_queue.end(), boost::bind(&entry::connecting, _1) == false);
		while (i != m_queue.end())
		{
			TORRENT_ASSERT(i->connecting == false);
			ptime expire = time_now() + i->timeout;
			if (m_num_connecting == 0)
			{
				asio::error_code ec;
				m_timer.expires_at(expire, ec);
				m_timer.async_wait(boost::bind(&connection_queue::on_timeout, this, _1));
			}
			i->connecting = true;
			++m_num_connecting;
			i->expires = expire;

			INVARIANT_CHECK;

			entry& ent = *i;
			++i;
#ifndef BOOST_NO_EXCEPTIONS
			try {
#endif
				ent.on_connect(ent.ticket);
#ifndef BOOST_NO_EXCEPTIONS
			} catch (std::exception&) {}
#endif

#ifdef TORRENT_CONNECTION_LOGGING
			m_log << log_time() << " " << free_slots() << std::endl;
#endif

			if (m_num_connecting >= m_half_open_limit
				&& m_half_open_limit > 0) break;
			i = std::find_if(i, m_queue.end(), boost::bind(&entry::connecting, _1) == false);
		}
	}

#ifndef NDEBUG
	struct function_guard
	{
		function_guard(bool& v): val(v) { TORRENT_ASSERT(!val); val = true; }
		~function_guard() { val = false; }

		bool& val;
	};
#endif

	void connection_queue::on_timeout(asio::error_code const& e)
	{
		mutex_t::scoped_lock l(m_mutex);

		INVARIANT_CHECK;
#ifndef NDEBUG
		function_guard guard_(m_in_timeout_function);
#endif

		TORRENT_ASSERT(!e || e == asio::error::operation_aborted);
		if (e) return;

		ptime next_expire = max_time();
		ptime now = time_now();
		std::list<entry> timed_out;
		for (std::list<entry>::iterator i = m_queue.begin();
			!m_queue.empty() && i != m_queue.end();)
		{
			if (i->connecting && i->expires < now)
			{
				std::list<entry>::iterator j = i;
				++i;
				timed_out.splice(timed_out.end(), m_queue, j, i);
				--m_num_connecting;
				continue;
			}
			if (i->expires < next_expire)
				next_expire = i->expires;
			++i;
		}

		// we don't want to call the timeout callback while we're locked
		// since that is a recepie for dead-locks
		l.unlock();

		for (std::list<entry>::iterator i = timed_out.begin()
			, end(timed_out.end()); i != end; ++i)
		{
			try { i->on_timeout(); } catch (std::exception&) {}
		}

		l.lock();

		if (next_expire < max_time())
		{
			asio::error_code ec;
			m_timer.expires_at(next_expire, ec);
			m_timer.async_wait(boost::bind(&connection_queue::on_timeout, this, _1));
		}
		try_connect();
	}

}

<|endoftext|>


<commit_before>///
/// @file ConsoleManager.cpp
///
/// @Copyright (C) 2013 The Imaging Source GmbH; Edgar Thier <edgarthier@gmail.com>
///

#include "ConsoleManager.h"
#include "CameraDiscovery.h"
#include "Camera.h"
#include "utils.h"
#include <algorithm>
#include <unistd.h>
#include <stdlib.h>
#include <limits.h>

#include <thread>
#include <mutex>
#include <exception>

namespace tis
{

std::string getArgumentValue (const std::vector<std::string>& args, const std::string& long_name, const std::string& short_name)
{
    std::string retv;

    auto iter = find_if(args.begin(), args.end(),  [&long_name, &short_name] (std::string s)
                        {
                            if ((startsWith(s, long_name)) || (startsWith(s, short_name)))
                            {
                                return true;
                            }
                            return false;
                        });

    if (iter == args.end())
    {
        return retv;
    }
    if ((*iter).find("=") != std::string::npos)
    {
            std::string s = *iter;
            unsigned pos = s.find("=");

            retv = s.substr(pos+1);
    }
    else if (std::next(iter) != args.end())
    {
        retv = *(std::next(iter));
    }

    return retv;
}

camera_list getCameraList ()
{
    camera_list cameras;
    std::mutex cam_lock;

    std::function<void(std::shared_ptr<Camera>)> f = [&cameras, &cam_lock] (std::shared_ptr<Camera> camera)
    {
        std::lock_guard<std::mutex> mutex_lock(cam_lock);
        cameras.push_back(camera);
    };

    discoverCameras(f);

    return cameras;
}

std::shared_ptr<Camera> findCamera (const std::vector<std::string>& args)
{
    std::shared_ptr<Camera> retv;

    std::string serial = getArgumentValue(args, "--serial", "-s");
    std::string name   = getArgumentValue(args, "--name",   "-n");
    std::string mac    = getArgumentValue(args, "--mac",    "-m");

    if (serial.empty() && name.empty() && mac.empty())
    {
        throw std::invalid_argument("No camera identifier found.");
    }

    camera_list cameras = getCameraList();

    if (cameras.size() == 0)
    {
        std::cout << "\nNo cameras found.\n" << std::endl;
        exit(1);
    }

    if (!serial.empty())
    {
        retv = getCameraFromList(cameras, serial, CAMERA_SERIAL);
    }
    else if (!name.empty())
    {
        retv = getCameraFromList(cameras, name, CAMERA_NAME);
    }
    else
    {
        retv = getCameraFromList(cameras, mac, CAMERA_MAC);
    }

    return retv;
}

void listCameras ()
{
    camera_list cameras = getCameraList();

    if (cameras.size() == 0)
    {
        std::cout << "\nNo cameras found.\n" << std::endl;
        return;
    }

    // header for table
    std::cout << std::endl << std::setw(12) << "Model"
              << std::setw(3)  << " - "
              << std::setw(9)  << "Serial"
              << std::setw(3)  << " - "
              << std::setw(15) << "User Def. Name"
              << std::setw(3)  << " - "
              << std::setw(15) << "Current IP"
              << std::setw(3)  << " - "
              << std::setw(15) << "Current Netmask"
              << std::setw(3)  << " - "
              << std::setw(15) << "Current Gateway"
              << std::endl;

    for (const auto& cam : cameras)
    {
        std::cout << std::setw(12) << cam->getModelName()
                  << std::setw(3)  << " - "
                  << std::setw(9)  << cam->getSerialNumber()
                  << std::setw(3)  << " - "
                  << std::setw(15) << cam->getUserDefinedName()
                  << std::setw(3)  << " - "
                  << std::setw(15) << cam->getCurrentIP()
                  << std::setw(3)  << " - "
                  << std::setw(15) << cam->getCurrentSubnet()
                  << std::setw(3)  << " - "
                  << std::setw(15) << cam->getCurrentGateway()
                  << std::endl;
    }
    std::cout << std::endl;
}

void printCameraInformation (const std::vector<std::string>& args)
{
    auto camera = findCamera(args);

    if (camera == NULL)
    {
        std::cout << "No camera found." << std::endl;
        return;
    }

    bool reachable = false;
    if(!camera->isReachable())
    {
        std::cout << "\n========================================"
                  << "\n>  Camera is currently not reachable!  <"
                  << "\n> To enable full communication set IP  <"
                  << "\n>     configuration via forceip        <"
                  << "\n========================================" << std::endl;
    }
    else
    {
        reachable = true;
    }

    std::cout << "\nModel:    " << camera->getModelName()
              << "\nSerial:   " << camera->getSerialNumber()
              << "\nFirmware: " << camera->getFirmwareVersion()
              << "\nUserName: " << camera->getUserDefinedName()
              << "\n\nMAC Address:        " << camera->getMAC()
              << "\nCurrent IP:         " << camera->getCurrentIP()
              << "\nCurrent Subnet:     " << camera->getCurrentSubnet()
              << "\nCurrent Gateway:    " << camera->getCurrentGateway()
              << "\n\nDHCP is:   " << (camera->isDHCPactive() ? "enabled" : "disabled")
              << "\nStatic is: " << (camera->isStaticIPactive() ? "enabled" : "disabled") << std::endl;

    if (reachable)
    {
        std::cout << "\n\nPersistent IP:      " << camera->getPersistentIP()
                  << "\nPersistent Subnet:  " << camera->getPersistentSubnet()
                  << "\nPersistent Gateway: " << camera->getPersistentGateway() << "\n" <<  std::endl;
    }
}

void writeChanges (std::shared_ptr<Camera> camera, const std::string ip, const std::string subnet, const std::string gateway)
{
    std::cout << "Writing changes...." << std::endl;
    if (!camera->setPersistentIP(ip))
    {
        throw std::runtime_error( "  Unable to set IP address.");
    }

    if (!camera->setPersistentSubnet(subnet))
    {
        throw std::runtime_error( "  Unable to set Subnetmask.");
    }

    if (!camera->setPersistentGateway(gateway))
    {
        throw std::runtime_error("  Unable to set Gateway.");
    }
}

void setCamera (const std::vector<std::string>& args)
{
    auto camera = findCamera(args);

    if (camera == NULL)
    {
        std::cout << "No camera found." << std::endl;
        return;
    }

    bool write_changes = false;

    std::string ip = getArgumentValue(args, "ip", "");
    if (!ip.empty())
    {
        if (!isValidIpAddress(ip))
        {
            std::cout << "Please enter a valid IP address." << std::endl;
            return;
        }
        else
        {
            write_changes = true;
        }
    }
    else
    {
        ip = camera->getPersistentIP();
    }

    std::string subnet = getArgumentValue(args, "subnet", "");
    if (!subnet.empty())
    {
        if (!isValidIpAddress(subnet))
        {
            std::cout << "Please enter a valid subnet address." << std::endl;
            return;
        }
        else
        {
            write_changes = true;
        }
    }
    else
    {
        subnet = camera->getPersistentSubnet();
    }

    std::string gateway = getArgumentValue(args, "gateway", "");
    if (!gateway.empty())
    {
        if (!isValidIpAddress(gateway))
        {
            std::cout << "Please enter a valid gateway address." << std::endl;
            return;
        }
        else
        {
            write_changes = true;
        }
    }
    else
    {
        gateway = camera->getPersistentGateway();
    }

    if (write_changes)
    {
        try
        {
            writeChanges(camera, ip, subnet, gateway);
        }
        catch (std::runtime_error run)
        {
            throw run;
        }
    }

    // if one exists we have to check them both
    if (!getArgumentValue(args, "dhcp", "").empty() || !getArgumentValue(args, "static", "").empty())
    {
        bool dhcp = camera->isDHCPactive();
        bool staticIP = camera->isStaticIPactive();

        std::string d = getArgumentValue(args, "dhcp", "");
        if (d.compare("on") == 0 || d.compare("off") == 0)
        {
            (d.compare("on") == 0) ? dhcp = true : dhcp = false;
        }
        else
        {
            throw std::invalid_argument("Unable to interpret dhcp argument as value: " + d);
        }

        std::string s = getArgumentValue(args, "static", "");
        if (s.compare("on") == 0 || s.compare("off") == 0)
        {
            (s.compare("on") == 0) ? staticIP = true : staticIP = false;
        }
        else
        {
            throw std::invalid_argument("Unable to interpret static ip argument as value: " + s);
        }

        std::cout << "DHCP will be: " << ((dhcp) ? "on" : "off")
                  << "\nStatic IP to: " << ((staticIP) ? "on" : "off")
                  << "\n\nWriting IP configuration...." << std::endl;

        if (camera->setIPconfigState(dhcp, staticIP))
        {
            std::cout << "  Done." << std::endl;
        }
        else
        {
            throw std::runtime_error("  Error while setting IP configuration.");
        }
    }

    auto iter_name = find_if(args.begin(), args.end(), [] (std::string s)
                             {
                                 if (startsWith(s, "name"))
                                 {
                                     return true;
                                 }
                                 return false;
                             });
    // if name exists we have to evaluate to allow the setting of empty names
    if (iter_name != args.end())
    {
        std::string name = getArgumentValue(args, "name", "");
        std::cout << "Setting user defined name to \"" <<  name << "\" ...." << std::endl;
        if (camera->setUserDefinedName(name))
        {
            std::cout << "  Done." << std::endl;
        }
        else
        {
            std::cout << "  Unable to set name." << std::endl;
        }
    }
}

void forceIP (const std::vector<std::string>& args)
{
    std::string ip = getArgumentValue (args, "ip", "");
    if (ip.empty() || !isValidIpAddress(ip))
    {
        std::cout << "Please specifiy a valid IP address." << std::endl;
        return;
    }

    std::string subnet = getArgumentValue (args, "subnet", "");
    if (subnet.empty() || !isValidIpAddress(subnet))
    {
        std::cout << "Please specifiy a valid subnet mask." << std::endl;
        return;
    }

    std::string gateway = getArgumentValue (args, "gateway", "");
    if (gateway.empty() || !isValidIpAddress(gateway))
    {
        std::cout << "Please specifiy a gateway address." << std::endl;
        return;
    }

    auto camera = findCamera(args);

    if (camera == NULL)
    {
        std::cout << "No camera found." << std::endl;
        return;
    }

    std::cout << "\nEnforcing IP Configuration.\n\n"
              << "Serial Number:     " << camera->getSerialNumber()
              << "\nCurrent Settings:"
              << "\n    IP:      " << camera->getCurrentIP()
              << "\n    Subnet:  " << camera->getCurrentSubnet()
              << "\n    Gateway: " << camera->getCurrentGateway()
              << "\n\nDo you really want to enforce the following configuration?\n"
              << "\n    IP:     " << ip
              << "\n    Subnet: " << subnet
              << "\n    Gateway:" << gateway << std::endl;
    std::cout << "\n\nEnforce IP? [y/N] ";

    std::string really;
    std::cin >> really;
    if (really.compare("y") == 0 )
    {
        std::cout << "\nSending forceIP....\n" << std::endl;
        if (camera->forceIP(ip, subnet, gateway))
        {
            std::cout << "  Done." << std::endl;
        }
        else
        {
            std::cout << "  Failed to set address." << std::endl;
        }
    }
    else
    {
        std::cout << "\nAborted forceIP!\n" << std::endl;
    }
}

void upgradeFirmware (const std::vector<std::string>& args)
{
    std::string firmware = getArgumentValue(args, "firmware", "");
    if (firmware.empty())
    {
        std::cout << "Please specify a valid firmware file." << std::endl;
        return;
    }

    char actualpath [PATH_MAX+1];
    std::string cF (realpath(firmware.c_str(), actualpath));

    std::cout << "===========================" << firmware << " - " << cF << std::endl;

    auto camera = findCamera(args);

    if (camera == NULL)
    {
        std::cout << "No camera found." << std::endl;
        return;
    }

    auto func = [] (int progress)
        {
            std::cout << "\r";
            std::string progressSign = "[";

            int i = progress*10 / 100;
            for (int x = 0; x < i; ++x)
            {
                progressSign += "XX";
            }
            for (int x = 0; x < 20 - (i*2); ++x)
            {
                progressSign += " ";
            }

            progressSign += "] ";

            std::cout << progressSign;
            std::cout.flush();
        };

    std::cout << std::endl;
    if (camera->uploadFirmware(cF, func))
    {
        std::cout << "\nSuccessfully uploaded firmware. \
Please reconnect your camera to assure full functionality.\n";
    }
    else
    {
        std::cout << "\nERROR aborted upgrade.\n";
    }
    std::cout << std::endl;
}

void rescue (std::vector<std::string> args)
{
    std::string mac = getArgumentValue(args, "--mac", "-m");
    if (mac.empty())
    {
        std::cout << "Please specify the MAC address to use." << std::endl;
        return;
    }

    std::string ip = getArgumentValue(args, "ip", "");
    if (ip.empty() || !isValidIpAddress(ip))
    {
        std::cout << "Please specify a valid IP address." << std::endl;
        return;
    }

    std::string subnet = getArgumentValue(args, "subnet", "");
    if (subnet.empty() || !isValidIpAddress(subnet))
    {
        std::cout << "Please specify a valid subnet mask." << std::endl;
        return;
    }

    std::string gateway = getArgumentValue (args,"gateway", "");
    if (gateway.empty() || !isValidIpAddress(gateway))
    {
        std::cout << "Please specify a gateway address." << std::endl;
        return;
    }

    try
    {
        sendIpRecovery(mac, ip2int(ip), ip2int(subnet), ip2int(gateway));
    }
    catch (...)
    {
        std::cout << "An Error occured while sending the rescue packet." << std::endl;
    }
}

} /* namespace tis */
<commit_msg>Output formatting & error handling<commit_after>///
/// @file ConsoleManager.cpp
///
/// @Copyright (C) 2013 The Imaging Source GmbH; Edgar Thier <edgarthier@gmail.com>
///

#include "ConsoleManager.h"
#include "CameraDiscovery.h"
#include "Camera.h"
#include "utils.h"
#include <algorithm>
#include <unistd.h>
#include <stdlib.h>
#include <limits.h>

#include <thread>
#include <mutex>
#include <exception>

namespace tis
{

std::string getArgumentValue (const std::vector<std::string>& args, const std::string& long_name, const std::string& short_name)
{
    std::string retv;

    auto iter = find_if(args.begin(), args.end(),  [&long_name, &short_name] (std::string s)
                        {
                            if ((startsWith(s, long_name)) || (startsWith(s, short_name)))
                            {
                                return true;
                            }
                            return false;
                        });

    if (iter == args.end())
    {
        return retv;
    }
    if ((*iter).find("=") != std::string::npos)
    {
            std::string s = *iter;
            unsigned pos = s.find("=");

            retv = s.substr(pos+1);
    }
    else if (std::next(iter) != args.end())
    {
        retv = *(std::next(iter));
    }

    return retv;
}

camera_list getCameraList ()
{
    camera_list cameras;
    std::mutex cam_lock;

    std::function<void(std::shared_ptr<Camera>)> f = [&cameras, &cam_lock] (std::shared_ptr<Camera> camera)
    {
        std::lock_guard<std::mutex> mutex_lock(cam_lock);
        cameras.push_back(camera);
    };

    discoverCameras(f);

    return cameras;
}

std::shared_ptr<Camera> findCamera (const std::vector<std::string>& args)
{
    std::shared_ptr<Camera> retv;

    std::string serial = getArgumentValue(args, "--serial", "-s");
    std::string name   = getArgumentValue(args, "--name",   "-n");
    std::string mac    = getArgumentValue(args, "--mac",    "-m");

    if (serial.empty() && name.empty() && mac.empty())
    {
        throw std::invalid_argument("No camera identifier found.");
    }

    camera_list cameras = getCameraList();

    if (cameras.size() == 0)
    {
        throw std::runtime_error("\nNo cameras found.\n");
    }

    if (!serial.empty())
    {
        retv = getCameraFromList(cameras, serial, CAMERA_SERIAL);
    }
    else if (!name.empty())
    {
        retv = getCameraFromList(cameras, name, CAMERA_NAME);
    }
    else
    {
        retv = getCameraFromList(cameras, mac, CAMERA_MAC);
    }

    return retv;
}

void listCameras ()
{
    camera_list cameras = getCameraList();

    if (cameras.size() == 0)
    {
        std::cout << "\nNo cameras found.\n" << std::endl;
        return;
    }

    // header for table
    std::cout << "\n" << std::setw(12) << "Model"
              << std::setw(3)  << " - "
              << std::setw(9)  << "Serial"
              << std::setw(3)  << " - "
              << std::setw(15) << "User Def. Name"
              << std::setw(3)  << " - "
              << std::setw(15) << "Current IP"
              << std::setw(3)  << " - "
              << std::setw(15) << "Current Netmask"
              << std::setw(3)  << " - "
              << std::setw(15) << "Current Gateway"
              << std::endl;

    for (const auto& cam : cameras)
    {
        std::cout << std::setw(12) << cam->getModelName()
                  << std::setw(3)  << " - "
                  << std::setw(9)  << cam->getSerialNumber()
                  << std::setw(3)  << " - "
                  << std::setw(15) << cam->getUserDefinedName()
                  << std::setw(3)  << " - "
                  << std::setw(15) << cam->getCurrentIP()
                  << std::setw(3)  << " - "
                  << std::setw(15) << cam->getCurrentSubnet()
                  << std::setw(3)  << " - "
                  << std::setw(15) << cam->getCurrentGateway()
                  << std::endl;
    }
    std::cout << std::endl;
}

void printCameraInformation (const std::vector<std::string>& args)
{
    auto camera = findCamera(args);

    if (camera == NULL)
    {
        std::cout << "No camera found." << std::endl;
        return;
    }

    bool reachable = false;
    if(!camera->isReachable())
    {
        std::cout << "\n========================================"
                  << "\n>  Camera is currently not reachable!  <"
                  << "\n> To enable full communication set IP  <"
                  << "\n>     configuration via forceip        <"
                  << "\n========================================" << std::endl;
    }
    else
    {
        reachable = true;
    }

    std::cout << "\nModel:    " << camera->getModelName()
              << "\nSerial:   " << camera->getSerialNumber()
              << "\nFirmware: " << camera->getFirmwareVersion()
              << "\nUserName: " << camera->getUserDefinedName()
              << "\n\nMAC Address:        " << camera->getMAC()
              << "\nCurrent IP:         " << camera->getCurrentIP()
              << "\nCurrent Subnet:     " << camera->getCurrentSubnet()
              << "\nCurrent Gateway:    " << camera->getCurrentGateway()
              << "\n\nDHCP is:   " << (camera->isDHCPactive() ? "enabled" : "disabled")
              << "\nStatic is: " << (camera->isStaticIPactive() ? "enabled" : "disabled") << std::endl;

    if (reachable)
    {
        std::cout << "\n\nPersistent IP:      " << camera->getPersistentIP()
                  << "\nPersistent Subnet:  " << camera->getPersistentSubnet()
                  << "\nPersistent Gateway: " << camera->getPersistentGateway() << "\n" <<  std::endl;
    }
}

void writeChanges (std::shared_ptr<Camera> camera, const std::string ip, const std::string subnet, const std::string gateway)
{
    std::cout << "Writing changes...." << std::endl;
    if (!camera->setPersistentIP(ip))
    {
        throw std::runtime_error( "  Unable to set IP address.");
    }

    if (!camera->setPersistentSubnet(subnet))
    {
        throw std::runtime_error( "  Unable to set Subnetmask.");
    }

    if (!camera->setPersistentGateway(gateway))
    {
        throw std::runtime_error("  Unable to set Gateway.");
    }
}

void setCamera (const std::vector<std::string>& args)
{
    auto camera = findCamera(args);

    if (camera == NULL)
    {
        std::cout << "No camera found." << std::endl;
        return;
    }

    bool write_changes = false;

    std::string ip = getArgumentValue(args, "ip", "");
    if (!ip.empty())
    {
        if (!isValidIpAddress(ip))
        {
            std::cout << "Please enter a valid IP address." << std::endl;
            return;
        }
        else
        {
            write_changes = true;
        }
    }
    else
    {
        ip = camera->getPersistentIP();
    }

    std::string subnet = getArgumentValue(args, "subnet", "");
    if (!subnet.empty())
    {
        if (!isValidIpAddress(subnet))
        {
            std::cout << "Please enter a valid subnet address." << std::endl;
            return;
        }
        else
        {
            write_changes = true;
        }
    }
    else
    {
        subnet = camera->getPersistentSubnet();
    }

    std::string gateway = getArgumentValue(args, "gateway", "");
    if (!gateway.empty())
    {
        if (!isValidIpAddress(gateway))
        {
            std::cout << "Please enter a valid gateway address." << std::endl;
            return;
        }
        else
        {
            write_changes = true;
        }
    }
    else
    {
        gateway = camera->getPersistentGateway();
    }

    if (write_changes)
    {
        try
        {
            writeChanges(camera, ip, subnet, gateway);
        }
        catch (std::runtime_error run)
        {
            throw run;
        }
    }

    // if one exists we have to check them both
    if (!getArgumentValue(args, "dhcp", "").empty() || !getArgumentValue(args, "static", "").empty())
    {
        bool dhcp = camera->isDHCPactive();
        bool staticIP = camera->isStaticIPactive();

        std::string d = getArgumentValue(args, "dhcp", "");
        if (d.compare("on") == 0 || d.compare("off") == 0)
        {
            (d.compare("on") == 0) ? dhcp = true : dhcp = false;
        }
        else
        {
            throw std::invalid_argument("Unable to interpret dhcp argument as value: " + d);
        }

        std::string s = getArgumentValue(args, "static", "");
        if (s.compare("on") == 0 || s.compare("off") == 0)
        {
            (s.compare("on") == 0) ? staticIP = true : staticIP = false;
        }
        else
        {
            throw std::invalid_argument("Unable to interpret static ip argument as value: " + s);
        }

        std::cout << "DHCP will be: " << ((dhcp) ? "on" : "off")
                  << "\nStatic IP to: " << ((staticIP) ? "on" : "off")
                  << "\n\nWriting IP configuration...." << std::endl;

        if (camera->setIPconfigState(dhcp, staticIP))
        {
            std::cout << "  Done." << std::endl;
        }
        else
        {
            throw std::runtime_error("  Error while setting IP configuration.");
        }
    }

    auto iter_name = find_if(args.begin(), args.end(), [] (std::string s)
                             {
                                 if (startsWith(s, "name"))
                                 {
                                     return true;
                                 }
                                 return false;
                             });
    // if name exists we have to evaluate to allow the setting of empty names
    if (iter_name != args.end())
    {
        std::string name = getArgumentValue(args, "name", "");
        std::cout << "Setting user defined name to \"" <<  name << "\" ...." << std::endl;
        if (camera->setUserDefinedName(name))
        {
            std::cout << "  Done." << std::endl;
        }
        else
        {
            throw std::runtime_error("  Unable to set name.");
        }
    }
    std::cout << std::endl;
}

void forceIP (const std::vector<std::string>& args)
{
    std::string ip = getArgumentValue (args, "ip", "");
    if (ip.empty() || !isValidIpAddress(ip))
    {
        std::cout << "Please specifiy a valid IP address." << std::endl;
        return;
    }

    std::string subnet = getArgumentValue (args, "subnet", "");
    if (subnet.empty() || !isValidIpAddress(subnet))
    {
        std::cout << "Please specifiy a valid subnet mask." << std::endl;
        return;
    }

    std::string gateway = getArgumentValue (args, "gateway", "");
    if (gateway.empty() || !isValidIpAddress(gateway))
    {
        std::cout << "Please specifiy a gateway address." << std::endl;
        return;
    }

    auto camera = findCamera(args);

    if (camera == NULL)
    {
        std::cout << "No camera found." << std::endl;
        return;
    }

    std::cout << "\nEnforcing IP Configuration.\n\n"
              << "Serial Number:     " << camera->getSerialNumber()
              << "\nCurrent Settings:"
              << "\n    IP:      " << camera->getCurrentIP()
              << "\n    Subnet:  " << camera->getCurrentSubnet()
              << "\n    Gateway: " << camera->getCurrentGateway()
              << "\n\nDo you really want to enforce the following configuration?\n"
              << "\n    IP:     " << ip
              << "\n    Subnet: " << subnet
              << "\n    Gateway:" << gateway << std::endl;
    std::cout << "\n\nEnforce IP? [y/N] ";

    std::string really;
    std::cin >> really;
    if (really.compare("y") == 0 )
    {
        std::cout << "\nSending forceIP....\n" << std::endl;
        if (camera->forceIP(ip, subnet, gateway))
        {
            std::cout << "  Done." << std::endl;
        }
        else
        {
            std::cout << "  Failed to set address." << std::endl;
        }
    }
    else
    {
        std::cout << "\nAborted forceIP!\n" << std::endl;
    }
}

void upgradeFirmware (const std::vector<std::string>& args)
{
    std::string firmware = getArgumentValue(args, "firmware", "");
    if (firmware.empty())
    {
        std::cout << "Please specify a valid firmware file." << std::endl;
        return;
    }

    char actualpath [PATH_MAX+1];
    std::string cF (realpath(firmware.c_str(), actualpath));

    std::cout << "===========================" << firmware << " - " << cF << std::endl;

    auto camera = findCamera(args);

    if (camera == NULL)
    {
        std::cout << "No camera found." << std::endl;
        return;
    }

    auto func = [] (int progress)
        {
            std::cout << "\r";
            std::string progressSign = "[";

            int i = progress*10 / 100;
            for (int x = 0; x < i; ++x)
            {
                progressSign += "XX";
            }
            for (int x = 0; x < 20 - (i*2); ++x)
            {
                progressSign += " ";
            }

            progressSign += "] ";

            std::cout << progressSign;
            std::cout.flush();
        };

    std::cout << std::endl;
    if (camera->uploadFirmware(cF, func))
    {
        std::cout << "\nSuccessfully uploaded firmware. \
Please reconnect your camera to assure full functionality.\n";
    }
    else
    {
        std::cout << "\nERROR aborted upgrade.\n";
    }
    std::cout << std::endl;
}

void rescue (std::vector<std::string> args)
{
    std::string mac = getArgumentValue(args, "--mac", "-m");
    if (mac.empty())
    {
        std::cout << "Please specify the MAC address to use." << std::endl;
        return;
    }

    std::string ip = getArgumentValue(args, "ip", "");
    if (ip.empty() || !isValidIpAddress(ip))
    {
        std::cout << "Please specify a valid IP address." << std::endl;
        return;
    }

    std::string subnet = getArgumentValue(args, "subnet", "");
    if (subnet.empty() || !isValidIpAddress(subnet))
    {
        std::cout << "Please specify a valid subnet mask." << std::endl;
        return;
    }

    std::string gateway = getArgumentValue (args,"gateway", "");
    if (gateway.empty() || !isValidIpAddress(gateway))
    {
        std::cout << "Please specify a gateway address." << std::endl;
        return;
    }

    try
    {
        sendIpRecovery(mac, ip2int(ip), ip2int(subnet), ip2int(gateway));
    }
    catch (...)
    {
        std::cout << "An Error occured while sending the rescue packet." << std::endl;
    }
}

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