<commit_before>/*
 * $Id$
 */

#include <sys/time.h>
#include <stdio.h>
#include <fstream>
#include <map>
#include <list>
#include <iostream>
#include <sstream>
#include <cmath>
#include <set>
#include "crf.h"
#include "common.h"

using namespace std;

multimap<string, string> WNdic;

void tokenize(const string &s1, list<string> &lt);
string base_form(const string &s, const string &pos);

extern int push_stop_watch();

static string normalize(const string &s) {
  string tmp(s);
  for (size_t i = 0; i < tmp.size(); i++) {
    tmp[i] = tolower(tmp[i]);
    if (isdigit(tmp[i])) tmp[i] = '#';
  }
  return tmp;
}

static CRF_State crfstate(const vector<Token> &vt, int i) {
  CRF_State sample;

  string str = vt[i].str;

  sample.label = vt[i].pos;

  sample.add_feature("W0_" + vt[i].str);

  sample.add_feature("NW0_" + normalize(str));

  string prestr = "BOS";
  if (i > 0) prestr = vt[i - 1].str;

  string prestr2 = "BOS";
  if (i > 1) prestr2 = vt[i - 2].str;

  string poststr = "EOS";
  if (i < (int)vt.size() - 1) poststr = vt[i + 1].str;

  string poststr2 = "EOS";
  if (i < (int)vt.size() - 2) poststr2 = vt[i + 2].str;

  sample.add_feature("W-1_" + prestr);
  sample.add_feature("W+1_" + poststr);

  sample.add_feature("W-2_" + prestr2);
  sample.add_feature("W+2_" + poststr2);

  sample.add_feature("W-10_" + prestr + "_" + str);
  sample.add_feature("W0+1_" + str + "_" + poststr);
  sample.add_feature("W-1+1_" + prestr + "_" + poststr);

  for (size_t j = 1; j <= 10; j++) {
    char buf[1000];
    if (str.size() >= j) {
      sprintf(buf, "SUF%d_%s", (int)j, str.substr(str.size() - j).c_str());
      sample.add_feature(buf);
    }
    if (str.size() >= j) {
      sprintf(buf, "PRE%d_%s", (int)j, str.substr(0, j).c_str());
      sample.add_feature(buf);
    }
  }

  for (size_t j = 0; j < str.size(); j++) {
    if (isdigit(str[j])) {
      sample.add_feature("CTN_NUM");
      break;
    }
  }
  for (size_t j = 0; j < str.size(); j++) {
    if (isupper(str[j])) {
      sample.add_feature("CTN_UPP");
      break;
    }
  }
  for (size_t j = 0; j < str.size(); j++) {
    if (str[j] == '-') {
      sample.add_feature("CTN_HPN");
      break;
    }
  }
  bool allupper = true;
  for (size_t j = 0; j < str.size(); j++) {
    if (!isupper(str[j])) {
      allupper = false;
      break;
    }
  }
  if (allupper) sample.add_feature("ALL_UPP");

  if (WNdic.size() > 0) {
    const string n = normalize(str);
    for (map<string, string>::const_iterator i = WNdic.lower_bound(n);
         i != WNdic.upper_bound(n); i++) {
      sample.add_feature("WN_" + i->second);
    }
  }

  return sample;
}

int crftrain(const CRF_Model::OptimizationMethod method, CRF_Model &m,
             const vector<Sentence> &vs, double gaussian, const bool use_l1) {
  if (method != CRF_Model::BFGS && use_l1) {
    cerr << "error: L1 regularization is currently not supported in this mode. "
            "Please use other optimziation methods." << endl;
    exit(1);
  }

  for (vector<Sentence>::const_iterator i = vs.begin(); i != vs.end(); i++) {
    const Sentence &s = *i;
    CRF_Sequence cs;
    for (size_t j = 0; j < s.size(); j++) cs.add_state(crfstate(s, j));
    m.add_training_sample(cs);
  }

  if (use_l1)
    m.train(method, 0, 0, 1.0);
  else
    m.train(method, 0, gaussian);

  return 0;
}

void crf_decode_lookahead(Sentence &s, CRF_Model &m,
                          vector<map<string, double> > &tagp) {
  CRF_Sequence cs;
  for (size_t j = 0; j < s.size(); j++) cs.add_state(crfstate(s, j));

  m.decode_lookahead(cs);

  tagp.clear();
  for (size_t k = 0; k < s.size(); k++) {
    s[k].prd = cs.vs[k].label;
    map<string, double> vp;
    vp[s[k].prd] = 1.0;
    tagp.push_back(vp);
  }
}

void crf_decode_forward_backward(Sentence &s, CRF_Model &m,
                                 vector<map<string, double> > &tagp) {
  CRF_Sequence cs;
  for (size_t j = 0; j < s.size(); j++) cs.add_state(crfstate(s, j));

  m.decode_forward_backward(cs, tagp);

  for (size_t k = 0; k < s.size(); k++) s[k].prd = cs.vs[k].label;
}

void crf_decode_nbest(Sentence &s, CRF_Model &m,
                      vector<pair<double, vector<string> > > &nbest_seqs,
                      int n) {
  CRF_Sequence cs;
  for (size_t j = 0; j < s.size(); j++) cs.add_state(crfstate(s, j));

  m.decode_nbest(cs, nbest_seqs, n, 0);

  for (size_t k = 0; k < s.size(); k++) s[k].prd = cs.vs[k].label;
}
<commit_msg>pthread/crfpos.cpp: use !empty() instead of 'size() > 0'<commit_after>/*
 * $Id$
 */

#include <sys/time.h>
#include <stdio.h>
#include <fstream>
#include <map>
#include <list>
#include <iostream>
#include <sstream>
#include <cmath>
#include <set>
#include "crf.h"
#include "common.h"

using namespace std;

multimap<string, string> WNdic;

void tokenize(const string &s1, list<string> &lt);
string base_form(const string &s, const string &pos);

extern int push_stop_watch();

static string normalize(const string &s) {
  string tmp(s);
  for (size_t i = 0; i < tmp.size(); i++) {
    tmp[i] = tolower(tmp[i]);
    if (isdigit(tmp[i])) tmp[i] = '#';
  }
  return tmp;
}

static CRF_State crfstate(const vector<Token> &vt, int i) {
  CRF_State sample;

  string str = vt[i].str;

  sample.label = vt[i].pos;

  sample.add_feature("W0_" + vt[i].str);

  sample.add_feature("NW0_" + normalize(str));

  string prestr = "BOS";
  if (i > 0) prestr = vt[i - 1].str;

  string prestr2 = "BOS";
  if (i > 1) prestr2 = vt[i - 2].str;

  string poststr = "EOS";
  if (i < (int)vt.size() - 1) poststr = vt[i + 1].str;

  string poststr2 = "EOS";
  if (i < (int)vt.size() - 2) poststr2 = vt[i + 2].str;

  sample.add_feature("W-1_" + prestr);
  sample.add_feature("W+1_" + poststr);

  sample.add_feature("W-2_" + prestr2);
  sample.add_feature("W+2_" + poststr2);

  sample.add_feature("W-10_" + prestr + "_" + str);
  sample.add_feature("W0+1_" + str + "_" + poststr);
  sample.add_feature("W-1+1_" + prestr + "_" + poststr);

  for (size_t j = 1; j <= 10; j++) {
    char buf[1000];
    if (str.size() >= j) {
      sprintf(buf, "SUF%d_%s", (int)j, str.substr(str.size() - j).c_str());
      sample.add_feature(buf);
    }
    if (str.size() >= j) {
      sprintf(buf, "PRE%d_%s", (int)j, str.substr(0, j).c_str());
      sample.add_feature(buf);
    }
  }

  for (size_t j = 0; j < str.size(); j++) {
    if (isdigit(str[j])) {
      sample.add_feature("CTN_NUM");
      break;
    }
  }
  for (size_t j = 0; j < str.size(); j++) {
    if (isupper(str[j])) {
      sample.add_feature("CTN_UPP");
      break;
    }
  }
  for (size_t j = 0; j < str.size(); j++) {
    if (str[j] == '-') {
      sample.add_feature("CTN_HPN");
      break;
    }
  }
  bool allupper = true;
  for (size_t j = 0; j < str.size(); j++) {
    if (!isupper(str[j])) {
      allupper = false;
      break;
    }
  }
  if (allupper) sample.add_feature("ALL_UPP");

  if (!WNdic.empty()) {
    const string n = normalize(str);
    for (map<string, string>::const_iterator i = WNdic.lower_bound(n);
         i != WNdic.upper_bound(n); i++) {
      sample.add_feature("WN_" + i->second);
    }
  }

  return sample;
}

int crftrain(const CRF_Model::OptimizationMethod method, CRF_Model &m,
             const vector<Sentence> &vs, double gaussian, const bool use_l1) {
  if (method != CRF_Model::BFGS && use_l1) {
    cerr << "error: L1 regularization is currently not supported in this mode. "
            "Please use other optimziation methods." << endl;
    exit(1);
  }

  for (vector<Sentence>::const_iterator i = vs.begin(); i != vs.end(); i++) {
    const Sentence &s = *i;
    CRF_Sequence cs;
    for (size_t j = 0; j < s.size(); j++) cs.add_state(crfstate(s, j));
    m.add_training_sample(cs);
  }

  if (use_l1)
    m.train(method, 0, 0, 1.0);
  else
    m.train(method, 0, gaussian);

  return 0;
}

void crf_decode_lookahead(Sentence &s, CRF_Model &m,
                          vector<map<string, double> > &tagp) {
  CRF_Sequence cs;
  for (size_t j = 0; j < s.size(); j++) cs.add_state(crfstate(s, j));

  m.decode_lookahead(cs);

  tagp.clear();
  for (size_t k = 0; k < s.size(); k++) {
    s[k].prd = cs.vs[k].label;
    map<string, double> vp;
    vp[s[k].prd] = 1.0;
    tagp.push_back(vp);
  }
}

void crf_decode_forward_backward(Sentence &s, CRF_Model &m,
                                 vector<map<string, double> > &tagp) {
  CRF_Sequence cs;
  for (size_t j = 0; j < s.size(); j++) cs.add_state(crfstate(s, j));

  m.decode_forward_backward(cs, tagp);

  for (size_t k = 0; k < s.size(); k++) s[k].prd = cs.vs[k].label;
}

void crf_decode_nbest(Sentence &s, CRF_Model &m,
                      vector<pair<double, vector<string> > > &nbest_seqs,
                      int n) {
  CRF_Sequence cs;
  for (size_t j = 0; j < s.size(); j++) cs.add_state(crfstate(s, j));

  m.decode_nbest(cs, nbest_seqs, n, 0);

  for (size_t k = 0; k < s.size(); k++) s[k].prd = cs.vs[k].label;
}
<|endoftext|>


<commit_before>/**
 * @file Dtw.cpp
 *
 * An implementation of the Dynamic Time Warping algorithm.
 *
 * This file is part of the Aquila DSP library.
 * Aquila is free software, licensed under the MIT/X11 License. A copy of
 * the license is provided with the library in the LICENSE file.
 *
 * @package Aquila
 * @version 3.0.0-dev
 * @author Zbigniew Siciarz
 * @date 2007-2014
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @since 0.5.7
 */

#include "Dtw.h"

namespace Aquila
{
    /**
     * Computes the distance between two sets of data.
     *
     * @param from first vector of features
     * @param to second vector of features
     * @return double DTW distance
     */
    double Dtw::getDistance(const DtwDataType& from, const DtwDataType& to)
    {
        m_fromSize = from.size();
        m_toSize = to.size();

        // fill the local distances array
        m_points.clear();
        m_points.resize(m_fromSize);
        for (std::size_t i = 0; i < m_fromSize; ++i)
        {
            m_points[i].reserve(m_toSize);
            for (std::size_t j = 0; j < m_toSize; ++j)
            {
                // use emplace_back, once all compilers support it correctly
                m_points[i].push_back(
                    DtwPoint(i, j, m_distanceFunction(from[i], to[j])
                ));
            }
        }

        // the actual pathfinding algorithm
        DtwPoint *top = 0, *center = 0, *bottom = 0, *previous = 0;
        for (std::size_t i = 1; i < m_fromSize; ++i)
        {
            for (std::size_t j = 1; j < m_toSize; ++j)
            {
                center = &m_points[i - 1][j - 1];
                if (Neighbors == m_passType)
                {
                    top = &m_points[i - 1][j];
                    bottom = &m_points[i][j - 1];
                }
                else // Diagonals
                {
                    if (i > 1 && j > 1)
                    {
                        top = &m_points[i - 2][j - 1];
                        bottom = &m_points[i - 1][j - 2];
                    }
                    else
                    {
                        top = &m_points[i - 1][j];
                        bottom = &m_points[i][j - 1];
                    }
                }

                if (top->dAccumulated < center->dAccumulated)
                {
                    previous = top;
                }
                else
                {
                    previous = center;
                }

                if (bottom->dAccumulated < previous->dAccumulated)
                {
                    previous = bottom;
                }

                m_points[i][j].dAccumulated = m_points[i][j].dLocal + previous->dAccumulated;
                m_points[i][j].previous = previous;
            }
        }

        return getFinalPoint().dAccumulated;
    }

    /**
     * Returns the lowest-cost path in the DTW array.
     *
     * @return path
     */
    DtwPathType Dtw::getPath() const
    {
        DtwPathType path;
        DtwPoint finalPoint = getFinalPoint();
        DtwPoint* point = &finalPoint;

        path.push_back(*point);
        while(point->previous != 0)
        {
            point = point->previous;
            path.push_back(*point);
        }

        return path;
    }
}
<commit_msg>Be more explicit about null pointers in DTW.<commit_after>/**
 * @file Dtw.cpp
 *
 * An implementation of the Dynamic Time Warping algorithm.
 *
 * This file is part of the Aquila DSP library.
 * Aquila is free software, licensed under the MIT/X11 License. A copy of
 * the license is provided with the library in the LICENSE file.
 *
 * @package Aquila
 * @version 3.0.0-dev
 * @author Zbigniew Siciarz
 * @date 2007-2014
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @since 0.5.7
 */

#include "Dtw.h"

namespace Aquila
{
    /**
     * Computes the distance between two sets of data.
     *
     * @param from first vector of features
     * @param to second vector of features
     * @return double DTW distance
     */
    double Dtw::getDistance(const DtwDataType& from, const DtwDataType& to)
    {
        m_fromSize = from.size();
        m_toSize = to.size();

        // fill the local distances array
        m_points.clear();
        m_points.resize(m_fromSize);
        for (std::size_t i = 0; i < m_fromSize; ++i)
        {
            m_points[i].reserve(m_toSize);
            for (std::size_t j = 0; j < m_toSize; ++j)
            {
                // use emplace_back, once all compilers support it correctly
                m_points[i].push_back(
                    DtwPoint(i, j, m_distanceFunction(from[i], to[j])
                ));
            }
        }

        // the actual pathfinding algorithm
        DtwPoint *top = nullptr, *center = nullptr, *bottom = nullptr, *previous = nullptr;
        for (std::size_t i = 1; i < m_fromSize; ++i)
        {
            for (std::size_t j = 1; j < m_toSize; ++j)
            {
                center = &m_points[i - 1][j - 1];
                if (Neighbors == m_passType)
                {
                    top = &m_points[i - 1][j];
                    bottom = &m_points[i][j - 1];
                }
                else // Diagonals
                {
                    if (i > 1 && j > 1)
                    {
                        top = &m_points[i - 2][j - 1];
                        bottom = &m_points[i - 1][j - 2];
                    }
                    else
                    {
                        top = &m_points[i - 1][j];
                        bottom = &m_points[i][j - 1];
                    }
                }

                if (top->dAccumulated < center->dAccumulated)
                {
                    previous = top;
                }
                else
                {
                    previous = center;
                }

                if (bottom->dAccumulated < previous->dAccumulated)
                {
                    previous = bottom;
                }

                m_points[i][j].dAccumulated = m_points[i][j].dLocal + previous->dAccumulated;
                m_points[i][j].previous = previous;
            }
        }

        return getFinalPoint().dAccumulated;
    }

    /**
     * Returns the lowest-cost path in the DTW array.
     *
     * @return path
     */
    DtwPathType Dtw::getPath() const
    {
        DtwPathType path;
        DtwPoint finalPoint = getFinalPoint();
        DtwPoint* point = &finalPoint;

        path.push_back(*point);
        while(point->previous)
        {
            point = point->previous;
            path.push_back(*point);
        }

        return path;
    }
}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
#include "config.h"
#include "ep.hh"

const double BgFetcher::sleepInterval = 1.0;

bool BgFetcherCallback::callback(Dispatcher &, TaskId t) {
    return bgfetcher->run(t);
}

void BgFetcher::start() {
    LockHolder lh(taskMutex);
    dispatcher->schedule(shared_ptr<BgFetcherCallback>(new BgFetcherCallback(this)),
                         &task, Priority::BgFetcherPriority);
    assert(task.get());
}

void BgFetcher::stop() {
    LockHolder lh(taskMutex);
    assert(task.get());
    dispatcher->cancel(task);
}

void BgFetcher::doFetch(uint16_t vbId) {
    hrtime_t startTime(gethrtime());
    getLogger()->log(EXTENSION_LOG_DEBUG, NULL,
                     "BgFetcher is fetching data, vBucket = %d numDocs = %d, "
                     "startTime = %lld\n",
                     vbId, items2fetch.size(), startTime/1000000);

    store->getROUnderlying()->getMulti(vbId, items2fetch);

    int totalfetches = 0;
    std::vector<VBucketBGFetchItem *> fetchedItems;
    vb_bgfetch_queue_t::iterator itr = items2fetch.begin();
    for (; itr != items2fetch.end(); itr++) {
        std::list<VBucketBGFetchItem *> &requestedItems = (*itr).second;
        std::list<VBucketBGFetchItem *>::iterator itm = requestedItems.begin();
        for(; itm != requestedItems.end(); itm++) {
            fetchedItems.push_back(*itm);
            ++totalfetches;
        }
    }
    store->completeBGFetchMulti(vbId, fetchedItems, startTime);
    stats.getMultiHisto.add(startTime-gethrtime()/1000, totalfetches);
    clearItems();
}

void BgFetcher::clearItems(void) {
    vb_bgfetch_queue_t::iterator itr = items2fetch.begin();
    for(; itr != items2fetch.end(); itr++) {
        // every fetched item belonging to the same seq_id shares
        // the same buffer, just delete it from the first fetched item
        std::list<VBucketBGFetchItem *> &doneItems = (*itr).second;
        VBucketBGFetchItem *firstItem = doneItems.front();
        delete firstItem;
    }
}

bool BgFetcher::run(TaskId tid) {
    assert(tid.get());
    size_t num_fetched_items = 0;

    const VBucketMap &vbMap = store->getVBuckets();
    size_t numVbuckets = vbMap.getSize();
    for (size_t vbid = 0; vbid < numVbuckets; vbid++) {
        RCPtr<VBucket> vb = vbMap.getBucket(vbid);
        assert(items2fetch.empty());
        if (vb && vb->getBGFetchItems(items2fetch)) {
            doFetch(vbid);
            num_fetched_items += items2fetch.size();
            items2fetch.clear();
        }
    }

    size_t remains = stats.numRemainingBgJobs.decr(num_fetched_items);
    if (!pendingJob()) {
        stats.numRemainingBgJobs.cas(remains, 0); // Reset the remaining counter
        // wait a bit until next fetche request arrives
        double sleep = std::max(store->getBGFetchDelay(), sleepInterval);
        dispatcher->snooze(tid, sleep);
    }
    return true;
}

bool BgFetcher::pendingJob() {
    const VBucketMap &vbMap = store->getVBuckets();
    size_t numVbuckets = vbMap.getSize();
    for (size_t vbid = 0; vbid < numVbuckets; ++vbid) {
        RCPtr<VBucket> vb = vbMap.getBucket(vbid);
        if (vb && vb->hasPendingBGFetchItems()) {
            return true;
        }
    }
    return false;
}
<commit_msg>Fix BG fetcher histogram computation<commit_after>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
#include "config.h"
#include "ep.hh"

const double BgFetcher::sleepInterval = 1.0;

bool BgFetcherCallback::callback(Dispatcher &, TaskId t) {
    return bgfetcher->run(t);
}

void BgFetcher::start() {
    LockHolder lh(taskMutex);
    dispatcher->schedule(shared_ptr<BgFetcherCallback>(new BgFetcherCallback(this)),
                         &task, Priority::BgFetcherPriority);
    assert(task.get());
}

void BgFetcher::stop() {
    LockHolder lh(taskMutex);
    assert(task.get());
    dispatcher->cancel(task);
}

void BgFetcher::doFetch(uint16_t vbId) {
    hrtime_t startTime(gethrtime());
    getLogger()->log(EXTENSION_LOG_DEBUG, NULL,
                     "BgFetcher is fetching data, vBucket = %d numDocs = %d, "
                     "startTime = %lld\n",
                     vbId, items2fetch.size(), startTime/1000000);

    store->getROUnderlying()->getMulti(vbId, items2fetch);

    int totalfetches = 0;
    std::vector<VBucketBGFetchItem *> fetchedItems;
    vb_bgfetch_queue_t::iterator itr = items2fetch.begin();
    for (; itr != items2fetch.end(); itr++) {
        std::list<VBucketBGFetchItem *> &requestedItems = (*itr).second;
        std::list<VBucketBGFetchItem *>::iterator itm = requestedItems.begin();
        for(; itm != requestedItems.end(); itm++) {
            fetchedItems.push_back(*itm);
            ++totalfetches;
        }
    }
    store->completeBGFetchMulti(vbId, fetchedItems, startTime);
    stats.getMultiHisto.add((gethrtime()-startTime)/1000, totalfetches);
    clearItems();
}

void BgFetcher::clearItems(void) {
    vb_bgfetch_queue_t::iterator itr = items2fetch.begin();
    for(; itr != items2fetch.end(); itr++) {
        // every fetched item belonging to the same seq_id shares
        // the same buffer, just delete it from the first fetched item
        std::list<VBucketBGFetchItem *> &doneItems = (*itr).second;
        VBucketBGFetchItem *firstItem = doneItems.front();
        delete firstItem;
    }
}

bool BgFetcher::run(TaskId tid) {
    assert(tid.get());
    size_t num_fetched_items = 0;

    const VBucketMap &vbMap = store->getVBuckets();
    size_t numVbuckets = vbMap.getSize();
    for (size_t vbid = 0; vbid < numVbuckets; vbid++) {
        RCPtr<VBucket> vb = vbMap.getBucket(vbid);
        assert(items2fetch.empty());
        if (vb && vb->getBGFetchItems(items2fetch)) {
            doFetch(vbid);
            num_fetched_items += items2fetch.size();
            items2fetch.clear();
        }
    }

    size_t remains = stats.numRemainingBgJobs.decr(num_fetched_items);
    if (!pendingJob()) {
        stats.numRemainingBgJobs.cas(remains, 0); // Reset the remaining counter
        // wait a bit until next fetche request arrives
        double sleep = std::max(store->getBGFetchDelay(), sleepInterval);
        dispatcher->snooze(tid, sleep);
    }
    return true;
}

bool BgFetcher::pendingJob() {
    const VBucketMap &vbMap = store->getVBuckets();
    size_t numVbuckets = vbMap.getSize();
    for (size_t vbid = 0; vbid < numVbuckets; ++vbid) {
        RCPtr<VBucket> vb = vbMap.getBucket(vbid);
        if (vb && vb->hasPendingBGFetchItems()) {
            return true;
        }
    }
    return false;
}
<|endoftext|>


<commit_before>/***************************************************************************
 *   Copyright (C) 2006 by Tobias Koenig <tokoe@kde.org>                   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU Library General Public License as       *
 *   published by the Free Software Foundation; either version 2 of the    *
 *   License, or (at your option) any later version.                       *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this program; if not, write to the                 *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
 ***************************************************************************/

#include "processcontrol.h"

#include <QtCore/QDebug>
#include <QtCore/QTimer>
#include <QtDebug>

#ifdef Q_OS_UNIX
#include <sys/types.h>
#include <signal.h>
#endif

using namespace Akonadi;

ProcessControl::ProcessControl( QObject *parent )
  : QObject( parent ), mFailedToStart( false ), mCrashCount( 0 )
{
  connect( &mProcess, SIGNAL( error( QProcess::ProcessError ) ),
           this, SLOT( slotError( QProcess::ProcessError ) ) );
  connect( &mProcess, SIGNAL( finished( int, QProcess::ExitStatus ) ),
           this, SLOT( slotFinished( int, QProcess::ExitStatus ) ) );
  connect( &mProcess, SIGNAL( readyReadStandardError() ),
           this, SLOT( slotErrorMessages() ) );
  connect( &mProcess, SIGNAL( readyReadStandardOutput() ),
            this, SLOT( slotStdoutMessages() ) );
}

ProcessControl::~ProcessControl()
{
  stop();
}

void ProcessControl::start( const QString &application, const QStringList &arguments, CrashPolicy policy )
{
  mFailedToStart = false;

  mApplication = application;
  mArguments = arguments;
  mPolicy = policy;

  start();
}

void ProcessControl::setCrashPolicy( CrashPolicy policy )
{
  mPolicy = policy;
}

void ProcessControl::stop()
{
  if ( mProcess.state() != QProcess::NotRunning ) {
    mProcess.waitForFinished( 10000 );
    mProcess.terminate();
  }
}

void ProcessControl::slotError( QProcess::ProcessError error )
{
  switch ( error ) {
    case QProcess::Crashed:
      // do nothing, we'll respawn in slotFinished
      break;
    case QProcess::FailedToStart:
    default:
        mFailedToStart = true;
      break;
  }

  qDebug( "ProcessControl: Application '%s' stopped unexpected (%s)",
          qPrintable( mApplication ), qPrintable( mProcess.errorString() ) );
}

void ProcessControl::slotFinished( int exitCode, QProcess::ExitStatus exitStatus )
{
  if ( exitStatus == QProcess::CrashExit ) {
    if ( mPolicy == RestartOnCrash ) {
      if ( !mFailedToStart ) // don't try to start an unstartable application
        start();
    }
  } else {
    if ( exitCode != 0 ) {
      qDebug( "ProcessControl: Application '%s' returned with exit code %d (%s)",
              qPrintable( mApplication ), exitCode, qPrintable( mProcess.errorString() ) );
      if ( mPolicy == RestartOnCrash ) {
        if ( mCrashCount > 3 ) {
          qWarning() << mApplication << "crashed too often and will not be restarted!";
          mPolicy = StopOnCrash;
          return;
        }
        ++mCrashCount;
        QTimer::singleShot( 5000, this, SLOT(resetCrashCount()) );
        if ( !mFailedToStart ) // don't try to start an unstartable application
          start();
      }
    } else {
      qDebug( "Application '%s' exited normally...", qPrintable( mApplication ) );
    }
  }
}

void ProcessControl::slotErrorMessages()
{
  QString message = QString::fromUtf8( mProcess.readAllStandardError() );
  emit processErrorMessages( message );
  qDebug( "[%s] %s", qPrintable( mApplication ), qPrintable( message.trimmed() ) );
}

void ProcessControl::start()
{
#ifdef Q_OS_UNIX
  QString agentValgrind = QString::fromLocal8Bit( qgetenv("AKONADI_VALGRIND") );
  if ( !agentValgrind.isEmpty() && mApplication.contains( agentValgrind ) ) {
    qDebug();
    qDebug() << "============================================================";
    qDebug() << "ProcessControl: Valgrinding process" << mApplication;
    qDebug() << "============================================================";
    qDebug();
    QString valgrindSkin = QString::fromLocal8Bit( qgetenv( "AKONADI_VALGRIND_SKIN" ) );

    mArguments.prepend( mApplication );
    mApplication = QString::fromLocal8Bit( "valgrind" );
    if ( !valgrindSkin.isEmpty() )
      mArguments.prepend( QLatin1String( "--tool=" ) + valgrindSkin );
    else
      mArguments.prepend (QLatin1String( "--tool=memcheck") );
  }
#endif

  mProcess.start( mApplication, mArguments );
  if ( !mProcess.waitForStarted( ) ) {
    qDebug( "ProcessControl: Unable to start application '%s' (%s)",
            qPrintable( mApplication ), qPrintable( mProcess.errorString() ) );
    return;
  }

#ifdef Q_OS_UNIX
  else {
    QString agentDebug = QString::fromLocal8Bit( qgetenv( "AKONADI_DEBUG_WAIT" ) );
    pid_t pid = mProcess.pid();
    if ( !agentDebug.isEmpty() && mApplication.contains( agentDebug ) ) {
      qDebug();
      qDebug() << "============================================================";
      qDebug() << "ProcessControl: Suspending process" << mApplication;
      qDebug() << "'gdb" << pid << "' to debug";
      qDebug() << "'kill -SIGCONT" << pid << "' to continue";
      qDebug() << "============================================================";
      qDebug();
      kill( pid, SIGSTOP );
    }
  }
#endif
}

void Akonadi::ProcessControl::slotStdoutMessages()
{
  QString message = QString::fromUtf8( mProcess.readAllStandardOutput() );
  qDebug() << mApplication << "[out]" << message;
}

void ProcessControl::resetCrashCount()
{
  mCrashCount = 0;
}

#include "processcontrol.moc"
<commit_msg>Up the time for the crash timer reset to one minute. Now it actually seems to work for me.<commit_after>/***************************************************************************
 *   Copyright (C) 2006 by Tobias Koenig <tokoe@kde.org>                   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU Library General Public License as       *
 *   published by the Free Software Foundation; either version 2 of the    *
 *   License, or (at your option) any later version.                       *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this program; if not, write to the                 *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
 ***************************************************************************/

#include "processcontrol.h"

#include <QtCore/QDebug>
#include <QtCore/QTimer>
#include <QtDebug>

#ifdef Q_OS_UNIX
#include <sys/types.h>
#include <signal.h>
#endif

using namespace Akonadi;

ProcessControl::ProcessControl( QObject *parent )
  : QObject( parent ), mFailedToStart( false ), mCrashCount( 0 )
{
  connect( &mProcess, SIGNAL( error( QProcess::ProcessError ) ),
           this, SLOT( slotError( QProcess::ProcessError ) ) );
  connect( &mProcess, SIGNAL( finished( int, QProcess::ExitStatus ) ),
           this, SLOT( slotFinished( int, QProcess::ExitStatus ) ) );
  connect( &mProcess, SIGNAL( readyReadStandardError() ),
           this, SLOT( slotErrorMessages() ) );
  connect( &mProcess, SIGNAL( readyReadStandardOutput() ),
            this, SLOT( slotStdoutMessages() ) );
}

ProcessControl::~ProcessControl()
{
  stop();
}

void ProcessControl::start( const QString &application, const QStringList &arguments, CrashPolicy policy )
{
  mFailedToStart = false;

  mApplication = application;
  mArguments = arguments;
  mPolicy = policy;

  start();
}

void ProcessControl::setCrashPolicy( CrashPolicy policy )
{
  mPolicy = policy;
}

void ProcessControl::stop()
{
  if ( mProcess.state() != QProcess::NotRunning ) {
    mProcess.waitForFinished( 10000 );
    mProcess.terminate();
  }
}

void ProcessControl::slotError( QProcess::ProcessError error )
{
  switch ( error ) {
    case QProcess::Crashed:
      // do nothing, we'll respawn in slotFinished
      break;
    case QProcess::FailedToStart:
    default:
        mFailedToStart = true;
      break;
  }

  qDebug( "ProcessControl: Application '%s' stopped unexpected (%s)",
          qPrintable( mApplication ), qPrintable( mProcess.errorString() ) );
}

void ProcessControl::slotFinished( int exitCode, QProcess::ExitStatus exitStatus )
{
  if ( exitStatus == QProcess::CrashExit ) {
    if ( mPolicy == RestartOnCrash ) {
      if ( !mFailedToStart ) // don't try to start an unstartable application
        start();
    }
  } else {
    if ( exitCode != 0 ) {
      qDebug( "ProcessControl: Application '%s' returned with exit code %d (%s)",
              qPrintable( mApplication ), exitCode, qPrintable( mProcess.errorString() ) );
      if ( mPolicy == RestartOnCrash ) {
        if ( mCrashCount > 3 ) {
          qWarning() << mApplication << "crashed too often and will not be restarted!";
          mPolicy = StopOnCrash;
          return;
        }
        ++mCrashCount;
        QTimer::singleShot( 60000, this, SLOT(resetCrashCount()) );
        if ( !mFailedToStart ) // don't try to start an unstartable application
          start();
      }
    } else {
      qDebug( "Application '%s' exited normally...", qPrintable( mApplication ) );
    }
  }
}

void ProcessControl::slotErrorMessages()
{
  QString message = QString::fromUtf8( mProcess.readAllStandardError() );
  emit processErrorMessages( message );
  qDebug( "[%s] %s", qPrintable( mApplication ), qPrintable( message.trimmed() ) );
}

void ProcessControl::start()
{
#ifdef Q_OS_UNIX
  QString agentValgrind = QString::fromLocal8Bit( qgetenv("AKONADI_VALGRIND") );
  if ( !agentValgrind.isEmpty() && mApplication.contains( agentValgrind ) ) {
    qDebug();
    qDebug() << "============================================================";
    qDebug() << "ProcessControl: Valgrinding process" << mApplication;
    qDebug() << "============================================================";
    qDebug();
    QString valgrindSkin = QString::fromLocal8Bit( qgetenv( "AKONADI_VALGRIND_SKIN" ) );

    mArguments.prepend( mApplication );
    mApplication = QString::fromLocal8Bit( "valgrind" );
    if ( !valgrindSkin.isEmpty() )
      mArguments.prepend( QLatin1String( "--tool=" ) + valgrindSkin );
    else
      mArguments.prepend (QLatin1String( "--tool=memcheck") );
  }
#endif

  mProcess.start( mApplication, mArguments );
  if ( !mProcess.waitForStarted( ) ) {
    qDebug( "ProcessControl: Unable to start application '%s' (%s)",
            qPrintable( mApplication ), qPrintable( mProcess.errorString() ) );
    return;
  }

#ifdef Q_OS_UNIX
  else {
    QString agentDebug = QString::fromLocal8Bit( qgetenv( "AKONADI_DEBUG_WAIT" ) );
    pid_t pid = mProcess.pid();
    if ( !agentDebug.isEmpty() && mApplication.contains( agentDebug ) ) {
      qDebug();
      qDebug() << "============================================================";
      qDebug() << "ProcessControl: Suspending process" << mApplication;
      qDebug() << "'gdb" << pid << "' to debug";
      qDebug() << "'kill -SIGCONT" << pid << "' to continue";
      qDebug() << "============================================================";
      qDebug();
      kill( pid, SIGSTOP );
    }
  }
#endif
}

void Akonadi::ProcessControl::slotStdoutMessages()
{
  QString message = QString::fromUtf8( mProcess.readAllStandardOutput() );
  qDebug() << mApplication << "[out]" << message;
}

void ProcessControl::resetCrashCount()
{
  mCrashCount = 0;
}

#include "processcontrol.moc"
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/phy/phy_cntrl.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file phy_cntrl.C
/// @brief Subroutines for the PHY PC registers
///
// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB

#include <fapi2.H>
#include <lib/phy/phy_cntrl.H>
#include <generic/memory/lib/utils/scom.H>
#include <generic/memory/lib/utils/c_str.H>
#include <lib/utils/index.H>

#include <lib/mss_attribute_accessors.H>

using fapi2::TARGET_TYPE_MCA;

namespace mss
{

// Definition of the PHY PC MR shadow registers
// indexed by [rank_pair][MR index]
const std::vector< std::vector<uint64_t> > pcTraits<TARGET_TYPE_MCA>::PC_MR_SHADOW_REGS =
{
    {
        MCA_DDRPHY_PC_MR0_PRI_RP0_P0,
        MCA_DDRPHY_PC_MR1_PRI_RP0_P0,
        MCA_DDRPHY_PC_MR2_PRI_RP0_P0,
        MCA_DDRPHY_PC_MR3_PRI_RP0_P0,
        MCA_DDRPHY_PC_MR0_SEC_RP0_P0,
        MCA_DDRPHY_PC_MR1_SEC_RP0_P0,
        MCA_DDRPHY_PC_MR2_SEC_RP0_P0,
    },
    {
        MCA_DDRPHY_PC_MR0_PRI_RP1_P0,
        MCA_DDRPHY_PC_MR1_PRI_RP1_P0,
        MCA_DDRPHY_PC_MR2_PRI_RP1_P0,
        MCA_DDRPHY_PC_MR3_PRI_RP1_P0,
        MCA_DDRPHY_PC_MR0_SEC_RP1_P0,
        MCA_DDRPHY_PC_MR1_SEC_RP1_P0,
        MCA_DDRPHY_PC_MR2_SEC_RP1_P0,
    },
    {
        MCA_DDRPHY_PC_MR0_PRI_RP2_P0,
        MCA_DDRPHY_PC_MR1_PRI_RP2_P0,
        MCA_DDRPHY_PC_MR2_PRI_RP2_P0,
        MCA_DDRPHY_PC_MR3_PRI_RP2_P0,
        MCA_DDRPHY_PC_MR0_SEC_RP2_P0,
        MCA_DDRPHY_PC_MR1_SEC_RP2_P0,
        MCA_DDRPHY_PC_MR2_SEC_RP2_P0,
    },
    {
        MCA_DDRPHY_PC_MR0_PRI_RP3_P0,
        MCA_DDRPHY_PC_MR1_PRI_RP3_P0,
        MCA_DDRPHY_PC_MR2_PRI_RP3_P0,
        MCA_DDRPHY_PC_MR3_PRI_RP3_P0,
        MCA_DDRPHY_PC_MR0_SEC_RP3_P0,
        MCA_DDRPHY_PC_MR1_SEC_RP3_P0,
        MCA_DDRPHY_PC_MR2_SEC_RP3_P0,
    },
};

namespace pc
{

///
/// @brief Reset the PC CONFIG0 register
/// @param[in] i_target the target (MCA or MBA?)
/// @return FAPI2_RC_SUCCESS if and only if ok
///
template<>
fapi2::ReturnCode reset_config0(const fapi2::Target<TARGET_TYPE_MCA>& i_target)
{
    typedef pcTraits<TARGET_TYPE_MCA> TT;

    fapi2::buffer<uint64_t> l_data;

    l_data.setBit<TT::DDR4_CMD_SIG_REDUCTION>();
    l_data.setBit<TT::DDR4_VLEVEL_BANK_GROUP>();

    FAPI_TRY( write_config0(i_target, l_data) );

fapi_try_exit:
    return fapi2::current_err;
}

///
/// @brief Reset the PC CONFIG1 register
/// @param[in] i_target <the target (MCA or MBA?)
/// @return FAPI2_RC_SUCCESS if and only if ok
///
template<>
fapi2::ReturnCode reset_config1(const fapi2::Target<TARGET_TYPE_MCA>& i_target)
{
    typedef pcTraits<TARGET_TYPE_MCA> TT;

    // Static table of PHY config values for MEMORY_TYPE.
    // [EMPTY, RDIMM, CDIMM, or LRDIMM][EMPTY, DDR3 or DDR4]
    constexpr uint64_t memory_type[4][3] =
    {
        { 0, 0,     0     },  // Empty, never really used.
        { 0, 0b001, 0b101 },  // RDIMM
        { 0, 0b000, 0b000 },  // CDIMM bits, UDIMM enum (placeholder, never used on Nimbus)
        { 0, 0b011, 0b111 },  // LRDIMM
    };

    fapi2::buffer<uint64_t> l_data;

    uint8_t l_rlo = 0;
    uint8_t l_wlo = 0;
    uint8_t l_dram_gen[MAX_DIMM_PER_PORT]    = {0};
    uint8_t l_dimm_type[MAX_DIMM_PER_PORT]   = {0};
    uint8_t l_type_index = 0;
    uint8_t l_gen_index = 0;

    FAPI_TRY( mss::vpd_mr_dphy_rlo(i_target, l_rlo) );
    FAPI_TRY( mss::vpd_mr_dphy_wlo(i_target, l_wlo) );
    FAPI_TRY( mss::eff_dram_gen(i_target, &(l_dram_gen[0])) );
    FAPI_TRY( mss::eff_dimm_type(i_target, &(l_dimm_type[0])) );

    // There's no way to configure the PHY for more than one value. However, we don't know if there's
    // a DIMM in one slot, the other or double drop. So we do a little gyration here to make sure
    // we have one of the two values (and assume effective config caught a bad config)
    l_type_index = l_dimm_type[0] | l_dimm_type[1];
    l_gen_index = l_dram_gen[0] | l_dram_gen[1];

    // FOR NIMBUS PHY (as the protocol choice above is) BRS
    FAPI_TRY( mss::getScom(i_target, MCA_DDRPHY_PC_CONFIG1_P0, l_data) );

    l_data.insertFromRight<TT::MEMORY_TYPE, TT::MEMORY_TYPE_LEN>(memory_type[l_type_index][l_gen_index]);
    l_data.insertFromRight<TT::WRITE_LATENCY_OFFSET, TT::WRITE_LATENCY_OFFSET_LEN>(l_wlo);

    // Always set this bit. It forces the PHY to use A12 when figuring out latency. This makes sense in
    // all cases as A12 is 0 for non-3DS in MR0.
    l_data.setBit<TT::DDR4_LATENCY_SW>();

    // If we are 2N mode we add one to the RLO (see also Centaur initfile)
    l_data.insertFromRight<TT::READ_LATENCY_OFFSET, TT::READ_LATENCY_OFFSET_LEN>(
        mss::two_n_mode_helper(i_target) ? l_rlo + 1 : l_rlo);

    FAPI_TRY( write_config1(i_target, l_data) );

fapi_try_exit:
    return fapi2::current_err;
}

} // close namespace pc
} // close namespace mss
<commit_msg>Move index API to generic/memory folder<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/phy/phy_cntrl.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file phy_cntrl.C
/// @brief Subroutines for the PHY PC registers
///
// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB

#include <fapi2.H>
#include <lib/phy/phy_cntrl.H>
#include <generic/memory/lib/utils/scom.H>
#include <generic/memory/lib/utils/c_str.H>
#include <generic/memory/lib/utils/index.H>

#include <lib/mss_attribute_accessors.H>

using fapi2::TARGET_TYPE_MCA;

namespace mss
{

// Definition of the PHY PC MR shadow registers
// indexed by [rank_pair][MR index]
const std::vector< std::vector<uint64_t> > pcTraits<TARGET_TYPE_MCA>::PC_MR_SHADOW_REGS =
{
    {
        MCA_DDRPHY_PC_MR0_PRI_RP0_P0,
        MCA_DDRPHY_PC_MR1_PRI_RP0_P0,
        MCA_DDRPHY_PC_MR2_PRI_RP0_P0,
        MCA_DDRPHY_PC_MR3_PRI_RP0_P0,
        MCA_DDRPHY_PC_MR0_SEC_RP0_P0,
        MCA_DDRPHY_PC_MR1_SEC_RP0_P0,
        MCA_DDRPHY_PC_MR2_SEC_RP0_P0,
    },
    {
        MCA_DDRPHY_PC_MR0_PRI_RP1_P0,
        MCA_DDRPHY_PC_MR1_PRI_RP1_P0,
        MCA_DDRPHY_PC_MR2_PRI_RP1_P0,
        MCA_DDRPHY_PC_MR3_PRI_RP1_P0,
        MCA_DDRPHY_PC_MR0_SEC_RP1_P0,
        MCA_DDRPHY_PC_MR1_SEC_RP1_P0,
        MCA_DDRPHY_PC_MR2_SEC_RP1_P0,
    },
    {
        MCA_DDRPHY_PC_MR0_PRI_RP2_P0,
        MCA_DDRPHY_PC_MR1_PRI_RP2_P0,
        MCA_DDRPHY_PC_MR2_PRI_RP2_P0,
        MCA_DDRPHY_PC_MR3_PRI_RP2_P0,
        MCA_DDRPHY_PC_MR0_SEC_RP2_P0,
        MCA_DDRPHY_PC_MR1_SEC_RP2_P0,
        MCA_DDRPHY_PC_MR2_SEC_RP2_P0,
    },
    {
        MCA_DDRPHY_PC_MR0_PRI_RP3_P0,
        MCA_DDRPHY_PC_MR1_PRI_RP3_P0,
        MCA_DDRPHY_PC_MR2_PRI_RP3_P0,
        MCA_DDRPHY_PC_MR3_PRI_RP3_P0,
        MCA_DDRPHY_PC_MR0_SEC_RP3_P0,
        MCA_DDRPHY_PC_MR1_SEC_RP3_P0,
        MCA_DDRPHY_PC_MR2_SEC_RP3_P0,
    },
};

namespace pc
{

///
/// @brief Reset the PC CONFIG0 register
/// @param[in] i_target the target (MCA or MBA?)
/// @return FAPI2_RC_SUCCESS if and only if ok
///
template<>
fapi2::ReturnCode reset_config0(const fapi2::Target<TARGET_TYPE_MCA>& i_target)
{
    typedef pcTraits<TARGET_TYPE_MCA> TT;

    fapi2::buffer<uint64_t> l_data;

    l_data.setBit<TT::DDR4_CMD_SIG_REDUCTION>();
    l_data.setBit<TT::DDR4_VLEVEL_BANK_GROUP>();

    FAPI_TRY( write_config0(i_target, l_data) );

fapi_try_exit:
    return fapi2::current_err;
}

///
/// @brief Reset the PC CONFIG1 register
/// @param[in] i_target <the target (MCA or MBA?)
/// @return FAPI2_RC_SUCCESS if and only if ok
///
template<>
fapi2::ReturnCode reset_config1(const fapi2::Target<TARGET_TYPE_MCA>& i_target)
{
    typedef pcTraits<TARGET_TYPE_MCA> TT;

    // Static table of PHY config values for MEMORY_TYPE.
    // [EMPTY, RDIMM, CDIMM, or LRDIMM][EMPTY, DDR3 or DDR4]
    constexpr uint64_t memory_type[4][3] =
    {
        { 0, 0,     0     },  // Empty, never really used.
        { 0, 0b001, 0b101 },  // RDIMM
        { 0, 0b000, 0b000 },  // CDIMM bits, UDIMM enum (placeholder, never used on Nimbus)
        { 0, 0b011, 0b111 },  // LRDIMM
    };

    fapi2::buffer<uint64_t> l_data;

    uint8_t l_rlo = 0;
    uint8_t l_wlo = 0;
    uint8_t l_dram_gen[MAX_DIMM_PER_PORT]    = {0};
    uint8_t l_dimm_type[MAX_DIMM_PER_PORT]   = {0};
    uint8_t l_type_index = 0;
    uint8_t l_gen_index = 0;

    FAPI_TRY( mss::vpd_mr_dphy_rlo(i_target, l_rlo) );
    FAPI_TRY( mss::vpd_mr_dphy_wlo(i_target, l_wlo) );
    FAPI_TRY( mss::eff_dram_gen(i_target, &(l_dram_gen[0])) );
    FAPI_TRY( mss::eff_dimm_type(i_target, &(l_dimm_type[0])) );

    // There's no way to configure the PHY for more than one value. However, we don't know if there's
    // a DIMM in one slot, the other or double drop. So we do a little gyration here to make sure
    // we have one of the two values (and assume effective config caught a bad config)
    l_type_index = l_dimm_type[0] | l_dimm_type[1];
    l_gen_index = l_dram_gen[0] | l_dram_gen[1];

    // FOR NIMBUS PHY (as the protocol choice above is) BRS
    FAPI_TRY( mss::getScom(i_target, MCA_DDRPHY_PC_CONFIG1_P0, l_data) );

    l_data.insertFromRight<TT::MEMORY_TYPE, TT::MEMORY_TYPE_LEN>(memory_type[l_type_index][l_gen_index]);
    l_data.insertFromRight<TT::WRITE_LATENCY_OFFSET, TT::WRITE_LATENCY_OFFSET_LEN>(l_wlo);

    // Always set this bit. It forces the PHY to use A12 when figuring out latency. This makes sense in
    // all cases as A12 is 0 for non-3DS in MR0.
    l_data.setBit<TT::DDR4_LATENCY_SW>();

    // If we are 2N mode we add one to the RLO (see also Centaur initfile)
    l_data.insertFromRight<TT::READ_LATENCY_OFFSET, TT::READ_LATENCY_OFFSET_LEN>(
        mss::two_n_mode_helper(i_target) ? l_rlo + 1 : l_rlo);

    FAPI_TRY( write_config1(i_target, l_data) );

fapi_try_exit:
    return fapi2::current_err;
}

} // close namespace pc
} // close namespace mss
<|endoftext|>


<commit_before>#include "config.h"

#include <stddef.h>
#ifdef _WIN32
#include <io.h>
#else
#include <fcntl.h>
#endif

#include "config.pb.h"
#include "util.h"
#include "google/protobuf/io/zero_copy_stream_impl.h"
#include "google/protobuf/text_format.h"

namespace grr {
ClientConfig::ClientConfig(const std::string& configuration_file) :
    configuration_filename_(configuration_file) {}

bool ClientConfig::ReadConfig() {
  ClientConfiguration proto;
  if (!MergeConfigFile(configuration_filename_, &proto)) {
    GOOGLE_LOG(ERROR) << "Unable to read config:" << configuration_filename_;
    return false;
  }
  std::unique_lock<std::mutex> l(lock_);

  writeback_filename_ = proto.writeback_filename();
  if (!writeback_filename_.empty()) {
    if (!MergeConfigFile(writeback_filename_, &proto)) {
      GOOGLE_LOG(ERROR) << "Unable to read writeback:" << writeback_filename_;
    }
  } else {
    GOOGLE_LOG(WARNING) << "No writeback filename. Writeback disabled.";
  }

  subprocess_config_ = proto.subprocess_config();
  last_server_cert_serial_number_ = proto.last_server_cert_serial_number();

  control_urls_ = proto.control_url();
  proxy_servers_ = proto.proxy_server();

  key_.FromPEM(proto.client_private_key_pem());
  ca_cert_.FromPEM(proto.ca_cert_pem());

  client_id_ = MakeClientId();
  if (control_urls_.empty()) {
    GOOGLE_LOG(ERROR) << "No control URLs.";
    return false;
  }
  if (ca_cert_.get() == NULL) {
    GOOGLE_LOG(ERROR) << "Missing or bad ca cert.";
    return false;
  }
  return true;
}

bool ClientConfig::CheckUpdateServerSerial(int new_serial) {
  std::unique_lock<std::mutex> l(lock_);
  if (new_serial < last_server_cert_serial_number_) {
    return false;
  }
  if (new_serial > last_server_cert_serial_number_) {
    last_server_cert_serial_number_ = new_serial;
    return WriteBackConfig();
  }
  return true;
}

bool ClientConfig::ResetKey() {
  std::unique_lock<std::mutex> l(lock_);
  if (!key_.Generate()) {
    return false;
  }
  client_id_ = MakeClientId();
  return WriteBackConfig();
}

std::vector<std::string> ClientConfig::ControlUrls() const {
  std::unique_lock<std::mutex> l(lock_);
  return std::vector<std::string>(control_urls_.begin(), control_urls_.end());
}

std::vector<std::string> ClientConfig::ProxyServers() const {
  std::unique_lock<std::mutex> l(lock_);
  return std::vector<std::string>(proxy_servers_.begin(), proxy_servers_.end());
}

ClientConfiguration::SubprocessConfig ClientConfig::SubprocessConfig() const {
  std::unique_lock<std::mutex> l(lock_);
  return subprocess_config_;
}

bool ClientConfig::WriteBackConfig() {
  if (writeback_filename_.empty()) {
    return true;
  }
  int fd = open(writeback_filename_.c_str(), O_WRONLY | O_TRUNC | O_CREAT,
                S_IWUSR | S_IRUSR);
  if (fd < 0) {
    GOOGLE_LOG(ERROR) << "Unable to open writeback: " << writeback_filename_;
    return false;
  }
  // Re-read the original configuration file, so we can tell what has changed.
  ClientConfiguration base_config;
  if (!MergeConfigFile(configuration_filename_, &base_config)) {
    GOOGLE_LOG(ERROR) << "Unable to read config: " << configuration_filename_;
  }
  // Currently only 2 fields can be changed through the config interface.
  ClientConfiguration proto;
  if (base_config.last_server_cert_serial_number() !=
      last_server_cert_serial_number_) {
    proto.set_last_server_cert_serial_number(last_server_cert_serial_number_);
  }
  std::string key_pem = key_.ToStringPEM();
  if (base_config.client_private_key_pem() != key_pem) {
    proto.set_client_private_key_pem(key_pem);
  }

  google::protobuf::io::FileOutputStream output(fd);
  bool result = google::protobuf::TextFormat::Print(proto, &output);
  output.Close();
  return result;
}

std::string ClientConfig::MakeClientId() {
  if (!key_.get()) {
    return "";
  }
  return "C." + BytesToHex(Digest::Sha256(key_.PublicKeyN()).substr(0, 8));
}

bool ClientConfig::MergeConfigFile(const std::string& config_file,
                                   ClientConfiguration* config) {
  int fd = open(config_file.c_str(), O_RDONLY);
  if (fd < 0) {
    GOOGLE_LOG(ERROR) << "Failed to open:" << config_file;
    return false;
  }

  google::protobuf::io::FileInputStream input(fd);
  if (!google::protobuf::TextFormat::Merge(&input, config)) {
    GOOGLE_LOG(ERROR) << "Failed to parse:" << config_file;
    input.Close();
    return false;
  }
  input.Close();
  return true;
}
}  // namespace grr
<commit_msg>Fix compatibility with older versions of proto library.<commit_after>#include "config.h"

#include <stddef.h>
#ifdef _WIN32
#include <io.h>
#else
#include <fcntl.h>
#endif

#include "config.pb.h"
#include "util.h"
#include "google/protobuf/io/zero_copy_stream_impl.h"
#include "google/protobuf/text_format.h"

namespace grr {
ClientConfig::ClientConfig(const std::string& configuration_file) :
    configuration_filename_(configuration_file) {}

bool ClientConfig::ReadConfig() {
  ClientConfiguration proto;
  if (!MergeConfigFile(configuration_filename_, &proto)) {
    GOOGLE_LOG(ERROR) << "Unable to read config:" << configuration_filename_;
    return false;
  }
  std::unique_lock<std::mutex> l(lock_);

  writeback_filename_ = proto.writeback_filename();
  if (!writeback_filename_.empty()) {
    if (!MergeConfigFile(writeback_filename_, &proto)) {
      GOOGLE_LOG(ERROR) << "Unable to read writeback:" << writeback_filename_;
    }
  } else {
    GOOGLE_LOG(WARNING) << "No writeback filename. Writeback disabled.";
  }

  subprocess_config_ = proto.subprocess_config();
  last_server_cert_serial_number_ = proto.last_server_cert_serial_number();

  control_urls_ = proto.control_url();
  proxy_servers_ = proto.proxy_server();

  key_.FromPEM(proto.client_private_key_pem());
  ca_cert_.FromPEM(proto.ca_cert_pem());

  client_id_ = MakeClientId();
  if (!control_urls_.size()) {
    GOOGLE_LOG(ERROR) << "No control URLs.";
    return false;
  }
  if (ca_cert_.get() == NULL) {
    GOOGLE_LOG(ERROR) << "Missing or bad ca cert.";
    return false;
  }
  return true;
}

bool ClientConfig::CheckUpdateServerSerial(int new_serial) {
  std::unique_lock<std::mutex> l(lock_);
  if (new_serial < last_server_cert_serial_number_) {
    return false;
  }
  if (new_serial > last_server_cert_serial_number_) {
    last_server_cert_serial_number_ = new_serial;
    return WriteBackConfig();
  }
  return true;
}

bool ClientConfig::ResetKey() {
  std::unique_lock<std::mutex> l(lock_);
  if (!key_.Generate()) {
    return false;
  }
  client_id_ = MakeClientId();
  return WriteBackConfig();
}

std::vector<std::string> ClientConfig::ControlUrls() const {
  std::unique_lock<std::mutex> l(lock_);
  return std::vector<std::string>(control_urls_.begin(), control_urls_.end());
}

std::vector<std::string> ClientConfig::ProxyServers() const {
  std::unique_lock<std::mutex> l(lock_);
  return std::vector<std::string>(proxy_servers_.begin(), proxy_servers_.end());
}

ClientConfiguration::SubprocessConfig ClientConfig::SubprocessConfig() const {
  std::unique_lock<std::mutex> l(lock_);
  return subprocess_config_;
}

bool ClientConfig::WriteBackConfig() {
  if (writeback_filename_.empty()) {
    return true;
  }
  int fd = open(writeback_filename_.c_str(), O_WRONLY | O_TRUNC | O_CREAT,
                S_IWUSR | S_IRUSR);
  if (fd < 0) {
    GOOGLE_LOG(ERROR) << "Unable to open writeback: " << writeback_filename_;
    return false;
  }
  // Re-read the original configuration file, so we can tell what has changed.
  ClientConfiguration base_config;
  if (!MergeConfigFile(configuration_filename_, &base_config)) {
    GOOGLE_LOG(ERROR) << "Unable to read config: " << configuration_filename_;
  }
  // Currently only 2 fields can be changed through the config interface.
  ClientConfiguration proto;
  if (base_config.last_server_cert_serial_number() !=
      last_server_cert_serial_number_) {
    proto.set_last_server_cert_serial_number(last_server_cert_serial_number_);
  }
  std::string key_pem = key_.ToStringPEM();
  if (base_config.client_private_key_pem() != key_pem) {
    proto.set_client_private_key_pem(key_pem);
  }

  google::protobuf::io::FileOutputStream output(fd);
  bool result = google::protobuf::TextFormat::Print(proto, &output);
  output.Close();
  return result;
}

std::string ClientConfig::MakeClientId() {
  if (!key_.get()) {
    return "";
  }
  return "C." + BytesToHex(Digest::Sha256(key_.PublicKeyN()).substr(0, 8));
}

bool ClientConfig::MergeConfigFile(const std::string& config_file,
                                   ClientConfiguration* config) {
  int fd = open(config_file.c_str(), O_RDONLY);
  if (fd < 0) {
    GOOGLE_LOG(ERROR) << "Failed to open:" << config_file;
    return false;
  }

  google::protobuf::io::FileInputStream input(fd);
  if (!google::protobuf::TextFormat::Merge(&input, config)) {
    GOOGLE_LOG(ERROR) << "Failed to parse:" << config_file;
    input.Close();
    return false;
  }
  input.Close();
  return true;
}
}  // namespace grr
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: soundplayer.hxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: obo $ $Date: 2007-07-17 15:16:37 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef INCLUDED_SLIDESHOW_SOUNDPLAYER_HXX
#define INCLUDED_SLIDESHOW_SOUNDPLAYER_HXX

#include <rtl/ustring.hxx>

#include <com/sun/star/uno/XComponentContext.hpp>
#include <com/sun/star/media/XManager.hpp>
#include <com/sun/star/media/XPlayer.hpp>

#include <boost/shared_ptr.hpp>

#include "pauseeventhandler.hxx"
#include "disposable.hxx"
#include "eventmultiplexer.hxx"

/* Definition of SoundPlayer class */

namespace slideshow
{
    namespace internal
    {
        /** Little class that plays a sound from a URL.
            TODO:
            Must be explicitly disposed (as long as enable_shared_ptr_from_this
            isn't available)!
         */
        class SoundPlayer : public PauseEventHandler,
                            public Disposable
        {
        public:
            /** Create a sound player object.

                @param rSoundURL
                URL to a sound file.

                @param rComponentContext
                Reference to a component context, used to create the
                needed services

                @throws ::com::sun::star::lang::NoSupportException, if
                the sound file is invalid, or not supported by the
                player service.
             */
            static ::boost::shared_ptr<SoundPlayer> create(
                EventMultiplexer & rEventMultiplexer,
                const ::rtl::OUString& rSoundURL,
                const ::com::sun::star::uno::Reference<
                ::com::sun::star::uno::XComponentContext>& rComponentContext );

            virtual ~SoundPlayer();

            /** Query duration of sound playback.

                If the sound is already playing, this method
                returns the remaining playback time.

                @return the playback duration in seconds.
             */
            double getDuration() const;

            bool startPlayback();
            bool stopPlayback();

            void setPlaybackLoop( bool bLoop );

            // PauseEventHandler:
            virtual bool handlePause( bool bPauseShow );

            // Disposable
            virtual void dispose();

        private:
            SoundPlayer(
                EventMultiplexer & rEventMultiplexer,
                const ::rtl::OUString& rSoundURL,
                const ::com::sun::star::uno::Reference<
                ::com::sun::star::uno::XComponentContext>& rComponentContext );

            EventMultiplexer & mrEventMultiplexer;
            // TODO(Q3): obsolete when boost::enable_shared_ptr_from_this
            //           is available
            ::boost::shared_ptr<SoundPlayer> mThis;
            ::com::sun::star::uno::Reference< ::com::sun::star::media::XPlayer > mxPlayer;
        };

        typedef ::boost::shared_ptr< SoundPlayer > SoundPlayerSharedPtr;
    }
}

#endif /* INCLUDED_SLIDESHOW_SOUNDPLAYER_HXX */
<commit_msg>INTEGRATION: CWS changefileheader (1.7.46); FILE MERGED 2008/03/31 14:00:31 rt 1.7.46.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: soundplayer.hxx,v $
 * $Revision: 1.8 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef INCLUDED_SLIDESHOW_SOUNDPLAYER_HXX
#define INCLUDED_SLIDESHOW_SOUNDPLAYER_HXX

#include <rtl/ustring.hxx>

#include <com/sun/star/uno/XComponentContext.hpp>
#include <com/sun/star/media/XManager.hpp>
#include <com/sun/star/media/XPlayer.hpp>

#include <boost/shared_ptr.hpp>

#include "pauseeventhandler.hxx"
#include "disposable.hxx"
#include "eventmultiplexer.hxx"

/* Definition of SoundPlayer class */

namespace slideshow
{
    namespace internal
    {
        /** Little class that plays a sound from a URL.
            TODO:
            Must be explicitly disposed (as long as enable_shared_ptr_from_this
            isn't available)!
         */
        class SoundPlayer : public PauseEventHandler,
                            public Disposable
        {
        public:
            /** Create a sound player object.

                @param rSoundURL
                URL to a sound file.

                @param rComponentContext
                Reference to a component context, used to create the
                needed services

                @throws ::com::sun::star::lang::NoSupportException, if
                the sound file is invalid, or not supported by the
                player service.
             */
            static ::boost::shared_ptr<SoundPlayer> create(
                EventMultiplexer & rEventMultiplexer,
                const ::rtl::OUString& rSoundURL,
                const ::com::sun::star::uno::Reference<
                ::com::sun::star::uno::XComponentContext>& rComponentContext );

            virtual ~SoundPlayer();

            /** Query duration of sound playback.

                If the sound is already playing, this method
                returns the remaining playback time.

                @return the playback duration in seconds.
             */
            double getDuration() const;

            bool startPlayback();
            bool stopPlayback();

            void setPlaybackLoop( bool bLoop );

            // PauseEventHandler:
            virtual bool handlePause( bool bPauseShow );

            // Disposable
            virtual void dispose();

        private:
            SoundPlayer(
                EventMultiplexer & rEventMultiplexer,
                const ::rtl::OUString& rSoundURL,
                const ::com::sun::star::uno::Reference<
                ::com::sun::star::uno::XComponentContext>& rComponentContext );

            EventMultiplexer & mrEventMultiplexer;
            // TODO(Q3): obsolete when boost::enable_shared_ptr_from_this
            //           is available
            ::boost::shared_ptr<SoundPlayer> mThis;
            ::com::sun::star::uno::Reference< ::com::sun::star::media::XPlayer > mxPlayer;
        };

        typedef ::boost::shared_ptr< SoundPlayer > SoundPlayerSharedPtr;
    }
}

#endif /* INCLUDED_SLIDESHOW_SOUNDPLAYER_HXX */
<|endoftext|>


<commit_before>/*
 * Copyright 2015 Cloudius Systems
 */

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE core

#include <boost/test/included/unit_test.hpp>
#include "types.hh"
#include "tuple.hh"

BOOST_AUTO_TEST_CASE(test_bytes_type_string_conversions) {
    BOOST_REQUIRE(bytes_type->equal(bytes_type->from_string("616263646566"), bytes_type->decompose(bytes{"abcdef"})));
}

BOOST_AUTO_TEST_CASE(test_int32_type_string_conversions) {
    BOOST_REQUIRE(int32_type->equal(int32_type->from_string("1234567890"), int32_type->decompose(1234567890)));
    BOOST_REQUIRE_EQUAL(int32_type->to_string(int32_type->decompose(1234567890)), "1234567890");

    BOOST_REQUIRE(int32_type->equal(int32_type->from_string("12"), int32_type->decompose(12)));
    BOOST_REQUIRE(int32_type->equal(int32_type->from_string("0012"), int32_type->decompose(12)));
    BOOST_REQUIRE(int32_type->equal(int32_type->from_string("+12"), int32_type->decompose(12)));
    BOOST_REQUIRE_EQUAL(int32_type->to_string(int32_type->decompose(12)), "12");
    BOOST_REQUIRE(int32_type->equal(int32_type->from_string("-12"), int32_type->decompose(-12)));
    BOOST_REQUIRE_EQUAL(int32_type->to_string(int32_type->decompose(-12)), "-12");

    BOOST_REQUIRE(int32_type->equal(int32_type->from_string("0"), int32_type->decompose(0)));
    BOOST_REQUIRE(int32_type->equal(int32_type->from_string("-0"), int32_type->decompose(0)));
    BOOST_REQUIRE(int32_type->equal(int32_type->from_string("+0"), int32_type->decompose(0)));
    BOOST_REQUIRE_EQUAL(int32_type->to_string(int32_type->decompose(0)), "0");

    BOOST_REQUIRE(int32_type->equal(int32_type->from_string("-2147483648"), int32_type->decompose((int32_t)-2147483648)));
    BOOST_REQUIRE_EQUAL(int32_type->to_string(int32_type->decompose((int32_t)-2147483648)), "-2147483648");

    BOOST_REQUIRE(int32_type->equal(int32_type->from_string("2147483647"), int32_type->decompose((int32_t)2147483647)));
    BOOST_REQUIRE_EQUAL(int32_type->to_string(int32_type->decompose((int32_t)-2147483647)), "-2147483647");

    auto test_parsing_fails = [] (sstring text) {
        try {
            int32_type->from_string(text);
            BOOST_FAIL(sprint("Parsing of '%s' should have failed", text));
        } catch (const marshal_exception& e) {
            // expected
        }
    };

    test_parsing_fails("asd");
    test_parsing_fails("-2147483649");
    test_parsing_fails("2147483648");
    test_parsing_fails("2147483648123");

    BOOST_REQUIRE_EQUAL(int32_type->to_string(bytes()), "");
}

BOOST_AUTO_TEST_CASE(test_tuple_is_prefix_of) {
    tuple_type<> type({utf8_type, utf8_type, utf8_type});
    auto prefix_type = type.as_prefix();

    auto val = type.serialize_value({{bytes("a")}, {bytes("b")}, {bytes("c")}});

    BOOST_REQUIRE(prefix_type.is_prefix_of(prefix_type.serialize_value({}), val));
    BOOST_REQUIRE(prefix_type.is_prefix_of(prefix_type.serialize_value({{bytes("a")}}), val));
    BOOST_REQUIRE(prefix_type.is_prefix_of(prefix_type.serialize_value({{bytes("a")}, {bytes("b")}}), val));
    BOOST_REQUIRE(prefix_type.is_prefix_of(prefix_type.serialize_value({{bytes("a")}, {bytes("b")}, {bytes("c")}}), val));

    BOOST_REQUIRE(!prefix_type.is_prefix_of(prefix_type.serialize_value({{}}), val));
    BOOST_REQUIRE(!prefix_type.is_prefix_of(prefix_type.serialize_value({{bytes()}}), val));
    BOOST_REQUIRE(!prefix_type.is_prefix_of(prefix_type.serialize_value({{bytes("b")}, {bytes("c")}}), val));
    BOOST_REQUIRE(!prefix_type.is_prefix_of(prefix_type.serialize_value({{bytes("a")}, {bytes("c")}, {bytes("b")}}), val));
    BOOST_REQUIRE(!prefix_type.is_prefix_of(prefix_type.serialize_value({{bytes("abc")}}), val));
    BOOST_REQUIRE(!prefix_type.is_prefix_of(prefix_type.serialize_value({{bytes("ab")}}), val));

    auto val2 = type.serialize_value({{bytes("a")}, {bytes("b")}, {}});
    BOOST_REQUIRE(prefix_type.is_prefix_of(prefix_type.serialize_value({{bytes("a")}, {bytes("b")}}), val2));
    BOOST_REQUIRE(prefix_type.is_prefix_of(prefix_type.serialize_value({{bytes("a")}, {bytes("b")}, {}}), val2));
    BOOST_REQUIRE(!prefix_type.is_prefix_of(prefix_type.serialize_value({{bytes("a")}, {bytes("b")}, {bytes()}}), val2));
}
<commit_msg>tests: Add test for tuple_type::compare()<commit_after>/*
 * Copyright 2015 Cloudius Systems
 */

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE core

#include <boost/test/included/unit_test.hpp>
#include "types.hh"
#include "tuple.hh"

BOOST_AUTO_TEST_CASE(test_bytes_type_string_conversions) {
    BOOST_REQUIRE(bytes_type->equal(bytes_type->from_string("616263646566"), bytes_type->decompose(bytes{"abcdef"})));
}

BOOST_AUTO_TEST_CASE(test_int32_type_string_conversions) {
    BOOST_REQUIRE(int32_type->equal(int32_type->from_string("1234567890"), int32_type->decompose(1234567890)));
    BOOST_REQUIRE_EQUAL(int32_type->to_string(int32_type->decompose(1234567890)), "1234567890");

    BOOST_REQUIRE(int32_type->equal(int32_type->from_string("12"), int32_type->decompose(12)));
    BOOST_REQUIRE(int32_type->equal(int32_type->from_string("0012"), int32_type->decompose(12)));
    BOOST_REQUIRE(int32_type->equal(int32_type->from_string("+12"), int32_type->decompose(12)));
    BOOST_REQUIRE_EQUAL(int32_type->to_string(int32_type->decompose(12)), "12");
    BOOST_REQUIRE(int32_type->equal(int32_type->from_string("-12"), int32_type->decompose(-12)));
    BOOST_REQUIRE_EQUAL(int32_type->to_string(int32_type->decompose(-12)), "-12");

    BOOST_REQUIRE(int32_type->equal(int32_type->from_string("0"), int32_type->decompose(0)));
    BOOST_REQUIRE(int32_type->equal(int32_type->from_string("-0"), int32_type->decompose(0)));
    BOOST_REQUIRE(int32_type->equal(int32_type->from_string("+0"), int32_type->decompose(0)));
    BOOST_REQUIRE_EQUAL(int32_type->to_string(int32_type->decompose(0)), "0");

    BOOST_REQUIRE(int32_type->equal(int32_type->from_string("-2147483648"), int32_type->decompose((int32_t)-2147483648)));
    BOOST_REQUIRE_EQUAL(int32_type->to_string(int32_type->decompose((int32_t)-2147483648)), "-2147483648");

    BOOST_REQUIRE(int32_type->equal(int32_type->from_string("2147483647"), int32_type->decompose((int32_t)2147483647)));
    BOOST_REQUIRE_EQUAL(int32_type->to_string(int32_type->decompose((int32_t)-2147483647)), "-2147483647");

    auto test_parsing_fails = [] (sstring text) {
        try {
            int32_type->from_string(text);
            BOOST_FAIL(sprint("Parsing of '%s' should have failed", text));
        } catch (const marshal_exception& e) {
            // expected
        }
    };

    test_parsing_fails("asd");
    test_parsing_fails("-2147483649");
    test_parsing_fails("2147483648");
    test_parsing_fails("2147483648123");

    BOOST_REQUIRE_EQUAL(int32_type->to_string(bytes()), "");
}

BOOST_AUTO_TEST_CASE(test_tuple_is_prefix_of) {
    tuple_type<> type({utf8_type, utf8_type, utf8_type});
    auto prefix_type = type.as_prefix();

    auto val = type.serialize_value({{bytes("a")}, {bytes("b")}, {bytes("c")}});

    BOOST_REQUIRE(prefix_type.is_prefix_of(prefix_type.serialize_value({}), val));
    BOOST_REQUIRE(prefix_type.is_prefix_of(prefix_type.serialize_value({{bytes("a")}}), val));
    BOOST_REQUIRE(prefix_type.is_prefix_of(prefix_type.serialize_value({{bytes("a")}, {bytes("b")}}), val));
    BOOST_REQUIRE(prefix_type.is_prefix_of(prefix_type.serialize_value({{bytes("a")}, {bytes("b")}, {bytes("c")}}), val));

    BOOST_REQUIRE(!prefix_type.is_prefix_of(prefix_type.serialize_value({{}}), val));
    BOOST_REQUIRE(!prefix_type.is_prefix_of(prefix_type.serialize_value({{bytes()}}), val));
    BOOST_REQUIRE(!prefix_type.is_prefix_of(prefix_type.serialize_value({{bytes("b")}, {bytes("c")}}), val));
    BOOST_REQUIRE(!prefix_type.is_prefix_of(prefix_type.serialize_value({{bytes("a")}, {bytes("c")}, {bytes("b")}}), val));
    BOOST_REQUIRE(!prefix_type.is_prefix_of(prefix_type.serialize_value({{bytes("abc")}}), val));
    BOOST_REQUIRE(!prefix_type.is_prefix_of(prefix_type.serialize_value({{bytes("ab")}}), val));

    auto val2 = type.serialize_value({{bytes("a")}, {bytes("b")}, {}});
    BOOST_REQUIRE(prefix_type.is_prefix_of(prefix_type.serialize_value({{bytes("a")}, {bytes("b")}}), val2));
    BOOST_REQUIRE(prefix_type.is_prefix_of(prefix_type.serialize_value({{bytes("a")}, {bytes("b")}, {}}), val2));
    BOOST_REQUIRE(!prefix_type.is_prefix_of(prefix_type.serialize_value({{bytes("a")}, {bytes("b")}, {bytes()}}), val2));
}

BOOST_AUTO_TEST_CASE(test_tuple_type_compare) {
    tuple_type<> type({utf8_type, utf8_type, utf8_type});

    BOOST_REQUIRE(type.compare(
        type.serialize_value({{bytes("a")}, {bytes("b")}, {bytes("c")}}),
        type.serialize_value({{bytes("a")}, {bytes("b")}, {bytes("c")}})) == 0);

    BOOST_REQUIRE(type.compare(
        type.serialize_value({{bytes("a")}, {bytes("b")}, {bytes("c")}}),
        type.serialize_value({{bytes("a")}, {bytes("b")}, {bytes("d")}})) < 0);

    BOOST_REQUIRE(type.compare(
        type.serialize_value({{bytes("a")}, {bytes("b")}, {bytes("d")}}),
        type.serialize_value({{bytes("a")}, {bytes("b")}, {bytes("c")}})) > 0);

    BOOST_REQUIRE(type.compare(
        type.serialize_value({{bytes("a")}, {bytes("b")}, {bytes("d")}}),
        type.serialize_value({{bytes("a")}, {bytes("d")}, {bytes("c")}})) < 0);

    BOOST_REQUIRE(type.compare(
        type.serialize_value({{bytes("a")}, {bytes("d")}, {bytes("c")}}),
        type.serialize_value({{bytes("c")}, {bytes("b")}, {bytes("c")}})) < 0);

    BOOST_REQUIRE(type.compare(
        type.serialize_value({{bytes("a")}, {}, {bytes("c")}}),
        type.serialize_value({{bytes("a")}, {bytes("b")}, {bytes("c")}})) < 0);

    BOOST_REQUIRE(type.compare(
        type.serialize_value({{bytes("a")}, {bytes("b")}, {bytes("c")}}),
        type.serialize_value({{bytes("a")}, {}, {bytes("c")}})) > 0);

    BOOST_REQUIRE(type.compare(
        type.serialize_value({{}, {}, {}}),
        type.serialize_value({{}, {}, {}})) == 0);
}
<|endoftext|>


<commit_before>#ifndef CHS_HPP
#define CHS_HPP

//
// A class for CHS manipulation
//
//

class CHS
{
  long long cylinder,
            head,
            sector;
  unsigned int spt, // sectors per track
               tpc; // tracks per cylinder

  void calc(long long);

public:

  CHS(int c,int h, int s);
  CHS(long long lba);
  CHS();

  bool SetCylinder(long long);
  bool SetHead(unsigned int);
  bool SetSector(unsigned int);

  unsigned long GetCylinder();
  unsigned int GetHead();
  unsigned int GetSector();

  bool SetGeometry(int spt,int tpc);
  int GetSPT();
  int GetTPC();
  void SetSPT(int);
  void SetTPC(int);

  long long ToLBA();

  CHS &operator =(long long);
  bool operator ==(CHS &chs);
  CHS &operator ++();
  CHS &operator ++(int);

};

#endif
<commit_msg>Added MBR_CHS CHS::ToMbrChs() function<commit_after>#ifndef CHS_HPP
#define CHS_HPP

#include <stdint.h>

#pragma pack(1)
// Cylinder-head-sector structure for MBR
struct MBR_CHS
{
  uint8_t head;             // head (<255)
  uint8_t sector:6;         // sector (<64)
  uint8_t cylinder_bits:2;  // 2 bits of cylinder value
  uint8_t cylinder   ;      // cylinder (<=1023)
};
#pragma pack()

//
// A class for CHS manipulation
//

class CHS
{
  long long cylinder,
            head,
            sector;
  unsigned int spt, // sectors per track
               tpc; // tracks per cylinder

  void calc(long long);

public:

  CHS(int c,int h, int s);
  CHS(long long lba);
  CHS();

  bool SetCylinder(long long);
  bool SetHead(unsigned int);
  bool SetSector(unsigned int);

  unsigned long GetCylinder();
  unsigned int GetHead();
  unsigned int GetSector();

  bool SetGeometry(int spt,int tpc);
  int GetSPT();
  int GetTPC();
  void SetSPT(int);
  void SetTPC(int);

  long long ToLBA();

  CHS &operator =(long long);
  bool operator ==(CHS &chs);
  CHS &operator ++();
  CHS &operator ++(int);

  MBR_CHS ToMbrChs();

};

#endif
<|endoftext|>


<commit_before>//std
#include <sstream>

//naga
#include "model.hpp"
#include "model_component.hpp"
#include "model_animation.hpp"
#include "collision.hpp"
#include "resource_manager.hpp"
#include "material_instance.hpp"
#include "debug_renderer.hpp"
#include "game_object.hpp"
#include "camera_params.hpp"
#include "bisect.hpp"

//glm
#include <glm\glm.hpp>

namespace naga
{
    void ModelComponent::on_tick(f32 dt)
    {
		if (animation != nullptr)
		{
			t += dt;

			// TODO: extract this to a function to get the frame index
			auto frame_count = static_cast<f32>(animation->frame_count);
			auto seconds_per_frame = 1.0f / animation->frames_per_second;
			auto frame_0_index = static_cast<size_t>(glm::floor(glm::mod(t / seconds_per_frame, frame_count)));
			auto frame_1_index = (frame_0_index + 1) % animation->frame_count;
			auto interpolate_t = glm::mod(t, seconds_per_frame) / seconds_per_frame;
			auto& frame_skeleton_0 = animation->frame_skeletons[frame_0_index];
			auto& frame_skeleton_1 = animation->frame_skeletons[frame_1_index];

			skeleton.interpolate(frame_skeleton_0, frame_skeleton_1, interpolate_t);
		}

        //TODO: the AABB is not calculated if there is no animation

        for (size_t i = 0; i < skeleton.bones.size(); ++i)
        {
            bone_matrices[i] = skeleton.bone_matrices[i] * model->get_bones()[i].inverse_bind_pose_matrix;
        }

        aabb = skeleton.aabb << get_owner()->pose.to_matrix();

        sphere.origin = aabb.center();
        sphere.radius = glm::length(aabb.extents());
    }

	void ModelComponent::on_render(CameraParameters& camera_parameters)
    {
        if (model == nullptr)
        {
            throw std::exception();
        }

		// TODO: problem here is that the frustum/sphere/aabb are not
		if (intersects(camera_parameters.frustum, sphere) == IntersectType::DISJOINT ||
			intersects(camera_parameters.frustum, aabb) == IntersectType::DISJOINT)
        {
            //skeleton aabb does not intersect camera frustum
            return;
        }

        // TODO: need to figure out a better way to feed light data into the shaders
        vec3 light_location;

        const auto world_matrix = get_owner()->pose.to_matrix();
		auto view_projection_matrix = camera_parameters.projection_matrix * camera_parameters.view_matrix;

		model->render(camera_parameters.location, world_matrix, view_projection_matrix, bone_matrices, light_location, mesh_materials);

#if defined (DEBUG)
        render_aabb(mat4(1.0f), view_projection_matrix, aabb, vec4(1, 0, 0, 1));
		render_sphere(mat4(1.0f), view_projection_matrix, sphere, vec4(1));

		for (size_t i = 0; i < model->get_bones().size(); ++i)
		{
			if (skeleton.bones[i].parent_index != 255)
			{
				const auto& a = skeleton.bones[i].pose.location;
				const auto& b = skeleton.bones[skeleton.bones[i].parent_index].pose.location;
				render_line_loop(world_matrix, view_projection_matrix, std::vector<vec3>({ a, b }), vec4(0.5f));
			}

			render_axes(skeleton.bones[i].pose.to_matrix() * world_matrix, view_projection_matrix);
			//render_sphere(, view_projection_matrix, Sphere(vec3(), 0.5f), vec4(1));
		}
#endif
    }

	Pose3 ModelComponent::get_bone_pose(const std::string& bone_name) const
    {
		auto bone_index = model->get_bone_index(bone_name);

        if (!bone_index)
        {
            std::ostringstream oss;
            oss << "model contains no bone " << bone_name;
            throw std::invalid_argument(oss.str().c_str());
        }

        return get_owner()->pose * skeleton.bones[*bone_index].pose;
    }

	void ModelComponent::set_model(const boost::shared_ptr<Model>& model)
    {
        this->model = model;

        skeleton.bones.resize(model->get_bones().size());
        skeleton.bone_matrices.resize(model->get_bones().size());

        for (size_t i = 0; i < skeleton.bones.size(); ++i)
        {
            skeleton.bone_matrices[i] = model->get_bones()[i].bind_pose_matrix;
        }

        bone_matrices.resize(skeleton.bones.size());

        for (size_t i = 0; i < skeleton.bones.size(); ++i)
        {
            bone_matrices[i] = skeleton.bone_matrices[i] * model->get_bones()[i].inverse_bind_pose_matrix;
        }

        for (const auto& mesh : model->get_meshes())
        {
			mesh_materials.push_back(boost::make_shared<MaterialInstance>(mesh->material));
        }
    }

	void ModelComponent::play(const std::string& animation_name)
    {
		animation = resources.get<ModelAnimation>(animation_name);
    }

	void pause();
}
<commit_msg>Fixed a problem where the debug skeleton bone axes would draw in the wrong place.<commit_after>//std
#include <sstream>

//naga
#include "model.hpp"
#include "model_component.hpp"
#include "model_animation.hpp"
#include "collision.hpp"
#include "resource_manager.hpp"
#include "material_instance.hpp"
#include "debug_renderer.hpp"
#include "game_object.hpp"
#include "camera_params.hpp"
#include "bisect.hpp"

//glm
#include <glm\glm.hpp>

namespace naga
{
    void ModelComponent::on_tick(f32 dt)
    {
		if (animation != nullptr)
		{
			t += dt;

			// TODO: extract this to a function to get the frame index
			auto frame_count = static_cast<f32>(animation->frame_count);
			auto seconds_per_frame = 1.0f / animation->frames_per_second;
			auto frame_0_index = static_cast<size_t>(glm::floor(glm::mod(t / seconds_per_frame, frame_count)));
			auto frame_1_index = (frame_0_index + 1) % animation->frame_count;
			auto interpolate_t = glm::mod(t, seconds_per_frame) / seconds_per_frame;
			auto& frame_skeleton_0 = animation->frame_skeletons[frame_0_index];
			auto& frame_skeleton_1 = animation->frame_skeletons[frame_1_index];

			skeleton.interpolate(frame_skeleton_0, frame_skeleton_1, interpolate_t);
		}

        //TODO: the AABB is not calculated if there is no animation

        for (size_t i = 0; i < skeleton.bones.size(); ++i)
        {
            bone_matrices[i] = skeleton.bone_matrices[i] * model->get_bones()[i].inverse_bind_pose_matrix;
        }

        aabb = skeleton.aabb << get_owner()->pose.to_matrix();

        sphere.origin = aabb.center();
        sphere.radius = glm::length(aabb.extents());
    }

	void ModelComponent::on_render(CameraParameters& camera_parameters)
    {
        if (model == nullptr)
        {
            throw std::exception();
        }

		// TODO: problem here is that the frustum/sphere/aabb are not
		if (intersects(camera_parameters.frustum, sphere) == IntersectType::DISJOINT ||
			intersects(camera_parameters.frustum, aabb) == IntersectType::DISJOINT)
        {
            //skeleton aabb does not intersect camera frustum
            return;
        }

        // TODO: need to figure out a better way to feed light data into the shaders
        vec3 light_location;

        const auto world_matrix = get_owner()->pose.to_matrix();
		auto view_projection_matrix = camera_parameters.projection_matrix * camera_parameters.view_matrix;

		model->render(camera_parameters.location, world_matrix, view_projection_matrix, bone_matrices, light_location, mesh_materials);

#if defined (DEBUG)
        render_aabb(mat4(1.0f), view_projection_matrix, aabb, vec4(1, 0, 0, 1));
		render_sphere(mat4(1.0f), view_projection_matrix, sphere, vec4(1));

		for (size_t i = 0; i < model->get_bones().size(); ++i)
		{
			if (skeleton.bones[i].parent_index != 255)
			{
				const auto& a = skeleton.bones[i].pose.location;
				const auto& b = skeleton.bones[skeleton.bones[i].parent_index].pose.location;
				render_line_loop(world_matrix, view_projection_matrix, std::vector<vec3>({ a, b }), vec4(0.5f));
			}

			render_axes(world_matrix * skeleton.bones[i].pose.to_matrix(), view_projection_matrix);
		}
#endif
    }

	Pose3 ModelComponent::get_bone_pose(const std::string& bone_name) const
    {
		auto bone_index = model->get_bone_index(bone_name);

        if (!bone_index)
        {
            std::ostringstream oss;
            oss << "model contains no bone " << bone_name;
            throw std::invalid_argument(oss.str().c_str());
        }

        return get_owner()->pose * skeleton.bones[*bone_index].pose;
    }

	void ModelComponent::set_model(const boost::shared_ptr<Model>& model)
    {
        this->model = model;

        skeleton.bones.resize(model->get_bones().size());
        skeleton.bone_matrices.resize(model->get_bones().size());

        for (size_t i = 0; i < skeleton.bones.size(); ++i)
        {
            skeleton.bone_matrices[i] = model->get_bones()[i].bind_pose_matrix;
        }

        bone_matrices.resize(skeleton.bones.size());

        for (size_t i = 0; i < skeleton.bones.size(); ++i)
        {
            bone_matrices[i] = skeleton.bone_matrices[i] * model->get_bones()[i].inverse_bind_pose_matrix;
        }

        for (const auto& mesh : model->get_meshes())
        {
			mesh_materials.push_back(boost::make_shared<MaterialInstance>(mesh->material));
        }
    }

	void ModelComponent::play(const std::string& animation_name)
    {
		animation = resources.get<ModelAnimation>(animation_name);
    }

	void pause();
}
<|endoftext|>


<commit_before>// $Id: rtti.C,v 1.6 2001/06/22 11:06:37 oliver Exp $

#include <BALL/COMMON/rtti.h>
#include <typeinfo>
#include <ctype.h>

#ifdef __GNUC__
	extern "C" char* cplus_demangle(const char* s, int options);
#endif

namespace BALL
{

	string streamClassName(const std::type_info& t)
	{
#ifdef __GNUC__
    // s = GNUDemangling::demangle(s);
		string s("_Z");
		s += t.name();
		char* name = cplus_demangle(s.c_str(), 1 << 8);
		if (name != 0)
		{
			 s = name;
		}

#else
		string s(t.name());
#endif

		for (unsigned int i = 0; i < s.size(); i++)
		{
			if (s[i] == ' ')
			{
				s[i] = '_';
			}
		}

		if (string(s, 0, 6) == "const_")
		{
			s.erase(0, 6);
		}

		return s;
	}

#ifdef __GNUC__

	namespace GNUDemangling
	{

		string decode_mangling(string& s)
		{
			string tmp;
			int i,len;

			if (s.size() == 0)
				return "";

			if (!isdigit(s[0]))
			{ // decode GNU shortcuts for built-in types
				char c = s[0];
				s.erase(0, 1);
				switch (c)
				{
					case 'Q': // start of class name
						len = atoi(string(s,1,1).c_str());
						s.erase(0, 1);
						for (i = 0; i < len; i++)
						{
							tmp.append(decode_mangling(s));
							tmp.append("::");
						}
						tmp.erase(tmp.end() - 2, tmp.end());
						break;
					case 'Z': // template parameter
						return decode_mangling(s);
						break;

					case 'i':
						return "int";
						break;

					case 'l':
						return "long";
						break;

					case 's':
						return "short";
						break;

					case 'c':
						return "char";
						break;

					case 'x':
						return "long long";
						break;

					case 'f':
						return "float";
						break;

					case 'd':
						return "double";
						break;

					case 'b':
						return "bool";
						break;

					case 'w':
						return "wchar_t";
						break;

					case 'U': // unsigned variants
						tmp = "unsigned ";
						tmp.append(decode_mangling(s));
						break;

					case 'C': // const
						tmp = "const ";
						tmp.append(decode_mangling(s));
						break;

					case 'P': // pointer
						tmp = decode_mangling(s);
						tmp.append("*");
						break;

					case 'R': // reference
						tmp = decode_mangling(s);
						tmp.append("&");
						break;

					case 't':
						tmp = decode_mangling(s);
						tmp.append("<");

						len = atoi(string(1, s[0]).c_str());
						s.erase(0,1);
						for (i = 0; i < len; i++)
						{
							tmp.append(decode_mangling(s));
							tmp.append(",");
						}

						// remove last ','
						tmp.erase(tmp.end() - 1, tmp.end());
						tmp.append(">");
						break;

					default:
						tmp = "?";
				}
				return tmp;
			}
			else
			{
				i = s.find_first_not_of("0123456789");
				len = atol(string(s, 0, i).c_str());
				if (len == 0)
				{
					s.erase(0,1);

					if (s.size() > 0)
					{
						return decode_mangling(s);
					}
					else
					{
						return "";
					}
				}
				else
				{
					string h(s, i, len);
					s.erase(0, i + len);

					return h;
				}
			}
		}

		string demangle(string s)
		{
			string tmp = decode_mangling(s);

			while (tmp[tmp.size() - 1] == ':')
			{
				tmp.erase(tmp.end() - 1, tmp.end());
			}

			while (tmp[0] == ':')
			{
				tmp.erase(0, 1);
			}

			return tmp;
		}

	} // namespace GNUDemangling

#endif // __GNUC__

} // namespace BALL

<commit_msg>fixed: gnu demangling was broken for GCC 2, reintroduced demangloing by hand   and use if libiberty.a for GCC3<commit_after>// $Id: rtti.C,v 1.7 2001/06/28 14:13:34 oliver Exp $

#include <BALL/COMMON/rtti.h>
#include <typeinfo>
#include <ctype.h>

#ifdef __GNUC__
	extern "C" char* cplus_demangle(const char* s, int options);
#endif

namespace BALL
{

	string streamClassName(const std::type_info& t)
	{
#ifdef __GNUC__
    #if (__GNUC__ < 3)
			string s(t.name());
      s = GNUDemangling::demangle(s);
    #else
      string s("_Z");
      s += t.name();
      char* name = cplus_demangle(s.c_str(), 1 << 8);
      if (name != 0)
      {
        s = name;
			}
    #endif
#else
		string s(t.name());
#endif

		for (unsigned int i = 0; i < s.size(); i++)
		{
			if (s[i] == ' ')
			{
				s[i] = '_';
			}
		}

		if (string(s, 0, 6) == "const_")
		{
			s.erase(0, 6);
		}

		return s;
	}

#ifdef __GNUC__

	namespace GNUDemangling
	{

		string decode_mangling(string& s)
		{
			string tmp;
			int i,len;

			if (s.size() == 0)
				return "";

			if (!isdigit(s[0]))
			{ // decode GNU shortcuts for built-in types
				char c = s[0];
				s.erase(0, 1);
				switch (c)
				{
					case 'Q': // start of class name
						len = atoi(string(s,1,1).c_str());
						s.erase(0, 1);
						for (i = 0; i < len; i++)
						{
							tmp.append(decode_mangling(s));
							tmp.append("::");
						}
						tmp.erase(tmp.end() - 2, tmp.end());
						break;
					case 'Z': // template parameter
						return decode_mangling(s);
						break;

					case 'i':
						return "int";
						break;

					case 'l':
						return "long";
						break;

					case 's':
						return "short";
						break;

					case 'c':
						return "char";
						break;

					case 'x':
						return "long long";
						break;

					case 'f':
						return "float";
						break;

					case 'd':
						return "double";
						break;

					case 'b':
						return "bool";
						break;

					case 'w':
						return "wchar_t";
						break;

					case 'U': // unsigned variants
						tmp = "unsigned ";
						tmp.append(decode_mangling(s));
						break;

					case 'C': // const
						tmp = "const ";
						tmp.append(decode_mangling(s));
						break;

					case 'P': // pointer
						tmp = decode_mangling(s);
						tmp.append("*");
						break;

					case 'R': // reference
						tmp = decode_mangling(s);
						tmp.append("&");
						break;

					case 't':
						tmp = decode_mangling(s);
						tmp.append("<");

						len = atoi(string(1, s[0]).c_str());
						s.erase(0,1);
						for (i = 0; i < len; i++)
						{
							tmp.append(decode_mangling(s));
							tmp.append(",");
						}

						// remove last ','
						tmp.erase(tmp.end() - 1, tmp.end());
						tmp.append(">");
						break;

					default:
						tmp = "?";
				}
				return tmp;
			}
			else
			{
				i = s.find_first_not_of("0123456789");
				len = atol(string(s, 0, i).c_str());
				if (len == 0)
				{
					s.erase(0,1);

					if (s.size() > 0)
					{
						return decode_mangling(s);
					}
					else
					{
						return "";
					}
				}
				else
				{
					string h(s, i, len);
					s.erase(0, i + len);

					return h;
				}
			}
		}

		string demangle(string s)
		{
			string tmp = decode_mangling(s);

			while (tmp[tmp.size() - 1] == ':')
			{
				tmp.erase(tmp.end() - 1, tmp.end());
			}

			while (tmp[0] == ':')
			{
				tmp.erase(0, 1);
			}

			return tmp;
		}

	} // namespace GNUDemangling

#endif // __GNUC__

} // namespace BALL

<|endoftext|>