<commit_before>/*
 * Copyright © 2017 AperLambda <aper.entertainment@gmail.com>
 *
 * This file is part of λcommon.
 *
 * Licensed under the MIT license. For more information,
 * see the LICENSE file.
 */

#include "../../include/lambdacommon/system/system.h"
#include "../../include/lambdacommon/string.h"
#include <sstream>

#ifdef LAMBDA_WINDOWS

#  define INFO_BUFFER_SIZE 32767

#include <intrin.h>
#include <ShlObj.h>
#include <VersionHelpers.h>

#else

#include <unistd.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/sysinfo.h>
#include <sys/utsname.h>
#include <pwd.h>
#include <fstream>

#endif

using namespace std;

namespace lambdacommon
{
    namespace system
    {
        std::string osName = "";

#ifdef LAMBDA_WINDOWS

        string LAMBDACOMMON_API getProcessorName()
        {
            int cpuInfo[4] = {-1};
            char cpuBrandStr[0x40];
            __cpuid(cpuInfo, 0x80000000);
            unsigned int nExIds = static_cast<unsigned int>(cpuInfo[0]);

            memset(cpuBrandStr, 0, sizeof(cpuBrandStr));

            // Get the information associated with each extended ID.
            for (unsigned int i = 0x80000000; i <= nExIds; ++i)
            {
                __cpuid(cpuInfo, i);
                // Interpret CPU brand string.
                if (i == 0x80000002)
                    memcpy(cpuBrandStr, cpuInfo, sizeof(cpuInfo));
                else if (i == 0x80000003)
                    memcpy(cpuBrandStr + 16, cpuInfo, sizeof(cpuInfo));
                else if (i == 0x80000004)
                    memcpy(cpuBrandStr + 32, cpuInfo, sizeof(cpuInfo));
            }
            string cpuName{cpuBrandStr};
            return cpuName;
        }

        uint32_t LAMBDACOMMON_API getProcessorCores()
        {
            SYSTEM_INFO sysinfo;
            GetSystemInfo(&sysinfo);
            return sysinfo.dwNumberOfProcessors;
        }

        uint64_t LAMBDACOMMON_API getPhysicalMemory()
        {
            MEMORYSTATUSEX statex;
            statex.dwLength = sizeof(statex);
            GlobalMemoryStatusEx(&statex);
            return statex.ullTotalPhys;
        }

        uint64_t LAMBDACOMMON_API getAvailablePhysicalMemory()
        {
            MEMORYSTATUSEX statex;
            statex.dwLength = sizeof(statex);
            GlobalMemoryStatusEx(&statex);
            return statex.ullAvailPhys;
        }

        uint64_t LAMBDACOMMON_API getUsedPhysicalMemory()
        {
            return getPhysicalMemory() - getAvailablePhysicalMemory();
        }

        string LAMBDACOMMON_API getComputerName()
        {
            char infoBuf[INFO_BUFFER_SIZE];
            DWORD bufCharCount = INFO_BUFFER_SIZE;

            if (!GetComputerName(infoBuf, &bufCharCount))
                return "";

            return string(infoBuf);
        }

        string LAMBDACOMMON_API getOSName()
        {
            // Holy shit, what the fuck is this shitty code?
            // Fuck you Microsoft!
            string winName = "Windows ";

            if (IsWindowsServer())
                winName += "Server ";

            if (IsWindows10OrGreater())
                winName += "10";
            else if (IsWindows8Point1OrGreater())
                winName += "8.1";
            else if (IsWindows8OrGreater())
                winName += "8";
            else if (IsWindows7SP1OrGreater())
                winName += "7 SP1";
            else if (IsWindows7OrGreater())
                winName += "7";
            else if (IsWindowsVistaSP2OrGreater())
                winName += "Vista SP2";
            else if (IsWindowsVistaSP1OrGreater())
                winName += "Vista SP1";
            else if (IsWindowsVistaOrGreater())
                winName += "Vista";
            else if (IsWindowsXPOrGreater())
                winName += "XP";
            return winName;
        }

        string LAMBDACOMMON_API getKernelVersion()
        {
            OSVERSIONINFO vi;
            vi.dwOSVersionInfoSize = sizeof(vi);
            if (GetVersionEx(&vi) == 0) return "UNKNOWN";
            std::ostringstream str;
            str << vi.dwMajorVersion << "." << vi.dwMinorVersion << " (Build " << (vi.dwBuildNumber & 0xFFFF);
            if (vi.szCSDVersion[0]) str << ": " << vi.szCSDVersion;
            str << ")";
            return str.str();
        }

        string LAMBDACOMMON_API getUserName()
        {
            char infoBuf[INFO_BUFFER_SIZE];
            DWORD bufCharCount = INFO_BUFFER_SIZE;

            if (!GetUserName(infoBuf, &bufCharCount))
                return "";

            return string(infoBuf);
        }

        string LAMBDACOMMON_API getUserDirectoryStr()
        {
#  ifdef __MINGW32__
            TCHAR path[MAX_PATH];
            if (FAILED(SHGetFolderPath(NULL, CSIDL_PROFILE, NULL, 0, path)))
                return "";
            return string(path);
#  else // __MINGW32__
            PWSTR szPath;
            if (FAILED(SHGetKnownFolderPath(FOLDERID_Profile, KF_FLAG_NO_ALIAS, NULL, &szPath)))
                return "";
            return string(lambdastring::convertWStringToString(wstring(szPath)));
#  endif // __MINGW32__
        }

#else

        string LAMBDACOMMON_API getProcessorName()
        {
            ifstream cpuinfo;
            cpuinfo.open("/proc/cpuinfo", ios::in);
            string word;
            bool record = false;
            string cpu;
            if (cpuinfo.is_open())
            {
                while (cpuinfo >> word)
                {
                    if (word == "model" && cpuinfo >> word && word == "name" && cpuinfo >> word && cpuinfo >> word)
                    {
                        cpu = word;
                        record = true;
                    }
                    else if (record)
                    {
                        if (word == "stepping")
                            break;
                        else
                            cpu += (" " + word);
                    }
                }
                cpuinfo.close();
            }
            return cpu;
        }

        uint32_t LAMBDACOMMON_API getProcessorCores()
        {
            ifstream cpuinfo;
            cpuinfo.open("/proc/cpuinfo", ios::in);
            string word;
            uint32_t cpucount = 0;
            if (cpuinfo.is_open())
            {
                while (cpuinfo >> word)
                {
                    if (word == "processor")
                        cpucount++;
                }
                cpuinfo.close();
            }
            return cpucount;
        }

        uint64_t LAMBDACOMMON_API getPhysicalMemory()
        {
#  ifdef _SC_PHYS_PAGES
            long pages = sysconf(_SC_PHYS_PAGES);
            long page_size = sysconf(_SC_PAGE_SIZE);
            return static_cast<uint64_t>(pages * page_size);
#  else
            uint64_t mem;
            size_t len = sizeof(mem);
            sysctlbyname("hw.memsize", &mem, &len, NULL, 0);
            return mem / sysconf(_SC_PAGE_SIZE);
#  endif
        }

        uint64_t LAMBDACOMMON_API getAvailablePhysicalMemory()
        {
            struct sysinfo memInfo;

            sysinfo(&memInfo);

            return (memInfo.freeram * memInfo.mem_unit);
        }

        uint64_t LAMBDACOMMON_API getUsedPhysicalMemory()
        {
            struct sysinfo memInfo;

            sysinfo(&memInfo);

            return ((memInfo.totalram - memInfo.freeram) * memInfo.mem_unit);
        }

        string LAMBDACOMMON_API getComputerName()
        {
            char hostname[HOST_NAME_MAX];
            gethostname(hostname, HOST_NAME_MAX);
            return string(hostname);
        }

        string LAMBDACOMMON_API getOSName()
        {
            if (!osName.empty())
                return osName;
            filesystem::FilePath etc_os_release{"/etc/os-release"};
            filesystem::FilePath lsb_release{"/etc/lsb-release"};
            struct utsname uts;
            uname(&uts);
            if (!lsb_release.exists() && !etc_os_release.exists())
                osName = uts.sysname;

            if (lsb_release.exists())
            {
                ifstream lsb_release_in;
                lsb_release_in.open(lsb_release.toString(), ios::in);
                string word;
                bool record = false;
                if (lsb_release_in.is_open())
                {
                    while (lsb_release_in >> word)
                    {
                        if (word.find("DISTRIB_DESCRIPTION") != string::npos)
                        {
                            size_t a = word.find_last_of("N=") + 1;
                            osName = word.substr(a + 1, word.length() - a);
                            record = true;
                        }
                        else if (record)
                            osName += " " + lambdastring::replaceAll(word, "\"", "");
                    }
                    lsb_release_in.close();
                }
            }
            else
            {
                ifstream in;
                in.open(etc_os_release.toString(), ios::in);
                char line[256];
                if (in.is_open())
                {
                    while (in.getline(line, 256))
                    {
                        string line_{line};
                        if (line_.find("PRETTY_NAME=") != string::npos)
                        {
                            size_t equalSign = line_.find_first_of('"');
                            osName = line_.substr(equalSign + 1, line_.length() - equalSign - 2);
                            break;
                        }
                    }
                    in.close();
                }
            }

            if (string(uts.release).find("Microsoft") != string::npos)
                osName += " on Windows";
            return osName;
        }

        string LAMBDACOMMON_API getKernelVersion()
        {
            struct utsname uts;
            uname(&uts);
            return uts.release;
        }

        string LAMBDACOMMON_API getUserName()
        {
            struct passwd *userInfo;
            userInfo = getpwuid(getuid());
            return userInfo->pw_name;
        }

        string LAMBDACOMMON_API getUserDirectoryStr()
        {
            struct passwd *userInfo;
            userInfo = getpwuid(getuid());
            return userInfo->pw_dir;
        }

#endif

        filesystem::FilePath LAMBDACOMMON_API getUserDirectory()
        {
            return {getUserDirectoryStr()};
        }
    }
}

#ifdef LAMBDA_WINDOWS
#  undef INFO_BUFFER_SIZE
#endif<commit_msg>MinGW fix<commit_after>/*
 * Copyright © 2017 AperLambda <aper.entertainment@gmail.com>
 *
 * This file is part of λcommon.
 *
 * Licensed under the MIT license. For more information,
 * see the LICENSE file.
 */

#include "../../include/lambdacommon/system/system.h"
#include "../../include/lambdacommon/string.h"
#include <sstream>

#ifdef LAMBDA_WINDOWS

#  define INFO_BUFFER_SIZE 32767

#include <intrin.h>
#include <ShlObj.h>
#  ifndef __MINGW32__
#    include <VersionHelpers.h>
#  endif

#else

#include <unistd.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/sysinfo.h>
#include <sys/utsname.h>
#include <pwd.h>
#include <fstream>

#endif

using namespace std;

namespace lambdacommon
{
    namespace system
    {
        std::string osName = "";

#ifdef LAMBDA_WINDOWS

        string LAMBDACOMMON_API getProcessorName()
        {
            int cpuInfo[4] = {-1};
            char cpuBrandStr[0x40];
            __cpuid(cpuInfo, 0x80000000);
            unsigned int nExIds = static_cast<unsigned int>(cpuInfo[0]);

            memset(cpuBrandStr, 0, sizeof(cpuBrandStr));

            // Get the information associated with each extended ID.
            for (unsigned int i = 0x80000000; i <= nExIds; ++i)
            {
                __cpuid(cpuInfo, i);
                // Interpret CPU brand string.
                if (i == 0x80000002)
                    memcpy(cpuBrandStr, cpuInfo, sizeof(cpuInfo));
                else if (i == 0x80000003)
                    memcpy(cpuBrandStr + 16, cpuInfo, sizeof(cpuInfo));
                else if (i == 0x80000004)
                    memcpy(cpuBrandStr + 32, cpuInfo, sizeof(cpuInfo));
            }
            string cpuName{cpuBrandStr};
            return cpuName;
        }

        uint32_t LAMBDACOMMON_API getProcessorCores()
        {
            SYSTEM_INFO sysinfo;
            GetSystemInfo(&sysinfo);
            return sysinfo.dwNumberOfProcessors;
        }

        uint64_t LAMBDACOMMON_API getPhysicalMemory()
        {
            MEMORYSTATUSEX statex;
            statex.dwLength = sizeof(statex);
            GlobalMemoryStatusEx(&statex);
            return statex.ullTotalPhys;
        }

        uint64_t LAMBDACOMMON_API getAvailablePhysicalMemory()
        {
            MEMORYSTATUSEX statex;
            statex.dwLength = sizeof(statex);
            GlobalMemoryStatusEx(&statex);
            return statex.ullAvailPhys;
        }

        uint64_t LAMBDACOMMON_API getUsedPhysicalMemory()
        {
            return getPhysicalMemory() - getAvailablePhysicalMemory();
        }

        string LAMBDACOMMON_API getComputerName()
        {
            char infoBuf[INFO_BUFFER_SIZE];
            DWORD bufCharCount = INFO_BUFFER_SIZE;

            if (!GetComputerName(infoBuf, &bufCharCount))
                return "";

            return string(infoBuf);
        }

        string LAMBDACOMMON_API getOSName()
        {
#  ifdef __MINGW32__
            return "MinGW ¯\\_(ツ)_/¯";
#  elif defined(LAMBDA_CYGWIN)
            return "CYGWIN";
#  else
            // Holy shit, what the fuck is this shitty code?
            // Fuck you Microsoft!
            string winName = "Windows ";

            if (IsWindowsServer())
                winName += "Server ";

            if (IsWindows10OrGreater())
                winName += "10";
            else if (IsWindows8Point1OrGreater())
                winName += "8.1";
            else if (IsWindows8OrGreater())
                winName += "8";
            else if (IsWindows7SP1OrGreater())
                winName += "7 SP1";
            else if (IsWindows7OrGreater())
                winName += "7";
            else if (IsWindowsVistaSP2OrGreater())
                winName += "Vista SP2";
            else if (IsWindowsVistaSP1OrGreater())
                winName += "Vista SP1";
            else if (IsWindowsVistaOrGreater())
                winName += "Vista";
            else if (IsWindowsXPOrGreater())
                winName += "XP";
            return winName;
#  endif
        }

        string LAMBDACOMMON_API getKernelVersion()
        {
            OSVERSIONINFO vi;
            vi.dwOSVersionInfoSize = sizeof(vi);
            if (GetVersionEx(&vi) == 0) return "UNKNOWN";
            std::ostringstream str;
            str << vi.dwMajorVersion << "." << vi.dwMinorVersion << " (Build " << (vi.dwBuildNumber & 0xFFFF);
            if (vi.szCSDVersion[0]) str << ": " << vi.szCSDVersion;
            str << ")";
            return str.str();
        }

        string LAMBDACOMMON_API getUserName()
        {
            char infoBuf[INFO_BUFFER_SIZE];
            DWORD bufCharCount = INFO_BUFFER_SIZE;

            if (!GetUserName(infoBuf, &bufCharCount))
                return "";

            return string(infoBuf);
        }

        string LAMBDACOMMON_API getUserDirectoryStr()
        {
#  ifdef __MINGW32__
            TCHAR path[MAX_PATH];
            if (FAILED(SHGetFolderPath(NULL, CSIDL_PROFILE, NULL, 0, path)))
                return "";
            return string(path);
#  else // __MINGW32__
            PWSTR szPath;
            if (FAILED(SHGetKnownFolderPath(FOLDERID_Profile, KF_FLAG_NO_ALIAS, NULL, &szPath)))
                return "";
            return string(lambdastring::convertWStringToString(wstring(szPath)));
#  endif // __MINGW32__
        }

#else

        string LAMBDACOMMON_API getProcessorName()
        {
            ifstream cpuinfo;
            cpuinfo.open("/proc/cpuinfo", ios::in);
            string word;
            bool record = false;
            string cpu;
            if (cpuinfo.is_open())
            {
                while (cpuinfo >> word)
                {
                    if (word == "model" && cpuinfo >> word && word == "name" && cpuinfo >> word && cpuinfo >> word)
                    {
                        cpu = word;
                        record = true;
                    }
                    else if (record)
                    {
                        if (word == "stepping")
                            break;
                        else
                            cpu += (" " + word);
                    }
                }
                cpuinfo.close();
            }
            return cpu;
        }

        uint32_t LAMBDACOMMON_API getProcessorCores()
        {
            ifstream cpuinfo;
            cpuinfo.open("/proc/cpuinfo", ios::in);
            string word;
            uint32_t cpucount = 0;
            if (cpuinfo.is_open())
            {
                while (cpuinfo >> word)
                {
                    if (word == "processor")
                        cpucount++;
                }
                cpuinfo.close();
            }
            return cpucount;
        }

        uint64_t LAMBDACOMMON_API getPhysicalMemory()
        {
#  ifdef _SC_PHYS_PAGES
            long pages = sysconf(_SC_PHYS_PAGES);
            long page_size = sysconf(_SC_PAGE_SIZE);
            return static_cast<uint64_t>(pages * page_size);
#  else
            uint64_t mem;
            size_t len = sizeof(mem);
            sysctlbyname("hw.memsize", &mem, &len, NULL, 0);
            return mem / sysconf(_SC_PAGE_SIZE);
#  endif
        }

        uint64_t LAMBDACOMMON_API getAvailablePhysicalMemory()
        {
            struct sysinfo memInfo;

            sysinfo(&memInfo);

            return (memInfo.freeram * memInfo.mem_unit);
        }

        uint64_t LAMBDACOMMON_API getUsedPhysicalMemory()
        {
            struct sysinfo memInfo;

            sysinfo(&memInfo);

            return ((memInfo.totalram - memInfo.freeram) * memInfo.mem_unit);
        }

        string LAMBDACOMMON_API getComputerName()
        {
            char hostname[HOST_NAME_MAX];
            gethostname(hostname, HOST_NAME_MAX);
            return string(hostname);
        }

        string LAMBDACOMMON_API getOSName()
        {
            if (!osName.empty())
                return osName;
            filesystem::FilePath etc_os_release{"/etc/os-release"};
            filesystem::FilePath lsb_release{"/etc/lsb-release"};
            struct utsname uts;
            uname(&uts);
            if (!lsb_release.exists() && !etc_os_release.exists())
                osName = uts.sysname;

            if (lsb_release.exists())
            {
                ifstream lsb_release_in;
                lsb_release_in.open(lsb_release.toString(), ios::in);
                string word;
                bool record = false;
                if (lsb_release_in.is_open())
                {
                    while (lsb_release_in >> word)
                    {
                        if (word.find("DISTRIB_DESCRIPTION") != string::npos)
                        {
                            size_t a = word.find_last_of("N=") + 1;
                            osName = word.substr(a + 1, word.length() - a);
                            record = true;
                        }
                        else if (record)
                            osName += " " + lambdastring::replaceAll(word, "\"", "");
                    }
                    lsb_release_in.close();
                }
            }
            else
            {
                ifstream in;
                in.open(etc_os_release.toString(), ios::in);
                char line[256];
                if (in.is_open())
                {
                    while (in.getline(line, 256))
                    {
                        string line_{line};
                        if (line_.find("PRETTY_NAME=") != string::npos)
                        {
                            size_t equalSign = line_.find_first_of('"');
                            osName = line_.substr(equalSign + 1, line_.length() - equalSign - 2);
                            break;
                        }
                    }
                    in.close();
                }
            }

            if (string(uts.release).find("Microsoft") != string::npos)
                osName += " on Windows";
            return osName;
        }

        string LAMBDACOMMON_API getKernelVersion()
        {
            struct utsname uts;
            uname(&uts);
            return uts.release;
        }

        string LAMBDACOMMON_API getUserName()
        {
            struct passwd *userInfo;
            userInfo = getpwuid(getuid());
            return userInfo->pw_name;
        }

        string LAMBDACOMMON_API getUserDirectoryStr()
        {
            struct passwd *userInfo;
            userInfo = getpwuid(getuid());
            return userInfo->pw_dir;
        }

#endif

        filesystem::FilePath LAMBDACOMMON_API getUserDirectory()
        {
            return {getUserDirectoryStr()};
        }
    }
}

#ifdef LAMBDA_WINDOWS
#  undef INFO_BUFFER_SIZE
#endif<|endoftext|>


<commit_before>//---------------------------------------------------------- -*- Mode: C++ -*-
// $Id$
//
// Created 2006/10/28
// Author: Sriram Rao
//
// Copyright 2008 Quantcast Corp.
// Copyright 2006-2008 Kosmix Corp.
//
// This file is part of Kosmos File System (KFS).
//
// Licensed under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.
//
// \brief Tool for listing directory contents (ala ls -l).
//
//----------------------------------------------------------------------------

#include <iostream>
#include <fstream>
#include <cerrno>

extern "C" {
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
}

#include "libkfsClient/KfsClient.h"
#include "tools/KfsShell.h"

using std::cout;
using std::endl;
using std::ofstream;
using std::vector;

using namespace KFS;

static int dirList(string kfsdirname, bool longMode, bool humanReadable);
static int doDirList(string kfsdirname);
static int doDirListPlusAttr(string kfsdirname, bool humanReadable);
static void printFileInfo(const string &filename, time_t mtime, off_t filesize, bool humanReadable);
static void getTimeString(time_t time, char *buf, int bufLen = 256);

// may want to do "ls -r"
int
KFS::tools::handleLs(const vector<string> &args)
{
    bool longMode = false, humanReadable = false;
    vector<string>::size_type pathIndex = 0;

    if ((args.size() >= 1) && (args[0] == "--help")) {
        cout << "Usage: ls {-lh} {<dir>} " << endl;
        return 0;
    }

    if (args.size() >= 1) {
        if (args[0][0] == '-') {
            pathIndex = 1;
            for (uint32_t i = 1; i < args[0].size(); i++) {
                switch (args[0][i]) {
                    case 'l':
                        longMode = true;
                        break;
                    case 'h':
                        humanReadable = true;
                        break;
                }
            }
        }
    }

    if (args.size() > pathIndex)
        return dirList(args[pathIndex], longMode, humanReadable);
    else
        return dirList(".", longMode, humanReadable);
}

int
dirList(string kfsdirname, bool longMode, bool humanReadable)
{
    if (longMode)
        return doDirListPlusAttr(kfsdirname, humanReadable);
    else
        return doDirList(kfsdirname);
}

int
doDirList(string kfsdirname)
{
    string kfssubdir, subdir;
    int res;
    vector<string> entries;
    vector<string>::size_type i;

    KfsClientPtr kfsClient = getKfsClientFactory()->GetClient();

    if (kfsClient->IsFile((char *) kfsdirname.c_str())) {
        cout << kfsdirname << endl;
        return 0;
    }

    if ((res = kfsClient->Readdir((char *) kfsdirname.c_str(), entries)) < 0) {
        cout << "Readdir failed: " << ErrorCodeToStr(res) << endl;
        return res;
    }

    // we could provide info of whether the thing is a dir...but, later
    for (i = 0; i < entries.size(); ++i) {
        if ((entries[i] == ".") || (entries[i] == ".."))
            continue;
        cout << entries[i] << endl;
    }
    return 0;
}

int
doDirListPlusAttr(string kfsdirname, bool humanReadable)
{
    string kfssubdir, subdir;
    int res;
    vector<KfsFileAttr> fileInfo;
    vector<KfsFileAttr>::size_type i;

    KfsClientPtr kfsClient = getKfsClientFactory()->GetClient();

    if (kfsClient->IsFile((char *) kfsdirname.c_str())) {
        struct stat statInfo;

        kfsClient->Stat(kfsdirname.c_str(), statInfo);
        printFileInfo(kfsdirname, statInfo.st_mtime, statInfo.st_size, humanReadable);
        return 0;
    }
    if ((res = kfsClient->ReaddirPlus((char *) kfsdirname.c_str(), fileInfo)) < 0) {
        cout << "Readdir plus failed: " << ErrorCodeToStr(res) << endl;
        return res;
    }

    for (i = 0; i < fileInfo.size(); ++i) {
        if (fileInfo[i].isDirectory) {
            if ((fileInfo[i].filename == ".") ||
                (fileInfo[i].filename == ".."))
                continue;
            char timeBuf[256];

            getTimeString(fileInfo[i].mtime.tv_sec, timeBuf);

            cout << fileInfo[i].filename << "/" << '\t' << timeBuf << '\t' << "(dir)" << endl;
        } else {
            printFileInfo(fileInfo[i].filename, fileInfo[i].mtime.tv_sec,
                          fileInfo[i].fileSize, humanReadable);
        }
    }
    return 0;
}

void
printFileInfo(const string &filename, time_t mtime, off_t filesize, bool humanReadable)
{
    char timeBuf[256];

    getTimeString(mtime, timeBuf);

    if (!humanReadable) {
        cout << filename << '\t' << timeBuf << '\t' << filesize << endl;
        return;
    }
    if (filesize < (1 << 20)) {
        cout << filename << '\t' << timeBuf << '\t' << (float) (filesize) / (1 << 10) << " K";
    }
    else if (filesize < (1 << 30)) {
        cout << filename << '\t' << timeBuf << '\t' << (float) (filesize) / (1 << 20) << " M";
    }
    else {
        cout << filename << '\t' << timeBuf << '\t' << (float) (filesize) / (1 << 30) << " G";
    }
    cout << endl;
}

void
getTimeString(time_t time, char *buf, int bufLen)
{
    struct tm locTime;

    localtime_r(&time, &locTime);
    strftime(buf, bufLen, "%b %e %H:%M", &locTime);
}
<commit_msg> -- Add a "-t" option to ls to print out the epoch for the file modification  time.<commit_after>//---------------------------------------------------------- -*- Mode: C++ -*-
// $Id$
//
// Created 2006/10/28
// Author: Sriram Rao
//
// Copyright 2008 Quantcast Corp.
// Copyright 2006-2008 Kosmix Corp.
//
// This file is part of Kosmos File System (KFS).
//
// Licensed under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.
//
// \brief Tool for listing directory contents (ala ls -l).
//
//----------------------------------------------------------------------------

#include <iostream>
#include <fstream>
#include <cerrno>
#include <ostream>

extern "C" {
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
}

#include "libkfsClient/KfsClient.h"
#include "tools/KfsShell.h"

using std::cout;
using std::endl;
using std::ofstream;
using std::ostringstream;
using std::vector;

using namespace KFS;

static int dirList(string kfsdirname, bool longMode, bool humanReadable, bool timeInSecs);
static int doDirList(string kfsdirname);
static int doDirListPlusAttr(string kfsdirname, bool humanReadable, bool timeInSecs);
static void printFileInfo(const string &filename, time_t mtime, off_t filesize, bool humanReadable, bool timeInSecs);
static void getTimeString(time_t time, char *buf, int bufLen = 256);

// may want to do "ls -r"
int
KFS::tools::handleLs(const vector<string> &args)
{
    bool longMode = false, humanReadable = false, timeInSecs = false;
    vector<string>::size_type pathIndex = 0;

    if ((args.size() >= 1) && (args[0] == "--help")) {
        cout << "Usage: ls {-lht} {<dir>} " << endl;
        return 0;
    }

    if (args.size() >= 1) {
        if (args[0][0] == '-') {
            pathIndex = 1;
            for (uint32_t i = 1; i < args[0].size(); i++) {
                switch (args[0][i]) {
                    case 'l':
                        longMode = true;
                        break;
                    case 'h':
                        humanReadable = true;
                        break;
                    case 't':
                        timeInSecs = true;
                        break;
                }
            }
        }
    }

    if (args.size() > pathIndex)
        return dirList(args[pathIndex], longMode, humanReadable, timeInSecs);
    else
        return dirList(".", longMode, humanReadable, timeInSecs);
}

int
dirList(string kfsdirname, bool longMode, bool humanReadable, bool timeInSecs)
{
    if (longMode)
        return doDirListPlusAttr(kfsdirname, humanReadable, timeInSecs);
    else
        return doDirList(kfsdirname);
}

int
doDirList(string kfsdirname)
{
    string kfssubdir, subdir;
    int res;
    vector<string> entries;
    vector<string>::size_type i;

    KfsClientPtr kfsClient = getKfsClientFactory()->GetClient();

    if (kfsClient->IsFile((char *) kfsdirname.c_str())) {
        cout << kfsdirname << endl;
        return 0;
    }

    if ((res = kfsClient->Readdir((char *) kfsdirname.c_str(), entries)) < 0) {
        cout << "Readdir failed: " << ErrorCodeToStr(res) << endl;
        return res;
    }

    // we could provide info of whether the thing is a dir...but, later
    for (i = 0; i < entries.size(); ++i) {
        if ((entries[i] == ".") || (entries[i] == ".."))
            continue;
        cout << entries[i] << endl;
    }
    return 0;
}

int
doDirListPlusAttr(string kfsdirname, bool humanReadable, bool timeInSecs)
{
    string kfssubdir, subdir;
    int res;
    vector<KfsFileAttr> fileInfo;
    vector<KfsFileAttr>::size_type i;

    KfsClientPtr kfsClient = getKfsClientFactory()->GetClient();

    if (kfsClient->IsFile((char *) kfsdirname.c_str())) {
        struct stat statInfo;

        kfsClient->Stat(kfsdirname.c_str(), statInfo);
        printFileInfo(kfsdirname, statInfo.st_mtime, statInfo.st_size, humanReadable, timeInSecs);
        return 0;
    }
    if ((res = kfsClient->ReaddirPlus((char *) kfsdirname.c_str(), fileInfo)) < 0) {
        cout << "Readdir plus failed: " << ErrorCodeToStr(res) << endl;
        return res;
    }

    for (i = 0; i < fileInfo.size(); ++i) {
        if (fileInfo[i].isDirectory) {
            if ((fileInfo[i].filename == ".") ||
                (fileInfo[i].filename == ".."))
                continue;
            char timeBuf[256];

            getTimeString(fileInfo[i].mtime.tv_sec, timeBuf);

            cout << fileInfo[i].filename << "/" << '\t' << timeBuf << '\t' << "(dir)" << endl;
        } else {
            printFileInfo(fileInfo[i].filename, fileInfo[i].mtime.tv_sec,
                          fileInfo[i].fileSize, humanReadable, timeInSecs);
        }
    }
    return 0;
}

void
printFileInfo(const string &filename, time_t mtime, off_t filesize, bool humanReadable, bool timeInSecs)
{
    char timeBuf[256];

    if (timeInSecs) {
        ostringstream ost;

        ost << mtime;
        strncpy(timeBuf, ost.str().c_str(), 256);
        timeBuf[255] = '\0';
    }
    else
        getTimeString(mtime, timeBuf);

    if (!humanReadable) {
        cout << filename << '\t' << timeBuf << '\t' << filesize << endl;
        return;
    }
    if (filesize < (1 << 20)) {
        cout << filename << '\t' << timeBuf << '\t' << (float) (filesize) / (1 << 10) << " K";
    }
    else if (filesize < (1 << 30)) {
        cout << filename << '\t' << timeBuf << '\t' << (float) (filesize) / (1 << 20) << " M";
    }
    else {
        cout << filename << '\t' << timeBuf << '\t' << (float) (filesize) / (1 << 30) << " G";
    }
    cout << endl;
}

void
getTimeString(time_t time, char *buf, int bufLen)
{
    struct tm locTime;

    localtime_r(&time, &locTime);
    strftime(buf, bufLen, "%b %e %H:%M", &locTime);
}
<|endoftext|>


<commit_before>#include <iostream>
#include <fstream>
#include <cstdlib>
#include <cstdio>

using namespace std;

string without_end_after_slash(const string& str)
{
	int i=str.size();
	while(--i>=0 && str[i]!='/');
	if(i>=0 && str[i]=='/') return string(str, 0, i+1);
return str;
}

void change(string name)
{
	char tmp_file_name[]="/tmp/chmod_default.XXXXXX";
	mkstemp(tmp_file_name);
	system(("chmod 0755 "+name+" && ls -p -1 "+name+string(" > ")+tmp_file_name).c_str());
	cout << name << endl;
	fstream tmp_file(tmp_file_name, ios_base::in);
	if(tmp_file.good())
	{
		string new_name;
		while(!tmp_file.eof())
		{
			getline(tmp_file, new_name);
			if(new_name.empty()) continue;
			if(*--new_name.end()=='/')
			{
				system(("chmod 0755 "+name+new_name).c_str());
				change(name+new_name);
			}
			else
				system(("chmod 0644 "+name+new_name).c_str());
			cout << name+" : "+new_name+";" << endl;
		}
		tmp_file.close();
		remove(tmp_file_name);
	}
}

int main(int argc, char const **argv)
{
	ios_base::sync_with_stdio(false);
	if(argc<2) cout << "Usage: <files...>" << endl;
	for(int i=1; i<argc; ++i)
		change(argv[i]);
return 0;
}<commit_msg>Upgrade chmod-default.cpp<commit_after>#include <string>
#include <cstdio>
#include <sys/stat.h> // chmod()
#include <dirent.h>
#include <cstring>

using namespace std;

//         file -> 0644     dir -> 0755
const int file_mod = 420, dir_mod = 493;

void def_chmod_r(const char* path, bool show_info = false)
{
	DIR* directory;
	dirent* current_file;
	string tmp_dir_path = path;
	if(*tmp_dir_path.rbegin() != '/') tmp_dir_path += '/';
	if((directory = opendir(path)))
	{
		while((current_file = readdir(directory)))
			if(strcmp(current_file->d_name, ".") && strcmp(current_file->d_name, ".."))
					def_chmod_r((tmp_dir_path+current_file->d_name).c_str(), show_info);
		if(show_info)
			printf("chmod 0755 -> %s\n", path);
		chmod(path, dir_mod);
	}
	else
	{
		if(show_info)
			printf("chmod 0644 -> %s\n", path);
		chmod(path, file_mod);
	}
}

int main(int argc, char const **argv)
{
	if(argc < 2)
		printf("Usage: chmod-default [option] <files...>\nOptions:\n  --show-info - enable printing info about changed files\n  --no-show-info - disable --show-info\n");
	bool show_info = false;
	for(int i = 1; i < argc; ++i)
	{
		if(0 == strcmp(argv[i], "--show-info"))
			show_info = true;
		else if(0 == strcmp(argv[i], "--no-show-info"))
			show_info = true;
		else
			def_chmod_r(argv[i], show_info);
	}
return 0;
}<|endoftext|>


<commit_before>#include <string>
#include <string.h>
#include <cstring>
#include <vector>
#include <sys/types.h>
#include <dirent.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <iostream>
#include <cstring>
#include <string.h>
using namespace std;

bool rflag = false;

void print ( char ** argv )
{
        if( argv == NULL )
        {
                return;
        }
        for (unsigned i = 0; argv[i] != '\0'; ++i )
        {
                printf( argv[i]);
                cout << " ";
        }
        cout << endl;
}

void flags (int argc, char *const* argv)
{
        int c;
        opterr = 0;

        while( (c = getopt (argc, argv, "r")) != -1 )
        {
                switch (c)
                {
                        case 'r':
                                rflag = true;
                                break;
                        case '?':
                                if (isprint (optopt))
                                  fprintf (stderr, "rm: invalid option -- '%c'.\nTry 'r'\n", optopt);
                                else
                                  fprintf (stderr,
                                           "Unknown option character `\\x%x'.\n", optopt);
                        default:
                                abort ();
                }

	}
}

//bool is_dir(char *par_dir ,const char* pathname)
bool is_dir(const char* pathname)
{
	/*
        string p = static_cast<string>(par_dir)
        + "/" + static_cast<string>(pathname);
        char* p2 = const_cast<char*>(p.c_str());
	*/
        struct stat info;
        if( stat( pathname, &info ) != 0 )
        {
            	printf( "cannot access %s\n", pathname );
                perror("stat");
                exit(1);
        }
        else if( info.st_mode & S_IFDIR )
        {
            //printf( "%s is a directory\n", pathname );
            return true;
            exit(1);
        }
        //cout << pathname << " is not a directory." << endl;
        return false;
}

bool is_file(const char* pathname)
{
        struct stat info;
        if( stat( pathname, &info ) != 0 )
        {
            printf( "ls: cannot access %s -- ", pathname );
                perror("stat");
                return false;

        }
        else if( info.st_mode & S_IFREG )
        {
                return true;
        }
        return false;
}

void check( char ** argv )
{
	for(unsigned i = 1; argv[i] != NULL ; ++i)
	{
		if( argv[i][0] == '-')
		{
			continue;
		}
		//will also give error if invalid pathname
		if( !rflag && is_dir( argv[i] ) )
		{
			cerr << "error: r flag not passed in, but have directory as argument\n";
			exit(1);
		}

		if(!is_dir(argv[i]) )
		{
			if( unlink(argv[i] ) == -1)
			{
				perror("unlink"); //printf("\n unlink() failed - [%s]\n",strerror(errno));
			}
			else continue;
		}
		else{ //if( is_dir(argv[i])) {
			if(rmdir(argv[i]) == -1)
			{
				perror("rmdir");
			}
		}

	}
}

int main( int argc, char ** argv)
{

	if(argc == 1)
	{
		cerr << "error: invalied number of arguments.\n";
		exit(1);
	}
	flags(argc, argv);
	check( argv );
	//print(argv);

	return 0;
}
<commit_msg>recursive remove dir<commit_after>#include <string>
#include <cstring>
#include <vector>
#include <sys/types.h>
#include <dirent.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <iostream>
#include <cstring>
#include <string.h>
using namespace std;

bool rflag = false;

void print ( char ** argv )
{
        if( argv == NULL )
        {
                return;
        }
        for (unsigned i = 0; argv[i] != '\0'; ++i )
        {
                printf( argv[i]);
                cout << " ";
        }
        cout << endl;
}

void flags (int argc, char *const* argv)
{
        int c;
        opterr = 0;

        while( (c = getopt (argc, argv, "r")) != -1 )
        {
                switch (c)
                {
                        case 'r':
                                rflag = true;
                                break;
                        case '?':
                                if (isprint (optopt))
                                  fprintf (stderr, "rm: invalid option -- '%c'.\nTry 'r'\n", optopt);
                                else
                                  fprintf (stderr,
                                           "Unknown option character `\\x%x'.\n", optopt);
                        default:
                                abort ();
                }

	}
}

//bool is_dir(char *par_dir ,const char* pathname)
bool is_dir(const char* pathname)
{
	/*
        string p = static_cast<string>(par_dir)
        + "/" + static_cast<string>(pathname);
        char* p2 = const_cast<char*>(p.c_str());
	*/
        struct stat info;
        if( stat( pathname, &info ) != 0 )
        {
            	printf( "cannot access %s\n", pathname );
                perror("stat");
                exit(1);
        }
        else if( info.st_mode & S_IFDIR )
        {
            //printf( "%s is a directory\n", pathname );
            return true;
            exit(1);
        }
        //cout << pathname << " is not a directory." << endl;
        return false;
}

bool is_file(const char* pathname)
{
        struct stat info;
        if( stat( pathname, &info ) != 0 )
        {
            printf( "ls: cannot access %s -- ", pathname );
                perror("stat");
                return false;

        }
        else if( info.st_mode & S_IFREG )
        {
                return true;
        }
        return false;
}

void removeDir(string dirname) {

	DIR * dp;
	struct dirent *dt;
	struct stat statbuf;
	int status = 0;

	vector<string> filename;

	if ((dp = opendir(dirname.c_str())) == NULL) {
		perror("opendir");
		return;
	}

	while ((dt = readdir(dp)) != NULL) {
		if (dt->d_name[0] == '.')
			continue;
		string tmp = dirname + "/" + dt->d_name;
		//cerr << "tmp: " << tmp << endl;
		filename.push_back(tmp);
	}

	closedir(dp);

	if ((dp=opendir(dirname.c_str()))== NULL) {
		perror("opendir");
		return;
	}

	while ((dt = readdir(dp))) if (strncmp(dt->d_name, ".", 1)) {
		if (dt->d_type == 4) {
			string dirPath = dirname + "/" + dt->d_name;
			removeDir(dirPath);
		}
	}

	for (int i = 0; i < filename.size(); i++) {
		if (!is_dir(filename[i].c_str())) {
			//cerr << "file name: " << filename[i] << endl;
			if (unlink(filename[i].c_str()) == -1)
				perror("unlink");
		}

		else{
			//cerr << "dir name: " << filename[i] << endl;
			if (rmdir(filename[i].c_str()) == -1)
				perror("rmdir");
		}
	}

	closedir(dp);

}

void check( char ** argv )
{
	for(unsigned i = 1; argv[i] != NULL ; ++i)
	{
		if( argv[i][0] == '-')
		{
			continue;
		}
		//will also give error if invalid pathname
		if( !rflag && is_dir( argv[i] ) )
		{
			cerr << "error: r flag not passed in, but have directory as argument\n";
			exit(1);
		}

		if(!is_dir(argv[i]) )
		{
			if( unlink(argv[i] ) == -1)
			{
				perror("unlink"); //printf("\n unlink() failed - [%s]\n",strerror(errno));
			}
			else continue;
		}
		else{ //if( is_dir(argv[i])) {
	   		removeDir(argv[i]);
			rmdir(argv[i]);
		}

	}
}

int main( int argc, char ** argv)
{

	if(argc == 1)
	{
		cerr << "error: invalied number of arguments.\n";
		exit(1);
	}
	flags(argc, argv);
	check( argv );
	//print(argv);

	return 0;
}
<|endoftext|>


<commit_before>#include "array.hpp"
#include "string.hpp"
#include "fixnum.hpp"
#include "range.hpp"
#include "../runtime.hpp"

namespace Mirb
{
	value_t Array::allocate(Class *instance_of)
	{
		return Collector::allocate<Array>(instance_of);
	}

	value_t Array::unshift(Array *self, size_t argc, value_t argv[])
	{
		self->vector.push_entries_front(argv, argc);

		return self;
	}

	value_t Array::push(Array *self, size_t argc, value_t argv[])
	{
		self->vector.push_entries(argv, argc);

		return self;
	}

	value_t Array::pop(Array *self)
	{
		if(self->vector.size())
			return self->vector.pop();
		else
			return value_nil;
	}

	value_t Array::to_s(Array *self)
	{
		CharArray result = "[";

		OnStack<1> os1(self);
		OnStackString<1> os2(result);

		for(size_t i = 0; i < self->vector.size(); ++i)
		{
			String *desc = cast<String>(call(self->vector[i], "inspect"));

			if(!desc)
				return 0;

			result += desc->string;

			if(i != self->vector.size() - 1)
				result += ", ";
		}

		result += "]";

		return result.to_string();
	}

	value_t Array::join(Array *self, String *sep)
	{
		CharArray result;

		OnStack<1> os1(self);
		OnStackString<1> os2(result);

		for(size_t i = 0; i < self->vector.size(); ++i)
		{
			if(i && sep)
				result += sep->string;

			value_t value = self->vector[i];

			auto str = try_cast<String>(value);

			if(str)
				result += str->string;
			else
			{
				auto array = try_cast<Array>(value);

				if(array == self)
					result += "[...]";
				else
				{
					String *desc;

					if(array)
					{
						value_t vsep = sep;

						if(sep)
							desc = raise_cast<String>(call_argv(array, "join", 1, &vsep)); // TODO: Replace with variadic call
						else
							desc = raise_cast<String>(call(array, "join"));
					}
					else
						desc = raise_cast<String>(call(value, "to_s"));

					if(!desc)
						return 0;

					result += desc->string;
				}
			}
		}

		return result.to_string();
	}

	value_t Array::length(Array *self)
	{
		return Fixnum::from_size_t(self->vector.size());
	}

	value_t Array::each(Array *self, value_t block)
	{
		OnStack<2> os(self, block);

		for(size_t i = 0; i < self->vector.size(); ++i)
		{
			if(!yield_argv(block, 1, &self->vector[i]))
				return 0;
		}

		return self;
	}

	value_t Array::get(Array *self, value_t index, value_t size)
	{
		if(size)
		{
			if(!Value::is_fixnum(index) || !Value::is_fixnum(size))
				return raise(context->type_error, "Arguments must be instances of Fixnum");

			int start = Fixnum::to_size_t(index);
			int length = Fixnum::to_size_t(size);
			size_t vector_size = self->vector.size();

			if(start < 0)
			{
				start = -start;

				if(prelude_unlikely((size_t)start > vector_size))
					return value_nil;
				else
					start = vector_size - (size_t)start;
			}

			if(prelude_unlikely(length < 1))
				return value_nil;

			auto result = Collector::allocate<Array>();

			if((size_t)start < self->vector.size())
			{
				if((size_t)start + (size_t)length > vector_size)
					length = vector_size - start;

				result->vector.push_entries(&self->vector[start], length);
			}

			return result;
		}

		if(Value::is_fixnum(index))
		{
			size_t i = Fixnum::to_size_t(index);

			if(i < self->vector.size())
				return self->vector[i];
			else
				return value_nil;
		}
		else if(Value::of_type<Range>(index))
		{
			size_t start;
			size_t length;

			auto range = cast<Range>(index);

			if(!range->convert_to_index(start, length, self->vector.size()))
				return 0;

			auto result = Collector::allocate<Array>();

			result->vector.push_entries(&self->vector[start], length);

			return result;
		}
		else
			return type_error(index, "Range or Fixnum");
	}

	value_t Array::set(Array *self, size_t index, value_t value)
	{
		self->vector.expand_to(index + 1, value_nil);
		self->vector[index] = value;

		return value;
	}

	value_t first(Array *self)
	{
		if(self->vector.size() > 0)
			return self->vector[0];
		else
			return value_nil;
	}

	value_t last(Array *self)
	{
		if(self->vector.size() > 0)
			return self->vector[self->vector.size() - 1];
		else
			return value_nil;
	}

	value_t empty(Array *self)
	{
		return auto_cast(self->vector.size() == 0);
	}

	void Array::initialize()
	{
		context->array_class = define_class("Array", context->object_class);

		include_module(context->array_class, context->enumerable_module);

		singleton_method<Arg::SelfClass<Class>>(context->array_class, "allocate", &allocate);

		method<Arg::SelfClass<Array>>(context->array_class, "first", &first);
		method<Arg::SelfClass<Array>>(context->array_class, "last", &last);
		method<Arg::SelfClass<Array>>(context->array_class, "empty?", &empty);

		method<Arg::SelfClass<Array>, Arg::Count, Arg::Values>(context->array_class, "unshift", &unshift);
		method<Arg::SelfClass<Array>, Arg::Count, Arg::Values>(context->array_class, "push", &push);
		method<Arg::SelfClass<Array>, Arg::Count, Arg::Values>(context->array_class, "<<", &push);
		method<Arg::SelfClass<Array>>(context->array_class, "pop", &pop);
		method<Arg::SelfClass<Array>>(context->array_class, "length", &length);
		method<Arg::SelfClass<Array>, Arg::DefaultClass<String>>(context->array_class, "join", &join);
		method<Arg::SelfClass<Array>>(context->array_class, "to_s", &to_s);
		method<Arg::SelfClass<Array>, Arg::Block>(context->array_class, "each", &each);
		method<Arg::SelfClass<Array>, Arg::Value, Arg::Default>(context->array_class, "[]", &get);
		method<Arg::SelfClass<Array>, Arg::UInt, Arg::Value>(context->array_class, "[]=", &set);
	}
};

<commit_msg>Added Array#size.<commit_after>#include "array.hpp"
#include "string.hpp"
#include "fixnum.hpp"
#include "range.hpp"
#include "../runtime.hpp"

namespace Mirb
{
	value_t Array::allocate(Class *instance_of)
	{
		return Collector::allocate<Array>(instance_of);
	}

	value_t Array::unshift(Array *self, size_t argc, value_t argv[])
	{
		self->vector.push_entries_front(argv, argc);

		return self;
	}

	value_t Array::push(Array *self, size_t argc, value_t argv[])
	{
		self->vector.push_entries(argv, argc);

		return self;
	}

	value_t Array::pop(Array *self)
	{
		if(self->vector.size())
			return self->vector.pop();
		else
			return value_nil;
	}

	value_t Array::to_s(Array *self)
	{
		CharArray result = "[";

		OnStack<1> os1(self);
		OnStackString<1> os2(result);

		for(size_t i = 0; i < self->vector.size(); ++i)
		{
			String *desc = cast<String>(call(self->vector[i], "inspect"));

			if(!desc)
				return 0;

			result += desc->string;

			if(i != self->vector.size() - 1)
				result += ", ";
		}

		result += "]";

		return result.to_string();
	}

	value_t Array::join(Array *self, String *sep)
	{
		CharArray result;

		OnStack<1> os1(self);
		OnStackString<1> os2(result);

		for(size_t i = 0; i < self->vector.size(); ++i)
		{
			if(i && sep)
				result += sep->string;

			value_t value = self->vector[i];

			auto str = try_cast<String>(value);

			if(str)
				result += str->string;
			else
			{
				auto array = try_cast<Array>(value);

				if(array == self)
					result += "[...]";
				else
				{
					String *desc;

					if(array)
					{
						value_t vsep = sep;

						if(sep)
							desc = raise_cast<String>(call_argv(array, "join", 1, &vsep)); // TODO: Replace with variadic call
						else
							desc = raise_cast<String>(call(array, "join"));
					}
					else
						desc = raise_cast<String>(call(value, "to_s"));

					if(!desc)
						return 0;

					result += desc->string;
				}
			}
		}

		return result.to_string();
	}

	value_t Array::length(Array *self)
	{
		return Fixnum::from_size_t(self->vector.size());
	}

	value_t Array::each(Array *self, value_t block)
	{
		OnStack<2> os(self, block);

		for(size_t i = 0; i < self->vector.size(); ++i)
		{
			if(!yield_argv(block, 1, &self->vector[i]))
				return 0;
		}

		return self;
	}

	value_t Array::get(Array *self, value_t index, value_t size)
	{
		if(size)
		{
			if(!Value::is_fixnum(index) || !Value::is_fixnum(size))
				return raise(context->type_error, "Arguments must be instances of Fixnum");

			int start = Fixnum::to_size_t(index);
			int length = Fixnum::to_size_t(size);
			size_t vector_size = self->vector.size();

			if(start < 0)
			{
				start = -start;

				if(prelude_unlikely((size_t)start > vector_size))
					return value_nil;
				else
					start = vector_size - (size_t)start;
			}

			if(prelude_unlikely(length < 1))
				return value_nil;

			auto result = Collector::allocate<Array>();

			if((size_t)start < self->vector.size())
			{
				if((size_t)start + (size_t)length > vector_size)
					length = vector_size - start;

				result->vector.push_entries(&self->vector[start], length);
			}

			return result;
		}

		if(Value::is_fixnum(index))
		{
			size_t i = Fixnum::to_size_t(index);

			if(i < self->vector.size())
				return self->vector[i];
			else
				return value_nil;
		}
		else if(Value::of_type<Range>(index))
		{
			size_t start;
			size_t length;

			auto range = cast<Range>(index);

			if(!range->convert_to_index(start, length, self->vector.size()))
				return 0;

			auto result = Collector::allocate<Array>();

			result->vector.push_entries(&self->vector[start], length);

			return result;
		}
		else
			return type_error(index, "Range or Fixnum");
	}

	value_t Array::set(Array *self, size_t index, value_t value)
	{
		self->vector.expand_to(index + 1, value_nil);
		self->vector[index] = value;

		return value;
	}

	value_t first(Array *self)
	{
		if(self->vector.size() > 0)
			return self->vector[0];
		else
			return value_nil;
	}

	value_t last(Array *self)
	{
		if(self->vector.size() > 0)
			return self->vector[self->vector.size() - 1];
		else
			return value_nil;
	}

	value_t empty(Array *self)
	{
		return auto_cast(self->vector.size() == 0);
	}

	void Array::initialize()
	{
		context->array_class = define_class("Array", context->object_class);

		include_module(context->array_class, context->enumerable_module);

		singleton_method<Arg::SelfClass<Class>>(context->array_class, "allocate", &allocate);

		method<Arg::SelfClass<Array>>(context->array_class, "first", &first);
		method<Arg::SelfClass<Array>>(context->array_class, "last", &last);
		method<Arg::SelfClass<Array>>(context->array_class, "empty?", &empty);

		method<Arg::SelfClass<Array>, Arg::Count, Arg::Values>(context->array_class, "unshift", &unshift);
		method<Arg::SelfClass<Array>, Arg::Count, Arg::Values>(context->array_class, "push", &push);
		method<Arg::SelfClass<Array>, Arg::Count, Arg::Values>(context->array_class, "<<", &push);
		method<Arg::SelfClass<Array>>(context->array_class, "pop", &pop);
		method<Arg::SelfClass<Array>>(context->array_class, "length", &length);
		method<Arg::SelfClass<Array>>(context->array_class, "size", &length);
		method<Arg::SelfClass<Array>, Arg::DefaultClass<String>>(context->array_class, "join", &join);
		method<Arg::SelfClass<Array>>(context->array_class, "to_s", &to_s);
		method<Arg::SelfClass<Array>, Arg::Block>(context->array_class, "each", &each);
		method<Arg::SelfClass<Array>, Arg::Value, Arg::Default>(context->array_class, "[]", &get);
		method<Arg::SelfClass<Array>, Arg::UInt, Arg::Value>(context->array_class, "[]=", &set);
	}
};

<|endoftext|>


<commit_before>/*
 *  This file is part of Poedit (http://poedit.net)
 *
 *  Copyright (C) 2010-2014 Vaclav Slavik
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a
 *  copy of this software and associated documentation files (the "Software"),
 *  to deal in the Software without restriction, including without limitation
 *  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 *  and/or sell copies of the Software, and to permit persons to whom the
 *  Software is furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in
 *  all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 *  DEALINGS IN THE SOFTWARE.
 *
 */

#include "utility.h"

#include <stdio.h>
#include <wx/filename.h>
#include <wx/log.h>
#include <wx/config.h>
#include <wx/display.h>

#ifdef __WXOSX__
#include <wx/cocoa/string.h>
#endif

wxString EscapeMarkup(const wxString& str)
{
    wxString s(str);
    s.Replace("&", "&");
    s.Replace("<", "<");
    s.Replace(">", ">");
    return s;
}

// ----------------------------------------------------------------------
// TempDirectory
// ----------------------------------------------------------------------

bool TempDirectory::ms_keepFiles = false;

TempDirectory::TempDirectory() : m_counter(0)
{
#ifdef HAVE_MKDTEMP
    wxString path = wxFileName::GetTempDir();
    path += "/poeditXXXXXX";
    wxCharBuffer buf(path.fn_str());
    if ( mkdtemp(buf.data()) == NULL )
    {
        wxLogError(_("Cannot create temporary directory."));
        return;
    }
    m_dir = wxConvFile.cMB2WX(buf.data());
#else
    for ( ;; )
    {
        wxString name = wxFileName::CreateTempFileName("poedit");
        if ( name.empty() )
        {
            wxLogError(_("Cannot create temporary directory."));
            return;
        }

        wxLogNull null;
        if ( wxRemoveFile(name) && wxMkdir(name, 0700) )
        {
#ifdef __WXMSW__
            // prevent possible problems with Unicode filenames in launched
            // third party tools (e.g. gettext):
            m_dir = wxFileName(name).GetShortPath();
#else
            m_dir = name;
#endif
            wxLogTrace("poedit.tmp", "created temp dir %s", name.c_str());
            break;
        }
        // else: try again
    }
#endif
}

TempDirectory::~TempDirectory()
{
    if ( m_dir.empty() )
        return;

    if ( ms_keepFiles )
    {
        wxLogTrace("poedit.tmp", "keeping temp files in %s", m_dir.c_str());
        return;
    }

    for ( wxArrayString::const_iterator i = m_files.begin(); i != m_files.end(); ++i )
    {
        if ( wxFileName::FileExists(*i) )
        {
            wxLogTrace("poedit.tmp", "removing temp file %s", i->c_str());
            wxRemoveFile(*i);
        }
    }

    wxLogTrace("poedit.tmp", "removing temp dir %s", m_dir.c_str());
    wxFileName::Rmdir(m_dir);
}

wxString TempDirectory::CreateFileName(const wxString& suffix)
{
    wxString s = wxString::Format("%s%c%d%s",
                                  m_dir.c_str(), wxFILE_SEP_PATH,
                                  m_counter++,
                                  suffix.c_str());
    m_files.push_back(s);
    wxLogTrace("poedit.tmp", "new temp file %s", s.c_str());
    return s;
}

// ----------------------------------------------------------------------
// TempOutputFile
// ----------------------------------------------------------------------

TempOutputFileFor::TempOutputFileFor(const wxString& filename)
{
    wxString path, name, ext;
    wxFileName::SplitPath(filename, &path, &name, &ext);

#ifdef __WXOSX__
    NSURL *fileUrl = [NSURL fileURLWithPath:[NSString stringWithUTF8String: filename.utf8_str()]];
    NSURL *tempdirUrl =
        [[NSFileManager defaultManager] URLForDirectory:NSItemReplacementDirectory
                                               inDomain:NSUserDomainMask
                                      appropriateForURL:[fileUrl URLByDeletingLastPathComponent]
                                                 create:YES
                                                  error:nil];
    if (tempdirUrl)
    {
        NSURL *newFileUrl = [tempdirUrl URLByAppendingPathComponent:[fileUrl lastPathComponent]];
        NSString *newFilePath = [newFileUrl path];
        m_filenameTmp = wxStringWithNSString(newFilePath);
        m_tempDir = wxStringWithNSString([tempdirUrl path]);
    }
    // else: fall through to the generic code
#endif // __WXOSX__

    if (m_filenameTmp.empty())
    {
        m_filenameTmp = filename + ".temp." + ext;
    }

    if ( wxFileExists(m_filenameTmp) )
        wxRemoveFile(m_filenameTmp);
}

TempOutputFileFor::~TempOutputFileFor()
{
#ifdef __WXOSX__
    if (!m_tempDir.empty())
        wxFileName::Rmdir(m_tempDir, wxPATH_RMDIR_RECURSIVE);
#endif
}

// ----------------------------------------------------------------------
// Helpers for persisting windows' state
// ----------------------------------------------------------------------

void SaveWindowState(const wxTopLevelWindow *win, int flags)
{
    wxConfigBase *cfg = wxConfig::Get();
    const wxString path = WindowStatePath(win);

    if ( !win->IsIconized() )
    {
        if ( !win->IsMaximized() )
        {
#if defined(__WXMSW__) || defined(__WXOSX__)

            if ( flags & WinState_Pos )
            {
                const wxPoint pos = win->GetPosition();
                cfg->Write(path + "x", (long)pos.x);
                cfg->Write(path + "y", (long)pos.y);
            }
#endif // __WXMSW__/__WXOSX__
            if ( flags &  WinState_Size )
            {
                const wxSize sz = win->GetClientSize();
                cfg->Write(path + "w", (long)sz.x);
                cfg->Write(path + "h", (long)sz.y);
            }
        }

        if ( flags &  WinState_Size )
            cfg->Write(path + "maximized", (long)win->IsMaximized());
    }
}

void RestoreWindowState(wxTopLevelWindow *win, const wxSize& defaultSize, int flags)
{
    wxConfigBase *cfg = wxConfig::Get();
    const wxString path = WindowStatePath(win);

    if ( flags & WinState_Size )
    {
        int width = (int)cfg->Read(path + "w", defaultSize.x);
        int height = (int)cfg->Read(path + "h", defaultSize.y);
        if ( width != -1 || height != -1 )
            win->SetClientSize(width, height);
    }

#if defined(__WXMSW__) || defined(__WXOSX__)
    if ( flags & WinState_Pos )
    {
        wxPoint pos;
        pos.x = (int)cfg->Read(path + "x", -1);
        pos.y = (int)cfg->Read(path + "y", -1);
        if ( pos.x != -1 || pos.y != -1 )
        {
            // NB: if this is the only Poedit frame opened, place it at remembered
            //     position, but don't do that if there already are other frames,
            //     because they would overlap and nobody could recognize that there are
            //     many of them
            for (;;)
            {
                bool occupied = false;
                for (auto& w : wxTopLevelWindows)
                {
                    wxPrintf("win(%p) @ %d,%d\n" ,w, w->GetPosition().x, w->GetPosition().y);
                    if (w != win && w->GetPosition() == pos)
                    {
                        occupied = true;
                        break;
                    }
                }
                if (!occupied)
                    break;
                pos += wxPoint(20,20);
            }

            win->Move(pos);
        }
    }

    // If the window is completely out of all screens (e.g. because
    // screens configuration changed), move it to primary screen:
#ifdef __WXOSX__
    if ( win->GetPosition().x < 0 || win->GetPosition().y < 0 )
        win->Move(20, 30);
#else
    if ( wxDisplay::GetFromWindow(win) == wxNOT_FOUND )
        win->Move(0, 0);
#endif

#endif // __WXMSW__/__WXOSX__

#ifndef __WXOSX__
    // If the window is larger than current screen, resize it to fit:
    int display = wxDisplay::GetFromWindow(win);
    if ( display == wxNOT_FOUND )
        return;

    wxRect screenRect = wxDisplay(display).GetClientArea();

    wxRect winRect = win->GetRect();
    if ( winRect.GetPosition() == wxDefaultPosition )
        winRect.SetPosition(screenRect.GetPosition()); // not place yet, fake it

    if ( !screenRect.Contains(winRect) )
    {
        winRect.Intersect(screenRect);
        win->SetSize(winRect);
    }

    // Maximize if it should be
    if ( cfg->Read(path + "maximized", long(0)) )
    {
        win->Maximize();
    }
#endif // !__WXOSX__
}
<commit_msg>Remove forgotten debug output.<commit_after>/*
 *  This file is part of Poedit (http://poedit.net)
 *
 *  Copyright (C) 2010-2014 Vaclav Slavik
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a
 *  copy of this software and associated documentation files (the "Software"),
 *  to deal in the Software without restriction, including without limitation
 *  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 *  and/or sell copies of the Software, and to permit persons to whom the
 *  Software is furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in
 *  all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 *  DEALINGS IN THE SOFTWARE.
 *
 */

#include "utility.h"

#include <stdio.h>
#include <wx/filename.h>
#include <wx/log.h>
#include <wx/config.h>
#include <wx/display.h>

#ifdef __WXOSX__
#include <wx/cocoa/string.h>
#endif

wxString EscapeMarkup(const wxString& str)
{
    wxString s(str);
    s.Replace("&", "&");
    s.Replace("<", "<");
    s.Replace(">", ">");
    return s;
}

// ----------------------------------------------------------------------
// TempDirectory
// ----------------------------------------------------------------------

bool TempDirectory::ms_keepFiles = false;

TempDirectory::TempDirectory() : m_counter(0)
{
#ifdef HAVE_MKDTEMP
    wxString path = wxFileName::GetTempDir();
    path += "/poeditXXXXXX";
    wxCharBuffer buf(path.fn_str());
    if ( mkdtemp(buf.data()) == NULL )
    {
        wxLogError(_("Cannot create temporary directory."));
        return;
    }
    m_dir = wxConvFile.cMB2WX(buf.data());
#else
    for ( ;; )
    {
        wxString name = wxFileName::CreateTempFileName("poedit");
        if ( name.empty() )
        {
            wxLogError(_("Cannot create temporary directory."));
            return;
        }

        wxLogNull null;
        if ( wxRemoveFile(name) && wxMkdir(name, 0700) )
        {
#ifdef __WXMSW__
            // prevent possible problems with Unicode filenames in launched
            // third party tools (e.g. gettext):
            m_dir = wxFileName(name).GetShortPath();
#else
            m_dir = name;
#endif
            wxLogTrace("poedit.tmp", "created temp dir %s", name.c_str());
            break;
        }
        // else: try again
    }
#endif
}

TempDirectory::~TempDirectory()
{
    if ( m_dir.empty() )
        return;

    if ( ms_keepFiles )
    {
        wxLogTrace("poedit.tmp", "keeping temp files in %s", m_dir.c_str());
        return;
    }

    for ( wxArrayString::const_iterator i = m_files.begin(); i != m_files.end(); ++i )
    {
        if ( wxFileName::FileExists(*i) )
        {
            wxLogTrace("poedit.tmp", "removing temp file %s", i->c_str());
            wxRemoveFile(*i);
        }
    }

    wxLogTrace("poedit.tmp", "removing temp dir %s", m_dir.c_str());
    wxFileName::Rmdir(m_dir);
}

wxString TempDirectory::CreateFileName(const wxString& suffix)
{
    wxString s = wxString::Format("%s%c%d%s",
                                  m_dir.c_str(), wxFILE_SEP_PATH,
                                  m_counter++,
                                  suffix.c_str());
    m_files.push_back(s);
    wxLogTrace("poedit.tmp", "new temp file %s", s.c_str());
    return s;
}

// ----------------------------------------------------------------------
// TempOutputFile
// ----------------------------------------------------------------------

TempOutputFileFor::TempOutputFileFor(const wxString& filename)
{
    wxString path, name, ext;
    wxFileName::SplitPath(filename, &path, &name, &ext);

#ifdef __WXOSX__
    NSURL *fileUrl = [NSURL fileURLWithPath:[NSString stringWithUTF8String: filename.utf8_str()]];
    NSURL *tempdirUrl =
        [[NSFileManager defaultManager] URLForDirectory:NSItemReplacementDirectory
                                               inDomain:NSUserDomainMask
                                      appropriateForURL:[fileUrl URLByDeletingLastPathComponent]
                                                 create:YES
                                                  error:nil];
    if (tempdirUrl)
    {
        NSURL *newFileUrl = [tempdirUrl URLByAppendingPathComponent:[fileUrl lastPathComponent]];
        NSString *newFilePath = [newFileUrl path];
        m_filenameTmp = wxStringWithNSString(newFilePath);
        m_tempDir = wxStringWithNSString([tempdirUrl path]);
    }
    // else: fall through to the generic code
#endif // __WXOSX__

    if (m_filenameTmp.empty())
    {
        m_filenameTmp = filename + ".temp." + ext;
    }

    if ( wxFileExists(m_filenameTmp) )
        wxRemoveFile(m_filenameTmp);
}

TempOutputFileFor::~TempOutputFileFor()
{
#ifdef __WXOSX__
    if (!m_tempDir.empty())
        wxFileName::Rmdir(m_tempDir, wxPATH_RMDIR_RECURSIVE);
#endif
}

// ----------------------------------------------------------------------
// Helpers for persisting windows' state
// ----------------------------------------------------------------------

void SaveWindowState(const wxTopLevelWindow *win, int flags)
{
    wxConfigBase *cfg = wxConfig::Get();
    const wxString path = WindowStatePath(win);

    if ( !win->IsIconized() )
    {
        if ( !win->IsMaximized() )
        {
#if defined(__WXMSW__) || defined(__WXOSX__)

            if ( flags & WinState_Pos )
            {
                const wxPoint pos = win->GetPosition();
                cfg->Write(path + "x", (long)pos.x);
                cfg->Write(path + "y", (long)pos.y);
            }
#endif // __WXMSW__/__WXOSX__
            if ( flags &  WinState_Size )
            {
                const wxSize sz = win->GetClientSize();
                cfg->Write(path + "w", (long)sz.x);
                cfg->Write(path + "h", (long)sz.y);
            }
        }

        if ( flags &  WinState_Size )
            cfg->Write(path + "maximized", (long)win->IsMaximized());
    }
}

void RestoreWindowState(wxTopLevelWindow *win, const wxSize& defaultSize, int flags)
{
    wxConfigBase *cfg = wxConfig::Get();
    const wxString path = WindowStatePath(win);

    if ( flags & WinState_Size )
    {
        int width = (int)cfg->Read(path + "w", defaultSize.x);
        int height = (int)cfg->Read(path + "h", defaultSize.y);
        if ( width != -1 || height != -1 )
            win->SetClientSize(width, height);
    }

#if defined(__WXMSW__) || defined(__WXOSX__)
    if ( flags & WinState_Pos )
    {
        wxPoint pos;
        pos.x = (int)cfg->Read(path + "x", -1);
        pos.y = (int)cfg->Read(path + "y", -1);
        if ( pos.x != -1 || pos.y != -1 )
        {
            // NB: if this is the only Poedit frame opened, place it at remembered
            //     position, but don't do that if there already are other frames,
            //     because they would overlap and nobody could recognize that there are
            //     many of them
            for (;;)
            {
                bool occupied = false;
                for (auto& w : wxTopLevelWindows)
                {
                    if (w != win && w->GetPosition() == pos)
                    {
                        occupied = true;
                        break;
                    }
                }
                if (!occupied)
                    break;
                pos += wxPoint(20,20);
            }

            win->Move(pos);
        }
    }

    // If the window is completely out of all screens (e.g. because
    // screens configuration changed), move it to primary screen:
#ifdef __WXOSX__
    if ( win->GetPosition().x < 0 || win->GetPosition().y < 0 )
        win->Move(20, 30);
#else
    if ( wxDisplay::GetFromWindow(win) == wxNOT_FOUND )
        win->Move(0, 0);
#endif

#endif // __WXMSW__/__WXOSX__

#ifndef __WXOSX__
    // If the window is larger than current screen, resize it to fit:
    int display = wxDisplay::GetFromWindow(win);
    if ( display == wxNOT_FOUND )
        return;

    wxRect screenRect = wxDisplay(display).GetClientArea();

    wxRect winRect = win->GetRect();
    if ( winRect.GetPosition() == wxDefaultPosition )
        winRect.SetPosition(screenRect.GetPosition()); // not place yet, fake it

    if ( !screenRect.Contains(winRect) )
    {
        winRect.Intersect(screenRect);
        win->SetSize(winRect);
    }

    // Maximize if it should be
    if ( cfg->Read(path + "maximized", long(0)) )
    {
        win->Maximize();
    }
#endif // !__WXOSX__
}
<|endoftext|>


<commit_before>#ifndef VG_UTILITY_HPP_INCLUDED
#define VG_UTILITY_HPP_INCLUDED

#include <string>
#include <vector>
#include <sstream>
#include <omp.h>
#include <cstring>
#include <algorithm>
#include <numeric>
#include <cmath>
#include <unordered_set>
#include <unistd.h>
#include "vg.pb.h"
#include "sha1.hpp"
#include "Variant.h"

namespace vg {

using namespace std;

char reverse_complement(const char& c);
string reverse_complement(const string& seq);
/// Return True if the given string is entirely Ns of either case, and false
/// otherwise.
bool is_all_n(const string& seq);
int get_thread_count(void);
string wrap_text(const string& str, size_t width);
bool is_number(const string& s);

// split a string on any character found in the string of delimiters (delims)
std::vector<std::string>& split_delims(const std::string &s, const std::string& delims, std::vector<std::string> &elems);
std::vector<std::string> split_delims(const std::string &s, const std::string& delims);

const std::string sha1sum(const std::string& data);
const std::string sha1head(const std::string& data, size_t head);

bool allATGC(const string& s);
string nonATGCNtoN(const string& s);
double median(std::vector<int> &v);
double stdev(const std::vector<double>& v);

template<typename T>
double stdev(const T& v) {
    double sum = std::accumulate(v.begin(), v.end(), 0.0);
    double mean = sum / v.size();
    std::vector<double> diff(v.size());
    std::transform(v.begin(), v.end(), diff.begin(), [mean](double x) { return x - mean; });
    double sq_sum = std::inner_product(diff.begin(), diff.end(), diff.begin(), 0.0);
    return std::sqrt(sq_sum / v.size());
}

// Φ is the normal cumulative distribution function
// https://en.wikipedia.org/wiki/Cumulative_distribution_function
double phi(double x1, double x2);

/// Inverse CDF of a standard normal distribution. Must have 0 < quantile < 1.
double normal_inverse_cdf(double quantile);

inline double add_log(double log_x, double log_y) {
    return log_x > log_y ? log_x + log(1.0 + exp(log_y - log_x)) : log_y + log(1.0 + exp(log_x - log_y));
}

/**
 * Convert a number ln to the same number log 10.
 */
inline double ln_to_log10(double ln) {
    return ln / log(10);
}

/**
 * Convert a number log 10 to the same number ln.
 */
inline double log10_to_ln(double l10) {
    return l10 * log(10);
}

// Convert a probability to a natural log probability.
inline double prob_to_logprob(double prob) {
    return log(prob);
}
// Convert natural log probability to a probability
inline double logprob_to_prob(double logprob) {
    return exp(logprob);
}
// Add two probabilities (expressed as logprobs) together and return the result
// as a logprob.
inline double logprob_add(double logprob1, double logprob2) {
    // Pull out the larger one to avoid underflows
    double pulled_out = max(logprob1, logprob2);
    return pulled_out + prob_to_logprob(logprob_to_prob(logprob1 - pulled_out) + logprob_to_prob(logprob2 - pulled_out));
}
// Invert a logprob, and get the probability of its opposite.
inline double logprob_invert(double logprob) {
    return prob_to_logprob(1.0 - logprob_to_prob(logprob));
}

// Convert integer Phred quality score to probability of wrongness.
inline double phred_to_prob(int phred) {
    return pow(10, -((double)phred) / 10);
}

// Convert probability of wrongness to integer Phred quality score.
inline double prob_to_phred(double prob) {
    return -10.0 * log10(prob);
}

// Convert a Phred quality score directly to a natural log probability of wrongness.
inline double phred_to_logprob(int phred) {
    return (-((double)phred) / 10) / log10(exp(1.0));
}

// Convert a natural log probability of wrongness directly to a Phred quality score.
inline double logprob_to_phred(double logprob ) {
    return -10.0 * logprob * log10(exp(1.0));
}

// Take the geometric mean of two logprobs
inline double logprob_geometric_mean(double lnprob1, double lnprob2) {
    return log(sqrt(exp(lnprob1 + lnprob2)));
}

// Same thing in phred
inline double phred_geometric_mean(double phred1, double phred2) {
    return prob_to_phred(sqrt(phred_to_prob(phred1 + phred2)));
}

// normal pdf, from http://stackoverflow.com/a/10848293/238609
template <typename T>
T normal_pdf(T x, T m, T s)
{
    static const T inv_sqrt_2pi = 0.3989422804014327;
    T a = (x - m) / s;

    return inv_sqrt_2pi / s * std::exp(-T(0.5) * a * a);
}

template<typename T, typename V>
set<T> map_keys_to_set(const map<T, V>& m) {
    set<T> r;
    for (auto p : m) r.insert(p.first);
    return r;
}

// pairwise maximum
template<typename T>
vector<T> pmax(const std::vector<T>& a, const std::vector<T>& b) {
    std::vector<T> c;
    assert(a.size() == b.size());
    c.reserve(a.size());
    std::transform(a.begin(), a.end(), b.begin(),
                   std::back_inserter(c),
                   [](T a, T b) { return std::max<T>(a, b); });
    return c;
}

// maximum of all vectors
template<typename T>
vector<T> vpmax(const std::vector<std::vector<T>>& vv) {
    std::vector<T> c;
    if (vv.empty()) return c;
    c = vv.front();
    typename std::vector<std::vector<T> >::const_iterator v = vv.begin();
    ++v; // skip the first element
    for ( ; v != vv.end(); ++v) {
        c = pmax(c, *v);
    }
    return c;
}

/**
 * Compute the sum of the values in a collection. Values must be default-
 * constructable (like numbers are).
 */
template<typename Collection>
typename Collection::value_type sum(const Collection& collection) {

    // Set up an alias
    using Item = typename Collection::value_type;

    // Make a new zero-valued item to hold the sum
    auto total = Item();
    for(auto& to_sum : collection) {
        total += to_sum;
    }

    return total;

}

/**
 * Compute the sum of the values in a collection, where the values are log
 * probabilities and the result is the log of the total probability. Items must
 * be convertible to/from doubles for math.
 */
template<typename Collection>
typename Collection::value_type logprob_sum(const Collection& collection) {

    // Set up an alias
    using Item = typename Collection::value_type;

    // Pull out the minimum value
    auto min_iterator = min_element(begin(collection), end(collection));

    if(min_iterator == end(collection)) {
        // Nothing there, p = 0
        return Item(prob_to_logprob(0));
    }

    auto check_iterator = begin(collection);
    ++check_iterator;
    if(check_iterator == end(collection)) {
        // We only have a single element anyway. We don't want to subtract it
        // out because we'll get 0s.
        return *min_iterator;
    }

    // Pull this much out of every logprob.
    Item pulled_out = *min_iterator;

    if(logprob_to_prob(pulled_out) == 0) {
        // Can't divide by 0!
        // TODO: fix this in selection
        pulled_out = prob_to_logprob(1);
    }

    Item total(0);
    for(auto& to_add : collection) {
        // Sum up all the scaled probabilities.
        total += logprob_to_prob(to_add - pulled_out);
    }

    // Re-log and re-scale
    return pulled_out + prob_to_logprob(total);
}

/// Find the system temp directory using defaults and environment variables
string find_temp_dir();

/// Create a temporary file starting with the given base name
string tmpfilename(const string& base);

/// Create a temporary file in the appropriate system temporary directory
string tmpfilename();

// Code to detect if a variant lacks an ID and give it a unique but repeatable
// one.
string get_or_make_variant_id(const vcflib::Variant& variant);
string make_variant_id(const vcflib::Variant& variant);

// TODO: move these to genotypekit on a VCF emitter?

/**
 * Create the reference allele for an empty vcflib Variant, since apaprently
 * there's no method for that already. Must be called before any alt alleles are
 * added.
 */
void create_ref_allele(vcflib::Variant& variant, const std::string& allele);

/**
 * Add a new alt allele to a vcflib Variant, since apaprently there's no method
 * for that already.
 *
 * If that allele already exists in the variant, does not add it again.
 *
 * Retuerns the allele number (0, 1, 2, etc.) corresponding to the given allele
 * string in the given variant.
 */
int add_alt_allele(vcflib::Variant& variant, const std::string& allele);

// Simple little tree
template<typename T>
struct TreeNode {
    T v;
    vector<TreeNode<T>*> children;
    TreeNode<T>* parent;
    TreeNode() : parent(0) {}
    ~TreeNode() { for (auto c : children) { delete c; } }
    void for_each_preorder(function<void(TreeNode<T>*)> lambda) {
        lambda(this);
        for (auto c : children) {
            c->for_each_preorder(lambda);
        }
    }
    void for_each_postorder(function<void(TreeNode<T>*)> lambda) {
        for (auto c : children) {
            c->for_each_postorder(lambda);
        }
        lambda(this);
    }
};

/**
 * A custom Union-Find data structure that supports merging a set of indices in
 * disjoint sets in amortized nearly linear time. This implementation also supports
 * querying the size of the group containing an index in constant time and querying
 * the members of the group containing an index in linear time in the size of the group.
 */
class UnionFind {
public:
    /// Construct UnionFind for this many indices
    UnionFind(size_t size);

    /// Destructor
    ~UnionFind();

    /// Returns the number of indices in the UnionFind
    size_t size();

    /// Returns the group ID that index i belongs to (can change after calling union)
    size_t find_group(size_t i);

    /// Merges the group containing index i with the group containing index j
    void union_groups(size_t i, size_t j);

    /// Returns the size of the group containing index i
    size_t group_size(size_t i);

    /// Returns a vector of the indices in the same group as index i
    vector<size_t> group(size_t i);

    /// Returns all of the groups, each in a separate vector
    vector<vector<size_t>> all_groups();

    /// A string representation of the current state for debugging
    string current_state();

private:

    struct UFNode;
    vector<UFNode> uf_nodes;
};

struct UnionFind::UFNode {
    UFNode(size_t index) : head(index), rank(0), size(1) {}
    ~UFNode() {}

    size_t rank;
    size_t size;
    size_t head;
    unordered_set<size_t> children;
};

template<typename T>
struct Tree {
    typedef TreeNode<T> Node;
    Node* root;
    Tree(Node* r = 0) : root(r) { }
    ~Tree() { delete root; }
    void for_each_preorder(function<void(Node*)> lambda) {
        if (root) root->for_each_preorder(lambda);
    }
    void for_each_postorder(function<void(Node*)> lambda) {
       if (root) root->for_each_postorder(lambda);
    }

};

vector<size_t> range_vector(size_t begin, size_t end);

struct IncrementIter {
public:
    IncrementIter(size_t number) : current(number) {

    }

    inline IncrementIter& operator=(const IncrementIter& other) {
        current = other.current;
        return *this;
    }

    inline bool operator==(const IncrementIter& other) const {
        return current == other.current;
    }

    inline bool operator!=(const IncrementIter& other) const {
        return current != other.current;
    }

    inline IncrementIter operator++() {
        current++;
        return *this;
    }

    inline IncrementIter operator++( int ) {
        IncrementIter temp = *this;
        current++;
        return temp;
    }

    inline size_t operator*(){
        return current;
    }

private:
    size_t current;
};

size_t integer_power(size_t x, size_t power);

// Get a callback with an istream& to an open file if a file name argument is
// present after the parsed options, or print an error message and exit if one
// is not. Handles "-" as a filename as indicating standard input. The reference
// passed is guaranteed to be valid only until the callback returns. Bumps up
// optind to the next argument if a filename is found.
void get_input_file(int& optind, int argc, char** argv, function<void(istream&)> callback);

// Parse out the name of an input file (i.e. the next positional argument), or
// throw an error. File name must be nonempty, but may be "-" or may not exist.
string get_input_file_name(int& optind, int argc, char** argv);

// Parse out the name of an output file (i.e. the next positional argument), or
// throw an error. File name must be nonempty.
string get_output_file_name(int& optind, int argc, char** argv);

// Get a callback with an istream& to an open file. Handles "-" as a filename as
// indicating standard input. The reference passed is guaranteed to be valid
// only until the callback returns.
void get_input_file(const string& file_name, function<void(istream&)> callback);

double slope(const std::vector<double>& x, const std::vector<double>& y);
double fit_zipf(const vector<double>& y);

size_t integer_power(size_t base, size_t exponent);
size_t modular_exponent(size_t base, size_t exponent, size_t modulus);

}

#endif
<commit_msg>missed a file in previous commit<commit_after>#ifndef VG_UTILITY_HPP_INCLUDED
#define VG_UTILITY_HPP_INCLUDED

#include <string>
#include <vector>
#include <sstream>
#include <omp.h>
#include <cstring>
#include <algorithm>
#include <numeric>
#include <cmath>
#include <unordered_set>
#include <unistd.h>
#include "vg.pb.h"
#include "sha1.hpp"
#include "Variant.h"

namespace vg {

using namespace std;

char reverse_complement(const char& c);
string reverse_complement(const string& seq);
/// Return True if the given string is entirely Ns of either case, and false
/// otherwise.
bool is_all_n(const string& seq);
int get_thread_count(void);
string wrap_text(const string& str, size_t width);
bool is_number(const string& s);

// split a string on any character found in the string of delimiters (delims)
std::vector<std::string>& split_delims(const std::string &s, const std::string& delims, std::vector<std::string> &elems);
std::vector<std::string> split_delims(const std::string &s, const std::string& delims);

const std::string sha1sum(const std::string& data);
const std::string sha1head(const std::string& data, size_t head);

bool allATGC(const string& s);
string nonATGCNtoN(const string& s);
double median(std::vector<int> &v);
double stdev(const std::vector<double>& v);

template<typename T>
double stdev(const T& v) {
    double sum = std::accumulate(v.begin(), v.end(), 0.0);
    double mean = sum / v.size();
    std::vector<double> diff(v.size());
    std::transform(v.begin(), v.end(), diff.begin(), [mean](double x) { return x - mean; });
    double sq_sum = std::inner_product(diff.begin(), diff.end(), diff.begin(), 0.0);
    return std::sqrt(sq_sum / v.size());
}

// Φ is the normal cumulative distribution function
// https://en.wikipedia.org/wiki/Cumulative_distribution_function
double phi(double x1, double x2);

/// Inverse CDF of a standard normal distribution. Must have 0 < quantile < 1.
double normal_inverse_cdf(double quantile);

inline double add_log(double log_x, double log_y) {
    return log_x > log_y ? log_x + log(1.0 + exp(log_y - log_x)) : log_y + log(1.0 + exp(log_x - log_y));
}

/**
 * Convert a number ln to the same number log 10.
 */
inline double ln_to_log10(double ln) {
    return ln / log(10);
}

/**
 * Convert a number log 10 to the same number ln.
 */
inline double log10_to_ln(double l10) {
    return l10 * log(10);
}

// Convert a probability to a natural log probability.
inline double prob_to_logprob(double prob) {
    return log(prob);
}
// Convert natural log probability to a probability
inline double logprob_to_prob(double logprob) {
    return exp(logprob);
}
// Add two probabilities (expressed as logprobs) together and return the result
// as a logprob.
inline double logprob_add(double logprob1, double logprob2) {
    // Pull out the larger one to avoid underflows
    double pulled_out = max(logprob1, logprob2);
    return pulled_out + prob_to_logprob(logprob_to_prob(logprob1 - pulled_out) + logprob_to_prob(logprob2 - pulled_out));
}
// Invert a logprob, and get the probability of its opposite.
inline double logprob_invert(double logprob) {
    return prob_to_logprob(1.0 - logprob_to_prob(logprob));
}

// Convert integer Phred quality score to probability of wrongness.
inline double phred_to_prob(int phred) {
    return pow(10, -((double)phred) / 10);
}

// Convert probability of wrongness to integer Phred quality score.
inline double prob_to_phred(double prob) {
    return -10.0 * log10(prob);
}

// Convert a Phred quality score directly to a natural log probability of wrongness.
inline double phred_to_logprob(int phred) {
    return (-((double)phred) / 10) / log10(exp(1.0));
}

// Convert a natural log probability of wrongness directly to a Phred quality score.
inline double logprob_to_phred(double logprob ) {
    return -10.0 * logprob * log10(exp(1.0));
}

// Take the geometric mean of two logprobs
inline double logprob_geometric_mean(double lnprob1, double lnprob2) {
    return log(sqrt(exp(lnprob1 + lnprob2)));
}

// Same thing in phred
inline double phred_geometric_mean(double phred1, double phred2) {
    return prob_to_phred(sqrt(phred_to_prob(phred1 + phred2)));
}

// normal pdf, from http://stackoverflow.com/a/10848293/238609
template <typename T>
T normal_pdf(T x, T m, T s)
{
    static const T inv_sqrt_2pi = 0.3989422804014327;
    T a = (x - m) / s;

    return inv_sqrt_2pi / s * std::exp(-T(0.5) * a * a);
}

template<typename T, typename V>
set<T> map_keys_to_set(const map<T, V>& m) {
    set<T> r;
    for (auto p : m) r.insert(p.first);
    return r;
}

// pairwise maximum
template<typename T>
vector<T> pmax(const std::vector<T>& a, const std::vector<T>& b) {
    std::vector<T> c;
    assert(a.size() == b.size());
    c.reserve(a.size());
    std::transform(a.begin(), a.end(), b.begin(),
                   std::back_inserter(c),
                   [](T a, T b) { return std::max<T>(a, b); });
    return c;
}

// maximum of all vectors
template<typename T>
vector<T> vpmax(const std::vector<std::vector<T>>& vv) {
    std::vector<T> c;
    if (vv.empty()) return c;
    c = vv.front();
    typename std::vector<std::vector<T> >::const_iterator v = vv.begin();
    ++v; // skip the first element
    for ( ; v != vv.end(); ++v) {
        c = pmax(c, *v);
    }
    return c;
}

/**
 * Compute the sum of the values in a collection. Values must be default-
 * constructable (like numbers are).
 */
template<typename Collection>
typename Collection::value_type sum(const Collection& collection) {

    // Set up an alias
    using Item = typename Collection::value_type;

    // Make a new zero-valued item to hold the sum
    auto total = Item();
    for(auto& to_sum : collection) {
        total += to_sum;
    }

    return total;

}

/**
 * Compute the sum of the values in a collection, where the values are log
 * probabilities and the result is the log of the total probability. Items must
 * be convertible to/from doubles for math.
 */
template<typename Collection>
typename Collection::value_type logprob_sum(const Collection& collection) {

    // Set up an alias
    using Item = typename Collection::value_type;

    // Pull out the minimum value
    auto min_iterator = min_element(begin(collection), end(collection));

    if(min_iterator == end(collection)) {
        // Nothing there, p = 0
        return Item(prob_to_logprob(0));
    }

    auto check_iterator = begin(collection);
    ++check_iterator;
    if(check_iterator == end(collection)) {
        // We only have a single element anyway. We don't want to subtract it
        // out because we'll get 0s.
        return *min_iterator;
    }

    // Pull this much out of every logprob.
    Item pulled_out = *min_iterator;

    if(logprob_to_prob(pulled_out) == 0) {
        // Can't divide by 0!
        // TODO: fix this in selection
        pulled_out = prob_to_logprob(1);
    }

    Item total(0);
    for(auto& to_add : collection) {
        // Sum up all the scaled probabilities.
        total += logprob_to_prob(to_add - pulled_out);
    }

    // Re-log and re-scale
    return pulled_out + prob_to_logprob(total);
}

/// Find the system temp directory using defaults and environment variables
string find_temp_dir();

/// Create a temporary file starting with the given base name
string tmpfilename(const string& base);

/// Create a temporary file in the appropriate system temporary directory
string tmpfilename();

// Code to detect if a variant lacks an ID and give it a unique but repeatable
// one.
string get_or_make_variant_id(const vcflib::Variant& variant);
string make_variant_id(const vcflib::Variant& variant);

// TODO: move these to genotypekit on a VCF emitter?

/**
 * Create the reference allele for an empty vcflib Variant, since apaprently
 * there's no method for that already. Must be called before any alt alleles are
 * added.
 */
void create_ref_allele(vcflib::Variant& variant, const std::string& allele);

/**
 * Add a new alt allele to a vcflib Variant, since apaprently there's no method
 * for that already.
 *
 * If that allele already exists in the variant, does not add it again.
 *
 * Retuerns the allele number (0, 1, 2, etc.) corresponding to the given allele
 * string in the given variant.
 */
int add_alt_allele(vcflib::Variant& variant, const std::string& allele);

// Simple little tree
template<typename T>
struct TreeNode {
    T v;
    vector<TreeNode<T>*> children;
    TreeNode<T>* parent;
    TreeNode() : parent(0) {}
    ~TreeNode() { for (auto c : children) { delete c; } }
    void for_each_preorder(function<void(TreeNode<T>*)> lambda) {
        lambda(this);
        for (auto c : children) {
            c->for_each_preorder(lambda);
        }
    }
    void for_each_postorder(function<void(TreeNode<T>*)> lambda) {
        for (auto c : children) {
            c->for_each_postorder(lambda);
        }
        lambda(this);
    }
};

/**
 * A custom Union-Find data structure that supports merging a set of indices in
 * disjoint sets in amortized nearly linear time. This implementation also supports
 * querying the size of the group containing an index in constant time and querying
 * the members of the group containing an index in linear time in the size of the group.
 */
class UnionFind {
public:
    /// Construct UnionFind for this many indices
    UnionFind(size_t size);

    /// Destructor
    ~UnionFind();

    /// Returns the number of indices in the UnionFind
    size_t size();

    /// Returns the group ID that index i belongs to (can change after calling union)
    size_t find_group(size_t i);

    /// Merges the group containing index i with the group containing index j
    void union_groups(size_t i, size_t j);

    /// Returns the size of the group containing index i
    size_t group_size(size_t i);

    /// Returns a vector of the indices in the same group as index i
    vector<size_t> group(size_t i);

    /// Returns all of the groups, each in a separate vector
    vector<vector<size_t>> all_groups();

    /// A string representation of the current state for debugging
    string current_state();

private:

    struct UFNode;
    vector<UFNode> uf_nodes;
};

struct UnionFind::UFNode {
    UFNode(size_t index) : head(index), rank(0), size(1) {}
    ~UFNode() {}

    size_t rank;
    size_t size;
    size_t head;
    unordered_set<size_t> children;
};

template<typename T>
struct Tree {
    typedef TreeNode<T> Node;
    Node* root;
    Tree(Node* r = 0) : root(r) { }
    ~Tree() { delete root; }
    void for_each_preorder(function<void(Node*)> lambda) {
        if (root) root->for_each_preorder(lambda);
    }
    void for_each_postorder(function<void(Node*)> lambda) {
       if (root) root->for_each_postorder(lambda);
    }

};

vector<size_t> range_vector(size_t begin, size_t end);

struct IncrementIter {
public:
    IncrementIter(size_t number) : current(number) {

    }

    inline IncrementIter& operator=(const IncrementIter& other) {
        current = other.current;
        return *this;
    }

    inline bool operator==(const IncrementIter& other) const {
        return current == other.current;
    }

    inline bool operator!=(const IncrementIter& other) const {
        return current != other.current;
    }

    inline IncrementIter operator++() {
        current++;
        return *this;
    }

    inline IncrementIter operator++( int ) {
        IncrementIter temp = *this;
        current++;
        return temp;
    }

    inline size_t operator*(){
        return current;
    }

private:
    size_t current;
};

size_t integer_power(size_t x, size_t power);

// Get a callback with an istream& to an open file if a file name argument is
// present after the parsed options, or print an error message and exit if one
// is not. Handles "-" as a filename as indicating standard input. The reference
// passed is guaranteed to be valid only until the callback returns. Bumps up
// optind to the next argument if a filename is found.
void get_input_file(int& optind, int argc, char** argv, function<void(istream&)> callback);

// Parse out the name of an input file (i.e. the next positional argument), or
// throw an error. File name must be nonempty, but may be "-" or may not exist.
string get_input_file_name(int& optind, int argc, char** argv);

// Parse out the name of an output file (i.e. the next positional argument), or
// throw an error. File name must be nonempty.
string get_output_file_name(int& optind, int argc, char** argv);

// Get a callback with an istream& to an open file. Handles "-" as a filename as
// indicating standard input. The reference passed is guaranteed to be valid
// only until the callback returns.
void get_input_file(const string& file_name, function<void(istream&)> callback);

double slope(const std::vector<double>& x, const std::vector<double>& y);
double fit_zipf(const vector<double>& y);

/// Computes base^exponent in log(exponent) time
size_t integer_power(size_t base, size_t exponent);
/// Computes base^exponent mod modulus in log(exponent) time without requiring more
/// than 64 bits to represent exponentiated number
size_t modular_exponent(size_t base, size_t exponent, size_t modulus);

}

#endif
<|endoftext|>