<commit_before>//
//  inpal_prime.cpp
//  Inverse Palindrome Library
//
//  Created by Bryan Triana on 7/21/16.
//  Copyright © 2016 Inverse Palindrome. All rights reserved.
//

#include "inpal_prime.hpp"
#include "inpal_algorithm.hpp"

std::vector<std::size_t> inpal::prime::prime_list(std::size_t range)
{
    const auto primes = prime_sieve(range);
    std::vector<std::size_t> p_list;

    for(std::size_t i=2; i<=range; i++) if(primes[i]) p_list.push_back(i);

    return p_list;
}

std::vector<bool> inpal::prime::prime_sieve(std::size_t range)
{
    std::vector<bool> p_test(range+1, false);

    //defines square root of range for future usage
    const std::size_t root = ceil(sqrt(range));

    //sieve axioms
    for(std::size_t x=1; x<=root; x++)
        for(std::size_t y=1; y<=root; y++)
        {
            std::size_t i = (4*x*x)+(y*y);
            if(i<=range && (i%12==1 || i%12==5)) p_test[i].flip();

            i = (3*x*x)+(y*y);
            if(i<=range && i%12==7) p_test[i].flip();

            i = (3*x*x)-(y*y);
            if(x>y && i<=range && i%12==11) p_test[i].flip();
        }

    //marks 2,3,5 and 7 as prime numbers to deal with input smaller than 7
    p_test[2]=p_test[3]=p_test[5]=true;

    //marks all multiples of primes as non primes
    for(std::size_t r=5; r<=root; r++)
    {
       if(p_test[r])
        {
            for(std::size_t j=r*r; j<=range; j+=r*r) p_test[j]=false;
        }
    }

    return p_test;
}

std::vector<std::size_t> inpal::prime::factor_list(std::size_t num)
{
    std::vector<std::size_t> factors;
    std::vector<std::size_t> primes;

    std::size_t factor = algorithm::pollard_rho(num);
    factors.push_back(num/factor);
    factors.push_back(factor);

    do
    {
        std::size_t m = factors.back();
        factors.pop_back();

        if(m==1) continue;
        if(prime_test(m))
        {
            primes.push_back(m);

            //decomposes the factors into primes
            for(std::size_t i=0; i<factors.size(); i++)
            {
                std::size_t k = factors[i];
                if(k%m==0)
                {
                    do k/=m;
                    while(k%m==0);

                    factors[i]=k;
                }
            }
        }
        else
        {
            factor=algorithm::pollard_rho(m);
            factors.push_back(m/factor);
            factors.push_back(factor);
        }
    }
    while(factors.size());

    //prime factors found by pollard rho arent always ordered
    std::sort(primes.begin(), primes.end());

    return primes;
}

std::size_t inpal::prime::prime_locate(std::size_t pos)
{
    //index starts at 1 instead of 0, eg 1st prime is 2
    pos = pos-1;

    //return values for input less or equal to 10
    const auto small_primes = prime_list(29);
    if(pos<10) return small_primes[pos];

    //denotes the limit of the sieve
    std::size_t limit = pos*log(pos)+pos*log(log(pos));
    const auto primes = prime_list(limit);

    return primes[pos];
}

std::size_t inpal::prime::max_prime(std::size_t range)
{
    for(std::size_t i=range; i>0; i--) if(prime_test(i)) return i;

    return 2;
}

std::size_t inpal::prime::prime_count(std::size_t range)
{
    const auto primes = prime_sieve(range);

    return std::count(primes.begin(), primes.end(), true);
}

double inpal::prime::prime_density(double range)
{
    return prime_count(range)/range;
}

bool inpal::prime::prime_test(std::size_t num)
{
    if(num!=2 && num%2==0) return false;

    //iterations will occur 20 times to ensure that the margin of error is less than 4^-20
    const std::size_t cycle = 20;
    std::size_t s = num-1;
    while(s%2==0) s/=2;

    for(std::size_t i=0; i<cycle; i++)
    {
        std::size_t a = rand()%(num-1)+1;
        std::size_t b = s;
        std::size_t mod = algorithm::modulo(a,b,num);

        while(b!=num-1 && mod!=1 && mod!=num-1)
        {
            mod=algorithm::mulmod(mod,mod,num);
            b*=2;
        }
        if(mod!=num-1 && b%2==0) return false;
    }

    return true;
}

bool inpal::prime::twin_test(std::size_t num)
{
    return prime_test(num) && (prime_test(num-2) || prime_test(num+2));
}

bool inpal::prime::cousin_test(std::size_t num)
{
    return  prime_test(num) && (prime_test(num-4) || prime_test(num+4));
}

bool inpal::prime::sexy_test(std::size_t num)
{
    return num!=3 && prime_test(num) && (prime_test(num-6) || prime_test(num+6));
}

std::size_t inpal::prime::max_palprime(std::size_t range)
{
    for(std::size_t i=range; i>2; --i) if(algorithm::pal_test(i) && prime_test(i)) return i;

    return 2;
}

std::size_t inpal::prime::max_factor(std::size_t num)
{
    return factor_list(num).back();
}

std::size_t inpal::prime::factor_count(std::size_t num)
{
    return factor_list(num).size();
}

<commit_msg>Update inpal_prime.cpp<commit_after>//
//  inpal_prime.cpp
//  Inverse Palindrome Library
//
//  Created by Bryan Triana on 7/21/16.
//  Copyright © 2016 Inverse Palindrome. All rights reserved.
//

#include "inpal_prime.hpp"
#include "inpal_algorithm.hpp"

std::vector<std::size_t> inpal::prime::prime_list(std::size_t range)
{
    const auto primes = prime_sieve(range);
    std::vector<std::size_t> p_list;

    for(std::size_t i=2; i<=range; i++) if(primes[i]) p_list.push_back(i);

    return p_list;
}

std::vector<bool> inpal::prime::prime_sieve(std::size_t range)
{
    std::vector<bool> p_test(range+1, false);

    //defines square root of range for future usage
    const std::size_t root = ceil(sqrt(range));

    //sieve axioms
    for(std::size_t x=1; x<=root; x++)
        for(std::size_t y=1; y<=root; y++)
        {
            std::size_t i = (4*x*x)+(y*y);
            if(i<=range && (i%12==1 || i%12==5)) p_test[i].flip();

            i = (3*x*x)+(y*y);
            if(i<=range && i%12==7) p_test[i].flip();

            i = (3*x*x)-(y*y);
            if(x>y && i<=range && i%12==11) p_test[i].flip();
        }

    //marks 2, 3 and 5 as prime numbers to ignore these numbers in the next process
    p_test[2]=p_test[3]=p_test[5]=true;

    //marks all multiples of primes as non primes
    for(std::size_t r=5; r<=root; r++)
    {
       if(p_test[r])
        {
            for(std::size_t j=r*r; j<=range; j+=r*r) p_test[j]=false;
        }
    }

    return p_test;
}

std::vector<std::size_t> inpal::prime::factor_list(std::size_t num)
{
    std::vector<std::size_t> factors;
    std::vector<std::size_t> primes;

    std::size_t factor = algorithm::pollard_rho(num);
    factors.push_back(num/factor);
    factors.push_back(factor);

    do
    {
        std::size_t m = factors.back();
        factors.pop_back();

        if(m==1) continue;
        if(prime_test(m))
        {
            primes.push_back(m);

            //decomposes the factors into primes
            for(std::size_t i=0; i<factors.size(); i++)
            {
                std::size_t k = factors[i];
                if(k%m==0)
                {
                    do k/=m;
                    while(k%m==0);

                    factors[i]=k;
                }
            }
        }
        else
        {
            factor=algorithm::pollard_rho(m);
            factors.push_back(m/factor);
            factors.push_back(factor);
        }
    }
    while(factors.size());

    //prime factors found by pollard rho arent always ordered
    std::sort(primes.begin(), primes.end());

    return primes;
}

std::size_t inpal::prime::prime_locate(std::size_t pos)
{
    //index starts at 1 instead of 0, eg 1st prime is 2
    pos = pos-1;

    //return values for input less or equal to 10
    const auto small_primes = prime_list(29);
    if(pos<10) return small_primes[pos];

    //denotes the limit of the sieve
    std::size_t limit = pos*log(pos)+pos*log(log(pos));
    const auto primes = prime_list(limit);

    return primes[pos];
}

std::size_t inpal::prime::max_prime(std::size_t range)
{
    for(std::size_t i=range; i>0; i--) if(prime_test(i)) return i;

    return 2;
}

std::size_t inpal::prime::prime_count(std::size_t range)
{
    const auto primes = prime_sieve(range);

    return std::count(primes.begin(), primes.end(), true);
}

double inpal::prime::prime_density(double range)
{
    return prime_count(range)/range;
}

bool inpal::prime::prime_test(std::size_t num)
{
    if(num!=2 && num%2==0) return false;

    //iterations will occur 20 times to ensure that the margin of error is less than 4^-20
    const std::size_t cycle = 20;
    std::size_t s = num-1;
    while(s%2==0) s/=2;

    for(std::size_t i=0; i<cycle; i++)
    {
        std::size_t a = rand()%(num-1)+1;
        std::size_t b = s;
        std::size_t mod = algorithm::modulo(a,b,num);

        while(b!=num-1 && mod!=1 && mod!=num-1)
        {
            mod=algorithm::mulmod(mod,mod,num);
            b*=2;
        }
        if(mod!=num-1 && b%2==0) return false;
    }

    return true;
}

bool inpal::prime::twin_test(std::size_t num)
{
    return prime_test(num) && (prime_test(num-2) || prime_test(num+2));
}

bool inpal::prime::cousin_test(std::size_t num)
{
    return  prime_test(num) && (prime_test(num-4) || prime_test(num+4));
}

bool inpal::prime::sexy_test(std::size_t num)
{
    return num!=3 && prime_test(num) && (prime_test(num-6) || prime_test(num+6));
}

std::size_t inpal::prime::max_palprime(std::size_t range)
{
    for(std::size_t i=range; i>2; --i) if(algorithm::pal_test(i) && prime_test(i)) return i;

    return 2;
}

std::size_t inpal::prime::max_factor(std::size_t num)
{
    return factor_list(num).back();
}

std::size_t inpal::prime::factor_count(std::size_t num)
{
    return factor_list(num).size();
}

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2002-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Nathan Binkert
 *          Erik Hallnor
 *          Steve Reinhardt
 */

#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>

#include <fstream>
#include <list>
#include <string>
#include <vector>

#include "base/inifile.hh"
#include "base/misc.hh"
#include "base/output.hh"
#include "base/str.hh"
#include "base/trace.hh"
#include "sim/eventq.hh"
#include "sim/serialize.hh"
#include "sim/sim_events.hh"
#include "sim/sim_exit.hh"
#include "sim/sim_object.hh"

// For stat reset hack
#include "sim/stat_control.hh"

using namespace std;

extern SimObject *resolveSimObject(const string &);

//
// The base implementations use to_number for parsing and '<<' for
// displaying, suitable for integer types.
//
template <class T>
bool
parseParam(const string &s, T &value)
{
    return to_number(s, value);
}

template <class T>
void
showParam(ostream &os, const T &value)
{
    os << value;
}

//
// Template specializations:
// - char (8-bit integer)
// - floating-point types
// - bool
// - string
//

// Treat 8-bit ints (chars) as ints on output, not as chars
template <>
void
showParam(ostream &os, const char &value)
{
    os << (int)value;
}

template <>
void
showParam(ostream &os, const signed char &value)
{
    os << (int)value;
}

template <>
void
showParam(ostream &os, const unsigned char &value)
{
    os << (unsigned int)value;
}

// Use sscanf() for FP types as to_number() only handles integers
template <>
bool
parseParam(const string &s, float &value)
{
    return (sscanf(s.c_str(), "%f", &value) == 1);
}

template <>
bool
parseParam(const string &s, double &value)
{
    return (sscanf(s.c_str(), "%lf", &value) == 1);
}

template <>
bool
parseParam(const string &s, bool &value)
{
    const string &ls = to_lower(s);

    if (ls == "true") {
        value = true;
        return true;
    }

    if (ls == "false") {
        value = false;
        return true;
    }

    return false;
}

// Display bools as strings
template <>
void
showParam(ostream &os, const bool &value)
{
    os << (value ? "true" : "false");
}

// String requires no processing to speak of
template <>
bool
parseParam(const string &s, string &value)
{
    value = s;
    return true;
}

int Serializable::ckptMaxCount = 0;
int Serializable::ckptCount = 0;
int Serializable::ckptPrevCount = -1;

void
Serializable::nameOut(ostream &os)
{
    os << "\n[" << name() << "]\n";
}

void
Serializable::nameOut(ostream &os, const string &_name)
{
    os << "\n[" << _name << "]\n";
}

template <class T>
void
paramOut(ostream &os, const string &name, const T &param)
{
    os << name << "=";
    showParam(os, param);
    os << "\n";
}

template <class T>
void
arrayParamOut(ostream &os, const string &name, const vector<T> &param)
{
    typename vector<T>::size_type size = param.size();
    os << name << "=";
    if (size > 0)
        showParam(os, param[0]);
    for (typename vector<T>::size_type i = 1; i < size; ++i) {
        os << " ";
        showParam(os, param[i]);
    }
    os << "\n";
}

template <class T>
void
paramIn(Checkpoint *cp, const string &section, const string &name, T &param)
{
    string str;
    if (!cp->find(section, name, str) || !parseParam(str, param)) {
        fatal("Can't unserialize '%s:%s'\n", section, name);
    }
}

template <class T>
bool
optParamIn(Checkpoint *cp, const string &section, const string &name, T &param)
{
    string str;
    if (!cp->find(section, name, str) || !parseParam(str, param)) {
        warn("optional parameter %s:%s not present\n", section, name);
        return false;
    } else {
        return true;
    }
}

template <class T>
void
arrayParamOut(ostream &os, const string &name, const T *param, unsigned size)
{
    os << name << "=";
    if (size > 0)
        showParam(os, param[0]);
    for (unsigned i = 1; i < size; ++i) {
        os << " ";
        showParam(os, param[i]);
    }
    os << "\n";
}

template <class T>
void
arrayParamIn(Checkpoint *cp, const string &section, const string &name,
             T *param, unsigned size)
{
    string str;
    if (!cp->find(section, name, str)) {
        fatal("Can't unserialize '%s:%s'\n", section, name);
    }

    // code below stolen from VectorParam<T>::parse().
    // it would be nice to unify these somehow...

    vector<string> tokens;

    tokenize(tokens, str, ' ');

    // Need this if we were doing a vector
    // value.resize(tokens.size());

    if (tokens.size() != size) {
        fatal("Array size mismatch on %s:%s'\n", section, name);
    }

    for (vector<string>::size_type i = 0; i < tokens.size(); i++) {
        // need to parse into local variable to handle vector<bool>,
        // for which operator[] returns a special reference class
        // that's not the same as 'bool&', (since it's a packed
        // vector)
        T scalar_value = 0;
        if (!parseParam(tokens[i], scalar_value)) {
            string err("could not parse \"");

            err += str;
            err += "\"";

            fatal(err);
        }

        // assign parsed value to vector
        param[i] = scalar_value;
    }
}

template <class T>
void
arrayParamIn(Checkpoint *cp, const string &section,
             const string &name, vector<T> &param)
{
    string str;
    if (!cp->find(section, name, str)) {
        fatal("Can't unserialize '%s:%s'\n", section, name);
    }

    // code below stolen from VectorParam<T>::parse().
    // it would be nice to unify these somehow...

    vector<string> tokens;

    tokenize(tokens, str, ' ');

    // Need this if we were doing a vector
    // value.resize(tokens.size());

    param.resize(tokens.size());

    for (vector<string>::size_type i = 0; i < tokens.size(); i++) {
        // need to parse into local variable to handle vector<bool>,
        // for which operator[] returns a special reference class
        // that's not the same as 'bool&', (since it's a packed
        // vector)
        T scalar_value = 0;
        if (!parseParam(tokens[i], scalar_value)) {
            string err("could not parse \"");

            err += str;
            err += "\"";

            fatal(err);
        }

        // assign parsed value to vector
        param[i] = scalar_value;
    }
}

void
objParamIn(Checkpoint *cp, const string &section,
           const string &name, SimObject * &param)
{
    if (!cp->findObj(section, name, param)) {
        fatal("Can't unserialize '%s:%s'\n", section, name);
    }
}

#define INSTANTIATE_PARAM_TEMPLATES(type)                               \
template void                                                           \
paramOut(ostream &os, const string &name, type const &param);           \
template void                                                           \
paramIn(Checkpoint *cp, const string &section,                          \
        const string &name, type & param);                              \
template bool                                                           \
optParamIn(Checkpoint *cp, const string &section,                       \
        const string &name, type & param);                              \
template void                                                           \
arrayParamOut(ostream &os, const string &name,                          \
              type const *param, unsigned size);                        \
template void                                                           \
arrayParamIn(Checkpoint *cp, const string &section,                     \
             const string &name, type *param, unsigned size);           \
template void                                                           \
arrayParamOut(ostream &os, const string &name,                          \
              const vector<type> &param);                               \
template void                                                           \
arrayParamIn(Checkpoint *cp, const string &section,                     \
             const string &name, vector<type> &param);

INSTANTIATE_PARAM_TEMPLATES(char)
INSTANTIATE_PARAM_TEMPLATES(signed char)
INSTANTIATE_PARAM_TEMPLATES(unsigned char)
INSTANTIATE_PARAM_TEMPLATES(signed short)
INSTANTIATE_PARAM_TEMPLATES(unsigned short)
INSTANTIATE_PARAM_TEMPLATES(signed int)
INSTANTIATE_PARAM_TEMPLATES(unsigned int)
INSTANTIATE_PARAM_TEMPLATES(signed long)
INSTANTIATE_PARAM_TEMPLATES(unsigned long)
INSTANTIATE_PARAM_TEMPLATES(signed long long)
INSTANTIATE_PARAM_TEMPLATES(unsigned long long)
INSTANTIATE_PARAM_TEMPLATES(bool)
INSTANTIATE_PARAM_TEMPLATES(float)
INSTANTIATE_PARAM_TEMPLATES(double)
INSTANTIATE_PARAM_TEMPLATES(string)

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

/// Container for serializing global variables (not associated with
/// any serialized object).
class Globals : public Serializable
{
  public:
    const string name() const;
    void serialize(ostream &os);
    void unserialize(Checkpoint *cp);
};

/// The one and only instance of the Globals class.
Globals globals;

const string
Globals::name() const
{
    return "Globals";
}

void
Globals::serialize(ostream &os)
{
    nameOut(os);
    SERIALIZE_SCALAR(curTick());

    nameOut(os, "MainEventQueue");
    mainEventQueue.serialize(os);
}

void
Globals::unserialize(Checkpoint *cp)
{
    const string &section = name();
    Tick tick;
    paramIn(cp, section, "curTick", tick);
    curTick(tick);

    mainEventQueue.unserialize(cp, "MainEventQueue");
}

Serializable::Serializable()
{
}

Serializable::~Serializable()
{
}

void
Serializable::serialize(ostream &os)
{
}

void
Serializable::unserialize(Checkpoint *cp, const string &section)
{
}

void
Serializable::serializeAll(const string &cpt_dir)
{
    string dir = Checkpoint::setDir(cpt_dir);
    if (mkdir(dir.c_str(), 0775) == -1 && errno != EEXIST)
            fatal("couldn't mkdir %s\n", dir);

    string cpt_file = dir + Checkpoint::baseFilename;
    ofstream outstream(cpt_file.c_str());
    time_t t = time(NULL);
    if (!outstream.is_open())
        fatal("Unable to open file %s for writing\n", cpt_file.c_str());
    outstream << "## checkpoint generated: " << ctime(&t);

    globals.serialize(outstream);
    SimObject::serializeAll(outstream);
}

void
Serializable::unserializeGlobals(Checkpoint *cp)
{
    globals.unserialize(cp);
}

void
debug_serialize(const string &cpt_dir)
{
    Serializable::serializeAll(cpt_dir);
}

////////////////////////////////////////////////////////////////////////
//
// SerializableClass member definitions
//
////////////////////////////////////////////////////////////////////////

// Map of class names to SerializableBuilder creation functions.
// Need to make this a pointer so we can force initialization on the
// first reference; otherwise, some SerializableClass constructors
// may be invoked before the classMap constructor.
map<string, SerializableClass::CreateFunc> *SerializableClass::classMap = 0;

// SerializableClass constructor: add mapping to classMap
SerializableClass::SerializableClass(const string &className,
                                     CreateFunc createFunc)
{
    if (classMap == NULL)
        classMap = new map<string, SerializableClass::CreateFunc>();

    if ((*classMap)[className])
        fatal("Error: simulation object class %s redefined\n", className);

    // add className --> createFunc to class map
    (*classMap)[className] = createFunc;
}

//
//
Serializable *
SerializableClass::createObject(Checkpoint *cp, const string &section)
{
    string className;

    if (!cp->find(section, "type", className)) {
        fatal("Serializable::create: no 'type' entry in section '%s'.\n",
              section);
    }

    CreateFunc createFunc = (*classMap)[className];

    if (createFunc == NULL) {
        fatal("Serializable::create: no create function for class '%s'.\n",
              className);
    }

    Serializable *object = createFunc(cp, section);

    assert(object != NULL);

    return object;
}

Serializable *
Serializable::create(Checkpoint *cp, const string &section)
{
    Serializable *object = SerializableClass::createObject(cp, section);
    object->unserialize(cp, section);
    return object;
}

const char *Checkpoint::baseFilename = "m5.cpt";

string Checkpoint::currentDirectory;

string
Checkpoint::setDir(const string &name)
{
    // use csprintf to insert curTick() into directory name if it
    // appears to have a format placeholder in it.
    currentDirectory = (name.find("%") != string::npos) ?
        csprintf(name, curTick()) : name;
    if (currentDirectory[currentDirectory.size() - 1] != '/')
        currentDirectory += "/";
    return currentDirectory;
}

string
Checkpoint::dir()
{
    return currentDirectory;
}

Checkpoint::Checkpoint(const string &cpt_dir)
    : db(new IniFile), cptDir(setDir(cpt_dir))
{
    string filename = cptDir + "/" + Checkpoint::baseFilename;
    if (!db->load(filename)) {
        fatal("Can't load checkpoint file '%s'\n", filename);
    }
}

bool
Checkpoint::find(const string &section, const string &entry, string &value)
{
    return db->find(section, entry, value);
}

bool
Checkpoint::findObj(const string &section, const string &entry,
                    SimObject *&value)
{
    string path;

    if (!db->find(section, entry, path))
        return false;

    value = resolveSimObject(path);
    return true;
}

bool
Checkpoint::sectionExists(const string &section)
{
    return db->sectionExists(section);
}
<commit_msg>checkpointing: fix bug from curTick accessor conversion.<commit_after>/*
 * Copyright (c) 2002-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Nathan Binkert
 *          Erik Hallnor
 *          Steve Reinhardt
 */

#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>

#include <fstream>
#include <list>
#include <string>
#include <vector>

#include "base/inifile.hh"
#include "base/misc.hh"
#include "base/output.hh"
#include "base/str.hh"
#include "base/trace.hh"
#include "sim/eventq.hh"
#include "sim/serialize.hh"
#include "sim/sim_events.hh"
#include "sim/sim_exit.hh"
#include "sim/sim_object.hh"

// For stat reset hack
#include "sim/stat_control.hh"

using namespace std;

extern SimObject *resolveSimObject(const string &);

//
// The base implementations use to_number for parsing and '<<' for
// displaying, suitable for integer types.
//
template <class T>
bool
parseParam(const string &s, T &value)
{
    return to_number(s, value);
}

template <class T>
void
showParam(ostream &os, const T &value)
{
    os << value;
}

//
// Template specializations:
// - char (8-bit integer)
// - floating-point types
// - bool
// - string
//

// Treat 8-bit ints (chars) as ints on output, not as chars
template <>
void
showParam(ostream &os, const char &value)
{
    os << (int)value;
}

template <>
void
showParam(ostream &os, const signed char &value)
{
    os << (int)value;
}

template <>
void
showParam(ostream &os, const unsigned char &value)
{
    os << (unsigned int)value;
}

// Use sscanf() for FP types as to_number() only handles integers
template <>
bool
parseParam(const string &s, float &value)
{
    return (sscanf(s.c_str(), "%f", &value) == 1);
}

template <>
bool
parseParam(const string &s, double &value)
{
    return (sscanf(s.c_str(), "%lf", &value) == 1);
}

template <>
bool
parseParam(const string &s, bool &value)
{
    const string &ls = to_lower(s);

    if (ls == "true") {
        value = true;
        return true;
    }

    if (ls == "false") {
        value = false;
        return true;
    }

    return false;
}

// Display bools as strings
template <>
void
showParam(ostream &os, const bool &value)
{
    os << (value ? "true" : "false");
}

// String requires no processing to speak of
template <>
bool
parseParam(const string &s, string &value)
{
    value = s;
    return true;
}

int Serializable::ckptMaxCount = 0;
int Serializable::ckptCount = 0;
int Serializable::ckptPrevCount = -1;

void
Serializable::nameOut(ostream &os)
{
    os << "\n[" << name() << "]\n";
}

void
Serializable::nameOut(ostream &os, const string &_name)
{
    os << "\n[" << _name << "]\n";
}

template <class T>
void
paramOut(ostream &os, const string &name, const T &param)
{
    os << name << "=";
    showParam(os, param);
    os << "\n";
}

template <class T>
void
arrayParamOut(ostream &os, const string &name, const vector<T> &param)
{
    typename vector<T>::size_type size = param.size();
    os << name << "=";
    if (size > 0)
        showParam(os, param[0]);
    for (typename vector<T>::size_type i = 1; i < size; ++i) {
        os << " ";
        showParam(os, param[i]);
    }
    os << "\n";
}

template <class T>
void
paramIn(Checkpoint *cp, const string &section, const string &name, T &param)
{
    string str;
    if (!cp->find(section, name, str) || !parseParam(str, param)) {
        fatal("Can't unserialize '%s:%s'\n", section, name);
    }
}

template <class T>
bool
optParamIn(Checkpoint *cp, const string &section, const string &name, T &param)
{
    string str;
    if (!cp->find(section, name, str) || !parseParam(str, param)) {
        warn("optional parameter %s:%s not present\n", section, name);
        return false;
    } else {
        return true;
    }
}

template <class T>
void
arrayParamOut(ostream &os, const string &name, const T *param, unsigned size)
{
    os << name << "=";
    if (size > 0)
        showParam(os, param[0]);
    for (unsigned i = 1; i < size; ++i) {
        os << " ";
        showParam(os, param[i]);
    }
    os << "\n";
}

template <class T>
void
arrayParamIn(Checkpoint *cp, const string &section, const string &name,
             T *param, unsigned size)
{
    string str;
    if (!cp->find(section, name, str)) {
        fatal("Can't unserialize '%s:%s'\n", section, name);
    }

    // code below stolen from VectorParam<T>::parse().
    // it would be nice to unify these somehow...

    vector<string> tokens;

    tokenize(tokens, str, ' ');

    // Need this if we were doing a vector
    // value.resize(tokens.size());

    if (tokens.size() != size) {
        fatal("Array size mismatch on %s:%s'\n", section, name);
    }

    for (vector<string>::size_type i = 0; i < tokens.size(); i++) {
        // need to parse into local variable to handle vector<bool>,
        // for which operator[] returns a special reference class
        // that's not the same as 'bool&', (since it's a packed
        // vector)
        T scalar_value = 0;
        if (!parseParam(tokens[i], scalar_value)) {
            string err("could not parse \"");

            err += str;
            err += "\"";

            fatal(err);
        }

        // assign parsed value to vector
        param[i] = scalar_value;
    }
}

template <class T>
void
arrayParamIn(Checkpoint *cp, const string &section,
             const string &name, vector<T> &param)
{
    string str;
    if (!cp->find(section, name, str)) {
        fatal("Can't unserialize '%s:%s'\n", section, name);
    }

    // code below stolen from VectorParam<T>::parse().
    // it would be nice to unify these somehow...

    vector<string> tokens;

    tokenize(tokens, str, ' ');

    // Need this if we were doing a vector
    // value.resize(tokens.size());

    param.resize(tokens.size());

    for (vector<string>::size_type i = 0; i < tokens.size(); i++) {
        // need to parse into local variable to handle vector<bool>,
        // for which operator[] returns a special reference class
        // that's not the same as 'bool&', (since it's a packed
        // vector)
        T scalar_value = 0;
        if (!parseParam(tokens[i], scalar_value)) {
            string err("could not parse \"");

            err += str;
            err += "\"";

            fatal(err);
        }

        // assign parsed value to vector
        param[i] = scalar_value;
    }
}

void
objParamIn(Checkpoint *cp, const string &section,
           const string &name, SimObject * &param)
{
    if (!cp->findObj(section, name, param)) {
        fatal("Can't unserialize '%s:%s'\n", section, name);
    }
}

#define INSTANTIATE_PARAM_TEMPLATES(type)                               \
template void                                                           \
paramOut(ostream &os, const string &name, type const &param);           \
template void                                                           \
paramIn(Checkpoint *cp, const string &section,                          \
        const string &name, type & param);                              \
template bool                                                           \
optParamIn(Checkpoint *cp, const string &section,                       \
        const string &name, type & param);                              \
template void                                                           \
arrayParamOut(ostream &os, const string &name,                          \
              type const *param, unsigned size);                        \
template void                                                           \
arrayParamIn(Checkpoint *cp, const string &section,                     \
             const string &name, type *param, unsigned size);           \
template void                                                           \
arrayParamOut(ostream &os, const string &name,                          \
              const vector<type> &param);                               \
template void                                                           \
arrayParamIn(Checkpoint *cp, const string &section,                     \
             const string &name, vector<type> &param);

INSTANTIATE_PARAM_TEMPLATES(char)
INSTANTIATE_PARAM_TEMPLATES(signed char)
INSTANTIATE_PARAM_TEMPLATES(unsigned char)
INSTANTIATE_PARAM_TEMPLATES(signed short)
INSTANTIATE_PARAM_TEMPLATES(unsigned short)
INSTANTIATE_PARAM_TEMPLATES(signed int)
INSTANTIATE_PARAM_TEMPLATES(unsigned int)
INSTANTIATE_PARAM_TEMPLATES(signed long)
INSTANTIATE_PARAM_TEMPLATES(unsigned long)
INSTANTIATE_PARAM_TEMPLATES(signed long long)
INSTANTIATE_PARAM_TEMPLATES(unsigned long long)
INSTANTIATE_PARAM_TEMPLATES(bool)
INSTANTIATE_PARAM_TEMPLATES(float)
INSTANTIATE_PARAM_TEMPLATES(double)
INSTANTIATE_PARAM_TEMPLATES(string)

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

/// Container for serializing global variables (not associated with
/// any serialized object).
class Globals : public Serializable
{
  public:
    const string name() const;
    void serialize(ostream &os);
    void unserialize(Checkpoint *cp);
};

/// The one and only instance of the Globals class.
Globals globals;

const string
Globals::name() const
{
    return "Globals";
}

void
Globals::serialize(ostream &os)
{
    nameOut(os);
    paramOut(os, "curTick", curTick());

    nameOut(os, "MainEventQueue");
    mainEventQueue.serialize(os);
}

void
Globals::unserialize(Checkpoint *cp)
{
    const string &section = name();
    Tick tick;
    paramIn(cp, section, "curTick", tick);
    curTick(tick);

    mainEventQueue.unserialize(cp, "MainEventQueue");
}

Serializable::Serializable()
{
}

Serializable::~Serializable()
{
}

void
Serializable::serialize(ostream &os)
{
}

void
Serializable::unserialize(Checkpoint *cp, const string &section)
{
}

void
Serializable::serializeAll(const string &cpt_dir)
{
    string dir = Checkpoint::setDir(cpt_dir);
    if (mkdir(dir.c_str(), 0775) == -1 && errno != EEXIST)
            fatal("couldn't mkdir %s\n", dir);

    string cpt_file = dir + Checkpoint::baseFilename;
    ofstream outstream(cpt_file.c_str());
    time_t t = time(NULL);
    if (!outstream.is_open())
        fatal("Unable to open file %s for writing\n", cpt_file.c_str());
    outstream << "## checkpoint generated: " << ctime(&t);

    globals.serialize(outstream);
    SimObject::serializeAll(outstream);
}

void
Serializable::unserializeGlobals(Checkpoint *cp)
{
    globals.unserialize(cp);
}

void
debug_serialize(const string &cpt_dir)
{
    Serializable::serializeAll(cpt_dir);
}

////////////////////////////////////////////////////////////////////////
//
// SerializableClass member definitions
//
////////////////////////////////////////////////////////////////////////

// Map of class names to SerializableBuilder creation functions.
// Need to make this a pointer so we can force initialization on the
// first reference; otherwise, some SerializableClass constructors
// may be invoked before the classMap constructor.
map<string, SerializableClass::CreateFunc> *SerializableClass::classMap = 0;

// SerializableClass constructor: add mapping to classMap
SerializableClass::SerializableClass(const string &className,
                                     CreateFunc createFunc)
{
    if (classMap == NULL)
        classMap = new map<string, SerializableClass::CreateFunc>();

    if ((*classMap)[className])
        fatal("Error: simulation object class %s redefined\n", className);

    // add className --> createFunc to class map
    (*classMap)[className] = createFunc;
}

//
//
Serializable *
SerializableClass::createObject(Checkpoint *cp, const string &section)
{
    string className;

    if (!cp->find(section, "type", className)) {
        fatal("Serializable::create: no 'type' entry in section '%s'.\n",
              section);
    }

    CreateFunc createFunc = (*classMap)[className];

    if (createFunc == NULL) {
        fatal("Serializable::create: no create function for class '%s'.\n",
              className);
    }

    Serializable *object = createFunc(cp, section);

    assert(object != NULL);

    return object;
}

Serializable *
Serializable::create(Checkpoint *cp, const string &section)
{
    Serializable *object = SerializableClass::createObject(cp, section);
    object->unserialize(cp, section);
    return object;
}

const char *Checkpoint::baseFilename = "m5.cpt";

string Checkpoint::currentDirectory;

string
Checkpoint::setDir(const string &name)
{
    // use csprintf to insert curTick() into directory name if it
    // appears to have a format placeholder in it.
    currentDirectory = (name.find("%") != string::npos) ?
        csprintf(name, curTick()) : name;
    if (currentDirectory[currentDirectory.size() - 1] != '/')
        currentDirectory += "/";
    return currentDirectory;
}

string
Checkpoint::dir()
{
    return currentDirectory;
}

Checkpoint::Checkpoint(const string &cpt_dir)
    : db(new IniFile), cptDir(setDir(cpt_dir))
{
    string filename = cptDir + "/" + Checkpoint::baseFilename;
    if (!db->load(filename)) {
        fatal("Can't load checkpoint file '%s'\n", filename);
    }
}

bool
Checkpoint::find(const string &section, const string &entry, string &value)
{
    return db->find(section, entry, value);
}

bool
Checkpoint::findObj(const string &section, const string &entry,
                    SimObject *&value)
{
    string path;

    if (!db->find(section, entry, path))
        return false;

    value = resolveSimObject(path);
    return true;
}

bool
Checkpoint::sectionExists(const string &section)
{
    return db->sectionExists(section);
}
<|endoftext|>


<commit_before>/* JDELAY - regenerating delay instrument, adapted from DELAY

   Compared with DELAY, JDELAY adds:
      - a simple low-pass filter
      - control over wet/dry mix
      - a DC blocking filter
      - switchable pre/post-fader delay

   Parameters:
      p0 = output start time
      p1 = input start time
      p2 = input duration
      p3 = amplitude multiplier
      p4 = delay time
      p5 = delay feedback (i.e., regeneration multiplier) [-1 to 1]
      p6 = ring-down duration
      p7 = cutoff freq for low-pass filter (in cps)  (0 to disable filter)
      p8 = wet/dry mix (0: dry -> 1: wet)
      p9 = input channel number [optional, default is 0]
      p10 = pan (in percent-to-left form: 0-1) [optional, default is .5]
      p11 = pre-fader send (0: No, 1: Yes) [optional, default is No]
      p12 = apply DC blocking filter (0: No, 1: Yes) [optional, default is Yes]
            (DC bias can affect sounds made with high feedback setting.)

   p3 (amplitude), p4 (delay time), p5 (feedback), p7 (cutoff), p8 (wet/dry)
   and p8 (pan) can receive dynamic updates from a table or real-time control
   source.

   If an old-style gen table 1 is present, its values will be multiplied
   by the p3 amplitude multiplier, even if the latter is dynamic.

   The point of the ring-down duration parameter is to let you control
   how long the delay will sound after the input has stopped.  Too short
   a time, and the sound may be cut off prematurely.

   If pre-fader send is set to 1, sends input signal to delay line with
   no attenuation.  Then p3 (amp multiplier) and setline controls entire
   note, including delay ring-down.

   John Gibson (jgg9c@virginia.edu), 6/23/99; rev for v4, 7/21/04
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <ugens.h>
#include <Instrument.h>
#include "JDELAY.h"
#include <rt.h>
#include <rtdefs.h>

#define MAXDELTIME 30.0    // seconds (176400 bytes per second at SR=44100)

// local functions
static void toneset(double, int, double []);
static double tone(double, double []);

JDELAY::JDELAY() : Instrument()
{
   in = NULL;
   delay = NULL;
   branch = 0;
   usefilt = false;
   warn_deltime = true;
}

JDELAY::~JDELAY()
{
   delete [] in;
   delete delay;
}

int JDELAY::init(double p[], int n_args)
{
   nargs = n_args;
   float outskip = p[0];
   float inskip = p[1];
   float dur = p[2];
   amp = p[3];
   float deltime = p[4];
   regen = p[5];
   float ringdur = p[6];
   cutoff = p[7];
   percent_wet = p[8];
   inchan = n_args > 9 ? (int) p[9] : 0;
   prefadersend = n_args > 11 ? (bool) p[11] : false;    // default is "no"
   dcblock = n_args > 12 ? (bool) p[12] : true;          // default is "yes"

   if (rtsetinput(inskip, this) != 0)
      return DONT_SCHEDULE;
   nsamps = rtsetoutput(outskip, dur + ringdur, this);
   insamps = (int) (dur * SR + 0.5);

   if (inchan >= inputChannels())
      return die("JDELAY", "You asked for channel %d of a %d-channel file.",
                                                      inchan, inputChannels());

   if (regen < -1.0 || regen > 1.0)
      return die("JDELAY", "Regeneration multiplier must be between -1 and 1.");

   if (cutoff < 0.0)
      return die("JDELAY",
              "Cutoff freq. should be positive (or zero to disable filter).");
   else if (cutoff == 0.0)
      advise("JDELAY", "Low-pass filter disabled.");
   else {
      usefilt = true;
      toneset(cutoff, 1, tonedata);
   }

   if (percent_wet < 0.0 || percent_wet > 1.0)
      return die("JDELAY", "Wet/dry mix must be between 0 and 1 inclusive.");

   if (deltime > MAXDELTIME)
      return die("JDELAY", "Maximum delay time (%g seconds) exceeded.",
                                                                  MAXDELTIME);

   long maxdelsamps = (long) (MAXDELTIME * SR + 0.5);
   delay = new Ozdelay(maxdelsamps);
   if (delay == NULL)
      return die("JDELAY", "Can't allocate delay line memory.");

   amptable = floc(1);
   if (amptable) {
      int amplen = fsize(1);
      if (prefadersend)
         tableset(dur + ringdur, amplen, amptabs);
      else
         tableset(dur, amplen, amptabs);
   }

   skip = (int) (SR / (float) resetval);

   prev_in = prev_out = 0.0;         // for DC-blocker

   return nsamps;
}

void JDELAY::doupdate(double p[])
{
   amp = p[3];
   if (amptable)
      amp *= tablei(currentFrame(), amptable, amptabs);

   float deltime = p[4];
   if (deltime > MAXDELTIME) {
      if (warn_deltime) {
         warn("JDELAY", "Maximum delay time (%g seconds) exceeded!",
                                                               MAXDELTIME);
         warn_deltime = false;
      }
      delsamps = MAXDELTIME * SR;
   }
   else
      delsamps = deltime * SR;

   regen = p[5];
   if (regen < -1.0)
      regen = -1.0;
   else if (regen > 1.0)
      regen = 1.0;

   if (usefilt && p[7] != cutoff) {
      cutoff = p[7];
      if (cutoff <= 0.0)
         cutoff = 0.1;
      toneset(cutoff, 0, tonedata);
   }

   percent_wet = p[8];
   if (percent_wet < 0.0)
      percent_wet = 0.0;
   else if (percent_wet > 1.0)
      percent_wet = 1.0;

   pctleft = nargs > 10 ? p[10] : 0.5;        // default is center
}

int JDELAY::configure()
{
   in = new float [RTBUFSAMPS * inputChannels()];
   return in ? 0 : -1;
}

int JDELAY::run()
{
   int samps = framesToRun() * inputChannels();

   if (currentFrame() < insamps)
      rtgetin(in, this, samps);

   for (int i = 0; i < samps; i += inputChannels()) {
      if (--branch <= 0) {
         double p[11];
         update(p, 11,
                kAmp | kDelTime | kDelRegen | kCutoff | kWetPercent | kPan);
         doupdate(p);
         branch = skip;
      }

      float delsig = delay->getsamp(delsamps) * regen;

      float insig;
      if (currentFrame() < insamps)          // still taking input from file
         insig = in[i + inchan];
      else
         insig = 0.0;

      float out[2];
      if (prefadersend) {
         delay->putsamp(insig + delsig);
         out[0] = insig * (1.0 - percent_wet) + delsig * percent_wet;
         out[0] *= amp;
      }
      else {
         insig *= amp;
         delay->putsamp(insig + delsig);
         out[0] = insig * (1.0 - percent_wet) + delsig * percent_wet;
      }

      /* NOTE: We filter the sig *after* putting it in the delay line.
               Otherwise, pitch for short delays drops with low cutoff freqs.
      */
      if (usefilt)
         out[0] = tone(out[0], tonedata);

      /* The DC-blocking code is from Perry Cook's STK (STK98v2/DCBlock.cpp).
         It works pretty well (and quickly) for all but extreme cases. But I've
         gotten JDELAY to generate files with a fair amount of DC even *with*
         this simple filter. The Remove DC function in mxv works better. It's
         the standard cmix elliptical filter with 60db atten., stopband at 5 hz,
         and passband at 20 hz. But that's overkill for here.
      */
      if (dcblock) {
         float tmp_in = out[0];
         out[0] = tmp_in - prev_in + (0.99 * prev_out);
         prev_in = tmp_in;
         prev_out = out[0];
      }

      if (outputChannels() == 2) {
         out[1] = out[0] * (1.0 - pctleft);
         out[0] *= pctleft;
      }
      rtaddout(out);
      increment();
   }

   return framesToRun();
}

/* -------------------------------------------------------------------------- */
/* This filter nabbed from Doug Scott's place program */

/* toneset calculates the coefficients for tone.
      <cutoff> is -3db point in cps
      <flag> will reset history if set to 1
      <data> is an array of 3 doubles, used for bookeeping
   NOTE: JDELAY doesn't try to use the inverse function cited below.
*/
static void
toneset(double cutoff, int flag, double data[])
{
   double x;

   x = 2.0 - cos(cutoff * PI2 / SR);        /* feedback coeff. */
   data[1] = x - sqrt(x * x - 1.0);
   data[0] = 1.0 - data[1];                 /* gain coeff. */
   if (cutoff < 0.0)
      data[1] *= -1.0;                      /* inverse function */
   if (flag)
      data[2] = 0.0;
}

/* tone is a simple 1st order recursive lowpass filter
      <data> is an array of 3 doubles, used for bookeeping
*/
static double
tone(double sig, double data[])
{
   data[2] = data[0] * sig + data[1] * data[2];
   return data[2];
}

Instrument *makeJDELAY()
{
   JDELAY *inst;

   inst = new JDELAY();
   inst->set_bus_config("JDELAY");

   return inst;
}

void rtprofile()
{
   RT_INTRO("JDELAY", makeJDELAY);
}

<commit_msg>Use nSamps() for init return.<commit_after>/* JDELAY - regenerating delay instrument, adapted from DELAY

   Compared with DELAY, JDELAY adds:
      - a simple low-pass filter
      - control over wet/dry mix
      - a DC blocking filter
      - switchable pre/post-fader delay

   Parameters:
      p0 = output start time
      p1 = input start time
      p2 = input duration
      p3 = amplitude multiplier
      p4 = delay time
      p5 = delay feedback (i.e., regeneration multiplier) [-1 to 1]
      p6 = ring-down duration
      p7 = cutoff freq for low-pass filter (in cps)  (0 to disable filter)
      p8 = wet/dry mix (0: dry -> 1: wet)
      p9 = input channel number [optional, default is 0]
      p10 = pan (in percent-to-left form: 0-1) [optional, default is .5]
      p11 = pre-fader send (0: No, 1: Yes) [optional, default is No]
      p12 = apply DC blocking filter (0: No, 1: Yes) [optional, default is Yes]
            (DC bias can affect sounds made with high feedback setting.)

   p3 (amplitude), p4 (delay time), p5 (feedback), p7 (cutoff), p8 (wet/dry)
   and p8 (pan) can receive dynamic updates from a table or real-time control
   source.

   If an old-style gen table 1 is present, its values will be multiplied
   by the p3 amplitude multiplier, even if the latter is dynamic.

   The point of the ring-down duration parameter is to let you control
   how long the delay will sound after the input has stopped.  Too short
   a time, and the sound may be cut off prematurely.

   If pre-fader send is set to 1, sends input signal to delay line with
   no attenuation.  Then p3 (amp multiplier) and setline controls entire
   note, including delay ring-down.

   John Gibson (jgg9c@virginia.edu), 6/23/99; rev for v4, 7/21/04
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <ugens.h>
#include <Instrument.h>
#include "JDELAY.h"
#include <rt.h>
#include <rtdefs.h>

#define MAXDELTIME 30.0    // seconds (176400 bytes per second at SR=44100)

// local functions
static void toneset(double, int, double []);
static double tone(double, double []);

JDELAY::JDELAY() : Instrument()
{
   in = NULL;
   delay = NULL;
   branch = 0;
   usefilt = false;
   warn_deltime = true;
}

JDELAY::~JDELAY()
{
   delete [] in;
   delete delay;
}

int JDELAY::init(double p[], int n_args)
{
   nargs = n_args;
   float outskip = p[0];
   float inskip = p[1];
   float dur = p[2];
   amp = p[3];
   float deltime = p[4];
   regen = p[5];
   float ringdur = p[6];
   cutoff = p[7];
   percent_wet = p[8];
   inchan = n_args > 9 ? (int) p[9] : 0;
   prefadersend = n_args > 11 ? (bool) p[11] : false;    // default is "no"
   dcblock = n_args > 12 ? (bool) p[12] : true;          // default is "yes"

   if (rtsetinput(inskip, this) != 0)
      return DONT_SCHEDULE;
   nsamps = rtsetoutput(outskip, dur + ringdur, this);
   insamps = (int) (dur * SR + 0.5);

   if (inchan >= inputChannels())
      return die("JDELAY", "You asked for channel %d of a %d-channel file.",
                                                      inchan, inputChannels());

   if (regen < -1.0 || regen > 1.0)
      return die("JDELAY", "Regeneration multiplier must be between -1 and 1.");

   if (cutoff < 0.0)
      return die("JDELAY",
              "Cutoff freq. should be positive (or zero to disable filter).");
   else if (cutoff == 0.0)
      advise("JDELAY", "Low-pass filter disabled.");
   else {
      usefilt = true;
      toneset(cutoff, 1, tonedata);
   }

   if (percent_wet < 0.0 || percent_wet > 1.0)
      return die("JDELAY", "Wet/dry mix must be between 0 and 1 inclusive.");

   if (deltime > MAXDELTIME)
      return die("JDELAY", "Maximum delay time (%g seconds) exceeded.",
                                                                  MAXDELTIME);

   long maxdelsamps = (long) (MAXDELTIME * SR + 0.5);
   delay = new Ozdelay(maxdelsamps);
   if (delay == NULL)
      return die("JDELAY", "Can't allocate delay line memory.");

   amptable = floc(1);
   if (amptable) {
      int amplen = fsize(1);
      if (prefadersend)
         tableset(dur + ringdur, amplen, amptabs);
      else
         tableset(dur, amplen, amptabs);
   }

   skip = (int) (SR / (float) resetval);

   prev_in = prev_out = 0.0;         // for DC-blocker

   return nSamps();
}

void JDELAY::doupdate(double p[])
{
   amp = p[3];
   if (amptable)
      amp *= tablei(currentFrame(), amptable, amptabs);

   float deltime = p[4];
   if (deltime > MAXDELTIME) {
      if (warn_deltime) {
         warn("JDELAY", "Maximum delay time (%g seconds) exceeded!",
                                                               MAXDELTIME);
         warn_deltime = false;
      }
      delsamps = MAXDELTIME * SR;
   }
   else
      delsamps = deltime * SR;

   regen = p[5];
   if (regen < -1.0)
      regen = -1.0;
   else if (regen > 1.0)
      regen = 1.0;

   if (usefilt && p[7] != cutoff) {
      cutoff = p[7];
      if (cutoff <= 0.0)
         cutoff = 0.1;
      toneset(cutoff, 0, tonedata);
   }

   percent_wet = p[8];
   if (percent_wet < 0.0)
      percent_wet = 0.0;
   else if (percent_wet > 1.0)
      percent_wet = 1.0;

   pctleft = nargs > 10 ? p[10] : 0.5;        // default is center
}

int JDELAY::configure()
{
   in = new float [RTBUFSAMPS * inputChannels()];
   return in ? 0 : -1;
}

int JDELAY::run()
{
   int samps = framesToRun() * inputChannels();

   if (currentFrame() < insamps)
      rtgetin(in, this, samps);

   for (int i = 0; i < samps; i += inputChannels()) {
      if (--branch <= 0) {
         double p[11];
         update(p, 11,
                kAmp | kDelTime | kDelRegen | kCutoff | kWetPercent | kPan);
         doupdate(p);
         branch = skip;
      }

      float delsig = delay->getsamp(delsamps) * regen;

      float insig;
      if (currentFrame() < insamps)          // still taking input from file
         insig = in[i + inchan];
      else
         insig = 0.0;

      float out[2];
      if (prefadersend) {
         delay->putsamp(insig + delsig);
         out[0] = insig * (1.0 - percent_wet) + delsig * percent_wet;
         out[0] *= amp;
      }
      else {
         insig *= amp;
         delay->putsamp(insig + delsig);
         out[0] = insig * (1.0 - percent_wet) + delsig * percent_wet;
      }

      /* NOTE: We filter the sig *after* putting it in the delay line.
               Otherwise, pitch for short delays drops with low cutoff freqs.
      */
      if (usefilt)
         out[0] = tone(out[0], tonedata);

      /* The DC-blocking code is from Perry Cook's STK (STK98v2/DCBlock.cpp).
         It works pretty well (and quickly) for all but extreme cases. But I've
         gotten JDELAY to generate files with a fair amount of DC even *with*
         this simple filter. The Remove DC function in mxv works better. It's
         the standard cmix elliptical filter with 60db atten., stopband at 5 hz,
         and passband at 20 hz. But that's overkill for here.
      */
      if (dcblock) {
         float tmp_in = out[0];
         out[0] = tmp_in - prev_in + (0.99 * prev_out);
         prev_in = tmp_in;
         prev_out = out[0];
      }

      if (outputChannels() == 2) {
         out[1] = out[0] * (1.0 - pctleft);
         out[0] *= pctleft;
      }
      rtaddout(out);
      increment();
   }

   return framesToRun();
}

/* -------------------------------------------------------------------------- */
/* This filter nabbed from Doug Scott's place program */

/* toneset calculates the coefficients for tone.
      <cutoff> is -3db point in cps
      <flag> will reset history if set to 1
      <data> is an array of 3 doubles, used for bookeeping
   NOTE: JDELAY doesn't try to use the inverse function cited below.
*/
static void
toneset(double cutoff, int flag, double data[])
{
   double x;

   x = 2.0 - cos(cutoff * PI2 / SR);        /* feedback coeff. */
   data[1] = x - sqrt(x * x - 1.0);
   data[0] = 1.0 - data[1];                 /* gain coeff. */
   if (cutoff < 0.0)
      data[1] *= -1.0;                      /* inverse function */
   if (flag)
      data[2] = 0.0;
}

/* tone is a simple 1st order recursive lowpass filter
      <data> is an array of 3 doubles, used for bookeeping
*/
static double
tone(double sig, double data[])
{
   data[2] = data[0] * sig + data[1] * data[2];
   return data[2];
}

Instrument *makeJDELAY()
{
   JDELAY *inst;

   inst = new JDELAY();
   inst->set_bus_config("JDELAY");

   return inst;
}

void rtprofile()
{
   RT_INTRO("JDELAY", makeJDELAY);
}

<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** If you have questions regarding the use of this file, please
** contact Nokia at http://qt.nokia.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qmessagestore.h"
#include "qmfhelpers_p.h"

#include <qmailstore.h>

#include <QCoreApplication>
#include <QEvent>

using namespace QmfHelpers;

class QMessageStorePrivate
{
public:
    QMessageStorePrivate() : _store(QMailStore::instance()), _error(QMessageStore::NoError) {}

    QMailStore *_store;
    QMessageStore::ErrorCode _error;

    static QMailStore *convert(QMessageStore *store);

    Q_SCOPED_STATIC_DECLARE(QMessageStore,storeInstance);

    static void registerMessageStatus(QMailStore *store, const QString &field);
    static void createNonexistentFolder(QMailStore *store, const QString &path, quint64 status);
};

Q_SCOPED_STATIC_DEFINE(QMessageStore,QMessageStorePrivate,storeInstance);

QMailStore *QMessageStorePrivate::convert(QMessageStore *store)
{
    return store->d_ptr->_store;
}

void QMessageStorePrivate::registerMessageStatus(QMailStore *store, const QString &field)
{
    store->registerMessageStatusFlag(field);
}

void QMessageStorePrivate::createNonexistentFolder(QMailStore *store, const QString &path, quint64 status)
{
    QMailFolderKey pathKey(QMailFolderKey::path(path));
    QMailFolderKey accountKey(QMailFolderKey::parentAccountId(QMailAccountId()));

    if (store->countFolders(pathKey & accountKey) == 0) {
        QMailFolder folder;
        folder.setPath(path);
        folder.setStatus(status);

        if (!store->addFolder(&folder)) {
            qWarning() << "Unable to add folder for:" << path;
        }
    }
}

namespace QmfHelpers {

QMailStore *convert(QMessageStore *store)
{
    return QMessageStorePrivate::convert(store);
}

}

QMessageStore::QMessageStore(QObject *parent)
    : QObject(parent),
      d_ptr(new QMessageStorePrivate)
{
    Q_ASSERT(instance() != 0);
}

QMessageStore::~QMessageStore()
{
    delete d_ptr;
}

QMessageStore::ErrorCode QMessageStore::lastError() const
{
    if (d_ptr->_error != QMessageStore::NoError) {
        return d_ptr->_error;
    }

    return convert(d_ptr->_store->lastError());
}

QMessageIdList QMessageStore::queryMessages(const QMessageFilterKey &key, const QMessageSortKey &sortKey, uint limit, uint offset) const
{
    if (key.options() != 0) {
        d_ptr->_error = QMessageStore::NotYetImplemented;
        return QMessageIdList();
    }

    d_ptr->_error = QMessageStore::NoError;
    return convert(d_ptr->_store->queryMessages(convert(key), convert(sortKey), limit, offset));
}

QMessageIdList QMessageStore::queryMessages(const QString &body, const QMessageFilterKey &key, const QMessageSortKey &sortKey, QMessageDataComparator::Options options, uint limit, uint offset) const
{
    Q_UNUSED(key)
    Q_UNUSED(sortKey)
    Q_UNUSED(body)
    Q_UNUSED(options)
    Q_UNUSED(limit)
    Q_UNUSED(offset)
    return QMessageIdList(); // stub
}

#ifdef QMESSAGING_OPTIONAL_FOLDER
QMessageFolderIdList QMessageStore::queryFolders(const QMessageFolderFilterKey &key, const QMessageFolderSortKey &sortKey, uint limit, uint offset) const
{
    if (key.options() != 0) {
        d_ptr->_error = QMessageStore::NotYetImplemented;
        return QMessageFolderIdList();
    }

    d_ptr->_error = QMessageStore::NoError;
    return convert(d_ptr->_store->queryFolders(convert(key), convert(sortKey), limit, offset));
}
#endif

QMessageAccountIdList QMessageStore::queryAccounts(const QMessageAccountFilterKey &key, const QMessageAccountSortKey &sortKey, uint limit, uint offset) const
{
    if (key.options() != 0) {
        d_ptr->_error = QMessageStore::NotYetImplemented;
        return QMessageAccountIdList();
    }

    d_ptr->_error = QMessageStore::NoError;
    return convert(d_ptr->_store->queryAccounts(convert(key), convert(sortKey), limit, offset));
}

int QMessageStore::countMessages(const QMessageFilterKey& key) const
{
    if (key.options() != 0) {
        d_ptr->_error = QMessageStore::NotYetImplemented;
        return 0;
    }

    d_ptr->_error = QMessageStore::NoError;
    return d_ptr->_store->countMessages(convert(key));
}

#ifdef QMESSAGING_OPTIONAL_FOLDER
int QMessageStore::countFolders(const QMessageFolderFilterKey& key) const
{
    if (key.options() != 0) {
        d_ptr->_error = QMessageStore::NotYetImplemented;
        return 0;
    }

    d_ptr->_error = QMessageStore::NoError;
    return d_ptr->_store->countFolders(convert(key));
}
#endif

int QMessageStore::countAccounts(const QMessageAccountFilterKey& key) const
{
    if (key.options() != 0) {
        d_ptr->_error = QMessageStore::NotYetImplemented;
        return 0;
    }

    d_ptr->_error = QMessageStore::NoError;
    return d_ptr->_store->countAccounts(convert(key));
}

bool QMessageStore::removeMessage(const QMessageId& id, QMessageStore::RemovalOption option)
{
    d_ptr->_error = QMessageStore::NoError;
    return d_ptr->_store->removeMessage(convert(id), convert(option));
}

bool QMessageStore::removeMessages(const QMessageFilterKey& key, QMessageStore::RemovalOption option)
{
    d_ptr->_error = QMessageStore::NoError;
    return d_ptr->_store->removeMessages(convert(key), convert(option));
}

bool QMessageStore::addMessage(QMessage *m)
{
    QMailMessage msg(convert(*m));

    d_ptr->_error = QMessageStore::NoError;
    return d_ptr->_store->addMessage(&msg);
}

bool QMessageStore::updateMessage(QMessage *m)
{
    QMailMessage msg(convert(*m));

    d_ptr->_error = QMessageStore::NoError;
    return d_ptr->_store->updateMessage(&msg);
}

QMessage QMessageStore::message(const QMessageId& id) const
{
    d_ptr->_error = QMessageStore::NoError;
    return convert(d_ptr->_store->message(convert(id)));
}

#ifdef QMESSAGING_OPTIONAL_FOLDER
QMessageFolder QMessageStore::folder(const QMessageFolderId& id) const
{
    d_ptr->_error = QMessageStore::NoError;
    return convert(d_ptr->_store->folder(convert(id)));
}
#endif

QMessageAccount QMessageStore::account(const QMessageAccountId& id) const
{
    d_ptr->_error = QMessageStore::NoError;
    return convert(d_ptr->_store->account(convert(id)));
}

QMessageStore* QMessageStore::instance()
{
    static bool initialised(false);

    QMessageStore* store(QMessageStorePrivate::storeInstance());

    if (!initialised) {
        initialised = true;

        QMailStore *mailStore(convert(store));

        // Perform any initialisation tasks
        QMessageStorePrivate::registerMessageStatus(mailStore, "QMessage::HighPriority");
        QMessageStorePrivate::registerMessageStatus(mailStore, "QMessage::LowPriority");

        // Create the standard folders if they do not exist
        typedef QPair<const char*, quint64> FolderAttributes;
        foreach (const FolderAttributes &folder, QList<FolderAttributes>() << FolderAttributes("Inbox", QMailFolder::Incoming)
                                                                           << FolderAttributes("Outbox", QMailFolder::Outgoing)
                                                                           << FolderAttributes("Drafts", QMailFolder::Outgoing | QMailFolder::Trash)
                                                                           << FolderAttributes("Sent", QMailFolder::Outgoing | QMailFolder::Sent)
                                                                           << FolderAttributes("Trash", QMailFolder::Trash)) {
            QMessageStorePrivate::createNonexistentFolder(mailStore, folder.first, folder.second);
        }
    }

    return store;
}

void QMessageStore::startNotifications(const QMessageFilterKey &key)
{
    if (key.options() != 0) {
        d_ptr->_error = QMessageStore::NotYetImplemented;
        return;
    }

    // TODO: implement notifications
    Q_UNUSED(key)
}

void QMessageStore::stopNotifications()
{
    // TODO: implement notifications
}

<commit_msg>Remove assertion causing infinite recursion.<commit_after>/****************************************************************************
**
** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** If you have questions regarding the use of this file, please
** contact Nokia at http://qt.nokia.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qmessagestore.h"
#include "qmfhelpers_p.h"

#include <qmailstore.h>

#include <QCoreApplication>
#include <QEvent>

using namespace QmfHelpers;

class QMessageStorePrivate
{
public:
    QMessageStorePrivate() : _store(QMailStore::instance()), _error(QMessageStore::NoError) {}

    QMailStore *_store;
    QMessageStore::ErrorCode _error;

    static QMailStore *convert(QMessageStore *store);

    Q_SCOPED_STATIC_DECLARE(QMessageStore,storeInstance);

    static void registerMessageStatus(QMailStore *store, const QString &field);
    static void createNonexistentFolder(QMailStore *store, const QString &path, quint64 status);
};

Q_SCOPED_STATIC_DEFINE(QMessageStore,QMessageStorePrivate,storeInstance);

QMailStore *QMessageStorePrivate::convert(QMessageStore *store)
{
    return store->d_ptr->_store;
}

void QMessageStorePrivate::registerMessageStatus(QMailStore *store, const QString &field)
{
    store->registerMessageStatusFlag(field);
}

void QMessageStorePrivate::createNonexistentFolder(QMailStore *store, const QString &path, quint64 status)
{
    QMailFolderKey pathKey(QMailFolderKey::path(path));
    QMailFolderKey accountKey(QMailFolderKey::parentAccountId(QMailAccountId()));

    if (store->countFolders(pathKey & accountKey) == 0) {
        QMailFolder folder;
        folder.setPath(path);
        folder.setStatus(status);

        if (!store->addFolder(&folder)) {
            qWarning() << "Unable to add folder for:" << path;
        }
    }
}

namespace QmfHelpers {

QMailStore *convert(QMessageStore *store)
{
    return QMessageStorePrivate::convert(store);
}

}

QMessageStore::QMessageStore(QObject *parent)
    : QObject(parent),
      d_ptr(new QMessageStorePrivate)
{
}

QMessageStore::~QMessageStore()
{
    delete d_ptr;
}

QMessageStore::ErrorCode QMessageStore::lastError() const
{
    if (d_ptr->_error != QMessageStore::NoError) {
        return d_ptr->_error;
    }

    return convert(d_ptr->_store->lastError());
}

QMessageIdList QMessageStore::queryMessages(const QMessageFilterKey &key, const QMessageSortKey &sortKey, uint limit, uint offset) const
{
    if (key.options() != 0) {
        d_ptr->_error = QMessageStore::NotYetImplemented;
        return QMessageIdList();
    }

    d_ptr->_error = QMessageStore::NoError;
    return convert(d_ptr->_store->queryMessages(convert(key), convert(sortKey), limit, offset));
}

QMessageIdList QMessageStore::queryMessages(const QString &body, const QMessageFilterKey &key, const QMessageSortKey &sortKey, QMessageDataComparator::Options options, uint limit, uint offset) const
{
    Q_UNUSED(key)
    Q_UNUSED(sortKey)
    Q_UNUSED(body)
    Q_UNUSED(options)
    Q_UNUSED(limit)
    Q_UNUSED(offset)
    return QMessageIdList(); // stub
}

#ifdef QMESSAGING_OPTIONAL_FOLDER
QMessageFolderIdList QMessageStore::queryFolders(const QMessageFolderFilterKey &key, const QMessageFolderSortKey &sortKey, uint limit, uint offset) const
{
    if (key.options() != 0) {
        d_ptr->_error = QMessageStore::NotYetImplemented;
        return QMessageFolderIdList();
    }

    d_ptr->_error = QMessageStore::NoError;
    return convert(d_ptr->_store->queryFolders(convert(key), convert(sortKey), limit, offset));
}
#endif

QMessageAccountIdList QMessageStore::queryAccounts(const QMessageAccountFilterKey &key, const QMessageAccountSortKey &sortKey, uint limit, uint offset) const
{
    if (key.options() != 0) {
        d_ptr->_error = QMessageStore::NotYetImplemented;
        return QMessageAccountIdList();
    }

    d_ptr->_error = QMessageStore::NoError;
    return convert(d_ptr->_store->queryAccounts(convert(key), convert(sortKey), limit, offset));
}

int QMessageStore::countMessages(const QMessageFilterKey& key) const
{
    if (key.options() != 0) {
        d_ptr->_error = QMessageStore::NotYetImplemented;
        return 0;
    }

    d_ptr->_error = QMessageStore::NoError;
    return d_ptr->_store->countMessages(convert(key));
}

#ifdef QMESSAGING_OPTIONAL_FOLDER
int QMessageStore::countFolders(const QMessageFolderFilterKey& key) const
{
    if (key.options() != 0) {
        d_ptr->_error = QMessageStore::NotYetImplemented;
        return 0;
    }

    d_ptr->_error = QMessageStore::NoError;
    return d_ptr->_store->countFolders(convert(key));
}
#endif

int QMessageStore::countAccounts(const QMessageAccountFilterKey& key) const
{
    if (key.options() != 0) {
        d_ptr->_error = QMessageStore::NotYetImplemented;
        return 0;
    }

    d_ptr->_error = QMessageStore::NoError;
    return d_ptr->_store->countAccounts(convert(key));
}

bool QMessageStore::removeMessage(const QMessageId& id, QMessageStore::RemovalOption option)
{
    d_ptr->_error = QMessageStore::NoError;
    return d_ptr->_store->removeMessage(convert(id), convert(option));
}

bool QMessageStore::removeMessages(const QMessageFilterKey& key, QMessageStore::RemovalOption option)
{
    d_ptr->_error = QMessageStore::NoError;
    return d_ptr->_store->removeMessages(convert(key), convert(option));
}

bool QMessageStore::addMessage(QMessage *m)
{
    QMailMessage msg(convert(*m));

    d_ptr->_error = QMessageStore::NoError;
    return d_ptr->_store->addMessage(&msg);
}

bool QMessageStore::updateMessage(QMessage *m)
{
    QMailMessage msg(convert(*m));

    d_ptr->_error = QMessageStore::NoError;
    return d_ptr->_store->updateMessage(&msg);
}

QMessage QMessageStore::message(const QMessageId& id) const
{
    d_ptr->_error = QMessageStore::NoError;
    return convert(d_ptr->_store->message(convert(id)));
}

#ifdef QMESSAGING_OPTIONAL_FOLDER
QMessageFolder QMessageStore::folder(const QMessageFolderId& id) const
{
    d_ptr->_error = QMessageStore::NoError;
    return convert(d_ptr->_store->folder(convert(id)));
}
#endif

QMessageAccount QMessageStore::account(const QMessageAccountId& id) const
{
    d_ptr->_error = QMessageStore::NoError;
    return convert(d_ptr->_store->account(convert(id)));
}

QMessageStore* QMessageStore::instance()
{
    static bool initialised(false);

    QMessageStore* store(QMessageStorePrivate::storeInstance());

    if (!initialised) {
        initialised = true;

        QMailStore *mailStore(convert(store));

        // Perform any initialisation tasks
        QMessageStorePrivate::registerMessageStatus(mailStore, "QMessage::HighPriority");
        QMessageStorePrivate::registerMessageStatus(mailStore, "QMessage::LowPriority");

        // Create the standard folders if they do not exist
        typedef QPair<const char*, quint64> FolderAttributes;
        foreach (const FolderAttributes &folder, QList<FolderAttributes>() << FolderAttributes("Inbox", QMailFolder::Incoming)
                                                                           << FolderAttributes("Outbox", QMailFolder::Outgoing)
                                                                           << FolderAttributes("Drafts", QMailFolder::Outgoing | QMailFolder::Trash)
                                                                           << FolderAttributes("Sent", QMailFolder::Outgoing | QMailFolder::Sent)
                                                                           << FolderAttributes("Trash", QMailFolder::Trash)) {
            QMessageStorePrivate::createNonexistentFolder(mailStore, folder.first, folder.second);
        }
    }

    return store;
}

void QMessageStore::startNotifications(const QMessageFilterKey &key)
{
    if (key.options() != 0) {
        d_ptr->_error = QMessageStore::NotYetImplemented;
        return;
    }

    // TODO: implement notifications
    Q_UNUSED(key)
}

void QMessageStore::stopNotifications()
{
    // TODO: implement notifications
}

<|endoftext|>


<commit_before>#include "VulkanTexture.hpp"

VulkanTexture::VulkanTexture(const char* data, unsigned int length) {

}

VulkanTexture::~VulkanTexture() {

}
<commit_msg>Load texture from memory<commit_after>#include "VulkanTexture.hpp"

#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>
#include <iostream>

VulkanTexture::VulkanTexture(const char* data, unsigned int length) {
    // Load texture from memory.
    int width, height, channels;
    stbi_uc* pixels = stbi_load_from_memory(reinterpret_cast<const unsigned char*>(data), length, &width, &height, &channels, 0);
    if (pixels == nullptr) {
        std::cerr << "Failed to load image from memory." << std::endl;
        exit(-1);
    }

    // Clean up.
    stbi_image_free(pixels);
}

VulkanTexture::~VulkanTexture() {

}
<|endoftext|>


<commit_before>// Module:  Log4CPLUS
// File:    socket-win32.cxx
// Created: 4/2003
// Author:  Tad E. Smith
//
//
// Copyright 2003-2010 Tad E. Smith
//
// 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 <log4cplus/config.hxx>
#if defined (LOG4CPLUS_USE_WINSOCK)

#include <cassert>
#include <cerrno>
#include <vector>
#include <cstring>
#include <log4cplus/internal/socket.h>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/thread/threads.h>
#include <log4cplus/helpers/stringhelper.h>

/////////////////////////////////////////////////////////////////////////////
// file LOCAL Classes
/////////////////////////////////////////////////////////////////////////////

namespace
{

enum WSInitStates
{
    WS_UNINITIALIZED,
    WS_INITIALIZING,
    WS_INITIALIZED
};

static WSADATA wsa;
static LONG volatile winsock_state = WS_UNINITIALIZED;

static
void
init_winsock_worker ()
{
    log4cplus::helpers::LogLog * loglog
        = log4cplus::helpers::LogLog::getLogLog ();

    // Try to change the state to WS_INITIALIZING.
    LONG val = ::InterlockedCompareExchange (
        const_cast<LPLONG>(&winsock_state), WS_INITIALIZING, WS_UNINITIALIZED);
    switch (val)
    {
    case WS_UNINITIALIZED:
    {
        int ret = WSAStartup (MAKEWORD (2, 2), &wsa);
        if (ret != 0)
        {
            // Revert the state back to WS_UNINITIALIZED to unblock other
            // threads and let them throw exception.
            val = ::InterlockedCompareExchange (
                const_cast<LPLONG>(&winsock_state), WS_UNINITIALIZED,
                WS_INITIALIZING);
            assert (val == WS_INITIALIZING);
            loglog->error (LOG4CPLUS_TEXT ("Could not initialize WinSock."),
                true);
        }

        // WinSock is initialized, change the state to WS_INITIALIZED.
        val = ::InterlockedCompareExchange (
            const_cast<LPLONG>(&winsock_state), WS_INITIALIZED,
            WS_INITIALIZING);
        assert (val == WS_INITIALIZING);
        return;
    }

    case WS_INITIALIZING:
        // Wait for state change.
        while (true)
        {
            switch (winsock_state)
            {
            case WS_INITIALIZED:
                return;

            case WS_INITIALIZING:
                log4cplus::thread::yield ();
                continue;

            default:
                assert (0);
                loglog->error (LOG4CPLUS_TEXT ("Unknown WinSock state."), true);
            }
        }

    case WS_INITIALIZED:
        // WinSock is already initialized.
        return;

    default:
        assert (0);
        loglog->error (LOG4CPLUS_TEXT ("Unknown WinSock state."), true);
    }
}

static
void
init_winsock ()
{
    // Quick check first to avoid the expensive interlocked compare
    // and exchange.
    if (winsock_state == WS_INITIALIZED)
        return;
    else
        init_winsock_worker ();
}

struct WinSockInitializer
{
    ~WinSockInitializer ()
    {
        if (winsock_state == WS_INITIALIZED)
            WSACleanup ();
    }

    static WinSockInitializer winSockInitializer;
};

WinSockInitializer WinSockInitializer::winSockInitializer;

} // namespace

namespace log4cplus { namespace helpers {

/////////////////////////////////////////////////////////////////////////////
// Global Methods
/////////////////////////////////////////////////////////////////////////////

SOCKET_TYPE
openSocket(unsigned short port, SocketState& state)
{
    struct sockaddr_in server;

    init_winsock ();

    SOCKET sock = WSASocket (AF_INET, SOCK_STREAM, AF_UNSPEC, 0, 0
#if defined (WSA_FLAG_NO_HANDLE_INHERIT)
        , WSA_FLAG_NO_HANDLE_INHERIT
#else
        , 0
#endif
        );

    if (sock == INVALID_OS_SOCKET_VALUE)
        goto error;

    server.sin_family = AF_INET;
    server.sin_addr.s_addr = htonl(INADDR_ANY);
    server.sin_port = htons(port);

    if (bind(sock, reinterpret_cast<struct sockaddr*>(&server), sizeof(server))
        != 0)
        goto error;

    if (::listen(sock, 10) != 0)
        goto error;

    state = ok;
    return to_log4cplus_socket (sock);

error:
    int eno = WSAGetLastError ();

    if (sock != INVALID_OS_SOCKET_VALUE)
        ::closesocket (sock);

    set_last_socket_error (eno);
    return INVALID_SOCKET_VALUE;
}

SOCKET_TYPE
connectSocket(const tstring& hostn, unsigned short port, bool udp, SocketState& state)
{
    struct hostent * hp;
    struct sockaddr_in insock;
    int retval;

    init_winsock ();

    SOCKET sock = WSASocket (AF_INET, (udp ? SOCK_DGRAM : SOCK_STREAM),
        AF_UNSPEC, 0, 0
#if defined (WSA_FLAG_NO_HANDLE_INHERIT)
        , WSA_FLAG_NO_HANDLE_INHERIT
#else
        , 0
#endif
        );
    if (sock == INVALID_OS_SOCKET_VALUE)
        goto error;

    hp = ::gethostbyname( LOG4CPLUS_TSTRING_TO_STRING(hostn).c_str() );
    if (hp == 0 || hp->h_addrtype != AF_INET)
    {
        insock.sin_family = AF_INET;
        INT insock_size = sizeof (insock);
        INT ret = WSAStringToAddress (const_cast<LPTSTR>(hostn.c_str ()),
            AF_INET, 0, reinterpret_cast<struct sockaddr *>(&insock),
            &insock_size);
        if (ret == SOCKET_ERROR || insock_size != sizeof (insock))
        {
            state = bad_address;
            goto error;
        }
    }
    else
        std::memcpy (&insock.sin_addr, hp->h_addr_list[0],
            sizeof (insock.sin_addr));

    insock.sin_port = htons(port);
    insock.sin_family = AF_INET;

    while(   (retval = ::connect(sock, (struct sockaddr*)&insock, sizeof(insock))) == -1
          && (WSAGetLastError() == WSAEINTR))
        ;
    if (retval == SOCKET_ERROR)
        goto error;

    state = ok;
    return to_log4cplus_socket (sock);

error:
    int eno = WSAGetLastError ();

    if (sock != INVALID_OS_SOCKET_VALUE)
        ::closesocket (sock);

    set_last_socket_error (eno);
    return INVALID_SOCKET_VALUE;
}

SOCKET_TYPE
acceptSocket(SOCKET_TYPE sock, SocketState & state)
{
    init_winsock ();

    SOCKET osSocket = to_os_socket (sock);

    // Prepare event objects.

    WSAEVENT close_ev = WSACreateEvent ();
    if (close_ev == WSA_INVALID_EVENT)
        goto error;

    WSAEVENT accept_ev = WSACreateEvent ();
    if (accept_ev == WSA_INVALID_EVENT)
        goto error;

    // Prime the socket to report FD_CLOSE.

    int ret = WSAEventSelect (osSocket, close_ev, FD_CLOSE);
    if (ret != SOCKET_ERROR)
        goto error;

    // Prime the socket to report FD_ACCEPT.

    ret = WSAEventSelect (osSocket, accept_ev, FD_ACCEPT);
    if (ret != SOCKET_ERROR)
        goto error;

    WSAEVENT events[2] = { close_ev, accept_ev };

    while (1)
    {
        DWORD wfme = WSAWaitForMultipleEvents (2, events, FALSE, WSA_INFINITE,
            TRUE);
        switch (wfme)
        {
        case WSA_WAIT_TIMEOUT:
            // This should not happen for WSA_INFINITE timeout.
            // Fall through.

        case WSA_WAIT_IO_COMPLETION:
            continue;

        case WSA_WAIT_EVENT_0:
            WSASetLastError (ERROR_NO_DATA);
            goto error;

        case WSA_WAIT_EVENT_0 + 1:
        {
            WSACloseEvent (close_ev);
            WSACloseEvent (accept_ev);

            SOCKET connected_socket = ::accept (osSocket, NULL, NULL);

            if (connected_socket != INVALID_OS_SOCKET_VALUE)
                state = ok;

            return to_log4cplus_socket (connected_socket);
        }

        default:
            helpers::getLogLog ().error (
                LOG4CPLUS_TEXT ("unexpected WSAWaitForMultipleEvents return value: ")
                + helpers::convertIntegerToString (wfme));

            goto error;
        }
    }

error:
    DWORD const eno = WSAGetLastError ();

    if (close_ev != WSA_INVALID_EVENT)
        WSACloseEvent (close_ev);

    if (accept_ev != WSA_INVALID_EVENT)
        WSACloseEvent (accept_ev);

    set_last_socket_error (eno);

    return to_log4cplus_socket (INVALID_SOCKET);
}

int
closeSocket(SOCKET_TYPE sock)
{
    return ::closesocket (to_os_socket (sock));
}

long
read(SOCKET_TYPE sock, SocketBuffer& buffer)
{
    long res, read = 0;

    do
    {
        res = ::recv(to_os_socket (sock),
                     buffer.getBuffer() + read,
                     static_cast<int>(buffer.getMaxSize() - read),
                     0);
        if (res == SOCKET_ERROR)
        {
            set_last_socket_error (WSAGetLastError ());
            return res;
        }
        read += res;
    }
    while (read < static_cast<long>(buffer.getMaxSize()));

    return read;
}

long
write(SOCKET_TYPE sock, const SocketBuffer& buffer)
{
    long ret = ::send (to_os_socket (sock), buffer.getBuffer(),
        static_cast<int>(buffer.getSize()), 0);
    if (ret == SOCKET_ERROR)
        set_last_socket_error (WSAGetLastError ());
    return ret;
}

long
write(SOCKET_TYPE sock, const std::string & buffer)
{
    long ret = ::send (to_os_socket (sock), buffer.c_str (),
        static_cast<int>(buffer.size ()), 0);
    if (ret == SOCKET_ERROR)
        set_last_socket_error (WSAGetLastError ());
    return ret;
}

tstring
getHostname (bool fqdn)
{
    char const * hostname = "unknown";
    int ret;
    std::vector<char> hn (1024, 0);

    while (true)
    {
        ret = ::gethostname (&hn[0], static_cast<int>(hn.size ()) - 1);
        if (ret == 0)
        {
            hostname = &hn[0];
            break;
        }
        else if (ret != 0 && WSAGetLastError () == WSAEFAULT)
            // Out buffer was too short. Retry with buffer twice the size.
            hn.resize (hn.size () * 2, 0);
        else
            break;
    }

    if (ret != 0 || (ret == 0 && ! fqdn))
        return LOG4CPLUS_STRING_TO_TSTRING (hostname);

    struct ::hostent * hp = ::gethostbyname (hostname);
    if (hp)
        hostname = hp->h_name;

    return LOG4CPLUS_STRING_TO_TSTRING (hostname);
}

int
setTCPNoDelay (SOCKET_TYPE sock, bool val)
{
    int result;
    int enabled = static_cast<int>(val);
    if ((result = setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
            reinterpret_cast<char*>(&enabled),sizeof(enabled))) != 0)
    {
        int eno = WSAGetLastError ();
        set_last_socket_error (eno);
    }

    return result;
}

} } // namespace log4cplus { namespace helpers {

#endif // LOG4CPLUS_USE_WINSOCK
<commit_msg>socket-win32.cxx: Fix reversed conditional logic.<commit_after>// Module:  Log4CPLUS
// File:    socket-win32.cxx
// Created: 4/2003
// Author:  Tad E. Smith
//
//
// Copyright 2003-2010 Tad E. Smith
//
// 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 <log4cplus/config.hxx>
#if defined (LOG4CPLUS_USE_WINSOCK)

#include <cassert>
#include <cerrno>
#include <vector>
#include <cstring>
#include <log4cplus/internal/socket.h>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/thread/threads.h>
#include <log4cplus/helpers/stringhelper.h>

/////////////////////////////////////////////////////////////////////////////
// file LOCAL Classes
/////////////////////////////////////////////////////////////////////////////

namespace
{

enum WSInitStates
{
    WS_UNINITIALIZED,
    WS_INITIALIZING,
    WS_INITIALIZED
};

static WSADATA wsa;
static LONG volatile winsock_state = WS_UNINITIALIZED;

static
void
init_winsock_worker ()
{
    log4cplus::helpers::LogLog * loglog
        = log4cplus::helpers::LogLog::getLogLog ();

    // Try to change the state to WS_INITIALIZING.
    LONG val = ::InterlockedCompareExchange (
        const_cast<LPLONG>(&winsock_state), WS_INITIALIZING, WS_UNINITIALIZED);
    switch (val)
    {
    case WS_UNINITIALIZED:
    {
        int ret = WSAStartup (MAKEWORD (2, 2), &wsa);
        if (ret != 0)
        {
            // Revert the state back to WS_UNINITIALIZED to unblock other
            // threads and let them throw exception.
            val = ::InterlockedCompareExchange (
                const_cast<LPLONG>(&winsock_state), WS_UNINITIALIZED,
                WS_INITIALIZING);
            assert (val == WS_INITIALIZING);
            loglog->error (LOG4CPLUS_TEXT ("Could not initialize WinSock."),
                true);
        }

        // WinSock is initialized, change the state to WS_INITIALIZED.
        val = ::InterlockedCompareExchange (
            const_cast<LPLONG>(&winsock_state), WS_INITIALIZED,
            WS_INITIALIZING);
        assert (val == WS_INITIALIZING);
        return;
    }

    case WS_INITIALIZING:
        // Wait for state change.
        while (true)
        {
            switch (winsock_state)
            {
            case WS_INITIALIZED:
                return;

            case WS_INITIALIZING:
                log4cplus::thread::yield ();
                continue;

            default:
                assert (0);
                loglog->error (LOG4CPLUS_TEXT ("Unknown WinSock state."), true);
            }
        }

    case WS_INITIALIZED:
        // WinSock is already initialized.
        return;

    default:
        assert (0);
        loglog->error (LOG4CPLUS_TEXT ("Unknown WinSock state."), true);
    }
}

static
void
init_winsock ()
{
    // Quick check first to avoid the expensive interlocked compare
    // and exchange.
    if (winsock_state == WS_INITIALIZED)
        return;
    else
        init_winsock_worker ();
}

struct WinSockInitializer
{
    ~WinSockInitializer ()
    {
        if (winsock_state == WS_INITIALIZED)
            WSACleanup ();
    }

    static WinSockInitializer winSockInitializer;
};

WinSockInitializer WinSockInitializer::winSockInitializer;

} // namespace

namespace log4cplus { namespace helpers {

/////////////////////////////////////////////////////////////////////////////
// Global Methods
/////////////////////////////////////////////////////////////////////////////

SOCKET_TYPE
openSocket(unsigned short port, SocketState& state)
{
    struct sockaddr_in server;

    init_winsock ();

    SOCKET sock = WSASocket (AF_INET, SOCK_STREAM, AF_UNSPEC, 0, 0
#if defined (WSA_FLAG_NO_HANDLE_INHERIT)
        , WSA_FLAG_NO_HANDLE_INHERIT
#else
        , 0
#endif
        );

    if (sock == INVALID_OS_SOCKET_VALUE)
        goto error;

    server.sin_family = AF_INET;
    server.sin_addr.s_addr = htonl(INADDR_ANY);
    server.sin_port = htons(port);

    if (bind(sock, reinterpret_cast<struct sockaddr*>(&server), sizeof(server))
        != 0)
        goto error;

    if (::listen(sock, 10) != 0)
        goto error;

    state = ok;
    return to_log4cplus_socket (sock);

error:
    int eno = WSAGetLastError ();

    if (sock != INVALID_OS_SOCKET_VALUE)
        ::closesocket (sock);

    set_last_socket_error (eno);
    return INVALID_SOCKET_VALUE;
}

SOCKET_TYPE
connectSocket(const tstring& hostn, unsigned short port, bool udp, SocketState& state)
{
    struct hostent * hp;
    struct sockaddr_in insock;
    int retval;

    init_winsock ();

    SOCKET sock = WSASocket (AF_INET, (udp ? SOCK_DGRAM : SOCK_STREAM),
        AF_UNSPEC, 0, 0
#if defined (WSA_FLAG_NO_HANDLE_INHERIT)
        , WSA_FLAG_NO_HANDLE_INHERIT
#else
        , 0
#endif
        );
    if (sock == INVALID_OS_SOCKET_VALUE)
        goto error;

    hp = ::gethostbyname( LOG4CPLUS_TSTRING_TO_STRING(hostn).c_str() );
    if (hp == 0 || hp->h_addrtype != AF_INET)
    {
        insock.sin_family = AF_INET;
        INT insock_size = sizeof (insock);
        INT ret = WSAStringToAddress (const_cast<LPTSTR>(hostn.c_str ()),
            AF_INET, 0, reinterpret_cast<struct sockaddr *>(&insock),
            &insock_size);
        if (ret == SOCKET_ERROR || insock_size != sizeof (insock))
        {
            state = bad_address;
            goto error;
        }
    }
    else
        std::memcpy (&insock.sin_addr, hp->h_addr_list[0],
            sizeof (insock.sin_addr));

    insock.sin_port = htons(port);
    insock.sin_family = AF_INET;

    while(   (retval = ::connect(sock, (struct sockaddr*)&insock, sizeof(insock))) == -1
          && (WSAGetLastError() == WSAEINTR))
        ;
    if (retval == SOCKET_ERROR)
        goto error;

    state = ok;
    return to_log4cplus_socket (sock);

error:
    int eno = WSAGetLastError ();

    if (sock != INVALID_OS_SOCKET_VALUE)
        ::closesocket (sock);

    set_last_socket_error (eno);
    return INVALID_SOCKET_VALUE;
}

SOCKET_TYPE
acceptSocket(SOCKET_TYPE sock, SocketState & state)
{
    init_winsock ();

    SOCKET osSocket = to_os_socket (sock);

    // Prepare event objects.

    WSAEVENT close_ev = WSACreateEvent ();
    if (close_ev == WSA_INVALID_EVENT)
        goto error;

    WSAEVENT accept_ev = WSACreateEvent ();
    if (accept_ev == WSA_INVALID_EVENT)
        goto error;

    // Prime the socket to report FD_CLOSE.

    int ret = WSAEventSelect (osSocket, close_ev, FD_CLOSE);
    if (ret == SOCKET_ERROR)
        goto error;

    // Prime the socket to report FD_ACCEPT.

    ret = WSAEventSelect (osSocket, accept_ev, FD_ACCEPT);
    if (ret == SOCKET_ERROR)
        goto error;

    WSAEVENT events[2] = { close_ev, accept_ev };

    while (1)
    {
        DWORD wfme = WSAWaitForMultipleEvents (2, events, FALSE, WSA_INFINITE,
            TRUE);
        switch (wfme)
        {
        case WSA_WAIT_TIMEOUT:
            // This should not happen for WSA_INFINITE timeout.
            // Fall through.

        case WSA_WAIT_IO_COMPLETION:
            continue;

        case WSA_WAIT_EVENT_0:
            WSASetLastError (ERROR_NO_DATA);
            goto error;

        case WSA_WAIT_EVENT_0 + 1:
        {
            WSACloseEvent (close_ev);
            WSACloseEvent (accept_ev);

            SOCKET connected_socket = ::accept (osSocket, NULL, NULL);

            if (connected_socket != INVALID_OS_SOCKET_VALUE)
                state = ok;

            return to_log4cplus_socket (connected_socket);
        }

        default:
            helpers::getLogLog ().error (
                LOG4CPLUS_TEXT ("unexpected WSAWaitForMultipleEvents return value: ")
                + helpers::convertIntegerToString (wfme));

            goto error;
        }
    }

error:
    DWORD const eno = WSAGetLastError ();

    if (close_ev != WSA_INVALID_EVENT)
        WSACloseEvent (close_ev);

    if (accept_ev != WSA_INVALID_EVENT)
        WSACloseEvent (accept_ev);

    set_last_socket_error (eno);

    return to_log4cplus_socket (INVALID_SOCKET);
}

int
closeSocket(SOCKET_TYPE sock)
{
    return ::closesocket (to_os_socket (sock));
}

long
read(SOCKET_TYPE sock, SocketBuffer& buffer)
{
    long res, read = 0;

    do
    {
        res = ::recv(to_os_socket (sock),
                     buffer.getBuffer() + read,
                     static_cast<int>(buffer.getMaxSize() - read),
                     0);
        if (res == SOCKET_ERROR)
        {
            set_last_socket_error (WSAGetLastError ());
            return res;
        }
        read += res;
    }
    while (read < static_cast<long>(buffer.getMaxSize()));

    return read;
}

long
write(SOCKET_TYPE sock, const SocketBuffer& buffer)
{
    long ret = ::send (to_os_socket (sock), buffer.getBuffer(),
        static_cast<int>(buffer.getSize()), 0);
    if (ret == SOCKET_ERROR)
        set_last_socket_error (WSAGetLastError ());
    return ret;
}

long
write(SOCKET_TYPE sock, const std::string & buffer)
{
    long ret = ::send (to_os_socket (sock), buffer.c_str (),
        static_cast<int>(buffer.size ()), 0);
    if (ret == SOCKET_ERROR)
        set_last_socket_error (WSAGetLastError ());
    return ret;
}

tstring
getHostname (bool fqdn)
{
    char const * hostname = "unknown";
    int ret;
    std::vector<char> hn (1024, 0);

    while (true)
    {
        ret = ::gethostname (&hn[0], static_cast<int>(hn.size ()) - 1);
        if (ret == 0)
        {
            hostname = &hn[0];
            break;
        }
        else if (ret != 0 && WSAGetLastError () == WSAEFAULT)
            // Out buffer was too short. Retry with buffer twice the size.
            hn.resize (hn.size () * 2, 0);
        else
            break;
    }

    if (ret != 0 || (ret == 0 && ! fqdn))
        return LOG4CPLUS_STRING_TO_TSTRING (hostname);

    struct ::hostent * hp = ::gethostbyname (hostname);
    if (hp)
        hostname = hp->h_name;

    return LOG4CPLUS_STRING_TO_TSTRING (hostname);
}

int
setTCPNoDelay (SOCKET_TYPE sock, bool val)
{
    int result;
    int enabled = static_cast<int>(val);
    if ((result = setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
            reinterpret_cast<char*>(&enabled),sizeof(enabled))) != 0)
    {
        int eno = WSAGetLastError ();
        set_last_socket_error (eno);
    }

    return result;
}

} } // namespace log4cplus { namespace helpers {

#endif // LOG4CPLUS_USE_WINSOCK
<|endoftext|>