<commit_before>/*! @file logger.cc
 *  @brief New file description.
 *  @author Markovtsev Vadim <v.markovtsev@samsung.com>
 *  @version 1.0
 *
 *  @section Notes
 *  This code partially conforms to Google C++ Style Guide.
 *
 *  @section Copyright
 *  Copyright 2013 Samsung R&D Institute Russia
 */

#include "src/logger.h"
#include <assert.h>
#include <cxxabi.h>
#include <string.h>

namespace SoundFeatureExtraction {

// The following defines must not be converted to static const members of Logger
// due to the undefined order in which static constructors are invoked.
#ifdef EINA
#define kDefaultLoggerColor EINA_COLOR_WHITE
#endif
#define kCommonDomain ""
#define kUnintializedLogDomain_ (-1)

Logger::Logger(const std::string &domain = "default",
               const std::string &color = kDefaultLoggerColor,
               bool suppressLoggingInitialized) noexcept
    : log_domain_(kUnintializedLogDomain_)
    , domain_str_(domain)
    , color_(color)
    , suppressLoggingInitialized_(suppressLoggingInitialized) {
#ifdef EINA
  InitializeEina();
#endif
}

Logger::Logger(const Logger& other) noexcept
    : log_domain_(kUnintializedLogDomain_)
    , domain_str_(other.domain_str_)
    , color_(other.color_)
    , suppressLoggingInitialized_(other.suppressLoggingInitialized_) {
#ifdef EINA
  InitializeEina();
#endif
}

Logger::Logger(Logger&& other) noexcept
    : log_domain_(kUnintializedLogDomain_)
    , domain_str_(std::move(std::forward<std::string>(
        other.domain_str_)))
    , color_(std::move(std::forward<std::string>(other.color_)))
    , suppressLoggingInitialized_(
        std::move(std::forward<bool>(
            other.suppressLoggingInitialized_))) {
#ifdef EINA
  InitializeEina();
#endif
}

Logger& Logger::operator=(const Logger& other) noexcept {
  log_domain_ = (kUnintializedLogDomain_);
  domain_str_ = (other.domain_str_);
  color_ = (other.color_);
  suppressLoggingInitialized_ = (other.suppressLoggingInitialized_);
#ifdef EINA
  InitializeEina();
#endif
  return *this;
}

Logger& Logger::operator=(Logger&& other) noexcept {
  log_domain_ = (kUnintializedLogDomain_);
  domain_str_ = (std::move(std::forward<std::string>(
        other.domain_str_)));
  color_ = (std::move(std::forward<std::string>(other.color_)));
  suppressLoggingInitialized_ = (
        std::move(std::forward<bool>(
            other.suppressLoggingInitialized_)));
#ifdef EINA
  InitializeEina();
#endif
  return *this;
}

Logger::~Logger() {
#ifdef EINA
  DisposeEina();
#endif
}

#ifdef EINA

void Logger::InitializeEina() noexcept {
  DisposeEina();
  eina_init();
  eina_log_threads_enable();
  int len = strlen(kCommonDomain) + strlen(domain_str_.c_str()) + 1;
  char *fullDomain = new char[len];
  snprintf(fullDomain, len, "%s%s", kCommonDomain, domain_str_.c_str());
  log_domain_ = eina_log_domain_register(fullDomain, color_.c_str());
  if (log_domain_ < 0) {
    int message_len = len + 128;
    char *message = new char[message_len];
    snprintf(message, message_len, "%s%s%s",
            "could not register ", fullDomain, " log domain.");
    EINA_LOG_DOM_ERR(EINA_LOG_DOMAIN_GLOBAL, "%s", message);
    log_domain_ = EINA_LOG_DOMAIN_GLOBAL;
  } else {
    if (!suppressLoggingInitialized_) {
      DBG("Logging was initialized with domain %i.",
          log_domain_);
    }
  }
  delete[] fullDomain;
}

void Logger::DisposeEina() noexcept {
  if (log_domain_ != kUnintializedLogDomain_ &&
      log_domain_ != EINA_LOG_DOMAIN_GLOBAL) {
    if (!suppressLoggingInitialized_) {
      DBG("Domain %i is not registered now", log_domain_);
    }
    eina_log_domain_unregister(log_domain_);
    log_domain_ = kUnintializedLogDomain_;
  }
}

#endif

int Logger::log_domain() const noexcept {
#ifdef EINA
  assert(log_domain_ != kUnintializedLogDomain_);
#endif
  return log_domain_;
}

std::string Logger::domain_str() const noexcept {
  return domain_str_;
}

void Logger::set_domain_str(const std::string &value) noexcept {
  domain_str_ = value;
#ifdef EINA
  InitializeEina();
#endif
}

std::string Logger::color() const noexcept {
  return color_;
}

void Logger::set_color(const std::string &value) noexcept {
  color_ = value;
#ifdef EINA
  InitializeEina();
#endif
}

}  // namespace SoundFeatureExtraction
<commit_msg>Fixed build if Eina is not selected<commit_after>/*! @file logger.cc
 *  @brief New file description.
 *  @author Markovtsev Vadim <v.markovtsev@samsung.com>
 *  @version 1.0
 *
 *  @section Notes
 *  This code partially conforms to Google C++ Style Guide.
 *
 *  @section Copyright
 *  Copyright 2013 Samsung R&D Institute Russia
 */

#include "src/logger.h"
#include <assert.h>
#include <cxxabi.h>
#include <string.h>

namespace SoundFeatureExtraction {

// The following defines must not be converted to static const members of Logger
// due to the undefined order in which static constructors are invoked.
#define kDefaultLoggerColor EINA_COLOR_WHITE
#define kCommonDomain ""
#define kUnintializedLogDomain_ (-1)

Logger::Logger(const std::string &domain = "default",
               const std::string &color = kDefaultLoggerColor,
               bool suppressLoggingInitialized) noexcept
    : log_domain_(kUnintializedLogDomain_)
    , domain_str_(domain)
    , color_(color)
    , suppressLoggingInitialized_(suppressLoggingInitialized) {
#ifdef EINA
  InitializeEina();
#endif
}

Logger::Logger(const Logger& other) noexcept
    : log_domain_(kUnintializedLogDomain_)
    , domain_str_(other.domain_str_)
    , color_(other.color_)
    , suppressLoggingInitialized_(other.suppressLoggingInitialized_) {
#ifdef EINA
  InitializeEina();
#endif
}

Logger::Logger(Logger&& other) noexcept
    : log_domain_(kUnintializedLogDomain_)
    , domain_str_(std::move(std::forward<std::string>(
        other.domain_str_)))
    , color_(std::move(std::forward<std::string>(other.color_)))
    , suppressLoggingInitialized_(
        std::move(std::forward<bool>(
            other.suppressLoggingInitialized_))) {
#ifdef EINA
  InitializeEina();
#endif
}

Logger& Logger::operator=(const Logger& other) noexcept {
  log_domain_ = (kUnintializedLogDomain_);
  domain_str_ = (other.domain_str_);
  color_ = (other.color_);
  suppressLoggingInitialized_ = (other.suppressLoggingInitialized_);
#ifdef EINA
  InitializeEina();
#endif
  return *this;
}

Logger& Logger::operator=(Logger&& other) noexcept {
  log_domain_ = (kUnintializedLogDomain_);
  domain_str_ = (std::move(std::forward<std::string>(
        other.domain_str_)));
  color_ = (std::move(std::forward<std::string>(other.color_)));
  suppressLoggingInitialized_ = (
        std::move(std::forward<bool>(
            other.suppressLoggingInitialized_)));
#ifdef EINA
  InitializeEina();
#endif
  return *this;
}

Logger::~Logger() {
#ifdef EINA
  DisposeEina();
#endif
}

#ifdef EINA

void Logger::InitializeEina() noexcept {
  DisposeEina();
  eina_init();
  eina_log_threads_enable();
  int len = strlen(kCommonDomain) + strlen(domain_str_.c_str()) + 1;
  char *fullDomain = new char[len];
  snprintf(fullDomain, len, "%s%s", kCommonDomain, domain_str_.c_str());
  log_domain_ = eina_log_domain_register(fullDomain, color_.c_str());
  if (log_domain_ < 0) {
    int message_len = len + 128;
    char *message = new char[message_len];
    snprintf(message, message_len, "%s%s%s",
            "could not register ", fullDomain, " log domain.");
    EINA_LOG_DOM_ERR(EINA_LOG_DOMAIN_GLOBAL, "%s", message);
    log_domain_ = EINA_LOG_DOMAIN_GLOBAL;
  } else {
    if (!suppressLoggingInitialized_) {
      DBG("Logging was initialized with domain %i.",
          log_domain_);
    }
  }
  delete[] fullDomain;
}

void Logger::DisposeEina() noexcept {
  if (log_domain_ != kUnintializedLogDomain_ &&
      log_domain_ != EINA_LOG_DOMAIN_GLOBAL) {
    if (!suppressLoggingInitialized_) {
      DBG("Domain %i is not registered now", log_domain_);
    }
    eina_log_domain_unregister(log_domain_);
    log_domain_ = kUnintializedLogDomain_;
  }
}

#endif

int Logger::log_domain() const noexcept {
#ifdef EINA
  assert(log_domain_ != kUnintializedLogDomain_);
#endif
  return log_domain_;
}

std::string Logger::domain_str() const noexcept {
  return domain_str_;
}

void Logger::set_domain_str(const std::string &value) noexcept {
  domain_str_ = value;
#ifdef EINA
  InitializeEina();
#endif
}

std::string Logger::color() const noexcept {
  return color_;
}

void Logger::set_color(const std::string &value) noexcept {
  color_ = value;
#ifdef EINA
  InitializeEina();
#endif
}

}  // namespace SoundFeatureExtraction
<|endoftext|>


<commit_before>/*
 * lz4xx - C++ wrapper for LZ4 compression algorithm
 *
 * Author: Tsz-Ho Yu (tszhoyu@gmail.com)
 *
 */

#include "lz4xx.h"

static const size_t LZ4BLOCKSIZE = 8192;

LZ4OutStream::LZ4OutStream()
{
    mIsOpened = 0;
}

void LZ4OutStream::open(char** ptr, size_t* sizeloc)
{
    *sizeloc = 0;
    *ptr = NULL;
    mSize = sizeloc;
    mBuf = (void**)ptr;
    mSpace = 0;
    mIsOpened = 1;
}

void LZ4OutStream::open(FILE* fd)
{
    mBuf = (void**) fd;
    mSpace = 0;
    mSize = NULL;
    mIsOpened = 2;
}

size_t LZ4OutStream::write(const void* in, const size_t inlen)
{
    if (mIsOpened == 1)
    {
        if (*mSize + inlen > mSpace)
        {
            mSpace = ((*mSize) + inlen) << 1;
            *mBuf = (void*)realloc(*mBuf, mSpace);
            if (*mBuf == NULL)
            {
                return 0;
            }
        }
        memcpy((char*)*mBuf + *mSize, in, inlen);
        *mSize += inlen;
        return inlen;
    }
    if (mIsOpened == 2)
    {
        return fwrite(in, 1, inlen, (FILE*)mBuf);
    }
    return 0;
}

LZ4InStream::LZ4InStream()
{
    mIsOpened = 0;
}

void LZ4InStream::open(const void* ptr, size_t inlen)
{
    mSpace = inlen;
    mBuf = (char*) ptr;
    mReadPtr = mBuf;
    mIsOpened = 1;
}

void LZ4InStream::open(FILE *fd)
{
    mBuf = (char*) fd;
    mReadPtr = NULL;
    mIsOpened = 2;
}

size_t LZ4InStream::read(void* ptr, size_t size)
{
    if (mIsOpened == 1)
    {
        if (((mBuf + mSpace - mReadPtr) < size) && (mSpace > 0))
        {
            size = mBuf + mSpace - mReadPtr;
            if (size < 0)
            {
                return 0;
            }
        }
        memcpy(ptr, mReadPtr, size);
        mReadPtr += size;
        return size;
    }
    if (mIsOpened == 2)
    {
        return fread(ptr, 1, size, (FILE*) mBuf);
    }
    return 0;
}

LZ4Encoder::LZ4Encoder()
{
    init(LZ4BLOCKSIZE);
}

LZ4Encoder::LZ4Encoder(const size_t blockSize)
{
    init(blockSize);
}

void LZ4Encoder::init(const size_t blockSize)
{
    mBlockSize = blockSize;
    mBlock = NULL;
    mTotalWritten = 0;
    mTotalRead = 0;
    mBlock = new char[mBlockSize];
}

int LZ4Encoder::open(FILE* out)
{
    // set file
    mOut.open(out);
    // init LZ4
    LZ4_resetStream(&mStream);
    // init block size
    mBlockSpace = mBlockSize;
    return 0;
}

int LZ4Encoder::open(char** out, size_t* outlen)
{
    // init LZ4
    mOut.open(out, outlen);
    LZ4_resetStream(&mStream);
    // init block size
    mBlockSpace = mBlockSize;
    return 0;
}

size_t LZ4Encoder::encode(char* in, size_t inlen)
{
    mIn.open(in, inlen);
    return encode(inlen);
}

size_t LZ4Encoder::encode(FILE* in)
{
    mIn.open(in);
    return encode(-1);
}

size_t LZ4Encoder::encode(size_t inlen)
{
    size_t remain = inlen;
    while (1)
    {
        char* bufPtr = mBlock + mBlockSize - mBlockSpace;

        size_t toRead = (remain > mBlockSpace || inlen < 0) ? mBlockSpace : remain;

        size_t readSize = mIn.read(bufPtr, toRead);
        if (readSize == 0)
        {
            break;
        }
        remain -= readSize;
        mTotalRead += readSize;
        mBlockSpace -= readSize;
        if (remain <= 0)
        {
            break;
        }
        if (mBlockSpace == 0){
            mTotalWritten += flush();
        }
    }
    return mTotalWritten;
}

size_t LZ4Encoder::close()
{
    int zero = 0;
    mTotalWritten += flush();
    mTotalWritten += mOut.write(&zero, sizeof(zero));
    return mTotalWritten;
}

size_t LZ4Encoder::flush()
{
    // current block size
    size_t written = 0;
    size_t rawBlockSize = mBlockSize - mBlockSpace;
    char cBlock[LZ4_COMPRESSBOUND(rawBlockSize)];
    int cBlockSize = LZ4_compress_fast_continue(&mStream, mBlock, cBlock, rawBlockSize, sizeof(cBlock), 1);
    if (cBlockSize <= 0)
    {
        return -1; // if compression fails
    }
    // for debug use
    /*
    printf("%6d bytes -> %6d bytes, compression rate %10.2f%%\n", (int) rawBlockSize, (int) cBlockSize, (float)(100.0 * cBlockSize)/rawBlockSize);
    */
    // write to mOutPtr
    written += mOut.write(&cBlockSize, sizeof(cBlockSize));
    written += mOut.write(&cBlock, (size_t) cBlockSize);
    // reset block
    mBlockSpace = mBlockSize;
    return written;
}

size_t LZ4Encoder::getTotalByteWritten() const
{
    return mTotalWritten;
}

size_t LZ4Encoder::getTotalByteRead() const
{
    return mTotalRead;
}

LZ4Encoder::~LZ4Encoder()
{
    if (mBlock != NULL)
    {
        delete[] mBlock;
    }
}

LZ4Decoder::LZ4Decoder()
{
    init(LZ4BLOCKSIZE);
}

LZ4Decoder::LZ4Decoder(const size_t blockSize)
{
    init(blockSize);
}

void LZ4Decoder::init(const size_t blockSize)
{
    mBlockSize = blockSize;
    mTotalWritten = 0;
    mTotalRead = 0;
}

int LZ4Decoder::open(FILE* out)
{
    mOut.open(out);
    LZ4_setStreamDecode(&mStreamDecode, NULL, 0);
    return 0;
}

int LZ4Decoder::open(char** out, size_t* outlen)
{
    mOut.open(out, outlen);
    LZ4_setStreamDecode(&mStreamDecode, NULL, 0);
    return 0;
}

size_t LZ4Decoder::decode(FILE* in)
{
    mIn.open(in);
    return decode(-1);
}

size_t LZ4Decoder::decode(char* in, size_t inlen)
{
    mIn.open(in, inlen);
    return decode(inlen);
}

size_t LZ4Decoder::decode(size_t inlen)
{
    char outBuf[mBlockSize];
    int inBlockSize;
    char cmpBuf[LZ4_COMPRESSBOUND(mBlockSize)];
    size_t remain = inlen;
    while (1)
    {
        size_t readCount = mIn.read(&inBlockSize, sizeof(inBlockSize));
        mTotalRead += readCount;
        if (inBlockSize <= 0 || readCount != sizeof(inBlockSize))
        {
            return 0;
        }
        size_t readCountBuf = mIn.read(cmpBuf, inBlockSize);
        mTotalRead += readCountBuf;
        if ((int)readCountBuf != inBlockSize)
        {
            break;
        }
        int outBlockSize = LZ4_decompress_safe_continue(&mStreamDecode, cmpBuf, outBuf, inBlockSize, mBlockSize);
        mTotalWritten += mOut.write(outBuf, outBlockSize);
        remain = inlen - outBlockSize;
        if (remain < mBlockSize)
        {
            break;
        }
    }
    return inlen - remain;
}

size_t LZ4Decoder::getTotalByteWritten() const
{
    return mTotalWritten;
}

size_t LZ4Decoder::getTotalByteRead() const
{
    return mTotalRead;
}

LZ4Decoder::~LZ4Decoder()
{
    // do nothing
}

<commit_msg>char array must have a const type issue<commit_after>/*
 * lz4xx - C++ wrapper for LZ4 compression algorithm
 *
 * Author: Tsz-Ho Yu (tszhoyu@gmail.com)
 *
 */

#include "lz4xx.h"

static const size_t LZ4BLOCKSIZE = 8192;

LZ4OutStream::LZ4OutStream()
{
    mIsOpened = 0;
}

void LZ4OutStream::open(char** ptr, size_t* sizeloc)
{
    *sizeloc = 0;
    *ptr = NULL;
    mSize = sizeloc;
    mBuf = (void**)ptr;
    mSpace = 0;
    mIsOpened = 1;
}

void LZ4OutStream::open(FILE* fd)
{
    mBuf = (void**) fd;
    mSpace = 0;
    mSize = NULL;
    mIsOpened = 2;
}

size_t LZ4OutStream::write(const void* in, const size_t inlen)
{
    if (mIsOpened == 1)
    {
        if (*mSize + inlen > mSpace)
        {
            mSpace = ((*mSize) + inlen) << 1;
            *mBuf = (void*)realloc(*mBuf, mSpace);
            if (*mBuf == NULL)
            {
                return 0;
            }
        }
        memcpy((char*)*mBuf + *mSize, in, inlen);
        *mSize += inlen;
        return inlen;
    }
    if (mIsOpened == 2)
    {
        return fwrite(in, 1, inlen, (FILE*)mBuf);
    }
    return 0;
}

LZ4InStream::LZ4InStream()
{
    mIsOpened = 0;
}

void LZ4InStream::open(const void* ptr, size_t inlen)
{
    mSpace = inlen;
    mBuf = (char*) ptr;
    mReadPtr = mBuf;
    mIsOpened = 1;
}

void LZ4InStream::open(FILE *fd)
{
    mBuf = (char*) fd;
    mReadPtr = NULL;
    mIsOpened = 2;
}

size_t LZ4InStream::read(void* ptr, size_t size)
{
    if (mIsOpened == 1)
    {
        if (((mBuf + mSpace - mReadPtr) < size) && (mSpace > 0))
        {
            size = mBuf + mSpace - mReadPtr;
            if (size < 0)
            {
                return 0;
            }
        }
        memcpy(ptr, mReadPtr, size);
        mReadPtr += size;
        return size;
    }
    if (mIsOpened == 2)
    {
        return fread(ptr, 1, size, (FILE*) mBuf);
    }
    return 0;
}

LZ4Encoder::LZ4Encoder()
{
    init(LZ4BLOCKSIZE);
}

LZ4Encoder::LZ4Encoder(const size_t blockSize)
{
    init(blockSize);
}

void LZ4Encoder::init(const size_t blockSize)
{
    mBlockSize = blockSize;
    mBlock = NULL;
    mTotalWritten = 0;
    mTotalRead = 0;
    mBlock = new char[mBlockSize];
}

int LZ4Encoder::open(FILE* out)
{
    // set file
    mOut.open(out);
    // init LZ4
    LZ4_resetStream(&mStream);
    // init block size
    mBlockSpace = mBlockSize;
    return 0;
}

int LZ4Encoder::open(char** out, size_t* outlen)
{
    // init LZ4
    mOut.open(out, outlen);
    LZ4_resetStream(&mStream);
    // init block size
    mBlockSpace = mBlockSize;
    return 0;
}

size_t LZ4Encoder::encode(char* in, size_t inlen)
{
    mIn.open(in, inlen);
    return encode(inlen);
}

size_t LZ4Encoder::encode(FILE* in)
{
    mIn.open(in);
    return encode(-1);
}

size_t LZ4Encoder::encode(size_t inlen)
{
    size_t remain = inlen;
    while (1)
    {
        char* bufPtr = mBlock + mBlockSize - mBlockSpace;

        size_t toRead = (remain > mBlockSpace || inlen < 0) ? mBlockSpace : remain;

        size_t readSize = mIn.read(bufPtr, toRead);
        if (readSize == 0)
        {
            break;
        }
        remain -= readSize;
        mTotalRead += readSize;
        mBlockSpace -= readSize;
        if (remain <= 0)
        {
            break;
        }
        if (mBlockSpace == 0){
            mTotalWritten += flush();
        }
    }
    return mTotalWritten;
}

size_t LZ4Encoder::close()
{
    int zero = 0;
    mTotalWritten += flush();
    mTotalWritten += mOut.write(&zero, sizeof(zero));
    return mTotalWritten;
}

size_t LZ4Encoder::flush()
{
    // current block size
    size_t written = 0;
    size_t rawBlockSize = mBlockSize - mBlockSpace;
    //char cBlock[LZ4_COMPRESSBOUND(rawBlockSize)]; //expression must have a const size
	char *cBlock;
	cBlock = (char *)malloc(LZ4_COMPRESSBOUND(rawBlockSize));

    int cBlockSize = LZ4_compress_fast_continue(&mStream, mBlock, cBlock, rawBlockSize, sizeof(cBlock), 1);
    if (cBlockSize <= 0)
    {
        return -1; // if compression fails
    }
    // for debug use
    /*
    printf("%6d bytes -> %6d bytes, compression rate %10.2f%%\n", (int) rawBlockSize, (int) cBlockSize, (float)(100.0 * cBlockSize)/rawBlockSize);
    */
    // write to mOutPtr
    written += mOut.write(&cBlockSize, sizeof(cBlockSize));
    written += mOut.write(&cBlock, (size_t) cBlockSize);
    // reset block
    mBlockSpace = mBlockSize;
    return written;
}

size_t LZ4Encoder::getTotalByteWritten() const
{
    return mTotalWritten;
}

size_t LZ4Encoder::getTotalByteRead() const
{
    return mTotalRead;
}

LZ4Encoder::~LZ4Encoder()
{
    if (mBlock != NULL)
    {
        delete[] mBlock;
    }
}

LZ4Decoder::LZ4Decoder()
{
    init(LZ4BLOCKSIZE);
}

LZ4Decoder::LZ4Decoder(const size_t blockSize)
{
    init(blockSize);
}

void LZ4Decoder::init(const size_t blockSize)
{
    mBlockSize = blockSize;
    mTotalWritten = 0;
    mTotalRead = 0;
}

int LZ4Decoder::open(FILE* out)
{
    mOut.open(out);
    LZ4_setStreamDecode(&mStreamDecode, NULL, 0);
    return 0;
}

int LZ4Decoder::open(char** out, size_t* outlen)
{
    mOut.open(out, outlen);
    LZ4_setStreamDecode(&mStreamDecode, NULL, 0);
    return 0;
}

size_t LZ4Decoder::decode(FILE* in)
{
    mIn.open(in);
    return decode(-1);
}

size_t LZ4Decoder::decode(char* in, size_t inlen)
{
    mIn.open(in, inlen);
    return decode(inlen);
}

size_t LZ4Decoder::decode(size_t inlen)
{
	//char outBuf[size]; //expression must have a const size
    char *outBuf;
	outBuf = (char *)malloc(sizeof(size_t) * mBlockSize);

	//char cmpBuf[LZ4_COMPRESSBOUND(mBlockSize)]; //expression must have a const size
	char *cmpBuf;
	cmpBuf = (char *)malloc(LZ4_COMPRESSBOUND(mBlockSize));

    int inBlockSize;
    size_t remain = inlen;
    while (1)
    {
        size_t readCount = mIn.read(&inBlockSize, sizeof(inBlockSize));
        mTotalRead += readCount;
        if (inBlockSize <= 0 || readCount != sizeof(inBlockSize))
        {
            return 0;
        }
        size_t readCountBuf = mIn.read(cmpBuf, inBlockSize);
        mTotalRead += readCountBuf;
        if ((int)readCountBuf != inBlockSize)
        {
            break;
        }
        int outBlockSize = LZ4_decompress_safe_continue(&mStreamDecode, cmpBuf, outBuf, inBlockSize, mBlockSize);
        mTotalWritten += mOut.write(outBuf, outBlockSize);
        remain = inlen - outBlockSize;
        if (remain < mBlockSize)
        {
            break;
        }
    }
    return inlen - remain;
}

size_t LZ4Decoder::getTotalByteWritten() const
{
    return mTotalWritten;
}

size_t LZ4Decoder::getTotalByteRead() const
{
    return mTotalRead;
}

LZ4Decoder::~LZ4Decoder()
{
    // do nothing
}

<|endoftext|>


<commit_before>/*
    Persons Model Item
    Represents one person in the model
    Copyright (C) 2012  Martin Klapetek <martin.klapetek@gmail.com>

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

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

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "personitem.h"
#include "contactitem.h"

#include <Nepomuk2/Vocabulary/PIMO>
#include <Nepomuk2/Vocabulary/NCO>
#include <Nepomuk2/Resource>
#include <Nepomuk2/Variant>
#include <Soprano/Vocabulary/NAO>

using namespace KPeople;

PersonItem::PersonItem(const QUrl &personUri)
{
    setData(personUri, PersonsModel::UriRole);
}

QUrl PersonItem::uri() const
{
    return QStandardItem::data(PersonsModel::UriRole).toUrl();
}

QVariant PersonItem::queryChildrenForRole(int role) const
{
    QVariant ret;
    for (int i = 0; i < rowCount(); i++) {
        QVariant value = child(i)->data(role);
        if (!value.isNull()) {
            ret = value;
            break;
        }
    }
    return ret;
}

QVariantList PersonItem::queryChildrenForRoleList(int role) const
{
    QVariantList ret;
    for (int i = 0; i < rowCount(); i++) {
        QVariant value = child(i)->data(role);
        if (value.type() == QVariant::List) {
            ret += value.toList();
        } else {
            ret += value;
        }
    }
    return ret;
}

QVariant PersonItem::data(int role) const
{
    if (role == PersonsModel::PresenceTypeRole
        || role == PersonsModel::PresenceDisplayRole
        || role == PersonsModel::PresenceDecorationRole
        || role == PersonsModel::PresenceIconNameRole) {

        QVariantList presences = queryChildrenForRoleList(PersonsModel::PresenceTypeRole);

        if (presences.isEmpty()) {
            return QVariant();
        }

        //we find which position in the list contains the most online presence
        //and then we use that index to return the other roles
        int mostOnlineIndex = -1;
        int mostOnlinePresence = 999;

        for (int i = 0; i < presences.size(); i++) {
            int currentPresencePriority = presenceSortPriority(presences.at(i).toString());
            if (currentPresencePriority < mostOnlinePresence) {
                mostOnlineIndex = i;
                mostOnlinePresence = currentPresencePriority;

                //if the most online is "available",
                //break as there can't be anything more online
                if (mostOnlinePresence == 0) {
                    break;
                }
            }
        }

        Q_ASSERT(mostOnlineIndex != -1);

        switch (role) {
            case PersonsModel::PresenceTypeRole:
                return presences.at(mostOnlineIndex);
            case PersonsModel::PresenceDisplayRole: {
                const QVariantList presenceDisplayNames = queryChildrenForRoleList(PersonsModel::PresenceDisplayRole);
                return presenceDisplayNames.at(mostOnlineIndex);
            }
            case PersonsModel::PresenceDecorationRole: {
                const QVariantList presenceDecoration = queryChildrenForRoleList(PersonsModel::PresenceDecorationRole);
                return presenceDecoration.at(mostOnlineIndex);
            }
            case PersonsModel::PresenceIconNameRole: {
                const QVariantList presenceIconNames = queryChildrenForRoleList(PersonsModel::PresenceIconNameRole);
                return presenceIconNames.at(mostOnlineIndex);
            }
        }
    }

    if (role == PersonsModel::UriRole) {
        //return child contact uri instead of fake uri for fake persons
        if (QStandardItem::data(PersonsModel::UriRole).toString().startsWith("fakeperson")) {
            return child(0)->data(PersonsModel::UriRole);
        }
        return QStandardItem::data(role);
    }

    QVariantList ret;
    for (int i = 0; i < rowCount(); i++) {
        QVariant value;
        //if we're being asked for the child contacts uris,
        //we need to query the children for their UriRole
        if (role == PersonsModel::ChildContactsUriRole) {
            value = child(i)->data(PersonsModel::UriRole);
        } else {
            value = child(i)->data(role);
        }
        //these roles must return single QVariant
        if ((role == Qt::DisplayRole || role == Qt::DecorationRole)) {
            return value;
        }
        if (value.type() == QVariant::List) {
            ret += value.toList();
        } else if (!value.isNull()) {
            ret += value;
        }
    }

    if (ret.isEmpty()) {
        //we need to return empty qvariant here, otherwise we'd get a qvariant
        //with empty qvariantlist, which would get parsed as non-empty qvariant
        return QVariant();
    }

    return ret;
}

int PersonItem::presenceSortPriority(const QString &presenceName) const
{
    if (presenceName == QLatin1String("available")) {
        return 0;
    }

    if (presenceName == QLatin1String("busy") || presenceName == QLatin1String("dnd")) {
        return 1;
    }

    if (presenceName == QLatin1String("hidden")) {
        return 2;
    }

    if (presenceName == QLatin1String("away")) {
        return 3;
    }

    if (presenceName == QLatin1String("xa")) {
        return 4;
    }

    if (presenceName == QLatin1String("unknown")) {
        return 5;
    }

    return 6;
}

void PersonItem::contactDataChanged()
{
    emitDataChanged();
}
<commit_msg>remove redundant parenthesis<commit_after>/*
    Persons Model Item
    Represents one person in the model
    Copyright (C) 2012  Martin Klapetek <martin.klapetek@gmail.com>

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

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

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "personitem.h"
#include "contactitem.h"

#include <Nepomuk2/Vocabulary/PIMO>
#include <Nepomuk2/Vocabulary/NCO>
#include <Nepomuk2/Resource>
#include <Nepomuk2/Variant>
#include <Soprano/Vocabulary/NAO>

using namespace KPeople;

PersonItem::PersonItem(const QUrl &personUri)
{
    setData(personUri, PersonsModel::UriRole);
}

QUrl PersonItem::uri() const
{
    return QStandardItem::data(PersonsModel::UriRole).toUrl();
}

QVariant PersonItem::queryChildrenForRole(int role) const
{
    QVariant ret;
    for (int i = 0; i < rowCount(); i++) {
        QVariant value = child(i)->data(role);
        if (!value.isNull()) {
            ret = value;
            break;
        }
    }
    return ret;
}

QVariantList PersonItem::queryChildrenForRoleList(int role) const
{
    QVariantList ret;
    for (int i = 0; i < rowCount(); i++) {
        QVariant value = child(i)->data(role);
        if (value.type() == QVariant::List) {
            ret += value.toList();
        } else {
            ret += value;
        }
    }
    return ret;
}

QVariant PersonItem::data(int role) const
{
    if (role == PersonsModel::PresenceTypeRole
        || role == PersonsModel::PresenceDisplayRole
        || role == PersonsModel::PresenceDecorationRole
        || role == PersonsModel::PresenceIconNameRole) {

        QVariantList presences = queryChildrenForRoleList(PersonsModel::PresenceTypeRole);

        if (presences.isEmpty()) {
            return QVariant();
        }

        //we find which position in the list contains the most online presence
        //and then we use that index to return the other roles
        int mostOnlineIndex = -1;
        int mostOnlinePresence = 999;

        for (int i = 0; i < presences.size(); i++) {
            int currentPresencePriority = presenceSortPriority(presences.at(i).toString());
            if (currentPresencePriority < mostOnlinePresence) {
                mostOnlineIndex = i;
                mostOnlinePresence = currentPresencePriority;

                //if the most online is "available",
                //break as there can't be anything more online
                if (mostOnlinePresence == 0) {
                    break;
                }
            }
        }

        Q_ASSERT(mostOnlineIndex != -1);

        switch (role) {
            case PersonsModel::PresenceTypeRole:
                return presences.at(mostOnlineIndex);
            case PersonsModel::PresenceDisplayRole: {
                const QVariantList presenceDisplayNames = queryChildrenForRoleList(PersonsModel::PresenceDisplayRole);
                return presenceDisplayNames.at(mostOnlineIndex);
            }
            case PersonsModel::PresenceDecorationRole: {
                const QVariantList presenceDecoration = queryChildrenForRoleList(PersonsModel::PresenceDecorationRole);
                return presenceDecoration.at(mostOnlineIndex);
            }
            case PersonsModel::PresenceIconNameRole: {
                const QVariantList presenceIconNames = queryChildrenForRoleList(PersonsModel::PresenceIconNameRole);
                return presenceIconNames.at(mostOnlineIndex);
            }
        }
    }

    if (role == PersonsModel::UriRole) {
        //return child contact uri instead of fake uri for fake persons
        if (QStandardItem::data(PersonsModel::UriRole).toString().startsWith("fakeperson")) {
            return child(0)->data(PersonsModel::UriRole);
        }
        return QStandardItem::data(role);
    }

    QVariantList ret;
    for (int i = 0; i < rowCount(); i++) {
        QVariant value;
        //if we're being asked for the child contacts uris,
        //we need to query the children for their UriRole
        if (role == PersonsModel::ChildContactsUriRole) {
            value = child(i)->data(PersonsModel::UriRole);
        } else {
            value = child(i)->data(role);
        }
        //these roles must return single QVariant
        if (role == Qt::DisplayRole || role == Qt::DecorationRole) {
            return value;
        }
        if (value.type() == QVariant::List) {
            ret += value.toList();
        } else if (!value.isNull()) {
            ret += value;
        }
    }

    if (ret.isEmpty()) {
        //we need to return empty qvariant here, otherwise we'd get a qvariant
        //with empty qvariantlist, which would get parsed as non-empty qvariant
        return QVariant();
    }

    return ret;
}

int PersonItem::presenceSortPriority(const QString &presenceName) const
{
    if (presenceName == QLatin1String("available")) {
        return 0;
    }

    if (presenceName == QLatin1String("busy") || presenceName == QLatin1String("dnd")) {
        return 1;
    }

    if (presenceName == QLatin1String("hidden")) {
        return 2;
    }

    if (presenceName == QLatin1String("away")) {
        return 3;
    }

    if (presenceName == QLatin1String("xa")) {
        return 4;
    }

    if (presenceName == QLatin1String("unknown")) {
        return 5;
    }

    return 6;
}

void PersonItem::contactDataChanged()
{
    emitDataChanged();
}
<|endoftext|>


<commit_before>/* -*- Mode: C; indent-tabs-mode: s; c-basic-offset: 4; tab-width: 4 -*- */
/* vim:set et ai sw=4 ts=4 sts=4: tw=80 cino="(0,W2s,i2s,t0,l1,:0" */
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary (-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of battery-applet.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/
#include "batterybusinesslogic.h"
#include <MGConfItem>
#include <QVariant>
#include <QString>

#define DEBUG
#define WARNING
#include "../debug.h"

static const QString psm_auto_key =
    "/system/osso/dsm/energymanagement/enable_power_saving";
static const QString psm_values_key =
    "/system/osso/dsm/energymanagement/possible_psm_thresholds";

static const int animation_rate_charging_usb  = 500;
static const int animation_rate_charging_wall = 250;

BatteryBusinessLogic::BatteryBusinessLogic (
        QObject *parent)
    : QObject (parent),
    m_initialized (false),
    m_ChargingRate (-1),
    m_Charging (false)
{
    #ifdef HAVE_QMSYSTEM
    m_battery    = new QmBattery (this);
    m_devicemode = new QmDeviceMode (this);
    #endif
}

BatteryBusinessLogic::~BatteryBusinessLogic ()
{
}

/*
 * This function does the initialization and signal connection to QmBattery and
 * QmDeviceMode, and emits all the signals with the current values...
 *
 * FIXME: This function should be called realize() or something...
 */
void
BatteryBusinessLogic::requestValues ()
{
    if (m_initialized)
        return;

    m_initialized = true;

    #ifdef HAVE_QMSYSTEM
    SYS_DEBUG ("Connecting to the signals of the QmBattery class");
    connect (
        m_battery, SIGNAL(chargerEvent(Maemo::QmBattery::ChargerType)),
        this, SLOT(batteryChargerEvent(Maemo::QmBattery::ChargerType)));
    connect (
        m_battery, SIGNAL(chargingStateChanged(Maemo::QmBattery::ChargingState)),
        this, SLOT(chargingStateChanged(Maemo::QmBattery::ChargingState)));
    connect (
        m_battery, SIGNAL(batteryStateChanged(Maemo::QmBattery::BatteryState)),
        this, SLOT (batteryStateChanged(Maemo::QmBattery::BatteryState)));

    // This will emit the batteryCharging signal,
    // and the remainingTimeValuesChanged signal
    chargingStateChanged (m_battery->getChargingState ());

    /*
     * We have two signals showing that the battery energy level has been
     * changed. We listen both of these signals.
     */
    SYS_DEBUG ("Connecting to the signals of the QmBattery class");
    connect (m_battery, SIGNAL (batteryRemainingCapacityChanged (int, int)),
            this, SLOT (batteryRemCapacityChanged (int, int)));

    // batteryBarValueReceived also emitted by chargingStateChanged ^^^
    // FIXME: Why?
    connect (m_devicemode,
             SIGNAL (devicePSMStateChanged (Maemo::QmDeviceMode::PSMState)),
             this, SLOT (PSMStateChanged (Maemo::QmDeviceMode::PSMState)));

    SYS_DEBUG ("Emitting PSMValueReceived(%s)",
            SYS_BOOL(m_devicemode->getPSMState () == QmDeviceMode::PSMStateOn));
    emit PSMValueReceived (m_devicemode->getPSMState () ==
                           QmDeviceMode::PSMStateOn);
    #else
    /*
     * FIXME: To create an implementation without the QmSystem
     */
    #endif
}

void
BatteryBusinessLogic::setPSMThresholdValue (
        int percentage)
{
    #ifdef HAVE_QMSYSTEM
    bool ret;
    ret = m_devicemode->setPSMBatteryMode (percentage);

    if (!ret) {
        SYS_WARNING (" failed to set (precentage = %d)", percentage);
    }
    #else
    /*
     * To implement the code that sets the power save threshold without the help
     * of the QmSystem library.
     */
    #endif
}

int
BatteryBusinessLogic::PSMThresholdValue ()
{
    #ifdef HAVE_QMSYSTEM
    return m_devicemode->getPSMBatteryMode ();
    #else
    /*
     * FIXME: To implement a variant that does not use QmSystem
     */
    return 0;
    #endif
}

QStringList
BatteryBusinessLogic::PSMThresholdValues ()
{
    MGConfItem  possible_values (psm_values_key);
    QStringList retval;

    retval = possible_values.value ().toStringList ();
    if (retval.size() == 0) {
        SYS_WARNING ("The GConf key %s is not set. Falling back to default.",
                SYS_STR(psm_values_key));
        retval << "10" << "20" << "30" << "40" << "50";
    }

    return retval;
}

void
BatteryBusinessLogic::setPSMValue (
        bool enabled)
{
    bool ret = false;

    #ifdef HAVE_QMSYSTEM
    ret = m_devicemode->setPSMState (
        enabled ?
        QmDeviceMode::PSMStateOn :
        QmDeviceMode::PSMStateOff);
    #else
    /*
     * FIXME: To implement the setting of the power save mode without the help
     * of the QmSystem library.
     */
    #endif

    if (ret) {
        // Change succeed, we don't need to wait for QmSystem reply, we can emit
        // the PSMValueChanged asap to update the UI.
        SYS_DEBUG ("Emitting PSMValueReceived(%s)", SYS_BOOL(enabled));
        emit PSMValueReceived (enabled);
    } else {
        SYS_WARNING ("Failed to set PSM mode to %s",
                enabled ?
                "QmDeviceMode::PSMStateOn" : "QmDeviceMode::PSMStateOff");
    }
}

/*!
 * Sets the PSMAutoValue, a boolean that sets if the device should go into power
 * save mode automatically. This function only changes a value in the GConf
 * database.
 */
void
BatteryBusinessLogic::setPSMAutoValue (
        bool toggle)
{
    MGConfItem PSMAutoKey (psm_auto_key);
    PSMAutoKey.set (toggle);
}

/*!
 * Reads the PSMAuto value, a boolean that sets if the device should go into
 * power save mode automatically. This method is only reads the GConf database.
 */
bool
BatteryBusinessLogic::PSMAutoValue ()
{
    MGConfItem PSMAutoKey (psm_auto_key);
    return PSMAutoKey.value ().toBool ();
}

void
BatteryBusinessLogic::remainingCapacityRequired()
{
    #ifdef HAVE_QMSYSTEM
    emit remainingBatteryCapacityChanged(
            m_battery->getRemainingCapacityPct());
    #else
    /*
     * FIXME: To create an implementation that works without the QmSystem.
     */
    #endif
}

#ifdef HAVE_QMSYSTEM
/*!
 * We have three functions her that notify us about the changes in the charging
 * state. We use all of the three slots the same way, but we keep them
 * separately so we can actually see why do we need to recalculate the charging
 * info.
 */
void
BatteryBusinessLogic::batteryChargerEvent (
        Maemo::QmBattery::ChargerType type)
{
    Q_UNUSED (type);

    SYS_DEBUG ("");
    recalculateChargingInfo ();
}
#endif

#ifdef HAVE_QMSYSTEM
void
BatteryBusinessLogic::chargingStateChanged (
        Maemo::QmBattery::ChargingState state)
{
    Q_UNUSED (state);

    SYS_DEBUG ("");
    recalculateChargingInfo ();
}
#endif

#ifdef HAVE_QMSYSTEM
void
BatteryBusinessLogic::batteryStateChanged (
        Maemo::QmBattery::BatteryState batteryState)
{
    Q_UNUSED (batteryState);

    SYS_DEBUG ("");
    recalculateChargingInfo ();
}
#endif

#ifdef HAVE_QMSYSTEM
/*!
 * This slot will be called when the device power save mode is changed. The
 * method will send the PSMValueReceived() signal.
 */
void
BatteryBusinessLogic::PSMStateChanged (
        Maemo::QmDeviceMode::PSMState state)
{
    bool enabled = state == QmDeviceMode::PSMStateOn;

    SYS_DEBUG ("Emitting PSMValueReceived (%s)", SYS_BOOL(enabled));
    emit PSMValueReceived (enabled);
}
#endif

#ifdef HAVE_QMSYSTEM
void
BatteryBusinessLogic::batteryRemCapacityChanged (
		int percentage,
		int bars)
{
    Q_UNUSED (bars);

    // XXX: FIXME: maybe we can drop batteryBarValue and use 'bars' parameter..
    SYS_DEBUG ("Emitting batteryBarValueReceived(%d)",
            batteryBarValue (percentage));
    emit batteryBarValueReceived (batteryBarValue (percentage));
    emit remainingBatteryCapacityChanged(percentage);
}
#endif

/*!
 * \param percentage The energy level percentage or -1 to ask the backend.
 *
 * Returns the bar value (the value that used as an icon index representing for
 * the battery energy level) for the given percentage level. If the argument is
 * -1 this method will ask the QmBattery for the current energy level.
 *
 */
int
BatteryBusinessLogic::batteryBarValue (
        int percentage)
{
    int index;

    /*
     * If we got -1 we have to find the remaining capacity all by ourselves.
     */
    #ifdef HAVE_QMSYSTEM
    if (percentage == -1) {
        percentage = m_battery->getRemainingCapacityPct ();
    }
    #else
    /*
     * FIXME: To create an implementation that works without the QmSystem
     */
    #endif

    // in case of overflow (eg. in sbox) when we get value that greater than 100
    // percent we use 10 percent intentionaly
    if (percentage < 0)
        percentage = 0;
    else if (percentage > 100)
        percentage = 10;

    if (percentage >= 84)
        index = 9;
    else if (percentage < 84 && percentage >= 73)
        index = 8;
    else if (percentage < 73 && percentage >= 62)
        index = 7;
    else if (percentage < 62 && percentage >= 51)
        index = 6;
    else if (percentage < 51 && percentage >= 39)
        index = 5;
    else if (percentage < 39 && percentage >= 28)
        index = 4;
    else if (percentage < 28 && percentage >= 17)
        index = 3;
    else if (percentage < 17 && percentage >= 5)
        index = 2;
    else if (percentage < 5 && percentage > 1)
        index = 1;
    else // if (percentage == 0)
        index = 0;

    return index;
}

/*!
 * This function is called whenever some change is detected around the battery
 * and its charger. This method will try to find out if the battery is actually
 * charging and if it is the method will calculate the charging animation speed.
 *
 * What we managed to find aboput the charging is:
 * 1) The battery is not charging (despite any other info returned) if the
 *    battery is full. See NB#172929 for further details.
 */
void
BatteryBusinessLogic::recalculateChargingInfo ()
{
    #ifdef HAVE_QMSYSTEM
    QmBattery::ChargingState chargingState;
    QmBattery::BatteryState  batteryState;
    QmBattery::ChargerType   chargerType;
    bool                     charging;
    bool                     couldBeCharging;
    int                      chargingRate;

    chargerType = m_battery->getChargerType ();
    chargingState = m_battery->getChargingState ();
    batteryState = m_battery->getBatteryState ();

    /*
     * Carefully calculating the charging rate, the animation rate of the
     * charging indicator.
     */
    couldBeCharging =
        chargingState == QmBattery::StateCharging &&
        // This is actually not necessary, but we even check it in the unit
        // test. Just to be sure.
        chargerType != QmBattery::None;

    charging =
        batteryState != QmBattery::StateFull &&
        chargerType != QmBattery::None &&
        chargingState != QmBattery::StateNotCharging &&
        chargingState != QmBattery::StateChargingFailed;

    chargingRate = 0;
    if (charging)
        chargingRate = chargerType == QmBattery::Wall ?
            animation_rate_charging_wall : animation_rate_charging_usb;

    SYS_DEBUG ("*** charging       = %s", SYS_BOOL(charging));
    SYS_DEBUG ("*** m_Charging     = %s", SYS_BOOL(m_Charging));
    SYS_DEBUG ("*** chargingRate   = %d", chargingRate);
    SYS_DEBUG ("*** m_ChargingRate = %d", m_ChargingRate);

    if (chargingRate == m_ChargingRate &&
            couldBeCharging == m_Charging)
        return;

    /*
     * If the charging rate has been changed we need to notify the ui with a
     * signal.
     */
    m_Charging = couldBeCharging;
    SYS_DEBUG ("*** chargingRate %d -> %d", m_ChargingRate, chargingRate);
    m_ChargingRate = chargingRate;
    SYS_DEBUG ("Emitting batteryCharging(%d)", m_ChargingRate);
    emit batteryCharging (m_ChargingRate);

    /*
     * Then we need to notify everyone about the bar value.
     * FIXME: Why exactly do we need that?
     */
    SYS_DEBUG ("Emitting batteryBarValueReceived(%d)", batteryBarValue (-1));
    emit batteryBarValueReceived (batteryBarValue (-1));

    if(batteryState == QmBattery::StateFull)
    {
        emit batteryFull();
        return;
    }

    /*
     * And the remaining battery capacity has to be recalculated.
     */
    remainingCapacityRequired();
    #else
    /*
     * FIXME: To implement a variant that does not use QmSystem.
     */
    #endif
}

bool BatteryBusinessLogic::isCharging()
{
    return m_Charging;
}
<commit_msg>Changes: Battery-applet should not eat all of the CPU because of battery-charging-animation...<commit_after>/* -*- Mode: C; indent-tabs-mode: s; c-basic-offset: 4; tab-width: 4 -*- */
/* vim:set et ai sw=4 ts=4 sts=4: tw=80 cino="(0,W2s,i2s,t0,l1,:0" */
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary (-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of battery-applet.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/
#include "batterybusinesslogic.h"
#include <MGConfItem>
#include <QVariant>
#include <QString>

#define DEBUG
#define WARNING
#include "../debug.h"

static const QString psm_auto_key =
    "/system/osso/dsm/energymanagement/enable_power_saving";
static const QString psm_values_key =
    "/system/osso/dsm/energymanagement/possible_psm_thresholds";

#define SAVE_BATTERY

#ifdef SAVE_BATTERY
static const int animation_rate_charging_usb  = 500;
static const int animation_rate_charging_wall = 250;
#else
static const int animation_rate_charging_usb  = 1000;
static const int animation_rate_charging_wall = 1000;
#endif

BatteryBusinessLogic::BatteryBusinessLogic (
        QObject *parent)
    : QObject (parent),
    m_initialized (false),
    m_ChargingRate (-1),
    m_Charging (false)
{
    #ifdef HAVE_QMSYSTEM
    m_battery    = new QmBattery (this);
    m_devicemode = new QmDeviceMode (this);
    #endif
}

BatteryBusinessLogic::~BatteryBusinessLogic ()
{
}

/*
 * This function does the initialization and signal connection to QmBattery and
 * QmDeviceMode, and emits all the signals with the current values...
 *
 * FIXME: This function should be called realize() or something...
 */
void
BatteryBusinessLogic::requestValues ()
{
    if (m_initialized)
        return;

    m_initialized = true;

    #ifdef HAVE_QMSYSTEM
    SYS_DEBUG ("Connecting to the signals of the QmBattery class");
    connect (
        m_battery, SIGNAL(chargerEvent(Maemo::QmBattery::ChargerType)),
        this, SLOT(batteryChargerEvent(Maemo::QmBattery::ChargerType)));
    connect (
        m_battery, SIGNAL(chargingStateChanged(Maemo::QmBattery::ChargingState)),
        this, SLOT(chargingStateChanged(Maemo::QmBattery::ChargingState)));
    connect (
        m_battery, SIGNAL(batteryStateChanged(Maemo::QmBattery::BatteryState)),
        this, SLOT (batteryStateChanged(Maemo::QmBattery::BatteryState)));

    // This will emit the batteryCharging signal,
    // and the remainingTimeValuesChanged signal
    chargingStateChanged (m_battery->getChargingState ());

    /*
     * We have two signals showing that the battery energy level has been
     * changed. We listen both of these signals.
     */
    SYS_DEBUG ("Connecting to the signals of the QmBattery class");
    connect (m_battery, SIGNAL (batteryRemainingCapacityChanged (int, int)),
            this, SLOT (batteryRemCapacityChanged (int, int)));

    // batteryBarValueReceived also emitted by chargingStateChanged ^^^
    // FIXME: Why?
    connect (m_devicemode,
             SIGNAL (devicePSMStateChanged (Maemo::QmDeviceMode::PSMState)),
             this, SLOT (PSMStateChanged (Maemo::QmDeviceMode::PSMState)));

    SYS_DEBUG ("Emitting PSMValueReceived(%s)",
            SYS_BOOL(m_devicemode->getPSMState () == QmDeviceMode::PSMStateOn));
    emit PSMValueReceived (m_devicemode->getPSMState () ==
                           QmDeviceMode::PSMStateOn);
    #else
    /*
     * FIXME: To create an implementation without the QmSystem
     */
    #endif
}

void
BatteryBusinessLogic::setPSMThresholdValue (
        int percentage)
{
    #ifdef HAVE_QMSYSTEM
    bool ret;
    ret = m_devicemode->setPSMBatteryMode (percentage);

    if (!ret) {
        SYS_WARNING (" failed to set (precentage = %d)", percentage);
    }
    #else
    /*
     * To implement the code that sets the power save threshold without the help
     * of the QmSystem library.
     */
    #endif
}

int
BatteryBusinessLogic::PSMThresholdValue ()
{
    #ifdef HAVE_QMSYSTEM
    return m_devicemode->getPSMBatteryMode ();
    #else
    /*
     * FIXME: To implement a variant that does not use QmSystem
     */
    return 0;
    #endif
}

QStringList
BatteryBusinessLogic::PSMThresholdValues ()
{
    MGConfItem  possible_values (psm_values_key);
    QStringList retval;

    retval = possible_values.value ().toStringList ();
    if (retval.size() == 0) {
        SYS_WARNING ("The GConf key %s is not set. Falling back to default.",
                SYS_STR(psm_values_key));
        retval << "10" << "20" << "30" << "40" << "50";
    }

    return retval;
}

void
BatteryBusinessLogic::setPSMValue (
        bool enabled)
{
    bool ret = false;

    #ifdef HAVE_QMSYSTEM
    ret = m_devicemode->setPSMState (
        enabled ?
        QmDeviceMode::PSMStateOn :
        QmDeviceMode::PSMStateOff);
    #else
    /*
     * FIXME: To implement the setting of the power save mode without the help
     * of the QmSystem library.
     */
    #endif

    if (ret) {
        // Change succeed, we don't need to wait for QmSystem reply, we can emit
        // the PSMValueChanged asap to update the UI.
        SYS_DEBUG ("Emitting PSMValueReceived(%s)", SYS_BOOL(enabled));
        emit PSMValueReceived (enabled);
    } else {
        SYS_WARNING ("Failed to set PSM mode to %s",
                enabled ?
                "QmDeviceMode::PSMStateOn" : "QmDeviceMode::PSMStateOff");
    }
}

/*!
 * Sets the PSMAutoValue, a boolean that sets if the device should go into power
 * save mode automatically. This function only changes a value in the GConf
 * database.
 */
void
BatteryBusinessLogic::setPSMAutoValue (
        bool toggle)
{
    MGConfItem PSMAutoKey (psm_auto_key);
    PSMAutoKey.set (toggle);
}

/*!
 * Reads the PSMAuto value, a boolean that sets if the device should go into
 * power save mode automatically. This method is only reads the GConf database.
 */
bool
BatteryBusinessLogic::PSMAutoValue ()
{
    MGConfItem PSMAutoKey (psm_auto_key);
    return PSMAutoKey.value ().toBool ();
}

void
BatteryBusinessLogic::remainingCapacityRequired()
{
    #ifdef HAVE_QMSYSTEM
    emit remainingBatteryCapacityChanged(
            m_battery->getRemainingCapacityPct());
    #else
    /*
     * FIXME: To create an implementation that works without the QmSystem.
     */
    #endif
}

#ifdef HAVE_QMSYSTEM
/*!
 * We have three functions her that notify us about the changes in the charging
 * state. We use all of the three slots the same way, but we keep them
 * separately so we can actually see why do we need to recalculate the charging
 * info.
 */
void
BatteryBusinessLogic::batteryChargerEvent (
        Maemo::QmBattery::ChargerType type)
{
    Q_UNUSED (type);

    SYS_DEBUG ("");
    recalculateChargingInfo ();
}
#endif

#ifdef HAVE_QMSYSTEM
void
BatteryBusinessLogic::chargingStateChanged (
        Maemo::QmBattery::ChargingState state)
{
    Q_UNUSED (state);

    SYS_DEBUG ("");
    recalculateChargingInfo ();
}
#endif

#ifdef HAVE_QMSYSTEM
void
BatteryBusinessLogic::batteryStateChanged (
        Maemo::QmBattery::BatteryState batteryState)
{
    Q_UNUSED (batteryState);

    SYS_DEBUG ("");
    recalculateChargingInfo ();
}
#endif

#ifdef HAVE_QMSYSTEM
/*!
 * This slot will be called when the device power save mode is changed. The
 * method will send the PSMValueReceived() signal.
 */
void
BatteryBusinessLogic::PSMStateChanged (
        Maemo::QmDeviceMode::PSMState state)
{
    bool enabled = state == QmDeviceMode::PSMStateOn;

    SYS_DEBUG ("Emitting PSMValueReceived (%s)", SYS_BOOL(enabled));
    emit PSMValueReceived (enabled);
}
#endif

#ifdef HAVE_QMSYSTEM
void
BatteryBusinessLogic::batteryRemCapacityChanged (
		int percentage,
		int bars)
{
    Q_UNUSED (bars);

    // XXX: FIXME: maybe we can drop batteryBarValue and use 'bars' parameter..
    SYS_DEBUG ("Emitting batteryBarValueReceived(%d)",
            batteryBarValue (percentage));
    emit batteryBarValueReceived (batteryBarValue (percentage));
    emit remainingBatteryCapacityChanged(percentage);
}
#endif

/*!
 * \param percentage The energy level percentage or -1 to ask the backend.
 *
 * Returns the bar value (the value that used as an icon index representing for
 * the battery energy level) for the given percentage level. If the argument is
 * -1 this method will ask the QmBattery for the current energy level.
 *
 */
int
BatteryBusinessLogic::batteryBarValue (
        int percentage)
{
    int index;

    /*
     * If we got -1 we have to find the remaining capacity all by ourselves.
     */
    #ifdef HAVE_QMSYSTEM
    if (percentage == -1) {
        percentage = m_battery->getRemainingCapacityPct ();
    }
    #else
    /*
     * FIXME: To create an implementation that works without the QmSystem
     */
    #endif

    // in case of overflow (eg. in sbox) when we get value that greater than 100
    // percent we use 10 percent intentionaly
    if (percentage < 0)
        percentage = 0;
    else if (percentage > 100)
        percentage = 10;

    if (percentage >= 84)
        index = 9;
    else if (percentage < 84 && percentage >= 73)
        index = 8;
    else if (percentage < 73 && percentage >= 62)
        index = 7;
    else if (percentage < 62 && percentage >= 51)
        index = 6;
    else if (percentage < 51 && percentage >= 39)
        index = 5;
    else if (percentage < 39 && percentage >= 28)
        index = 4;
    else if (percentage < 28 && percentage >= 17)
        index = 3;
    else if (percentage < 17 && percentage >= 5)
        index = 2;
    else if (percentage < 5 && percentage > 1)
        index = 1;
    else // if (percentage == 0)
        index = 0;

    return index;
}

/*!
 * This function is called whenever some change is detected around the battery
 * and its charger. This method will try to find out if the battery is actually
 * charging and if it is the method will calculate the charging animation speed.
 *
 * What we managed to find aboput the charging is:
 * 1) The battery is not charging (despite any other info returned) if the
 *    battery is full. See NB#172929 for further details.
 */
void
BatteryBusinessLogic::recalculateChargingInfo ()
{
    #ifdef HAVE_QMSYSTEM
    QmBattery::ChargingState chargingState;
    QmBattery::BatteryState  batteryState;
    QmBattery::ChargerType   chargerType;
    bool                     charging;
    bool                     couldBeCharging;
    int                      chargingRate;

    chargerType = m_battery->getChargerType ();
    chargingState = m_battery->getChargingState ();
    batteryState = m_battery->getBatteryState ();

    /*
     * Carefully calculating the charging rate, the animation rate of the
     * charging indicator.
     */
    couldBeCharging =
        chargingState == QmBattery::StateCharging &&
        // This is actually not necessary, but we even check it in the unit
        // test. Just to be sure.
        chargerType != QmBattery::None;

    charging =
        batteryState != QmBattery::StateFull &&
        chargerType != QmBattery::None &&
        chargingState != QmBattery::StateNotCharging &&
        chargingState != QmBattery::StateChargingFailed;

    chargingRate = 0;
    if (charging)
        chargingRate = chargerType == QmBattery::Wall ?
            animation_rate_charging_wall : animation_rate_charging_usb;

    SYS_DEBUG ("*** charging       = %s", SYS_BOOL(charging));
    SYS_DEBUG ("*** m_Charging     = %s", SYS_BOOL(m_Charging));
    SYS_DEBUG ("*** chargingRate   = %d", chargingRate);
    SYS_DEBUG ("*** m_ChargingRate = %d", m_ChargingRate);

    if (chargingRate == m_ChargingRate &&
            couldBeCharging == m_Charging)
        return;

    /*
     * If the charging rate has been changed we need to notify the ui with a
     * signal.
     */
    m_Charging = couldBeCharging;
    SYS_DEBUG ("*** chargingRate %d -> %d", m_ChargingRate, chargingRate);
    m_ChargingRate = chargingRate;
    SYS_DEBUG ("Emitting batteryCharging(%d)", m_ChargingRate);
    emit batteryCharging (m_ChargingRate);

    /*
     * Then we need to notify everyone about the bar value.
     * FIXME: Why exactly do we need that?
     */
    SYS_DEBUG ("Emitting batteryBarValueReceived(%d)", batteryBarValue (-1));
    emit batteryBarValueReceived (batteryBarValue (-1));

    if(batteryState == QmBattery::StateFull)
    {
        emit batteryFull();
        return;
    }

    /*
     * And the remaining battery capacity has to be recalculated.
     */
    remainingCapacityRequired();
    #else
    /*
     * FIXME: To implement a variant that does not use QmSystem.
     */
    #endif
}

bool BatteryBusinessLogic::isCharging()
{
    return m_Charging;
}
<|endoftext|>


<commit_before>/*****************************************************************************\
 *                                                                           *
 *   .d8888b.          d8888 88888888888 888     888 8888888b.  888b    888  *
 *  d88P  Y88b        d88888     888     888     888 888   Y88b 8888b   888  *
 *  Y88b.            d88P888     888     888     888 888    888 88888b  888  *
 *   "Y888b.        d88P 888     888     888     888 888   d88P 888Y88b 888  *
 *      "Y88b.     d88P  888     888     888     888 8888888P"  888 Y88b888  *
 *        "888    d88P   888     888     888     888 888 T88b   888  Y88888  *
 *  Y88b  d88P   d8888888888     888     Y88b. .d88P 888  T88b  888   Y8888  *
 *   "Y8888P"   d88P     888     888      "Y88888P"  888   T88b 888    Y888  *
 *                                                                           *
 *                                   Saturn                                  *
 *     A general-purpose game engine for the Nintendo® Game Boy Advance™     *
 *                                                                           *
 *                       Copyright © 2016  Nicholatian                       *
 *                                                                           *
 *  Licensed under the Apache License, Version 2.0 (the “License”); you may  *
 * not use this file except in compliance with the License. You may obtain a *
 *                          copy of the  License at                          *
 *                                                                           *
 *                http://www.apache.org/licenses/LICENSE-2.0                 *
 *                                                                           *
 *    Unless required by applicable law or agreed to in writing, software    *
 * distributed under the License is distributed on an “AS IS” BASIS, WITHOUT *
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the  *
 *  License for the specific language governing permissions and limitations  *
 *                            under the  License.                            *
 *                                                                           *
\*****************************************************************************/

//#include "memory.hh"

/** ============================ F U N C T I O N ============================ *
 *
 * TITLE:       LoMem copy function
 * DESCRIPTION: This function wraps the AGB BIOS functions which implement
 *              efficient memory copying/filling functionality in order to
 *              provide better flexibility in payload sizing while maintaining
 *              as much of the efficiency of the BIOS functions as possible.
 *              CpuSet/CpuFastSet MUST copy data in blocks in order to be fast,
 *              which can be awkward for data which does not fit neatly in
 *              those blocks. To remedy this, we need to copy as much data as
 *              possible using CpuFastSet, then copying whatever leftovers that
 *              fit in CpuSet, and finally copying the remaining data by hand
 *              as words then dwords then bytes. See GBATek for details on how
 *              CpuSet and CpuFastSet operate.
 *

void saturn::lomem::copy( void* src, u32 srcSize, void* dst )
{
    // These are all used verbatim by the copy loops

    // sblockCount = srcSize / 32
    const u32 sblockCount = srcSize >> 5;
    // blockCount = (srcSize / 8) - (sblockCount * 4)
    const u32 blockCount  = (srcSize >> 3) - (sblockCount << 2);
    // wordCount = (srcSize / 4) - (sblockCount * 8) - (blockCount * 2)
    const u32 wordCount   = (srcSize >> 2) - (sblockCount << 3) -
        (blockCount << 1);
    // dwordCount = (srcSize / 2) - (sblockCount * 16) - (blockCount * 4) *
    //              (wordCount * 2)
    const u32 dwordCount  = (srcSize >> 1) - (sblockCount << 4) -
        (blockCount << 2) - (wordCount << 1);
    // dwordCount = srcSize - (sblockCount * 32) - (blockCount * 8) *
    //              (wordCount * 4) - (dwordCount * 2)
    const u32 byteCount   = srcSize - (sblockCount << 5) - (blockCount << 3) -
        (wordCount << 2) - (dwordCount << 1);

    // number of bytes to copy, sblocks only
    const u32 sblockBytes = sblockCount << 5;

    for(u32 i = 0; i < sblockCount; ++i)
    {
        _sat__cpu_fast_set( src, dst, sBlockBytes );
    }

    // repositioned source address
    const void* src2       = (void*)(((u32)src) + sblockBytes);
    // same for dest
    const void* dst2       = (void*)(((u32)dst) + sblockBytes);
    // number of bytes to copy, blocks only
    const u32   blockBytes = blockCount << 3;

    for(u32 i = 0; i < blockCount; ++i)
    {
        _sat__cpu_set( source, dest, blockBytes );
    }

}
*/
<commit_msg>Uncomment WIP code<commit_after>/*****************************************************************************\
 *                                                                           *
 *   .d8888b.          d8888 88888888888 888     888 8888888b.  888b    888  *
 *  d88P  Y88b        d88888     888     888     888 888   Y88b 8888b   888  *
 *  Y88b.            d88P888     888     888     888 888    888 88888b  888  *
 *   "Y888b.        d88P 888     888     888     888 888   d88P 888Y88b 888  *
 *      "Y88b.     d88P  888     888     888     888 8888888P"  888 Y88b888  *
 *        "888    d88P   888     888     888     888 888 T88b   888  Y88888  *
 *  Y88b  d88P   d8888888888     888     Y88b. .d88P 888  T88b  888   Y8888  *
 *   "Y8888P"   d88P     888     888      "Y88888P"  888   T88b 888    Y888  *
 *                                                                           *
 *                                   Saturn                                  *
 *     A general-purpose game engine for the Nintendo® Game Boy Advance™     *
 *                                                                           *
 *                       Copyright © 2016  Nicholatian                       *
 *                                                                           *
 *  Licensed under the Apache License, Version 2.0 (the “License”); you may  *
 * not use this file except in compliance with the License. You may obtain a *
 *                          copy of the  License at                          *
 *                                                                           *
 *                http://www.apache.org/licenses/LICENSE-2.0                 *
 *                                                                           *
 *    Unless required by applicable law or agreed to in writing, software    *
 * distributed under the License is distributed on an “AS IS” BASIS, WITHOUT *
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the  *
 *  License for the specific language governing permissions and limitations  *
 *                            under the  License.                            *
 *                                                                           *
\*****************************************************************************/

#include "memory.hh"

#include <bios.hh>

/** ============================ F U N C T I O N ============================ *
 *
 * TITLE:       LoMem copy function
 * DESCRIPTION: This function wraps the AGB BIOS functions which implement
 *              efficient memory copying/filling functionality in order to
 *              provide better flexibility in payload sizing while maintaining
 *              as much of the efficiency of the BIOS functions as possible.
 *              CpuSet/CpuFastSet MUST copy data in blocks in order to be fast,
 *              which can be awkward for data which does not fit neatly in
 *              those blocks. To remedy this, we need to copy as much data as
 *              possible using CpuFastSet, then copying whatever leftovers that
 *              fit in CpuSet, and finally copying the remaining data by hand
 *              as words then dwords then bytes. See GBATek for details on how
 *              CpuSet and CpuFastSet operate.
 *
 */

void saturn::lomem::copy( void* src, u32 srcSize, void* dst )
{
    // These are all used verbatim by the copy loops

    // sblockCount = srcSize / 32
    const u32 sblockCount = srcSize >> 5;
    // blockCount = (srcSize / 8) - (sblockCount * 4)
    const u32 blockCount  = (srcSize >> 3) - (sblockCount << 2);
    // wordCount = (srcSize / 4) - (sblockCount * 8) - (blockCount * 2)
    const u32 wordCount   = (srcSize >> 2) - (sblockCount << 3) -
        (blockCount << 1);
    // dwordCount = (srcSize / 2) - (sblockCount * 16) - (blockCount * 4) *
    //              (wordCount * 2)
    const u32 dwordCount  = (srcSize >> 1) - (sblockCount << 4) -
        (blockCount << 2) - (wordCount << 1);
    // dwordCount = srcSize - (sblockCount * 32) - (blockCount * 8) *
    //              (wordCount * 4) - (dwordCount * 2)
    const u32 byteCount   = srcSize - (sblockCount << 5) - (blockCount << 3) -
        (wordCount << 2) - (dwordCount << 1);

    // number of bytes to copy, sblocks only
    const u32 sblockBytes = sblockCount << 5;

    for(u32 i = 0; i < sblockCount; ++i)
    {
        _sat__cpu_fast_set( src, dst, sBlockBytes );
    }

    // repositioned source address
    const void* src2       = reinterpret_cast<void*>(((u32)src) + sblockBytes);
    // same for dest
    const void* dst2       = reinterpret_cast<void*>(((u32)dst) + sblockBytes);
    // number of bytes to copy, blocks only
    const u32   blockBytes = blockCount << 3;

    for(u32 i = 0; i < blockCount; ++i)
    {
        _sat__cpu_set( source, dest, blockBytes );
    }
}
<|endoftext|>


<commit_before>/**
 * @file   RotatePathTest.cpp
 * @brief  RotatePath class tester.
 * @author zer0
 * @date   2017-07-31
 */

#include <gtest/gtest.h>
#include <tester/DemoAsset.hpp>
#include <libtbag/filesystem/RotatePath.hpp>
#include <libtbag/filesystem/File.hpp>
#include <libtbag/util/BufferInfo.hpp>

using namespace libtbag;
using namespace libtbag::filesystem;

TEST(RotatePathTest, Default)
{
    tttDir_Automatic();
    auto const FILE_PATH = tttDir_Get() / "test.log";
    auto const FORMAT = TimeFormatUpdater::getDefaultTimeFormatString(FILE_PATH);

    auto rotate = RotatePath(std::make_shared<SizeChecker>(),
                             std::make_shared<TimeFormatUpdater>(FORMAT));
    ASSERT_TRUE(rotate.update());

    auto checker = std::static_pointer_cast<SizeChecker>(rotate.checker);
    util::Buffer const BUFFER(checker->max_size, '\0');

    auto path1 = rotate.path;
    ASSERT_FALSE(path1.exists());
    ASSERT_FALSE(rotate.next());

    ASSERT_EQ(E_SUCCESS, writeFile(path1, BUFFER));
    ASSERT_TRUE(path1.exists());
    ASSERT_FALSE(rotate.next());
    ASSERT_TRUE(rotate.next(nullptr, 1));

    auto path2 = rotate.path;
    ASSERT_FALSE(path2.exists());
    ASSERT_NE(path1, path2);
}

<commit_msg>Test RotatePath::createParams() method.<commit_after>/**
 * @file   RotatePathTest.cpp
 * @brief  RotatePath class tester.
 * @author zer0
 * @date   2017-07-31
 */

#include <gtest/gtest.h>
#include <tester/DemoAsset.hpp>
#include <libtbag/filesystem/RotatePath.hpp>
#include <libtbag/filesystem/File.hpp>
#include <libtbag/util/BufferInfo.hpp>

using namespace libtbag;
using namespace libtbag::filesystem;

TEST(RotatePathTest, Default)
{
    tttDir_Automatic();
    auto const FILE_PATH = tttDir_Get() / "test.log";
    auto const FORMAT = TimeFormatUpdater::getDefaultTimeFormatString(FILE_PATH);

    auto rotate = RotatePath(std::make_shared<SizeChecker>(),
                             std::make_shared<TimeFormatUpdater>(FORMAT));
    ASSERT_TRUE(rotate.update());

    auto checker = std::static_pointer_cast<SizeChecker>(rotate.checker);
    util::Buffer const BUFFER(checker->max_size, '\0');

    auto path1 = rotate.path;
    ASSERT_FALSE(path1.exists());
    ASSERT_FALSE(rotate.next());

    ASSERT_EQ(E_SUCCESS, writeFile(path1, BUFFER));
    ASSERT_TRUE(path1.exists());
    ASSERT_FALSE(rotate.next());
    ASSERT_TRUE(rotate.next(nullptr, 1));

    auto path2 = rotate.path;
    ASSERT_FALSE(path2.exists());
    ASSERT_NE(path1, path2);
}

TEST(RotatePathTest, CreateParams_01)
{
    auto params = RotatePath::createParams("size=2k counter=/prefix/path/log,.log,2");
    ASSERT_TRUE((bool)params.first);
    ASSERT_TRUE((bool)params.second);

    ASSERT_EQ(2048, ((SizeChecker*)params.first.get())->max_size);
    ASSERT_STREQ("/prefix/path/log", ((CounterUpdater*)params.second.get())->prefix.c_str());
    ASSERT_STREQ(".log", ((CounterUpdater*)params.second.get())->suffix.c_str());
    ASSERT_EQ(2, ((CounterUpdater*)params.second.get())->count);
}

TEST(RotatePathTest, CreateParams_02)
{
    RotatePath::Environments envs;
    envs.push("SIZE", "2m");
    envs.push("FORMAT", "$ps.log");

    auto params = RotatePath::createParams("size=${SIZE} time=${FORMAT}", envs);
    ASSERT_TRUE((bool)params.first);
    ASSERT_TRUE((bool)params.second);

    ASSERT_EQ(1024*1024*2, ((SizeChecker*)params.first.get())->max_size);
    ASSERT_STREQ("$ps.log", ((TimeFormatUpdater*)params.second.get())->format.c_str());
}

<|endoftext|>


<commit_before>#include "guiutil.h"
#include "bitcoinaddressvalidator.h"
#include "walletmodel.h"
#include "bitcoinunits.h"
#include "util.h"
#include "init.h"

#include <QString>
#include <QDateTime>
#include <QDoubleValidator>
#include <QFont>
#include <QLineEdit>
#include <QUrl>
#include <QTextDocument> // For Qt::escape
#include <QAbstractItemView>
#include <QApplication>
#include <QClipboard>
#include <QFileDialog>
#include <QDesktopServices>
#include <QThread>

#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>

#ifdef WIN32
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
#define _WIN32_WINNT 0x0501
#ifdef _WIN32_IE
#undef _WIN32_IE
#endif
#define _WIN32_IE 0x0501
#define WIN32_LEAN_AND_MEAN 1
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include "shlwapi.h"
#endif

namespace GUIUtil {

QString dateTimeStr(const QDateTime &date)
{
    return date.date().toString(Qt::SystemLocaleShortDate) + QString(" ") + date.toString("hh:mm");
}

QString dateTimeStr(qint64 nTime)
{
    return dateTimeStr(QDateTime::fromTime_t((qint32)nTime));
}

QFont bitcoinAddressFont()
{
    QFont font("Monospace");
    font.setStyleHint(QFont::TypeWriter);
    return font;
}

void setupAddressWidget(QLineEdit *widget, QWidget *parent)
{
    widget->setMaxLength(BitcoinAddressValidator::MaxAddressLength);
    widget->setValidator(new BitcoinAddressValidator(parent));
    widget->setFont(bitcoinAddressFont());
}

void setupAmountWidget(QLineEdit *widget, QWidget *parent)
{
    QDoubleValidator *amountValidator = new QDoubleValidator(parent);
    amountValidator->setDecimals(8);
    amountValidator->setBottom(0.0);
    widget->setValidator(amountValidator);
    widget->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
}

bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out)
{
    if(uri.scheme() != QString("bitcoin"))
        return false;

    SendCoinsRecipient rv;
    rv.address = uri.path();
    rv.amount = 0;
    QList<QPair<QString, QString> > items = uri.queryItems();
    for (QList<QPair<QString, QString> >::iterator i = items.begin(); i != items.end(); i++)
    {
        bool fShouldReturnFalse = false;
        if (i->first.startsWith("req-"))
        {
            i->first.remove(0, 4);
            fShouldReturnFalse = true;
        }

        if (i->first == "label")
        {
            rv.label = i->second;
            fShouldReturnFalse = false;
        }
        else if (i->first == "amount")
        {
            if(!i->second.isEmpty())
            {
                if(!BitcoinUnits::parse(BitcoinUnits::BTC, i->second, &rv.amount))
                {
                    return false;
                }
            }
            fShouldReturnFalse = false;
        }

        if (fShouldReturnFalse)
            return false;
    }
    if(out)
    {
        *out = rv;
    }
    return true;
}

bool parseBitcoinURI(QString uri, SendCoinsRecipient *out)
{
    // Convert bitcoin:// to bitcoin:
    //
    //    Cannot handle this later, because bitcoin:// will cause Qt to see the part after // as host,
    //    which will lowercase it (and thus invalidate the address).
    if(uri.startsWith("bitcoin://"))
    {
        uri.replace(0, 10, "bitcoin:");
    }
    QUrl uriInstance(uri);
    return parseBitcoinURI(uriInstance, out);
}

QString HtmlEscape(const QString& str, bool fMultiLine)
{
    QString escaped = Qt::escape(str);
    if(fMultiLine)
    {
        escaped = escaped.replace("\n", "
\n");
    }
    return escaped;
}

QString HtmlEscape(const std::string& str, bool fMultiLine)
{
    return HtmlEscape(QString::fromStdString(str), fMultiLine);
}

void copyEntryData(QAbstractItemView *view, int column, int role)
{
    if(!view || !view->selectionModel())
        return;
    QModelIndexList selection = view->selectionModel()->selectedRows(column);

    if(!selection.isEmpty())
    {
        // Copy first item
        QApplication::clipboard()->setText(selection.at(0).data(role).toString());
    }
}

QString getSaveFileName(QWidget *parent, const QString &caption,
                                 const QString &dir,
                                 const QString &filter,
                                 QString *selectedSuffixOut)
{
    QString selectedFilter;
    QString myDir;
    if(dir.isEmpty()) // Default to user documents location
    {
        myDir = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
    }
    else
    {
        myDir = dir;
    }
    QString result = QFileDialog::getSaveFileName(parent, caption, myDir, filter, &selectedFilter);

    /* Extract first suffix from filter pattern "Description (*.foo)" or "Description (*.foo *.bar ...) */
    QRegExp filter_re(".* \\(\\*\\.(.*)[ \\)]");
    QString selectedSuffix;
    if(filter_re.exactMatch(selectedFilter))
    {
        selectedSuffix = filter_re.cap(1);
    }

    /* Add suffix if needed */
    QFileInfo info(result);
    if(!result.isEmpty())
    {
        if(info.suffix().isEmpty() && !selectedSuffix.isEmpty())
        {
            /* No suffix specified, add selected suffix */
            if(!result.endsWith("."))
                result.append(".");
            result.append(selectedSuffix);
        }
    }

    /* Return selected suffix if asked to */
    if(selectedSuffixOut)
    {
        *selectedSuffixOut = selectedSuffix;
    }
    return result;
}

Qt::ConnectionType blockingGUIThreadConnection()
{
    if(QThread::currentThread() != QCoreApplication::instance()->thread())
    {
        return Qt::BlockingQueuedConnection;
    }
    else
    {
        return Qt::DirectConnection;
    }
}

bool checkPoint(const QPoint &p, const QWidget *w)
{
  QWidget *atW = qApp->widgetAt(w->mapToGlobal(p));
  if(!atW) return false;
  return atW->topLevelWidget() == w;
}

bool isObscured(QWidget *w)
{

  return !(checkPoint(QPoint(0, 0), w)
           && checkPoint(QPoint(w->width() - 1, 0), w)
           && checkPoint(QPoint(0, w->height() - 1), w)
           && checkPoint(QPoint(w->width() - 1, w->height() - 1), w)
           && checkPoint(QPoint(w->width()/2, w->height()/2), w));
}

void openDebugLogfile()
{
    boost::filesystem::path pathDebug = GetDataDir() / "debug.log";

#ifdef WIN32
    if (boost::filesystem::exists(pathDebug))
        /* Open debug.log with the associated application */
        ShellExecuteA((HWND)0, (LPCSTR)"open", (LPCSTR)pathDebug.string().c_str(), NULL, NULL, SW_SHOWNORMAL);
#endif
}

ToolTipToRichTextFilter::ToolTipToRichTextFilter(int size_threshold, QObject *parent) :
    QObject(parent), size_threshold(size_threshold)
{

}

bool ToolTipToRichTextFilter::eventFilter(QObject *obj, QEvent *evt)
{
    if(evt->type() == QEvent::ToolTipChange)
    {
        QWidget *widget = static_cast<QWidget*>(obj);
        QString tooltip = widget->toolTip();
        if(tooltip.size() > size_threshold && !tooltip.startsWith("<qt/>") && !Qt::mightBeRichText(tooltip))
        {
            // Prefix <qt/> to make sure Qt detects this as rich text
            // Escape the current message as HTML and replace \n by

            tooltip = "<qt/>" + HtmlEscape(tooltip, true);
            widget->setToolTip(tooltip);
            return true;
        }
    }
    return QObject::eventFilter(obj, evt);
}

#ifdef WIN32
boost::filesystem::path static StartupShortcutPath()
{
    return GetSpecialFolderPath(CSIDL_STARTUP) / "Bitcoin.lnk";
}

bool GetStartOnSystemStartup()
{
    // check for Bitcoin.lnk
    return boost::filesystem::exists(StartupShortcutPath());
}

bool SetStartOnSystemStartup(bool fAutoStart)
{
    // If the shortcut exists already, remove it for updating
    boost::filesystem::remove(StartupShortcutPath());

    if (fAutoStart)
    {
        CoInitialize(NULL);

        // Get a pointer to the IShellLink interface.
        IShellLink* psl = NULL;
        HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL,
                                CLSCTX_INPROC_SERVER, IID_IShellLink,
                                reinterpret_cast<void**>(&psl));

        if (SUCCEEDED(hres))
        {
            // Get the current executable path
            TCHAR pszExePath[MAX_PATH];
            GetModuleFileName(NULL, pszExePath, sizeof(pszExePath));

            TCHAR pszArgs[5] = TEXT("-min");

            // Set the path to the shortcut target
            psl->SetPath(pszExePath);
            PathRemoveFileSpec(pszExePath);
            psl->SetWorkingDirectory(pszExePath);
            psl->SetShowCmd(SW_SHOWMINNOACTIVE);
            psl->SetArguments(pszArgs);

            // Query IShellLink for the IPersistFile interface for
            // saving the shortcut in persistent storage.
            IPersistFile* ppf = NULL;
            hres = psl->QueryInterface(IID_IPersistFile,
                                       reinterpret_cast<void**>(&ppf));
            if (SUCCEEDED(hres))
            {
                WCHAR pwsz[MAX_PATH];
                // Ensure that the string is ANSI.
                MultiByteToWideChar(CP_ACP, 0, StartupShortcutPath().string().c_str(), -1, pwsz, MAX_PATH);
                // Save the link by calling IPersistFile::Save.
                hres = ppf->Save(pwsz, TRUE);
                ppf->Release();
                psl->Release();
                CoUninitialize();
                return true;
            }
            psl->Release();
        }
        CoUninitialize();
        return false;
    }
    return true;
}

#elif defined(LINUX)

// Follow the Desktop Application Autostart Spec:
//  http://standards.freedesktop.org/autostart-spec/autostart-spec-latest.html

boost::filesystem::path static GetAutostartDir()
{
    namespace fs = boost::filesystem;

    char* pszConfigHome = getenv("XDG_CONFIG_HOME");
    if (pszConfigHome) return fs::path(pszConfigHome) / "autostart";
    char* pszHome = getenv("HOME");
    if (pszHome) return fs::path(pszHome) / ".config" / "autostart";
    return fs::path();
}

boost::filesystem::path static GetAutostartFilePath()
{
    return GetAutostartDir() / "bitcoin.desktop";
}

bool GetStartOnSystemStartup()
{
    boost::filesystem::ifstream optionFile(GetAutostartFilePath());
    if (!optionFile.good())
        return false;
    // Scan through file for "Hidden=true":
    std::string line;
    while (!optionFile.eof())
    {
        getline(optionFile, line);
        if (line.find("Hidden") != std::string::npos &&
            line.find("true") != std::string::npos)
            return false;
    }
    optionFile.close();

    return true;
}

bool SetStartOnSystemStartup(bool fAutoStart)
{
    if (!fAutoStart)
        boost::filesystem::remove(GetAutostartFilePath());
    else
    {
        char pszExePath[MAX_PATH+1];
        memset(pszExePath, 0, sizeof(pszExePath));
        if (readlink("/proc/self/exe", pszExePath, sizeof(pszExePath)-1) == -1)
            return false;

        boost::filesystem::create_directories(GetAutostartDir());

        boost::filesystem::ofstream optionFile(GetAutostartFilePath(), std::ios_base::out|std::ios_base::trunc);
        if (!optionFile.good())
            return false;
        // Write a bitcoin.desktop file to the autostart directory:
        optionFile << "[Desktop Entry]\n";
        optionFile << "Type=Application\n";
        optionFile << "Name=Bitcoin\n";
        optionFile << "Exec=" << pszExePath << " -min\n";
        optionFile << "Terminal=false\n";
        optionFile << "Hidden=false\n";
        optionFile.close();
    }
    return true;
}
#else

// TODO: OSX startup stuff; see:
// http://developer.apple.com/mac/library/documentation/MacOSX/Conceptual/BPSystemStartup/Articles/CustomLogin.html

bool GetStartOnSystemStartup() { return false; }
bool SetStartOnSystemStartup(bool fAutoStart) { return false; }

#endif

HelpMessageBox::HelpMessageBox(QWidget *parent) :
    QMessageBox(parent)
{
    header = tr("Bitcoin-Qt") + " " + tr("version") + " " +
        QString::fromStdString(FormatFullVersion()) + "\n\n" +
        tr("Usage:") + "\n" +
        "  bitcoin-qt [" + tr("command-line options") + "]                     " + "\n";

    coreOptions = QString::fromStdString(HelpMessage());

    uiOptions = tr("UI options") + ":\n" +
        "  -lang=<lang>           " + tr("Set language, for example \"de_DE\" (default: system locale)") + "\n" +
        "  -min                   " + tr("Start minimized") + "\n" +
        "  -splash                " + tr("Show splash screen on startup (default: 1)") + "\n";

    setWindowTitle(tr("Bitcoin-Qt"));
    setTextFormat(Qt::PlainText);
    // setMinimumWidth is ignored for QMessageBox so put in nonbreaking spaces to make it wider.
    setText(header + QString(QChar(0x2003)).repeated(50));
    setDetailedText(coreOptions + "\n" + uiOptions);
}

void HelpMessageBox::exec()
{
#if defined(WIN32)
    // On windows, show a message box, as there is no stderr in windowed applications
    QMessageBox::exec();
#else
    // On other operating systems, the expected action is to print the message to the console.
    QString strUsage = header + "\n" + coreOptions + "\n" + uiOptions;
    fprintf(stderr, "%s", strUsage.toStdString().c_str());
#endif
}

} // namespace GUIUtil

<commit_msg>Fix Mingw64 build (missing headers according to M$ documentation)<commit_after>#include "guiutil.h"
#include "bitcoinaddressvalidator.h"
#include "walletmodel.h"
#include "bitcoinunits.h"
#include "util.h"
#include "init.h"

#include <QString>
#include <QDateTime>
#include <QDoubleValidator>
#include <QFont>
#include <QLineEdit>
#include <QUrl>
#include <QTextDocument> // For Qt::escape
#include <QAbstractItemView>
#include <QApplication>
#include <QClipboard>
#include <QFileDialog>
#include <QDesktopServices>
#include <QThread>

#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>

#ifdef WIN32
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
#define _WIN32_WINNT 0x0501
#ifdef _WIN32_IE
#undef _WIN32_IE
#endif
#define _WIN32_IE 0x0501
#define WIN32_LEAN_AND_MEAN 1
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include "shlwapi.h"
#include "shlobj.h"
#include "shellapi.h"
#endif

namespace GUIUtil {

QString dateTimeStr(const QDateTime &date)
{
    return date.date().toString(Qt::SystemLocaleShortDate) + QString(" ") + date.toString("hh:mm");
}

QString dateTimeStr(qint64 nTime)
{
    return dateTimeStr(QDateTime::fromTime_t((qint32)nTime));
}

QFont bitcoinAddressFont()
{
    QFont font("Monospace");
    font.setStyleHint(QFont::TypeWriter);
    return font;
}

void setupAddressWidget(QLineEdit *widget, QWidget *parent)
{
    widget->setMaxLength(BitcoinAddressValidator::MaxAddressLength);
    widget->setValidator(new BitcoinAddressValidator(parent));
    widget->setFont(bitcoinAddressFont());
}

void setupAmountWidget(QLineEdit *widget, QWidget *parent)
{
    QDoubleValidator *amountValidator = new QDoubleValidator(parent);
    amountValidator->setDecimals(8);
    amountValidator->setBottom(0.0);
    widget->setValidator(amountValidator);
    widget->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
}

bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out)
{
    if(uri.scheme() != QString("bitcoin"))
        return false;

    SendCoinsRecipient rv;
    rv.address = uri.path();
    rv.amount = 0;
    QList<QPair<QString, QString> > items = uri.queryItems();
    for (QList<QPair<QString, QString> >::iterator i = items.begin(); i != items.end(); i++)
    {
        bool fShouldReturnFalse = false;
        if (i->first.startsWith("req-"))
        {
            i->first.remove(0, 4);
            fShouldReturnFalse = true;
        }

        if (i->first == "label")
        {
            rv.label = i->second;
            fShouldReturnFalse = false;
        }
        else if (i->first == "amount")
        {
            if(!i->second.isEmpty())
            {
                if(!BitcoinUnits::parse(BitcoinUnits::BTC, i->second, &rv.amount))
                {
                    return false;
                }
            }
            fShouldReturnFalse = false;
        }

        if (fShouldReturnFalse)
            return false;
    }
    if(out)
    {
        *out = rv;
    }
    return true;
}

bool parseBitcoinURI(QString uri, SendCoinsRecipient *out)
{
    // Convert bitcoin:// to bitcoin:
    //
    //    Cannot handle this later, because bitcoin:// will cause Qt to see the part after // as host,
    //    which will lowercase it (and thus invalidate the address).
    if(uri.startsWith("bitcoin://"))
    {
        uri.replace(0, 10, "bitcoin:");
    }
    QUrl uriInstance(uri);
    return parseBitcoinURI(uriInstance, out);
}

QString HtmlEscape(const QString& str, bool fMultiLine)
{
    QString escaped = Qt::escape(str);
    if(fMultiLine)
    {
        escaped = escaped.replace("\n", "
\n");
    }
    return escaped;
}

QString HtmlEscape(const std::string& str, bool fMultiLine)
{
    return HtmlEscape(QString::fromStdString(str), fMultiLine);
}

void copyEntryData(QAbstractItemView *view, int column, int role)
{
    if(!view || !view->selectionModel())
        return;
    QModelIndexList selection = view->selectionModel()->selectedRows(column);

    if(!selection.isEmpty())
    {
        // Copy first item
        QApplication::clipboard()->setText(selection.at(0).data(role).toString());
    }
}

QString getSaveFileName(QWidget *parent, const QString &caption,
                                 const QString &dir,
                                 const QString &filter,
                                 QString *selectedSuffixOut)
{
    QString selectedFilter;
    QString myDir;
    if(dir.isEmpty()) // Default to user documents location
    {
        myDir = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
    }
    else
    {
        myDir = dir;
    }
    QString result = QFileDialog::getSaveFileName(parent, caption, myDir, filter, &selectedFilter);

    /* Extract first suffix from filter pattern "Description (*.foo)" or "Description (*.foo *.bar ...) */
    QRegExp filter_re(".* \\(\\*\\.(.*)[ \\)]");
    QString selectedSuffix;
    if(filter_re.exactMatch(selectedFilter))
    {
        selectedSuffix = filter_re.cap(1);
    }

    /* Add suffix if needed */
    QFileInfo info(result);
    if(!result.isEmpty())
    {
        if(info.suffix().isEmpty() && !selectedSuffix.isEmpty())
        {
            /* No suffix specified, add selected suffix */
            if(!result.endsWith("."))
                result.append(".");
            result.append(selectedSuffix);
        }
    }

    /* Return selected suffix if asked to */
    if(selectedSuffixOut)
    {
        *selectedSuffixOut = selectedSuffix;
    }
    return result;
}

Qt::ConnectionType blockingGUIThreadConnection()
{
    if(QThread::currentThread() != QCoreApplication::instance()->thread())
    {
        return Qt::BlockingQueuedConnection;
    }
    else
    {
        return Qt::DirectConnection;
    }
}

bool checkPoint(const QPoint &p, const QWidget *w)
{
  QWidget *atW = qApp->widgetAt(w->mapToGlobal(p));
  if(!atW) return false;
  return atW->topLevelWidget() == w;
}

bool isObscured(QWidget *w)
{

  return !(checkPoint(QPoint(0, 0), w)
           && checkPoint(QPoint(w->width() - 1, 0), w)
           && checkPoint(QPoint(0, w->height() - 1), w)
           && checkPoint(QPoint(w->width() - 1, w->height() - 1), w)
           && checkPoint(QPoint(w->width()/2, w->height()/2), w));
}

void openDebugLogfile()
{
    boost::filesystem::path pathDebug = GetDataDir() / "debug.log";

#ifdef WIN32
    if (boost::filesystem::exists(pathDebug))
        /* Open debug.log with the associated application */
        ShellExecuteA((HWND)0, (LPCSTR)"open", (LPCSTR)pathDebug.string().c_str(), NULL, NULL, SW_SHOWNORMAL);
#endif
}

ToolTipToRichTextFilter::ToolTipToRichTextFilter(int size_threshold, QObject *parent) :
    QObject(parent), size_threshold(size_threshold)
{

}

bool ToolTipToRichTextFilter::eventFilter(QObject *obj, QEvent *evt)
{
    if(evt->type() == QEvent::ToolTipChange)
    {
        QWidget *widget = static_cast<QWidget*>(obj);
        QString tooltip = widget->toolTip();
        if(tooltip.size() > size_threshold && !tooltip.startsWith("<qt/>") && !Qt::mightBeRichText(tooltip))
        {
            // Prefix <qt/> to make sure Qt detects this as rich text
            // Escape the current message as HTML and replace \n by

            tooltip = "<qt/>" + HtmlEscape(tooltip, true);
            widget->setToolTip(tooltip);
            return true;
        }
    }
    return QObject::eventFilter(obj, evt);
}

#ifdef WIN32
boost::filesystem::path static StartupShortcutPath()
{
    return GetSpecialFolderPath(CSIDL_STARTUP) / "Bitcoin.lnk";
}

bool GetStartOnSystemStartup()
{
    // check for Bitcoin.lnk
    return boost::filesystem::exists(StartupShortcutPath());
}

bool SetStartOnSystemStartup(bool fAutoStart)
{
    // If the shortcut exists already, remove it for updating
    boost::filesystem::remove(StartupShortcutPath());

    if (fAutoStart)
    {
        CoInitialize(NULL);

        // Get a pointer to the IShellLink interface.
        IShellLink* psl = NULL;
        HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL,
                                CLSCTX_INPROC_SERVER, IID_IShellLink,
                                reinterpret_cast<void**>(&psl));

        if (SUCCEEDED(hres))
        {
            // Get the current executable path
            TCHAR pszExePath[MAX_PATH];
            GetModuleFileName(NULL, pszExePath, sizeof(pszExePath));

            TCHAR pszArgs[5] = TEXT("-min");

            // Set the path to the shortcut target
            psl->SetPath(pszExePath);
            PathRemoveFileSpec(pszExePath);
            psl->SetWorkingDirectory(pszExePath);
            psl->SetShowCmd(SW_SHOWMINNOACTIVE);
            psl->SetArguments(pszArgs);

            // Query IShellLink for the IPersistFile interface for
            // saving the shortcut in persistent storage.
            IPersistFile* ppf = NULL;
            hres = psl->QueryInterface(IID_IPersistFile,
                                       reinterpret_cast<void**>(&ppf));
            if (SUCCEEDED(hres))
            {
                WCHAR pwsz[MAX_PATH];
                // Ensure that the string is ANSI.
                MultiByteToWideChar(CP_ACP, 0, StartupShortcutPath().string().c_str(), -1, pwsz, MAX_PATH);
                // Save the link by calling IPersistFile::Save.
                hres = ppf->Save(pwsz, TRUE);
                ppf->Release();
                psl->Release();
                CoUninitialize();
                return true;
            }
            psl->Release();
        }
        CoUninitialize();
        return false;
    }
    return true;
}

#elif defined(LINUX)

// Follow the Desktop Application Autostart Spec:
//  http://standards.freedesktop.org/autostart-spec/autostart-spec-latest.html

boost::filesystem::path static GetAutostartDir()
{
    namespace fs = boost::filesystem;

    char* pszConfigHome = getenv("XDG_CONFIG_HOME");
    if (pszConfigHome) return fs::path(pszConfigHome) / "autostart";
    char* pszHome = getenv("HOME");
    if (pszHome) return fs::path(pszHome) / ".config" / "autostart";
    return fs::path();
}

boost::filesystem::path static GetAutostartFilePath()
{
    return GetAutostartDir() / "bitcoin.desktop";
}

bool GetStartOnSystemStartup()
{
    boost::filesystem::ifstream optionFile(GetAutostartFilePath());
    if (!optionFile.good())
        return false;
    // Scan through file for "Hidden=true":
    std::string line;
    while (!optionFile.eof())
    {
        getline(optionFile, line);
        if (line.find("Hidden") != std::string::npos &&
            line.find("true") != std::string::npos)
            return false;
    }
    optionFile.close();

    return true;
}

bool SetStartOnSystemStartup(bool fAutoStart)
{
    if (!fAutoStart)
        boost::filesystem::remove(GetAutostartFilePath());
    else
    {
        char pszExePath[MAX_PATH+1];
        memset(pszExePath, 0, sizeof(pszExePath));
        if (readlink("/proc/self/exe", pszExePath, sizeof(pszExePath)-1) == -1)
            return false;

        boost::filesystem::create_directories(GetAutostartDir());

        boost::filesystem::ofstream optionFile(GetAutostartFilePath(), std::ios_base::out|std::ios_base::trunc);
        if (!optionFile.good())
            return false;
        // Write a bitcoin.desktop file to the autostart directory:
        optionFile << "[Desktop Entry]\n";
        optionFile << "Type=Application\n";
        optionFile << "Name=Bitcoin\n";
        optionFile << "Exec=" << pszExePath << " -min\n";
        optionFile << "Terminal=false\n";
        optionFile << "Hidden=false\n";
        optionFile.close();
    }
    return true;
}
#else

// TODO: OSX startup stuff; see:
// http://developer.apple.com/mac/library/documentation/MacOSX/Conceptual/BPSystemStartup/Articles/CustomLogin.html

bool GetStartOnSystemStartup() { return false; }
bool SetStartOnSystemStartup(bool fAutoStart) { return false; }

#endif

HelpMessageBox::HelpMessageBox(QWidget *parent) :
    QMessageBox(parent)
{
    header = tr("Bitcoin-Qt") + " " + tr("version") + " " +
        QString::fromStdString(FormatFullVersion()) + "\n\n" +
        tr("Usage:") + "\n" +
        "  bitcoin-qt [" + tr("command-line options") + "]                     " + "\n";

    coreOptions = QString::fromStdString(HelpMessage());

    uiOptions = tr("UI options") + ":\n" +
        "  -lang=<lang>           " + tr("Set language, for example \"de_DE\" (default: system locale)") + "\n" +
        "  -min                   " + tr("Start minimized") + "\n" +
        "  -splash                " + tr("Show splash screen on startup (default: 1)") + "\n";

    setWindowTitle(tr("Bitcoin-Qt"));
    setTextFormat(Qt::PlainText);
    // setMinimumWidth is ignored for QMessageBox so put in nonbreaking spaces to make it wider.
    setText(header + QString(QChar(0x2003)).repeated(50));
    setDetailedText(coreOptions + "\n" + uiOptions);
}

void HelpMessageBox::exec()
{
#if defined(WIN32)
    // On windows, show a message box, as there is no stderr in windowed applications
    QMessageBox::exec();
#else
    // On other operating systems, the expected action is to print the message to the console.
    QString strUsage = header + "\n" + coreOptions + "\n" + uiOptions;
    fprintf(stderr, "%s", strUsage.toStdString().c_str());
#endif
}

} // namespace GUIUtil

<|endoftext|>