<commit_before>#include <iostream>

#include "filelib.h"
#include "decoder.h"
#include "ff_register.h"
#include "verbose.h"

using namespace std;

int main(int argc, char** argv) {
  register_feature_functions();
  Decoder decoder(argc, argv);

  const string input = decoder.GetConf()["input"].as<string>();
  const bool show_feature_dictionary = decoder.GetConf().count("show_feature_dictionary");
  if (!SILENT) cerr << "Reading input from " << ((input == "-") ? "STDIN" : input.c_str()) << endl;
  ReadFile in_read(input);
  istream *in = in_read.stream();
  assert(*in);

  string buf;
#ifdef CP_TIME
    clock_t time_cp(0);//, end_cp;
#endif
  while(*in) {
    getline(*in, buf);
    if (buf.empty()) continue;
    decoder.Decode(buf);
  }
#ifdef CP_TIME
    cerr << "Time required for Cube Pruning execution: "
    << CpTime::Get()
    << " seconds." << "\n\n";
#endif
  if (show_feature_dictionary) {
    int num = FD::NumFeats();
    for (int i = 1; i < num; ++i) {
      cout << FD::Convert(i) << endl;
    }
  }
  return 0;
}

<commit_msg>Add memory size logging<commit_after>#include <iostream>

#include "filelib.h"
#include "decoder.h"
#include "ff_register.h"
#include "verbose.h"
#include "util/usage.hh"

using namespace std;

int main(int argc, char** argv) {
  register_feature_functions();
  Decoder decoder(argc, argv);

  const string input = decoder.GetConf()["input"].as<string>();
  const bool show_feature_dictionary = decoder.GetConf().count("show_feature_dictionary");
  if (!SILENT) cerr << "Reading input from " << ((input == "-") ? "STDIN" : input.c_str()) << endl;
  ReadFile in_read(input);
  istream *in = in_read.stream();
  assert(*in);

  string buf;
#ifdef CP_TIME
    clock_t time_cp(0);//, end_cp;
#endif
  while(*in) {
    getline(*in, buf);
    if (buf.empty()) continue;
    decoder.Decode(buf);
  }
#ifdef CP_TIME
    cerr << "Time required for Cube Pruning execution: "
    << CpTime::Get()
    << " seconds." << "\n\n";
#endif
  if (show_feature_dictionary) {
    int num = FD::NumFeats();
    for (int i = 1; i < num; ++i) {
      cout << FD::Convert(i) << endl;
    }
  }
  util::PrintUsage(std::cerr);
  return 0;
}

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013,2016-2018 ARM Limited
 * All rights reserved.
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Copyright (c) 2003-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Erik Hallnor
 *          Nikos Nikoleris
 */

/**
 * @file
 * Definitions a fully associative LRU tagstore.
 */

#include "mem/cache/tags/fa_lru.hh"

#include <cassert>
#include <sstream>

#include "base/intmath.hh"
#include "base/logging.hh"

FALRU::FALRU(const Params *p)
    : BaseTags(p),

      cacheTracking(p->min_tracked_cache_size, size, blkSize)
{
    if (!isPowerOf2(blkSize))
        fatal("cache block size (in bytes) `%d' must be a power of two",
              blkSize);
    if (!isPowerOf2(size))
        fatal("Cache Size must be power of 2 for now");

    blks = new FALRUBlk[numBlocks];

    head = &(blks[0]);
    head->prev = nullptr;
    head->next = &(blks[1]);
    head->set = 0;
    head->way = 0;
    head->data = &dataBlks[0];

    for (unsigned i = 1; i < numBlocks - 1; i++) {
        blks[i].prev = &(blks[i-1]);
        blks[i].next = &(blks[i+1]);
        blks[i].set = 0;
        blks[i].way = i;

        // Associate a data chunk to the block
        blks[i].data = &dataBlks[blkSize*i];
    }

    tail = &(blks[numBlocks - 1]);
    tail->prev = &(blks[numBlocks - 2]);
    tail->next = nullptr;
    tail->set = 0;
    tail->way = numBlocks - 1;
    tail->data = &dataBlks[(numBlocks - 1) * blkSize];

    cacheTracking.init(head, tail);
}

FALRU::~FALRU()
{
    delete[] blks;
}

void
FALRU::regStats()
{
    BaseTags::regStats();
    cacheTracking.regStats(name());
}

FALRUBlk *
FALRU::hashLookup(Addr addr) const
{
    tagIterator iter = tagHash.find(addr);
    if (iter != tagHash.end()) {
        return (*iter).second;
    }
    return nullptr;
}

void
FALRU::invalidate(CacheBlk *blk)
{
    BaseTags::invalidate(blk);

    // Move the block to the tail to make it the next victim
    moveToTail((FALRUBlk*)blk);

    // Erase block entry in the hash table
    tagHash.erase(blk->tag);
}

CacheBlk*
FALRU::accessBlock(Addr addr, bool is_secure, Cycles &lat)
{
    return accessBlock(addr, is_secure, lat, 0);
}

CacheBlk*
FALRU::accessBlock(Addr addr, bool is_secure, Cycles &lat,
                   CachesMask *in_caches_mask)
{
    CachesMask mask = 0;
    Addr blkAddr = blkAlign(addr);
    FALRUBlk* blk = hashLookup(blkAddr);

    if (blk && blk->isValid()) {
        // If a cache hit
        lat = accessLatency;
        // Check if the block to be accessed is available. If not,
        // apply the accessLatency on top of block->whenReady.
        if (blk->whenReady > curTick() &&
            cache->ticksToCycles(blk->whenReady - curTick()) >
            accessLatency) {
            lat = cache->ticksToCycles(blk->whenReady - curTick()) +
            accessLatency;
        }
        assert(blk->tag == blkAddr);
        mask = blk->inCachesMask;
        moveToHead(blk);
    } else {
        // If a cache miss
        lat = lookupLatency;
        blk = nullptr;
    }
    if (in_caches_mask) {
        *in_caches_mask = mask;
    }

    cacheTracking.recordAccess(blk);

    return blk;
}

CacheBlk*
FALRU::findBlock(Addr addr, bool is_secure) const
{
    Addr blkAddr = blkAlign(addr);
    FALRUBlk* blk = hashLookup(blkAddr);

    if (blk && blk->isValid()) {
        assert(blk->tag == blkAddr);
        assert(blk->isSecure() == is_secure);
    } else {
        blk = nullptr;
    }
    return blk;
}

CacheBlk*
FALRU::findBlockBySetAndWay(int set, int way) const
{
    assert(set == 0);
    return &blks[way];
}

CacheBlk*
FALRU::findVictim(Addr addr)
{
    return tail;
}

void
FALRU::insertBlock(PacketPtr pkt, CacheBlk *blk)
{
    FALRUBlk* falruBlk = static_cast<FALRUBlk*>(blk);

    // Make sure block is not present in the cache
    assert(falruBlk->inCachesMask == 0);

    // Do common block insertion functionality
    BaseTags::insertBlock(pkt, blk);

    // New block is the MRU
    moveToHead(falruBlk);

    // Insert new block in the hash table
    tagHash[falruBlk->tag] = falruBlk;
}

void
FALRU::moveToHead(FALRUBlk *blk)
{
    // If block is not already head, do the moving
    if (blk != head) {
        cacheTracking.moveBlockToHead(blk);
        // If block is tail, set previous block as new tail
        if (blk == tail){
            assert(blk->next == nullptr);
            tail = blk->prev;
            tail->next = nullptr;
        // Inform block's surrounding blocks that it has been moved
        } else {
            blk->prev->next = blk->next;
            blk->next->prev = blk->prev;
        }

        // Swap pointers
        blk->next = head;
        blk->prev = nullptr;
        head->prev = blk;
        head = blk;

        cacheTracking.check(head, tail);
    }
}

void
FALRU::moveToTail(FALRUBlk *blk)
{
    // If block is not already tail, do the moving
    if (blk != tail) {
        cacheTracking.moveBlockToTail(blk);
        // If block is head, set next block as new head
        if (blk == head){
            assert(blk->prev == nullptr);
            head = blk->next;
            head->prev = nullptr;
        // Inform block's surrounding blocks that it has been moved
        } else {
            blk->prev->next = blk->next;
            blk->next->prev = blk->prev;
        }

        // Swap pointers
        blk->prev = tail;
        blk->next = nullptr;
        tail->next = blk;
        tail = blk;

        cacheTracking.check(head, tail);
    }
}

FALRU *
FALRUParams::create()
{
    return new FALRU(this);
}

void
FALRU::CacheTracking::check(FALRUBlk *head, FALRUBlk *tail)
{
#ifdef FALRU_DEBUG
    FALRUBlk* blk = head;
    unsigned curr_size = 0;
    unsigned tracked_cache_size = minTrackedSize;
    CachesMask in_caches_mask = inAllCachesMask;
    int j = 0;

    while (blk) {
        panic_if(blk->inCachesMask != in_caches_mask, "Expected cache mask "
                 "%x found %x", blk->inCachesMask, in_caches_mask);

        curr_size += blkSize;
        if (curr_size == tracked_cache_size && blk != tail) {
            panic_if(boundaries[j] != blk, "Unexpected boundary for the %d-th "
                     "cache", j);
            tracked_cache_size <<= 1;
            // from this point, blocks fit only in the larger caches
            in_caches_mask &= ~(1U << j);
            ++j;
        }
        blk = blk->next;
    }
#endif // FALRU_DEBUG
}

void
FALRU::CacheTracking::init(FALRUBlk *head, FALRUBlk *tail)
{
    // early exit if we are not tracking any extra caches
    FALRUBlk* blk = numTrackedCaches ? head : nullptr;
    unsigned curr_size = 0;
    unsigned tracked_cache_size = minTrackedSize;
    CachesMask in_caches_mask = inAllCachesMask;
    int j = 0;

    while (blk) {
        blk->inCachesMask = in_caches_mask;

        curr_size += blkSize;
        if (curr_size == tracked_cache_size && blk != tail) {
            boundaries[j] = blk;

            tracked_cache_size <<= 1;
            // from this point, blocks fit only in the larger caches
            in_caches_mask &= ~(1U << j);
            ++j;
        }
        blk = blk->next;
    }
}

void
FALRU::CacheTracking::moveBlockToHead(FALRUBlk *blk)
{
    // Get the mask of all caches, in which the block didn't fit
    // before moving it to the head
    CachesMask update_caches_mask = inAllCachesMask ^ blk->inCachesMask;

    for (int i = 0; i < numTrackedCaches; i++) {
        CachesMask current_cache_mask = 1U << i;
        if (current_cache_mask & update_caches_mask) {
            // if the ith cache didn't fit the block (before it is moved to
            // the head), move the ith boundary 1 block closer to the
            // MRU
            boundaries[i]->inCachesMask &= ~current_cache_mask;
            boundaries[i] = boundaries[i]->prev;
        } else if (boundaries[i] == blk) {
            // Make sure the boundary doesn't point to the block
            // we are about to move
            boundaries[i] = blk->prev;
        }
    }

    // Make block reside in all caches
    blk->inCachesMask = inAllCachesMask;
}

void
FALRU::CacheTracking::moveBlockToTail(FALRUBlk *blk)
{
    CachesMask update_caches_mask = blk->inCachesMask;

    for (int i = 0; i < numTrackedCaches; i++) {
        CachesMask current_cache_mask = 1U << i;
        if (current_cache_mask & update_caches_mask) {
            // if the ith cache fitted the block (before it is moved to
            // the tail), move the ith boundary 1 block closer to the
            // LRU
            boundaries[i] = boundaries[i]->next;
            if (boundaries[i] == blk) {
                // Make sure the boundary doesn't point to the block
                // we are about to move
                boundaries[i] = blk->next;
            }
            boundaries[i]->inCachesMask |= current_cache_mask;
        }
    }

    // The block now fits only in the actual cache
    blk->inCachesMask = 0;
}

void
FALRU::CacheTracking::recordAccess(FALRUBlk *blk)
{
    for (int i = 0; i < numTrackedCaches; i++) {
        if (blk && ((1U << i) & blk->inCachesMask)) {
            hits[i]++;
        } else {
            misses[i]++;
        }
    }

    // Record stats for the actual cache too
    if (blk) {
        hits[numTrackedCaches]++;
    } else {
        misses[numTrackedCaches]++;
    }

    accesses++;
}

void
printSize(std::ostream &stream, size_t size)
{
    static const char *SIZES[] = { "B", "kB", "MB", "GB", "TB", "ZB" };
    int div = 0;
    while (size >= 1024 && div < (sizeof SIZES / sizeof *SIZES)) {
        div++;
        size >>= 10;
    }
    stream << size << SIZES[div];
}

void
FALRU::CacheTracking::regStats(std::string name)
{
    hits
        .init(numTrackedCaches + 1)
        .name(name + ".falru_hits")
        .desc("The number of hits in each cache size.")
        ;
    misses
        .init(numTrackedCaches + 1)
        .name(name + ".falru_misses")
        .desc("The number of misses in each cache size.")
        ;
    accesses
        .name(name + ".falru_accesses")
        .desc("The number of accesses to the FA LRU cache.")
        ;

    for (unsigned i = 0; i < numTrackedCaches + 1; ++i) {
        std::stringstream size_str;
        printSize(size_str, minTrackedSize << i);
        hits.subname(i, size_str.str());
        hits.subdesc(i, "Hits in a " + size_str.str() + " cache");
        misses.subname(i, size_str.str());
        misses.subdesc(i, "Misses in a " + size_str.str() + " cache");
    }
}
<commit_msg>mem-cache: Use findBlock in FALRU's block access<commit_after>/*
 * Copyright (c) 2013,2016-2018 ARM Limited
 * All rights reserved.
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Copyright (c) 2003-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Erik Hallnor
 *          Nikos Nikoleris
 */

/**
 * @file
 * Definitions a fully associative LRU tagstore.
 */

#include "mem/cache/tags/fa_lru.hh"

#include <cassert>
#include <sstream>

#include "base/intmath.hh"
#include "base/logging.hh"

FALRU::FALRU(const Params *p)
    : BaseTags(p),

      cacheTracking(p->min_tracked_cache_size, size, blkSize)
{
    if (!isPowerOf2(blkSize))
        fatal("cache block size (in bytes) `%d' must be a power of two",
              blkSize);
    if (!isPowerOf2(size))
        fatal("Cache Size must be power of 2 for now");

    blks = new FALRUBlk[numBlocks];

    head = &(blks[0]);
    head->prev = nullptr;
    head->next = &(blks[1]);
    head->set = 0;
    head->way = 0;
    head->data = &dataBlks[0];

    for (unsigned i = 1; i < numBlocks - 1; i++) {
        blks[i].prev = &(blks[i-1]);
        blks[i].next = &(blks[i+1]);
        blks[i].set = 0;
        blks[i].way = i;

        // Associate a data chunk to the block
        blks[i].data = &dataBlks[blkSize*i];
    }

    tail = &(blks[numBlocks - 1]);
    tail->prev = &(blks[numBlocks - 2]);
    tail->next = nullptr;
    tail->set = 0;
    tail->way = numBlocks - 1;
    tail->data = &dataBlks[(numBlocks - 1) * blkSize];

    cacheTracking.init(head, tail);
}

FALRU::~FALRU()
{
    delete[] blks;
}

void
FALRU::regStats()
{
    BaseTags::regStats();
    cacheTracking.regStats(name());
}

FALRUBlk *
FALRU::hashLookup(Addr addr) const
{
    tagIterator iter = tagHash.find(addr);
    if (iter != tagHash.end()) {
        return (*iter).second;
    }
    return nullptr;
}

void
FALRU::invalidate(CacheBlk *blk)
{
    BaseTags::invalidate(blk);

    // Move the block to the tail to make it the next victim
    moveToTail((FALRUBlk*)blk);

    // Erase block entry in the hash table
    tagHash.erase(blk->tag);
}

CacheBlk*
FALRU::accessBlock(Addr addr, bool is_secure, Cycles &lat)
{
    return accessBlock(addr, is_secure, lat, 0);
}

CacheBlk*
FALRU::accessBlock(Addr addr, bool is_secure, Cycles &lat,
                   CachesMask *in_caches_mask)
{
    CachesMask mask = 0;
    FALRUBlk* blk = static_cast<FALRUBlk*>(findBlock(addr, is_secure));

    if (blk != nullptr) {
        // If a cache hit
        lat = accessLatency;
        // Check if the block to be accessed is available. If not,
        // apply the accessLatency on top of block->whenReady.
        if (blk->whenReady > curTick() &&
            cache->ticksToCycles(blk->whenReady - curTick()) >
            accessLatency) {
            lat = cache->ticksToCycles(blk->whenReady - curTick()) +
            accessLatency;
        }
        mask = blk->inCachesMask;

        moveToHead(blk);
    } else {
        // If a cache miss
        lat = lookupLatency;
    }
    if (in_caches_mask) {
        *in_caches_mask = mask;
    }

    cacheTracking.recordAccess(blk);

    return blk;
}

CacheBlk*
FALRU::findBlock(Addr addr, bool is_secure) const
{
    Addr tag = extractTag(addr);
    FALRUBlk* blk = hashLookup(tag);

    if (blk && blk->isValid()) {
        assert(blk->tag == tag);
        assert(blk->isSecure() == is_secure);
    } else {
        blk = nullptr;
    }
    return blk;
}

CacheBlk*
FALRU::findBlockBySetAndWay(int set, int way) const
{
    assert(set == 0);
    return &blks[way];
}

CacheBlk*
FALRU::findVictim(Addr addr)
{
    return tail;
}

void
FALRU::insertBlock(PacketPtr pkt, CacheBlk *blk)
{
    FALRUBlk* falruBlk = static_cast<FALRUBlk*>(blk);

    // Make sure block is not present in the cache
    assert(falruBlk->inCachesMask == 0);

    // Do common block insertion functionality
    BaseTags::insertBlock(pkt, blk);

    // New block is the MRU
    moveToHead(falruBlk);

    // Insert new block in the hash table
    tagHash[falruBlk->tag] = falruBlk;
}

void
FALRU::moveToHead(FALRUBlk *blk)
{
    // If block is not already head, do the moving
    if (blk != head) {
        cacheTracking.moveBlockToHead(blk);
        // If block is tail, set previous block as new tail
        if (blk == tail){
            assert(blk->next == nullptr);
            tail = blk->prev;
            tail->next = nullptr;
        // Inform block's surrounding blocks that it has been moved
        } else {
            blk->prev->next = blk->next;
            blk->next->prev = blk->prev;
        }

        // Swap pointers
        blk->next = head;
        blk->prev = nullptr;
        head->prev = blk;
        head = blk;

        cacheTracking.check(head, tail);
    }
}

void
FALRU::moveToTail(FALRUBlk *blk)
{
    // If block is not already tail, do the moving
    if (blk != tail) {
        cacheTracking.moveBlockToTail(blk);
        // If block is head, set next block as new head
        if (blk == head){
            assert(blk->prev == nullptr);
            head = blk->next;
            head->prev = nullptr;
        // Inform block's surrounding blocks that it has been moved
        } else {
            blk->prev->next = blk->next;
            blk->next->prev = blk->prev;
        }

        // Swap pointers
        blk->prev = tail;
        blk->next = nullptr;
        tail->next = blk;
        tail = blk;

        cacheTracking.check(head, tail);
    }
}

FALRU *
FALRUParams::create()
{
    return new FALRU(this);
}

void
FALRU::CacheTracking::check(FALRUBlk *head, FALRUBlk *tail)
{
#ifdef FALRU_DEBUG
    FALRUBlk* blk = head;
    unsigned curr_size = 0;
    unsigned tracked_cache_size = minTrackedSize;
    CachesMask in_caches_mask = inAllCachesMask;
    int j = 0;

    while (blk) {
        panic_if(blk->inCachesMask != in_caches_mask, "Expected cache mask "
                 "%x found %x", blk->inCachesMask, in_caches_mask);

        curr_size += blkSize;
        if (curr_size == tracked_cache_size && blk != tail) {
            panic_if(boundaries[j] != blk, "Unexpected boundary for the %d-th "
                     "cache", j);
            tracked_cache_size <<= 1;
            // from this point, blocks fit only in the larger caches
            in_caches_mask &= ~(1U << j);
            ++j;
        }
        blk = blk->next;
    }
#endif // FALRU_DEBUG
}

void
FALRU::CacheTracking::init(FALRUBlk *head, FALRUBlk *tail)
{
    // early exit if we are not tracking any extra caches
    FALRUBlk* blk = numTrackedCaches ? head : nullptr;
    unsigned curr_size = 0;
    unsigned tracked_cache_size = minTrackedSize;
    CachesMask in_caches_mask = inAllCachesMask;
    int j = 0;

    while (blk) {
        blk->inCachesMask = in_caches_mask;

        curr_size += blkSize;
        if (curr_size == tracked_cache_size && blk != tail) {
            boundaries[j] = blk;

            tracked_cache_size <<= 1;
            // from this point, blocks fit only in the larger caches
            in_caches_mask &= ~(1U << j);
            ++j;
        }
        blk = blk->next;
    }
}

void
FALRU::CacheTracking::moveBlockToHead(FALRUBlk *blk)
{
    // Get the mask of all caches, in which the block didn't fit
    // before moving it to the head
    CachesMask update_caches_mask = inAllCachesMask ^ blk->inCachesMask;

    for (int i = 0; i < numTrackedCaches; i++) {
        CachesMask current_cache_mask = 1U << i;
        if (current_cache_mask & update_caches_mask) {
            // if the ith cache didn't fit the block (before it is moved to
            // the head), move the ith boundary 1 block closer to the
            // MRU
            boundaries[i]->inCachesMask &= ~current_cache_mask;
            boundaries[i] = boundaries[i]->prev;
        } else if (boundaries[i] == blk) {
            // Make sure the boundary doesn't point to the block
            // we are about to move
            boundaries[i] = blk->prev;
        }
    }

    // Make block reside in all caches
    blk->inCachesMask = inAllCachesMask;
}

void
FALRU::CacheTracking::moveBlockToTail(FALRUBlk *blk)
{
    CachesMask update_caches_mask = blk->inCachesMask;

    for (int i = 0; i < numTrackedCaches; i++) {
        CachesMask current_cache_mask = 1U << i;
        if (current_cache_mask & update_caches_mask) {
            // if the ith cache fitted the block (before it is moved to
            // the tail), move the ith boundary 1 block closer to the
            // LRU
            boundaries[i] = boundaries[i]->next;
            if (boundaries[i] == blk) {
                // Make sure the boundary doesn't point to the block
                // we are about to move
                boundaries[i] = blk->next;
            }
            boundaries[i]->inCachesMask |= current_cache_mask;
        }
    }

    // The block now fits only in the actual cache
    blk->inCachesMask = 0;
}

void
FALRU::CacheTracking::recordAccess(FALRUBlk *blk)
{
    for (int i = 0; i < numTrackedCaches; i++) {
        if (blk && ((1U << i) & blk->inCachesMask)) {
            hits[i]++;
        } else {
            misses[i]++;
        }
    }

    // Record stats for the actual cache too
    if (blk) {
        hits[numTrackedCaches]++;
    } else {
        misses[numTrackedCaches]++;
    }

    accesses++;
}

void
printSize(std::ostream &stream, size_t size)
{
    static const char *SIZES[] = { "B", "kB", "MB", "GB", "TB", "ZB" };
    int div = 0;
    while (size >= 1024 && div < (sizeof SIZES / sizeof *SIZES)) {
        div++;
        size >>= 10;
    }
    stream << size << SIZES[div];
}

void
FALRU::CacheTracking::regStats(std::string name)
{
    hits
        .init(numTrackedCaches + 1)
        .name(name + ".falru_hits")
        .desc("The number of hits in each cache size.")
        ;
    misses
        .init(numTrackedCaches + 1)
        .name(name + ".falru_misses")
        .desc("The number of misses in each cache size.")
        ;
    accesses
        .name(name + ".falru_accesses")
        .desc("The number of accesses to the FA LRU cache.")
        ;

    for (unsigned i = 0; i < numTrackedCaches + 1; ++i) {
        std::stringstream size_str;
        printSize(size_str, minTrackedSize << i);
        hits.subname(i, size_str.str());
        hits.subdesc(i, "Hits in a " + size_str.str() + " cache");
        misses.subname(i, size_str.str());
        misses.subdesc(i, "Misses in a " + size_str.str() + " cache");
    }
}
<|endoftext|>


<commit_before>#include <cppunit/BriefTestProgressListener.h>
#include <cppunit/CompilerOutputter.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/TestResult.h>
#include <cppunit/TestResultCollector.h>
#include <cppunit/TestRunner.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cdbjDALC.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <logging.h>
#include <loggingGenericLogger.h>
#include <ACSAlarmSystemInterfaceFactory.h>
#include <acsutilPorts.h>
#include <stdlib.h>
#include <MockManager.h>

#define XML_HEADER_LENGTH 4
#define XML_HEADER_LINE_ONE "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
#define XML_HEADER_LINE_TWO "<alarm-system-configuration xmlns=\"urn:schemas-cosylab-com:AcsAlarmSystem:1.0\" \n\t\t"
#define XML_HEADER_LINE_THREE "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"> \n"
#define XML_HEADER_LINE_FOUR "\t<configuration-property name=\"Implementation\">"
#define XML_TAIL "</configuration-property>\n</alarm-system-configuration>\n"

using namespace std;
using acsalarm::AlarmSystemInterface;

/**
 * NOTE: this tests the following scenarios:
 *
 * 1) NO "Alarms" branch present in the CDB - in this case, the "ACS" style alarms (i.e. to the logging system) should be used
 * 2) "ACS" as the implementation specified in the CDB/Alarms/AlarmSystemConfiguration/AlarmSystemConfiguration.xml file
 *    in this case, the ACS style alarms (i.e. to the logging system) should be used.
 * 3) An erroneous value (neither ACS nor CERN) in the CDB/Alarms/AlarmSystemConfiguration/AlarmSystemConfiguration.xml file;
 *    in this case, also, ACS style alarms (i.e. to the logging system) should be sent.
 *
 * NOTE ALSO: this test does not actually send alarms; it only checks which style alarms would be sent in different scenarios.
 *
 * FINAL NOTE: this test does not test CERN style alarms because this requires initializing the ACSAlarmSystemFactory with a non-NULL
 * manager reference, which we cannot do at this point in the build. This scenario is tested in the ACSLaser/laser-source-cpp/test
 * module.
 */
class FactoryTestCase : public CPPUNIT_NS::TestFixture
{
	CPPUNIT_TEST_SUITE(FactoryTestCase);
	CPPUNIT_TEST(testNoAlarmBranch);
	CPPUNIT_TEST(testACSAlarmSystem);
	CPPUNIT_TEST(testWrongImplementationProp);
	CPPUNIT_TEST(testCERNAlarmSystem);
	CPPUNIT_TEST(testFaultStateCreation);
	CPPUNIT_TEST(testAlarmSourceCreation);
	CPPUNIT_TEST_SUITE_END();

	public:
		FactoryTestCase();
		~FactoryTestCase();
		void setUp();
		void tearDown();

	protected:
		void testNoAlarmBranch();
		void testCERNAlarmSystem();
		void testACSAlarmSystem();
		void testWrongImplementationProp();
		void testFaultStateCreation();
		void testAlarmSourceCreation();

	private:
		char cwd[1024];
		maci::MockManager * myMockMgr;
		void configureAlarmBranch(string cdbdir, string alarmSystemImplementation);
		void replaceAlarmBranch(string cdbdir);
		void renameAlarmBranch(string cdbdir);
		void clearCdbCache();
};

FactoryTestCase::FactoryTestCase()
{
	ACS_TRACE("FactoryTestCase::FactoryTestCase entering");

	if (getcwd(cwd,sizeof(cwd)) == (char *) NULL) {
		ACS_SHORT_LOG((LM_ERROR, "FactoryTestCase::FactoryTestCase() - Failed to get current working dir"));
	}
	myMockMgr = new maci::MockManager();

	ACS_TRACE("FactoryTestCase::FactoryTestCase exiting");
}

FactoryTestCase::~FactoryTestCase()
{
	delete myMockMgr;
}

void FactoryTestCase::setUp()
{
}

void FactoryTestCase::tearDown()
{
	configureAlarmBranch(cwd,"CERN");
	ACSAlarmSystemInterfaceFactory::done();
}

void FactoryTestCase::clearCdbCache()
{
	system("cdbjDALClearCache");
}

/**
 * Check if the CERN implementation of the AS is choosen when
 * there CERN is in the CDB
 *
 * @throws Exception
 */
void FactoryTestCase::testCERNAlarmSystem()
{
	configureAlarmBranch(cwd,"CERN");
	clearCdbCache();
	ACSAlarmSystemInterfaceFactory::init(myMockMgr);
	CPPUNIT_ASSERT_MESSAGE("Wrong implementation in use (CERN case)", !ACSAlarmSystemInterfaceFactory::usingACSAlarmSystem());
}

/**
 * Check if the ACS implementation of the AS is choosen when
 * there is no Alarm branch in the CDB
 *
 * @throws Exception
 */
void FactoryTestCase::testNoAlarmBranch() {
	renameAlarmBranch(cwd);
	clearCdbCache();
	ACSAlarmSystemInterfaceFactory::init(myMockMgr);
	replaceAlarmBranch(cwd);
	CPPUNIT_ASSERT_MESSAGE("Wrong implementation in use (no Alarms in CDB case)", ACSAlarmSystemInterfaceFactory::usingACSAlarmSystem());
}

/**
 * Check if the ACS implementation of the AS is choosen when
 * there ACS is in the CDB
 *
 * @throws Exception
 */
void FactoryTestCase::testACSAlarmSystem() {
	configureAlarmBranch(cwd, "ACS");
	clearCdbCache();
	ACSAlarmSystemInterfaceFactory::init(myMockMgr);
	CPPUNIT_ASSERT_MESSAGE("Wrong implementation in use (ACS case)", ACSAlarmSystemInterfaceFactory::usingACSAlarmSystem());
}

/**
 * Check if the ACS implementation is used when the Implementation property is wrong
 * @throws Exception
 */
void FactoryTestCase::testWrongImplementationProp() {
	configureAlarmBranch(cwd, "Wrong property");
	clearCdbCache();
	ACSAlarmSystemInterfaceFactory::init(myMockMgr);
	CPPUNIT_ASSERT_MESSAGE("Wrong implementation in use (wrong prop case)", ACSAlarmSystemInterfaceFactory::usingACSAlarmSystem());
}

/**
 * Test the creation of a FaultState
 *
 * @throws Exception
 */
void FactoryTestCase::testFaultStateCreation()
{
	configureAlarmBranch(cwd, "ACS");
	clearCdbCache();
	ACSAlarmSystemInterfaceFactory::init(myMockMgr);
	auto_ptr<acsalarm::FaultState> fltstate = ACSAlarmSystemInterfaceFactory::createFaultState("Family", "Member", 0);
	CPPUNIT_ASSERT_MESSAGE("Error creating a FS", (fltstate.get() != NULL));
}

/**
 * Test the creation of a source (proxy)
 *
 * @throws Exception
 */
void FactoryTestCase::testAlarmSourceCreation()
{
	configureAlarmBranch(cwd, "ACS");
	clearCdbCache();
	ACSAlarmSystemInterfaceFactory::init(myMockMgr);
	auto_ptr<AlarmSystemInterface> alarmSource = ACSAlarmSystemInterfaceFactory::createSource();
	CPPUNIT_ASSERT_MESSAGE("Error creating an alarm source", (alarmSource.get() != NULL));
}

/**
 * Remove the Alarm branch from the CDB
 *
 * @param CDBFolder The directory of the CDB
 */
void FactoryTestCase::renameAlarmBranch(string CDBFolder)
{
	string CDBdir = CDBFolder + "/CDB/Alarms";
	string CDBbackupdir = CDBFolder + "/CDB/Alarms.bak";

	int result = std::rename(CDBdir.c_str(), CDBbackupdir.c_str());
	if (result != 0 ) {
		ACS_SHORT_LOG((LM_ERROR,"Error renaming CDB/Alarms directory"));
	}
}

/**
 * Replace the Alarm branch from the CDB
 *
 * @param CDBFolder The directory of the CDB
 */
void FactoryTestCase::replaceAlarmBranch(string CDBFolder)
{
	string CDBdir = CDBFolder + "/CDB/Alarms";
	string CDBbackupdir = CDBFolder + "/CDB/Alarms.bak";

	int result = std::rename(CDBbackupdir.c_str(), CDBdir.c_str());
	if (result != 0 ) {
		ACS_SHORT_LOG((LM_ERROR,"Error renaming CDB/Alarms.bak directory"));
	}
}

/**
 * Rewrite the Alarm branch of the CDB.
 *
 * @param CDBFolder The directory of the CDB
 * @param ASImplementation The value of the implementation property of the CDB
 */
void FactoryTestCase::configureAlarmBranch(string CDBFolder, string ASImplementation)
{
	string CDBdir = CDBFolder + "/CDB/Alarms";
	string configDirName = CDBdir + "/AlarmSystemConfiguration";
	string configFileName = configDirName + "/AlarmSystemConfiguration.xml";
	try
	{
		filebuf buffer;
		ostream output(&buffer);
		buffer.open(configFileName.c_str(), ios::out);
		output << XML_HEADER_LINE_ONE;
		output << XML_HEADER_LINE_TWO;
		output << XML_HEADER_LINE_THREE;
		output << XML_HEADER_LINE_FOUR;
		output << ASImplementation;
		output << XML_TAIL;
	}
	catch (...)
	{
		ACS_SHORT_LOG((LM_ERROR, "Error setting up the Alarm branch of the CDB:"));
	}
}

CPPUNIT_TEST_SUITE_REGISTRATION(FactoryTestCase);

int main(int argc, char *argv[])
{
	Logging::Logger::setGlobalLogger(new Logging::GenericLogger("testLogger"));

	// initialize the AlarmSystemInterfaceFactory
	//ACSAlarmSystemInterfaceFactory::init(NULL);

	// Create the event manager and test controller
	CPPUNIT_NS::TestResult controller;

	// Add a listener that colllects test result
	CPPUNIT_NS::TestResultCollector result;
	controller.addListener( &result );

	// Add a listener that print dots as test run.
	CPPUNIT_NS::BriefTestProgressListener progress;
	controller.addListener( &progress );

	// Add the top suite to the test runner
	CPPUNIT_NS::TestRunner runner;
	runner.addTest( CPPUNIT_NS::TestFactoryRegistry::getRegistry().makeTest() );
	runner.run( controller );

	// Print test in a compiler compatible format.
	CPPUNIT_NS::CompilerOutputter outputter( &result, std::cerr );
	outputter.write();

	// close the AlarmSystemInterfaceFactory
	//ACSAlarmSystemInterfaceFactory::done();

	return result.wasSuccessful() ? 0 : 1;
}

<commit_msg><commit_after>#include <cppunit/BriefTestProgressListener.h>
#include <cppunit/CompilerOutputter.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/TestResult.h>
#include <cppunit/TestResultCollector.h>
#include <cppunit/TestRunner.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cdbjDALC.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <logging.h>
#include <loggingGenericLogger.h>
#include <ACSAlarmSystemInterfaceFactory.h>
#include <acsutilPorts.h>
#include <stdlib.h>
#include <MockManager.h>

#define XML_HEADER_LENGTH 4
#define XML_HEADER_LINE_ONE "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
#define XML_HEADER_LINE_TWO "<alarm-system-configuration xmlns=\"urn:schemas-cosylab-com:AcsAlarmSystem:1.0\" \n\t\t"
#define XML_HEADER_LINE_THREE "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"> \n"
#define XML_HEADER_LINE_FOUR "\t<configuration-property name=\"Implementation\">"
#define XML_TAIL "</configuration-property>\n</alarm-system-configuration>\n"

using namespace std;
using acsalarm::AlarmSystemInterface;

/**
 * NOTE: this tests the following scenarios:
 *
 * 1) NO "Alarms" branch present in the CDB - in this case, the "ACS" style alarms (i.e. to the logging system) should be used
 * 2) "ACS" as the implementation specified in the CDB/Alarms/AlarmSystemConfiguration/AlarmSystemConfiguration.xml file
 *    in this case, the ACS style alarms (i.e. to the logging system) should be used.
 * 3) An erroneous value (neither ACS nor CERN) in the CDB/Alarms/AlarmSystemConfiguration/AlarmSystemConfiguration.xml file;
 *    in this case, also, ACS style alarms (i.e. to the logging system) should be sent.
 *
 * NOTE ALSO: this test does not actually send alarms; it only checks which style alarms would be sent in different scenarios.
 *
 * FINAL NOTE: this test does not test CERN style alarms because this requires initializing the ACSAlarmSystemFactory with a non-NULL
 * manager reference, which we cannot do at this point in the build. This scenario is tested in the ACSLaser/laser-source-cpp/test
 * module.
 */
class FactoryTestCase : public CPPUNIT_NS::TestFixture
{
	CPPUNIT_TEST_SUITE(FactoryTestCase);
	CPPUNIT_TEST(testNoAlarmBranch);
	CPPUNIT_TEST(testACSAlarmSystem);
	CPPUNIT_TEST(testWrongImplementationProp);
	CPPUNIT_TEST(testCERNAlarmSystem);
	CPPUNIT_TEST(testFaultStateCreation);
	CPPUNIT_TEST(testAlarmSourceCreation);
	CPPUNIT_TEST_SUITE_END();

	public:
		FactoryTestCase();
		~FactoryTestCase();
		void setUp();
		void tearDown();

	protected:
		void testNoAlarmBranch();
		void testCERNAlarmSystem();
		void testACSAlarmSystem();
		void testWrongImplementationProp();
		void testFaultStateCreation();
		void testAlarmSourceCreation();

	private:
		char cwd[1024];
		maci::MockManager * myMockMgr;
		void configureAlarmBranch(string cdbdir, string alarmSystemImplementation);
		void replaceAlarmBranch(string cdbdir);
		void renameAlarmBranch(string cdbdir);
		void clearCdbCache();
};

FactoryTestCase::FactoryTestCase()
{
	ACS_TRACE("FactoryTestCase::FactoryTestCase entering");

	if (getcwd(cwd,sizeof(cwd)) == (char *) NULL) {
		ACS_SHORT_LOG((LM_ERROR, "FactoryTestCase::FactoryTestCase() - Failed to get current working dir"));
	}
	myMockMgr = new maci::MockManager();

	ACS_TRACE("FactoryTestCase::FactoryTestCase exiting");
}

FactoryTestCase::~FactoryTestCase()
{
	delete myMockMgr;
}

void FactoryTestCase::setUp()
{
}

void FactoryTestCase::tearDown()
{
	configureAlarmBranch(cwd,"CERN");
	ACSAlarmSystemInterfaceFactory::done();
}

void FactoryTestCase::clearCdbCache()
{
	system("cdbjDALClearCache");
}

/**
 * Check if the CERN implementation of the AS is choosen when
 * there CERN is in the CDB
 *
 * @throws Exception
 */
void FactoryTestCase::testCERNAlarmSystem()
{
	configureAlarmBranch(cwd,"CERN");
	clearCdbCache();
	ACSAlarmSystemInterfaceFactory::init(myMockMgr);
	CPPUNIT_ASSERT_MESSAGE("Wrong implementation in use (CERN case)", !ACSAlarmSystemInterfaceFactory::usingACSAlarmSystem());
}

/**
 * Check if the ACS implementation of the AS is choosen when
 * there is no Alarm branch in the CDB
 *
 * @throws Exception
 */
void FactoryTestCase::testNoAlarmBranch() {
	renameAlarmBranch(cwd);
	clearCdbCache();
	ACSAlarmSystemInterfaceFactory::init(myMockMgr);
	replaceAlarmBranch(cwd);
	CPPUNIT_ASSERT_MESSAGE("Wrong implementation in use (no Alarms in CDB case)", ACSAlarmSystemInterfaceFactory::usingACSAlarmSystem());
}

/**
 * Check if the ACS implementation of the AS is choosen when
 * there ACS is in the CDB
 *
 * @throws Exception
 */
void FactoryTestCase::testACSAlarmSystem() {
	configureAlarmBranch(cwd, "ACS");
	clearCdbCache();
	ACSAlarmSystemInterfaceFactory::init(myMockMgr);
	CPPUNIT_ASSERT_MESSAGE("Wrong implementation in use (ACS case)", ACSAlarmSystemInterfaceFactory::usingACSAlarmSystem());
}

/**
 * Check if the ACS implementation is used when the Implementation property is wrong
 * @throws Exception
 */
void FactoryTestCase::testWrongImplementationProp() {
	configureAlarmBranch(cwd, "Wrong property");
	clearCdbCache();
	ACSAlarmSystemInterfaceFactory::init(myMockMgr);
	CPPUNIT_ASSERT_MESSAGE("Wrong implementation in use (wrong prop case)", ACSAlarmSystemInterfaceFactory::usingACSAlarmSystem());
}

/**
 * Test the creation of a FaultState
 *
 * @throws Exception
 */
void FactoryTestCase::testFaultStateCreation()
{
	configureAlarmBranch(cwd, "ACS");
	clearCdbCache();
	ACSAlarmSystemInterfaceFactory::init(myMockMgr);
	auto_ptr<acsalarm::FaultState> fltstate = ACSAlarmSystemInterfaceFactory::createFaultState("Family", "Member", 0);
	CPPUNIT_ASSERT_MESSAGE("Error creating a FS", (fltstate.get() != NULL));
}

/**
 * Test the creation of a source (proxy)
 *
 * @throws Exception
 */
void FactoryTestCase::testAlarmSourceCreation()
{
	configureAlarmBranch(cwd, "ACS");
	clearCdbCache();
	ACSAlarmSystemInterfaceFactory::init(myMockMgr);
	auto_ptr<AlarmSystemInterface> alarmSource = ACSAlarmSystemInterfaceFactory::createSource();
	CPPUNIT_ASSERT_MESSAGE("Error creating an alarm source", (alarmSource.get() != NULL));
}

/**
 * Remove the Alarm branch from the CDB
 *
 * @param CDBFolder The directory of the CDB
 */
void FactoryTestCase::renameAlarmBranch(string CDBFolder)
{
	string CDBdir = CDBFolder + "/CDB/Alarms";
	string CDBbackupdir = CDBFolder + "/CDB/Alarms.bak";

	int result = std::rename(CDBdir.c_str(), CDBbackupdir.c_str());
	if (result != 0 ) {
		ACS_SHORT_LOG((LM_ERROR,"Error renaming CDB/Alarms directory"));
	}
}

/**
 * Replace the Alarm branch from the CDB
 *
 * @param CDBFolder The directory of the CDB
 */
void FactoryTestCase::replaceAlarmBranch(string CDBFolder)
{
	string CDBdir = CDBFolder + "/CDB/Alarms";
	string CDBbackupdir = CDBFolder + "/CDB/Alarms.bak";

	int result = std::rename(CDBbackupdir.c_str(), CDBdir.c_str());
	if (result != 0 ) {
		ACS_SHORT_LOG((LM_ERROR,"Error renaming CDB/Alarms.bak directory"));
	}
}

/**
 * Rewrite the Alarm branch of the CDB.
 *
 * @param CDBFolder The directory of the CDB
 * @param ASImplementation The value of the implementation property of the CDB
 */
void FactoryTestCase::configureAlarmBranch(string CDBFolder, string ASImplementation)
{
	string CDBdir = CDBFolder + "/CDB/Alarms";
	string configDirName = CDBdir + "/AlarmSystemConfiguration";
	string configFileName = configDirName + "/AlarmSystemConfiguration.xml";
	try
	{
		filebuf buffer;
		ostream output(&buffer);
		buffer.open(configFileName.c_str(), ios::out);
		output << XML_HEADER_LINE_ONE;
		output << XML_HEADER_LINE_TWO;
		output << XML_HEADER_LINE_THREE;
		output << XML_HEADER_LINE_FOUR;
		output << ASImplementation;
		output << XML_TAIL;
	}
	catch (...)
	{
		ACS_SHORT_LOG((LM_ERROR, "Error setting up the Alarm branch of the CDB:"));
	}
}

CPPUNIT_TEST_SUITE_REGISTRATION(FactoryTestCase);

int main(int argc, char *argv[])
{
	Logging::Logger::setGlobalLogger(new Logging::GenericLogger("testLogger"));

	// Create the event manager and test controller
	CPPUNIT_NS::TestResult controller;

	// Add a listener that colllects test result
	CPPUNIT_NS::TestResultCollector result;
	controller.addListener( &result );

	// Add a listener that print dots as test run.
	CPPUNIT_NS::BriefTestProgressListener progress;
	controller.addListener( &progress );

	// Add the top suite to the test runner
	CPPUNIT_NS::TestRunner runner;
	runner.addTest( CPPUNIT_NS::TestFactoryRegistry::getRegistry().makeTest() );
	runner.run( controller );

	// Print test in a compiler compatible format.
	CPPUNIT_NS::CompilerOutputter outputter( &result, std::cerr );
	outputter.write();

	return result.wasSuccessful() ? 0 : 1;
}

<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2011.  All rights reserved
 */
#include	"../StroikaPreComp.h"

#include	<algorithm>

#if		qPlatform_Windows
	#include	<atlbase.h>		// For CComBSTR
#elif	qPlatform_POSIX
	#include <time.h>
#endif

#include	"../Characters/Format.h"
#include	"../Debug/Assertions.h"
#include	"../Execution/Exceptions.h"
#include	"../Memory/SmallStackBuffer.h"
#include	"../Linguistics/Words.h"
#include	"DateTime.h"

#include	"TimeOfDay.h"

using	namespace	Stroika;
using	namespace	Stroika::Foundation;
using	namespace	Stroika::Foundation::Characters;
using	namespace	Stroika::Foundation::Execution;
using	namespace	Stroika::Foundation::Memory;
using	namespace	Stroika::Foundation::Time;

using	Debug::TraceContextBumper;

using	namespace	Time;

#if		qPlatform_Windows
namespace	{
	wstring	GetLocaleInfo_ (LCID Locale, LCTYPE LCType)
		{
			int	sizeNeeded	=	::GetLocaleInfoW (Locale, LCType, nullptr, 0);
			SmallStackBuffer<wchar_t> buf (sizeNeeded + 1);
			Verify (::GetLocaleInfoW (Locale, LCType, buf, sizeNeeded + 1));
			return wstring (buf);
		}
}
#endif

#if		qPlatform_Windows
namespace	{
	TimeOfDay	mkTimeOfDay_ (const SYSTEMTIME& sysTime)
		{
			WORD	hour = max (sysTime.wHour, static_cast<WORD> (0));
			hour = min (hour, static_cast<WORD> (23));
			WORD	minute = max (sysTime.wMinute, static_cast<WORD> (0));
			minute = min (minute, static_cast<WORD> (59));
			WORD	secs = max (sysTime.wSecond, static_cast<WORD> (0));
			secs = min (secs, static_cast<WORD> (59));
			return TimeOfDay ((hour * 60 + minute) * 60 + secs);
		}
}
#endif

#if		qPlatform_Windows
namespace	{
	wstring	GenTimeStr4TOD_ (unsigned int hour, unsigned int minutes, unsigned int seconds)
		{
// Consider rewriting using Win32 GetTimeFormat () - and just futzing with teh format string for the case
// of zero minutes/seconds?? That might be more robust in case of changes in adding special tokens for some cultures/etc?
//
// Anyhow - I think what i have no works OK...
//		-- LGP 2009-06-18
			Require (hour < 24);
			Require (minutes < 60);
			Require (seconds < 60);

			/*
			 * From Windows Vista Regional Settings control panel:
			 *
			 *		h = hour, m = minute, s = second
			 *		tt = A.M. or P.M.
			 *
			 *		h = 12 hour
			 *		H = 24 hour
			 *
			 *		hh,mm,ss = display leading zero
			 *		h,m,s = do not display leading zero.
			 */

			// we could keep recomputing this, but why pay the runtime cost? Restart app to get new locale info
			#if		qPlatform_Windows
				static	const	wstring	kFormatStr	=	GetLocaleInfo_ (LOCALE_USER_DEFAULT, LOCALE_STIMEFORMAT);
			#else
			#endif

			// This is what I couldn't get the MSFT default locale display stuff todo
			// We want to show 3pm, not 3:00:00pm.
			bool	skipSeconds	=	seconds == 0;
			bool	skipMinutes	=	skipSeconds and minutes == 0 and kFormatStr.find (L"tt") != wstring::npos;	// only do if showing AM/PM, else show 1300 for time - not 13...

			wstring	outBuf;
			outBuf.reserve (kFormatStr.length () + 4);
			for (wstring::const_iterator i = kFormatStr.begin (); i != kFormatStr.end (); ++i) {
				switch (*i) {
					case 'h': {
						bool	leadingZero	=	false;
						if (i + 1 != kFormatStr.end () and *(i+1) == 'h') {
							++i;
							leadingZero = true;
						}
						unsigned int	useHour	=	hour;
						if (useHour > 12) {
							useHour -= 12;
						}
						outBuf += Format (leadingZero? L"%02d": L"%d", useHour);
					}
					break;
					case 'H': {
						bool	leadingZero	=	false;
						if (i + 1 != kFormatStr.end () and *(i+1) == 'H') {
							++i;
							leadingZero = true;
						}
						outBuf += Format (leadingZero? L"%02d": L"%d", hour);
					}
					break;
					case 'm': {
						bool	leadingZero	=	false;
						if (i + 1 != kFormatStr.end () and *(i+1) == 'm') {
							++i;
							leadingZero = true;
						}
						// This is what I couldn't get the MSFT default locale display stuff todo
						// We want to show 3pm, not 3:00:00pm.
						if (not skipMinutes) {
							outBuf += Format (leadingZero? L"%02d": L"%d", minutes);
						}
					}
					break;
					case 's': {
						bool	leadingZero	=	false;
						if (i + 1 != kFormatStr.end () and *(i+1) == 's') {
							++i;
							leadingZero = true;
						}
						if (not skipSeconds) {
							outBuf += Format (leadingZero? L"%02d": L"%d", seconds);
						}
					}
					break;
					case 't': {
						if (i + 1 != kFormatStr.end () and *(i+1) == 't') {
							/*
							 *	From the WinSDK docs...
							 *
							 *	LOCALE_S1159
							 *		String for the AM designator. The maximum number of characters allowed for this string is nine.
							 *	LOCALE_S2359
							 *		String for the PM designator. The maximum number of characters allowed for this string is nine.
							 */
							static	const	wstring	kAMSTR	=	GetLocaleInfo_ (LOCALE_USER_DEFAULT, LOCALE_S1159);
							static	const	wstring	kPMSTR	=	GetLocaleInfo_ (LOCALE_USER_DEFAULT, LOCALE_S2359);
							++i;
							int pmFlag =	hour>=12;
							//outBuf += (pmFlag?L"PM":L"AM");
							outBuf += (pmFlag?kPMSTR:kAMSTR);
						}
						else {
							outBuf.push_back (*i);
						}
					}
					break;
					case ':': {
						// Skip ':' separator if we are going to omit the following
						// stuff...
						if (i + 1 != kFormatStr.end () and *(i+1) == 's' and skipSeconds) {
							// SKIP
						}
						else if (i + 1 != kFormatStr.end () and *(i+1) == 'm' and skipMinutes) {
							// SKIP
						}
						else {
							outBuf.push_back (*i);
						}
					}
					break;
					default: {
						outBuf.push_back (*i);
					}
					break;
				}
			}
			return outBuf;
		}
}
#endif

/*
 ********************************************************************************
 *********************************** TimeOfDay **********************************
 ********************************************************************************
 */
const	TimeOfDay	TimeOfDay::kMin	=	TimeOfDay (0);
const	TimeOfDay	TimeOfDay::kMax	=	TimeOfDay (24 * 60 * 60 - 1);

TimeOfDay::TimeOfDay ()
  : fTime (-1)
{
}

TimeOfDay::TimeOfDay (uint32_t t)
  : fTime (t < 24 * 60 * 60? t: (24 * 60 * 60-1))
{
}

TimeOfDay	TimeOfDay::Parse (const wstring& rep, PrintFormat pf)
{
	if (rep.empty ()) {
		return TimeOfDay ();
	}
	switch (pf) {
		case	eCurrentLocale_PF:	{
			#if		qPlatform_Windows
				LCID lcid = LOCALE_USER_DEFAULT;
				DATE		d;
				(void)::memset (&d, 0, sizeof (d));
				try {
					ThrowIfErrorHRESULT (::VarDateFromStr (CComBSTR (rep.c_str ()), lcid, VAR_TIMEVALUEONLY, &d));
				}
				catch (...) {
					// Apparently military time (e.g. 1300 hours - where colon missing) - is rejected as mal-formed.
					// Detect that - and try to interpret it appropriately.
					wstring	newRep = rep;
					if (newRep.length () == 4 and
						iswdigit (newRep[0]) and iswdigit (newRep[1]) and iswdigit (newRep[2]) and iswdigit (newRep[3])
						) {
						newRep = newRep.substr (0, 2) + L":" + newRep.substr (2, 2);
						ThrowIfErrorHRESULT (::VarDateFromStr (CComBSTR (newRep.c_str ()), lcid, VAR_TIMEVALUEONLY, &d));
					}
					else {
						Execution::DoThrow (FormatException ());
					}
				}
				// SHOULD CHECK ERR RESULT (not sure if/when this can fail - so do a Verify for now)
				SYSTEMTIME	sysTime;
				memset (&sysTime, 0, sizeof (sysTime));
				Verify (::VariantTimeToSystemTime (d, &sysTime));
				return mkTimeOfDay_ (sysTime);
			#elif	qPlatform_POSIX
				AssertNotImplemented ();
				return TimeOfDay ();
			#else
				AssertNotImplemented ();
				return TimeOfDay ();
			#endif
		}
		case	eCurrentXML_PF: {
			int	hour	=	0;
			int	minute	=	0;
			int secs	=	0;
			#pragma	warning (push)
			#pragma	warning (4 : 4996)		// MSVC SILLY WARNING ABOUT USING swscanf_s
			if (::swscanf (rep.c_str (), L"%d:%d:d", &hour, &minute, &secs) >= 2) {
				hour = max (hour, 0);
				hour = min (hour, 23);
				minute = max (minute, 0);
				minute = min (minute, 59);
				secs = max (secs, 0);
				secs = min (secs, 59);
				return TimeOfDay ((hour * 60 + minute) * 60 + secs);
			}
			#pragma	warning (pop)
			return TimeOfDay ();
		}
		default: {
			AssertNotReached ();
			return TimeOfDay ();
		}
	}
}

#if		qPlatform_Windows
TimeOfDay	TimeOfDay::Parse (const wstring& rep, LCID lcid)
{
	if (rep.empty ()) {
		return TimeOfDay ();
	}
	DATE		d;
	(void)::memset (&d, 0, sizeof (d));
	try {
		ThrowIfErrorHRESULT (::VarDateFromStr (CComBSTR (rep.c_str ()), lcid, VAR_TIMEVALUEONLY, &d));
	}
	catch (...) {
		// Apparently military time (e.g. 1300 hours - where colon missing) - is rejected as mal-formed.
		// Detect that - and try to interpret it appropriately.
		wstring	newRep = rep;
		if (newRep.length () == 4 and
			iswdigit (newRep[0]) and iswdigit (newRep[1]) and iswdigit (newRep[2]) and iswdigit (newRep[3])
			) {
			newRep = newRep.substr (0, 2) + L":" + newRep.substr (2, 2);
			ThrowIfErrorHRESULT (::VarDateFromStr (CComBSTR (newRep.c_str ()), lcid, VAR_TIMEVALUEONLY, &d));
		}
		else {
			Execution::DoThrow (FormatException ());
		}
	}
	// SHOULD CHECK ERR RESULT (not sure if/when this can fail - so do a Verify for now)
	SYSTEMTIME	sysTime;
	memset (&sysTime, 0, sizeof (sysTime));
	Verify (::VariantTimeToSystemTime (d, &sysTime));
	return mkTimeOfDay_ (sysTime);
}
#endif

wstring	TimeOfDay::Format (PrintFormat pf) const
{
	if (empty ()) {
		return wstring ();
	}
	switch (pf) {
		case	eCurrentLocale_PF:	{
			#if		qPlatform_Windows
				return Format (LOCALE_USER_DEFAULT);
			#elif	qPlatform_POSIX
				AssertNotImplemented ();
				return wstring ();
			#else
				AssertNotImplemented ();
				return wstring ();
			#endif
		}
		case	eCurrentXML_PF: {
			uint32_t	hour = fTime/(60*60);
			uint32_t	minutes = (fTime - hour * 60 * 60) / 60;
			uint32_t	secs = fTime - hour * 60 * 60 - minutes * 60;
			Assert (hour >= 0 and hour < 24);
			Assert (minutes >= 0 and minutes < 60);
			Assert (secs >= 0 and secs < 60);
			return ::Format (L"%02d:%02d:%02d", hour, minutes, secs);
		}
		default: {
			AssertNotReached ();
			return wstring ();
		}
	}
}

void	TimeOfDay::ClearSecondsField ()
{
	int hour = fTime/(60*60);
	int minutes = (fTime - hour * 60 * 60) / 60;
	int secs = fTime - hour * 60 * 60 - minutes * 60;
	Assert (hour >= 0 and hour < 24);
	Assert (minutes >= 0 and minutes < 60);
	Assert (secs >= 0 and secs < 60);
	fTime -= secs;
}

#if		qPlatform_Windows
wstring	TimeOfDay::Format (LCID lcid) const
{
	if (empty ()) {
		return wstring ();
	}
	else {
		uint32_t hour = fTime/(60*60);
		uint32_t minutes = (fTime - hour * 60 * 60) / 60;
		uint32_t secs = fTime - hour * 60 * 60 - minutes * 60;
		Assert (hour >= 0 and hour < 24);
		Assert (minutes >= 0 and minutes < 60);
		Assert (secs >= 0 and secs < 60);
		return GenTimeStr4TOD_ (hour, minutes, secs);
	}
}
#endif

<commit_msg>Better code factoring in TimeOfDay (share parse code on windows side)<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2011.  All rights reserved
 */
#include	"../StroikaPreComp.h"

#include	<algorithm>

#if		qPlatform_Windows
	#include	<atlbase.h>		// For CComBSTR
#elif	qPlatform_POSIX
	#include <time.h>
#endif

#include	"../Characters/Format.h"
#include	"../Debug/Assertions.h"
#include	"../Execution/Exceptions.h"
#include	"../Memory/SmallStackBuffer.h"
#include	"../Linguistics/Words.h"
#include	"DateTime.h"

#include	"TimeOfDay.h"

using	namespace	Stroika;
using	namespace	Stroika::Foundation;
using	namespace	Stroika::Foundation::Characters;
using	namespace	Stroika::Foundation::Execution;
using	namespace	Stroika::Foundation::Memory;
using	namespace	Stroika::Foundation::Time;

using	Debug::TraceContextBumper;

using	namespace	Time;

#if		qPlatform_Windows
namespace	{
	wstring	GetLocaleInfo_ (LCID Locale, LCTYPE LCType)
		{
			int	sizeNeeded	=	::GetLocaleInfoW (Locale, LCType, nullptr, 0);
			SmallStackBuffer<wchar_t> buf (sizeNeeded + 1);
			Verify (::GetLocaleInfoW (Locale, LCType, buf, sizeNeeded + 1));
			return wstring (buf);
		}
}
#endif

#if		qPlatform_Windows
namespace	{
	TimeOfDay	mkTimeOfDay_ (const SYSTEMTIME& sysTime)
		{
			WORD	hour = max (sysTime.wHour, static_cast<WORD> (0));
			hour = min (hour, static_cast<WORD> (23));
			WORD	minute = max (sysTime.wMinute, static_cast<WORD> (0));
			minute = min (minute, static_cast<WORD> (59));
			WORD	secs = max (sysTime.wSecond, static_cast<WORD> (0));
			secs = min (secs, static_cast<WORD> (59));
			return TimeOfDay ((hour * 60 + minute) * 60 + secs);
		}
}
#endif

#if		qPlatform_Windows
namespace	{
	wstring	GenTimeStr4TOD_ (unsigned int hour, unsigned int minutes, unsigned int seconds)
		{
// Consider rewriting using Win32 GetTimeFormat () - and just futzing with teh format string for the case
// of zero minutes/seconds?? That might be more robust in case of changes in adding special tokens for some cultures/etc?
//
// Anyhow - I think what i have no works OK...
//		-- LGP 2009-06-18
			Require (hour < 24);
			Require (minutes < 60);
			Require (seconds < 60);

			/*
			 * From Windows Vista Regional Settings control panel:
			 *
			 *		h = hour, m = minute, s = second
			 *		tt = A.M. or P.M.
			 *
			 *		h = 12 hour
			 *		H = 24 hour
			 *
			 *		hh,mm,ss = display leading zero
			 *		h,m,s = do not display leading zero.
			 */

			// we could keep recomputing this, but why pay the runtime cost? Restart app to get new locale info
			#if		qPlatform_Windows
				static	const	wstring	kFormatStr	=	GetLocaleInfo_ (LOCALE_USER_DEFAULT, LOCALE_STIMEFORMAT);
			#else
			#endif

			// This is what I couldn't get the MSFT default locale display stuff todo
			// We want to show 3pm, not 3:00:00pm.
			bool	skipSeconds	=	seconds == 0;
			bool	skipMinutes	=	skipSeconds and minutes == 0 and kFormatStr.find (L"tt") != wstring::npos;	// only do if showing AM/PM, else show 1300 for time - not 13...

			wstring	outBuf;
			outBuf.reserve (kFormatStr.length () + 4);
			for (wstring::const_iterator i = kFormatStr.begin (); i != kFormatStr.end (); ++i) {
				switch (*i) {
					case 'h': {
						bool	leadingZero	=	false;
						if (i + 1 != kFormatStr.end () and *(i+1) == 'h') {
							++i;
							leadingZero = true;
						}
						unsigned int	useHour	=	hour;
						if (useHour > 12) {
							useHour -= 12;
						}
						outBuf += Format (leadingZero? L"%02d": L"%d", useHour);
					}
					break;
					case 'H': {
						bool	leadingZero	=	false;
						if (i + 1 != kFormatStr.end () and *(i+1) == 'H') {
							++i;
							leadingZero = true;
						}
						outBuf += Format (leadingZero? L"%02d": L"%d", hour);
					}
					break;
					case 'm': {
						bool	leadingZero	=	false;
						if (i + 1 != kFormatStr.end () and *(i+1) == 'm') {
							++i;
							leadingZero = true;
						}
						// This is what I couldn't get the MSFT default locale display stuff todo
						// We want to show 3pm, not 3:00:00pm.
						if (not skipMinutes) {
							outBuf += Format (leadingZero? L"%02d": L"%d", minutes);
						}
					}
					break;
					case 's': {
						bool	leadingZero	=	false;
						if (i + 1 != kFormatStr.end () and *(i+1) == 's') {
							++i;
							leadingZero = true;
						}
						if (not skipSeconds) {
							outBuf += Format (leadingZero? L"%02d": L"%d", seconds);
						}
					}
					break;
					case 't': {
						if (i + 1 != kFormatStr.end () and *(i+1) == 't') {
							/*
							 *	From the WinSDK docs...
							 *
							 *	LOCALE_S1159
							 *		String for the AM designator. The maximum number of characters allowed for this string is nine.
							 *	LOCALE_S2359
							 *		String for the PM designator. The maximum number of characters allowed for this string is nine.
							 */
							static	const	wstring	kAMSTR	=	GetLocaleInfo_ (LOCALE_USER_DEFAULT, LOCALE_S1159);
							static	const	wstring	kPMSTR	=	GetLocaleInfo_ (LOCALE_USER_DEFAULT, LOCALE_S2359);
							++i;
							int pmFlag =	hour>=12;
							//outBuf += (pmFlag?L"PM":L"AM");
							outBuf += (pmFlag?kPMSTR:kAMSTR);
						}
						else {
							outBuf.push_back (*i);
						}
					}
					break;
					case ':': {
						// Skip ':' separator if we are going to omit the following
						// stuff...
						if (i + 1 != kFormatStr.end () and *(i+1) == 's' and skipSeconds) {
							// SKIP
						}
						else if (i + 1 != kFormatStr.end () and *(i+1) == 'm' and skipMinutes) {
							// SKIP
						}
						else {
							outBuf.push_back (*i);
						}
					}
					break;
					default: {
						outBuf.push_back (*i);
					}
					break;
				}
			}
			return outBuf;
		}
}
#endif

/*
 ********************************************************************************
 *********************************** TimeOfDay **********************************
 ********************************************************************************
 */
const	TimeOfDay	TimeOfDay::kMin	=	TimeOfDay (0);
const	TimeOfDay	TimeOfDay::kMax	=	TimeOfDay (24 * 60 * 60 - 1);

TimeOfDay::TimeOfDay ()
  : fTime (-1)
{
}

TimeOfDay::TimeOfDay (uint32_t t)
  : fTime (t < 24 * 60 * 60? t: (24 * 60 * 60-1))
{
}

TimeOfDay	TimeOfDay::Parse (const wstring& rep, PrintFormat pf)
{
	if (rep.empty ()) {
		return TimeOfDay ();
	}
	switch (pf) {
		case	eCurrentLocale_PF:	{
			#if		qPlatform_Windows
				return Parse (rep, LOCALE_USER_DEFAULT);
			#elif	qPlatform_POSIX
				AssertNotImplemented ();
				return TimeOfDay ();
			#else
				AssertNotImplemented ();
				return TimeOfDay ();
			#endif
		}
		case	eCurrentXML_PF: {
			int	hour	=	0;
			int	minute	=	0;
			int secs	=	0;
			#pragma	warning (push)
			#pragma	warning (4 : 4996)		// MSVC SILLY WARNING ABOUT USING swscanf_s
			if (::swscanf (rep.c_str (), L"%d:%d:d", &hour, &minute, &secs) >= 2) {
				hour = max (hour, 0);
				hour = min (hour, 23);
				minute = max (minute, 0);
				minute = min (minute, 59);
				secs = max (secs, 0);
				secs = min (secs, 59);
				return TimeOfDay ((hour * 60 + minute) * 60 + secs);
			}
			#pragma	warning (pop)
			return TimeOfDay ();
		}
		default: {
			AssertNotReached ();
			return TimeOfDay ();
		}
	}
}

#if		qPlatform_Windows
TimeOfDay	TimeOfDay::Parse (const wstring& rep, LCID lcid)
{
	if (rep.empty ()) {
		return TimeOfDay ();
	}
	DATE		d;
	(void)::memset (&d, 0, sizeof (d));
	try {
		ThrowIfErrorHRESULT (::VarDateFromStr (CComBSTR (rep.c_str ()), lcid, VAR_TIMEVALUEONLY, &d));
	}
	catch (...) {
		// Apparently military time (e.g. 1300 hours - where colon missing) - is rejected as mal-formed.
		// Detect that - and try to interpret it appropriately.
		wstring	newRep = rep;
		if (newRep.length () == 4 and
			iswdigit (newRep[0]) and iswdigit (newRep[1]) and iswdigit (newRep[2]) and iswdigit (newRep[3])
			) {
			newRep = newRep.substr (0, 2) + L":" + newRep.substr (2, 2);
			ThrowIfErrorHRESULT (::VarDateFromStr (CComBSTR (newRep.c_str ()), lcid, VAR_TIMEVALUEONLY, &d));
		}
		else {
			Execution::DoThrow (FormatException ());
		}
	}
	// SHOULD CHECK ERR RESULT (not sure if/when this can fail - so do a Verify for now)
	SYSTEMTIME	sysTime;
	memset (&sysTime, 0, sizeof (sysTime));
	Verify (::VariantTimeToSystemTime (d, &sysTime));
	return mkTimeOfDay_ (sysTime);
}
#endif

wstring	TimeOfDay::Format (PrintFormat pf) const
{
	if (empty ()) {
		return wstring ();
	}
	switch (pf) {
		case	eCurrentLocale_PF:	{
			#if		qPlatform_Windows
				return Format (LOCALE_USER_DEFAULT);
			#elif	qPlatform_POSIX
				AssertNotImplemented ();
				return wstring ();
			#else
				AssertNotImplemented ();
				return wstring ();
			#endif
		}
		case	eCurrentXML_PF: {
			uint32_t	hour = fTime/(60*60);
			uint32_t	minutes = (fTime - hour * 60 * 60) / 60;
			uint32_t	secs = fTime - hour * 60 * 60 - minutes * 60;
			Assert (hour >= 0 and hour < 24);
			Assert (minutes >= 0 and minutes < 60);
			Assert (secs >= 0 and secs < 60);
			return ::Format (L"%02d:%02d:%02d", hour, minutes, secs);
		}
		default: {
			AssertNotReached ();
			return wstring ();
		}
	}
}

void	TimeOfDay::ClearSecondsField ()
{
	int hour = fTime/(60*60);
	int minutes = (fTime - hour * 60 * 60) / 60;
	int secs = fTime - hour * 60 * 60 - minutes * 60;
	Assert (hour >= 0 and hour < 24);
	Assert (minutes >= 0 and minutes < 60);
	Assert (secs >= 0 and secs < 60);
	fTime -= secs;
}

#if		qPlatform_Windows
wstring	TimeOfDay::Format (LCID lcid) const
{
	if (empty ()) {
		return wstring ();
	}
	else {
		uint32_t hour = fTime/(60*60);
		uint32_t minutes = (fTime - hour * 60 * 60) / 60;
		uint32_t secs = fTime - hour * 60 * 60 - minutes * 60;
		Assert (hour >= 0 and hour < 24);
		Assert (minutes >= 0 and minutes < 60);
		Assert (secs >= 0 and secs < 60);
		return GenTimeStr4TOD_ (hour, minutes, secs);
	}
}
#endif

<|endoftext|>


<commit_before>
#include "MessageBase.hpp"

#define LEGACY_SEND

//#ifndef LEGACY_SEND
#include "RDMAAggregator.hpp"
//#endif

namespace Grappa {

  /// Internal messaging functions
  namespace impl {

    /// @addtogroup Communication
    /// @{

    inline void Grappa::impl::MessageBase::enqueue() {
      CHECK( !is_moved_ ) << "Shouldn't be sending a message that has been moved!"
                          << " Your compiler's return value optimization failed you here.";
#ifndef LEGACY_SEND
      Grappa::impl::global_rdma_aggregator.enqueue( this );
#endif
      is_enqueued_ = true;
#ifdef LEGACY_SEND
      legacy_send();
#endif
    }

      inline void Grappa::impl::MessageBase::enqueue( Core c ) {
      CHECK( !is_moved_ ) << "Shouldn't be sending a message that has been moved!"
                          << " Your compiler's return value optimization failed you here.";
      destination_ = c;
#ifndef LEGACY_SEND
      Grappa::impl::global_rdma_aggregator.enqueue( this );
#endif
      is_enqueued_ = true;
#ifdef LEGACY_SEND
      legacy_send();
#endif
    }

    inline void Grappa::impl::MessageBase::send_immediate() {
      CHECK( !is_moved_ ) << "Shouldn't be sending a message that has been moved!"
                          << " Your compiler's return value optimization failed you here.";
      is_enqueued_ = true;
#ifndef LEGACY_SEND
      Grappa::impl::global_rdma_aggregator.send_immediate( this );
#endif
#ifdef LEGACY_SEND
      legacy_send();
#endif
    }

      inline void Grappa::impl::MessageBase::send_immediate( Core c ) {
      CHECK( !is_moved_ ) << "Shouldn't be sending a message that has been moved!"
                          << " Your compiler's return value optimization failed you here.";
      destination_ = c;
      is_enqueued_ = true;
#ifndef LEGACY_SEND
      Grappa::impl::global_rdma_aggregator.send_immediate( this );
#endif
#ifdef LEGACY_SEND
      legacy_send();
#endif
    }

    /// @}
  }
}
<commit_msg>guard MessageBaseImpl<commit_after>
#ifndef __MESSAGE_BASE_IMPL_HPP__
#define __MESSAGE_BASE_IMPL_HPP__

#include "MessageBase.hpp"

#define LEGACY_SEND

//#ifndef LEGACY_SEND
#include "RDMAAggregator.hpp"
//#endif

namespace Grappa {

  /// Internal messaging functions
  namespace impl {

    /// @addtogroup Communication
    /// @{

    inline void Grappa::impl::MessageBase::enqueue() {
      CHECK( !is_moved_ ) << "Shouldn't be sending a message that has been moved!"
                          << " Your compiler's return value optimization failed you here.";
#ifndef LEGACY_SEND
      Grappa::impl::global_rdma_aggregator.enqueue( this );
#endif
      is_enqueued_ = true;
#ifdef LEGACY_SEND
      legacy_send();
#endif
    }

      inline void Grappa::impl::MessageBase::enqueue( Core c ) {
      CHECK( !is_moved_ ) << "Shouldn't be sending a message that has been moved!"
                          << " Your compiler's return value optimization failed you here.";
      destination_ = c;
#ifndef LEGACY_SEND
      Grappa::impl::global_rdma_aggregator.enqueue( this );
#endif
      is_enqueued_ = true;
#ifdef LEGACY_SEND
      legacy_send();
#endif
    }

    inline void Grappa::impl::MessageBase::send_immediate() {
      CHECK( !is_moved_ ) << "Shouldn't be sending a message that has been moved!"
                          << " Your compiler's return value optimization failed you here.";
      is_enqueued_ = true;
#ifndef LEGACY_SEND
      Grappa::impl::global_rdma_aggregator.send_immediate( this );
#endif
#ifdef LEGACY_SEND
      legacy_send();
#endif
    }

      inline void Grappa::impl::MessageBase::send_immediate( Core c ) {
      CHECK( !is_moved_ ) << "Shouldn't be sending a message that has been moved!"
                          << " Your compiler's return value optimization failed you here.";
      destination_ = c;
      is_enqueued_ = true;
#ifndef LEGACY_SEND
      Grappa::impl::global_rdma_aggregator.send_immediate( this );
#endif
#ifdef LEGACY_SEND
      legacy_send();
#endif
    }

    /// @}
  }
}

#endif // __MESSAGE_BASE_IMPL_HPP__
<|endoftext|>


<commit_before>/*=========================================================================

  Library:   CTK

  Copyright (c) Kitware Inc.

  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.txt

  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.

=========================================================================*/

// Qt includes
#include <QCoreApplication>
#include <QDebug>
#include <QStringList>
#include <QVariant>

// ctkDICOMCore includes
#include "ctkDICOMDatabase.h"
#include "ctkDICOMQuery.h"
#include "ctkDICOMRetrieve.h"
#include "ctkDICOMTester.h"

// STD includes
#include <iostream>

void ctkDICOMRetrieveTest2PrintUsage()
{
  std::cout << " ctkDICOMRetrieveTest2 images" << std::endl;
}

// Test on a real local database
int ctkDICOMRetrieveTest2( int argc, char * argv [] )
{
  QCoreApplication app(argc, argv);

  ctkDICOMTester tester;
  tester.startDCMQRSCP();

  QStringList arguments = app.arguments();
  arguments.pop_front(); // remove application name
  arguments.pop_front(); // remove test name
  if (!arguments.count())
    {
    ctkDICOMRetrieveTest2PrintUsage();
    return EXIT_FAILURE;
    }
  tester.storeData(arguments);

  ctkDICOMDatabase queryDatabase;

  ctkDICOMQuery query;
  query.setCallingAETitle("CTK_AE");
  query.setCalledAETitle("CTK_AE");
  query.setHost("localhost");
  query.setPort(tester.dcmqrscpPort());

  bool res = query.query(queryDatabase);
  if (!res)
    {
    std::cout << "ctkDICOMQuery::query() failed" << std::endl;
    return EXIT_FAILURE;
    }
  if (query.studyInstanceUIDQueried().count() == 0)
    {
    std::cout << "ctkDICOMQuery::query() failed."
              << "No study instance retrieved" << std::endl;
    return EXIT_FAILURE;
    }

  QSharedPointer<ctkDICOMDatabase> retrieveDatabase(new ctkDICOMDatabase);
  retrieveDatabase->openDatabase( "./ctkDICOM.sql" );

  ctkDICOMRetrieve retrieve;
  retrieve.setCallingAETitle("CTK_AE");
  retrieve.setCallingPort(11113);
  retrieve.setCalledAETitle("CTK_AE");
  retrieve.setCalledPort(tester.dcmqrscpPort());
  retrieve.setHost("localhost");
  retrieve.setMoveDestinationAETitle("CTK_CLIENT_AE");

  retrieve.setRetrieveDatabase(retrieveDatabase);

  foreach(const QString& study, query.studyInstanceUIDQueried())
    {
    bool res = retrieve.retrieveStudy(study);
    if (!res)
      {
      std::cout << "ctkDICOMRetrieve::retrieveStudy() failed. "
                << "Study " << qPrintable(study) << " can't be retrieved"
                << std::endl;
      return EXIT_FAILURE;
      }
    }

  return EXIT_SUCCESS;
}
<commit_msg>Removed "calling port" parameter.<commit_after>/*=========================================================================

  Library:   CTK

  Copyright (c) Kitware Inc.

  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.txt

  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.

=========================================================================*/

// Qt includes
#include <QCoreApplication>
#include <QDebug>
#include <QStringList>
#include <QVariant>

// ctkDICOMCore includes
#include "ctkDICOMDatabase.h"
#include "ctkDICOMQuery.h"
#include "ctkDICOMRetrieve.h"
#include "ctkDICOMTester.h"

// STD includes
#include <iostream>

void ctkDICOMRetrieveTest2PrintUsage()
{
  std::cout << " ctkDICOMRetrieveTest2 images" << std::endl;
}

// Test on a real local database
int ctkDICOMRetrieveTest2( int argc, char * argv [] )
{
  QCoreApplication app(argc, argv);

  ctkDICOMTester tester;
  tester.startDCMQRSCP();

  QStringList arguments = app.arguments();
  arguments.pop_front(); // remove application name
  arguments.pop_front(); // remove test name
  if (!arguments.count())
    {
    ctkDICOMRetrieveTest2PrintUsage();
    return EXIT_FAILURE;
    }
  tester.storeData(arguments);

  ctkDICOMDatabase queryDatabase;

  ctkDICOMQuery query;
  query.setCallingAETitle("CTK_AE");
  query.setCalledAETitle("CTK_AE");
  query.setHost("localhost");
  query.setPort(tester.dcmqrscpPort());

  bool res = query.query(queryDatabase);
  if (!res)
    {
    std::cout << "ctkDICOMQuery::query() failed" << std::endl;
    return EXIT_FAILURE;
    }
  if (query.studyInstanceUIDQueried().count() == 0)
    {
    std::cout << "ctkDICOMQuery::query() failed."
              << "No study instance retrieved" << std::endl;
    return EXIT_FAILURE;
    }

  QSharedPointer<ctkDICOMDatabase> retrieveDatabase(new ctkDICOMDatabase);
  retrieveDatabase->openDatabase( "./ctkDICOM.sql" );

  ctkDICOMRetrieve retrieve;
  retrieve.setCallingAETitle("CTK_AE");
  retrieve.setCalledAETitle("CTK_AE");
  retrieve.setCalledPort(tester.dcmqrscpPort());
  retrieve.setHost("localhost");
  retrieve.setMoveDestinationAETitle("CTK_CLIENT_AE");

  retrieve.setRetrieveDatabase(retrieveDatabase);

  foreach(const QString& study, query.studyInstanceUIDQueried())
    {
    bool res = retrieve.retrieveStudy(study);
    if (!res)
      {
      std::cout << "ctkDICOMRetrieve::retrieveStudy() failed. "
                << "Study " << qPrintable(study) << " can't be retrieved"
                << std::endl;
      return EXIT_FAILURE;
      }
    }

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include "pch.h"
#include "axl_io_Socket.h"

namespace axl {
namespace io {

//.............................................................................

bool
CSocket::Accept (
	CSocket* pSocket,
	sockaddr* pAddr
	)
{
	int Socket = m_Socket.Accept (pAddr);
	if (Socket == -1)
		return false;

	pSocket->m_Socket.Attach (Socket);
	return true;
}

//.............................................................................

} // namespace io
} // namespace axl

<commit_msg>[ioninja] new logo [njscroll] hexedit -- always have 1 line; even when there is no data<commit_after>#include "pch.h"
#include "axl_io_Socket.h"

namespace axl {
namespace io {

//.............................................................................

bool
CSocket::Accept (
	CSocket* pSocket,
	sockaddr* pAddr
	)
{
#if (_AXL_ENV == AXL_ENV_WIN)
	SOCKET Socket = m_Socket.Accept (pAddr);
#else
	int Socket = m_Socket.Accept (pAddr);
#endif

	if (Socket == -1)
		return false;

	pSocket->m_Socket.Attach (Socket);
	return true;
}

//.............................................................................

} // namespace io
} // namespace axl

<|endoftext|>


<commit_before>#include "spbits.h"
#include <ap_int.h>
#include "primitive.h"
using namespace std;

void primitive::top_prim_conv(
			ap_uint<seg_ch> vpf,
			ap_uint<4> quality[seg_ch],
			ap_uint<bw_wg> wiregroup[seg_ch],
			ap_uint<bw_hs> hstrip[seg_ch],
			ap_uint<4> clctpat[seg_ch],
			ap_uint<8> station,
			ap_uint<8> cscid,
			ap_uint<13> r_in,
			ap_uint<1> we,
			ap_uint<bw_fph> ph[seg_ch],
			ap_uint<bw_th> th[seg_ch],
			ap_uint<seg_ch> *vl,
			ap_uint<3> *phzvl,
			ap_uint<seg_ch> *me11a,
			ap_uint<4> clctpat_r[seg_ch],
			ap_uint<ph_hit_w> *ph_hit,
			ap_uint<th_hit_w> *th_hit,
			ap_uint<2>  sel,
			ap_uint<bw_addr>  addr,
			ap_uint<1> endcap,
			ap_uint<1> lat_test,
			ap_uint<12> *r_out)

{
#pragma HLS INTERFACE ap_ctrl_none port=return
#pragma HLS INLINE off
#pragma HLS PIPELINE II=1

	ap_uint<3> a_phzvl;
	ap_uint<ph_hit_w> a_ph_hit;
	ap_uint<th_hit_w> a_th_hit;
if(we==1)
{
	this->mem( 	r_in,
			 we,
			 addr,
			 sel,
			 station,
			 cscid
			 );

}

else
{

		this->prim_conv(
					vpf, quality, wiregroup, hstrip, clctpat,
			 		station,cscid,
			 		ph,	th,	vl,	&a_phzvl, me11a, clctpat_r,
					&a_ph_hit, &a_th_hit, sel, addr,endcap,
			 		lat_test,r_out
			 		);

}

*phzvl=a_phzvl;
*ph_hit=a_ph_hit;
*th_hit=a_th_hit;
}

<commit_msg>Delete top_prim_conv.cpp<commit_after><|endoftext|>


<commit_before>// @(#)root/base:$Name:  $:$Id: TVirtualPS.cxx,v 1.7 2004/02/19 15:49:43 brun Exp $
// Author: Rene Brun   05/09/99

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TVirtualPS is an abstract interface to a Postscript and SVG drivers  //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "Riostream.h"
#include "TVirtualPS.h"

TVirtualPS *gVirtualPS = 0;

const Int_t  kMaxBuffer = 250;

ClassImp(TVirtualPS)

//______________________________________________________________________________
//
//  TVirtualPS is an abstract interface to a Postscript driver
//

//______________________________________________________________________________
TVirtualPS::TVirtualPS()
{
   // VirtualPS default constructor
   fStream    = 0;
   fNByte     = 0;
   fSizBuffer = kMaxBuffer;
   fBuffer    = new char[fSizBuffer];
}

//______________________________________________________________________________
TVirtualPS::TVirtualPS(const char *name, Int_t)
          : TNamed(name,"Postscript interface")
{
   // VirtualPS constructor
   fStream    = 0;
   fNByte     = 0;
   fSizBuffer = kMaxBuffer;
   fBuffer    = new char[fSizBuffer];
}

//______________________________________________________________________________
TVirtualPS::~TVirtualPS()
{
   // VirtualPS destructor

   if (fBuffer) delete [] fBuffer;
}

//______________________________________________________________________________
void TVirtualPS::PrintStr(const char *str)
{
   // Output the string str in the output buffer

   Int_t len = strlen(str);
   if (len == 0) return;
   if( str[0] == '@') {
      if( fLenBuffer ) {
         fStream->write(fBuffer, fLenBuffer);
         fStream->write("\n",1); fNByte++;
      }
      if ( len < 2)  {
         fBuffer[0] = ' ';
      } else {
         strcpy(fBuffer, str+1);
      }
      fLenBuffer = len-1;
      fPrinted = kTRUE;
      fNByte += len-1;
      return;
   }

   if( str[len-1] == '@') {
      if( fLenBuffer ) {
         fStream->write(fBuffer, fLenBuffer);
         fStream->write("\n",1); fNByte++;
      }
      fStream->write(str, len-1);
      fStream->write("\n",1);
      fLenBuffer = 0;
      fNByte += len;
      fPrinted = kTRUE;
      return;
   }

   if( (len + fLenBuffer ) > kMaxBuffer) {
      fStream->write(fBuffer, fLenBuffer);
      fStream->write("\n",1); fNByte++;
      strcpy(fBuffer, str);
      fLenBuffer = len;
      fNByte += len;
   } else {
      strcpy(fBuffer + fLenBuffer, str);
      fLenBuffer += len;
      fNByte += len;
   }
   fPrinted = kTRUE;
}

//______________________________________________________________________________
void TVirtualPS::PrintFast(Int_t len, const char *str)
{
   // Fast version of Print

   if( (len + fLenBuffer ) > kMaxBuffer) {
      fStream->write(fBuffer, fLenBuffer);
      fStream->write("\n",1); fNByte++;
      strcpy(fBuffer, str);
      fLenBuffer = len;
   } else {
      strcpy(fBuffer + fLenBuffer, str);
      fLenBuffer += len;
   }
   fNByte += len;
   fPrinted = kTRUE;
}

//______________________________________________________________________________
void TVirtualPS::WriteInteger(Int_t n, Bool_t space )
{
   // Write one Integer to the file
   //
   // n: Integer to be written in the file.
   // space: If TRUE, a space in written before the integer.

   char str[15];
   if (space) {
      sprintf(str," %d", n);
   } else {
      sprintf(str,"%d", n);
   }
   PrintStr(str);
}

//______________________________________________________________________________
void TVirtualPS::WriteReal(Float_t z)
{
   // Write a Real number to the file

   char str[15];
   sprintf(str," %g", z);
   PrintStr(str);
}
<commit_msg>From Olivier: - rootn.exe crashed when a PS file was generated from the "Save as" pad's   menu. fBuffer array is now created as char[fSizBuffer+1].<commit_after>// @(#)root/base:$Name:  $:$Id: TVirtualPS.cxx,v 1.8 2004/03/17 17:35:31 brun Exp $
// Author: Rene Brun   05/09/99

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TVirtualPS is an abstract interface to a Postscript and SVG drivers  //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "Riostream.h"
#include "TVirtualPS.h"

TVirtualPS *gVirtualPS = 0;

const Int_t  kMaxBuffer = 250;

ClassImp(TVirtualPS)

//______________________________________________________________________________
//
//  TVirtualPS is an abstract interface to a Postscript driver
//

//______________________________________________________________________________
TVirtualPS::TVirtualPS()
{
   // VirtualPS default constructor
   fStream    = 0;
   fNByte     = 0;
   fSizBuffer = kMaxBuffer;
   fBuffer    = new char[fSizBuffer+1];
}

//______________________________________________________________________________
TVirtualPS::TVirtualPS(const char *name, Int_t)
          : TNamed(name,"Postscript interface")
{
   // VirtualPS constructor
   fStream    = 0;
   fNByte     = 0;
   fSizBuffer = kMaxBuffer;
   fBuffer    = new char[fSizBuffer];
}

//______________________________________________________________________________
TVirtualPS::~TVirtualPS()
{
   // VirtualPS destructor

   if (fBuffer) delete [] fBuffer;
}

//______________________________________________________________________________
void TVirtualPS::PrintStr(const char *str)
{
   // Output the string str in the output buffer

   Int_t len = strlen(str);
   if (len == 0) return;
   if( str[0] == '@') {
      if( fLenBuffer ) {
         fStream->write(fBuffer, fLenBuffer);
         fStream->write("\n",1); fNByte++;
      }
      if ( len < 2)  {
         fBuffer[0] = ' ';
      } else {
         strcpy(fBuffer, str+1);
      }
      fLenBuffer = len-1;
      fPrinted = kTRUE;
      fNByte += len-1;
      return;
   }

   if( str[len-1] == '@') {
      if( fLenBuffer ) {
         fStream->write(fBuffer, fLenBuffer);
         fStream->write("\n",1); fNByte++;
      }
      fStream->write(str, len-1);
      fStream->write("\n",1);
      fLenBuffer = 0;
      fNByte += len;
      fPrinted = kTRUE;
      return;
   }

   if( (len + fLenBuffer ) > kMaxBuffer) {
      fStream->write(fBuffer, fLenBuffer);
      fStream->write("\n",1); fNByte++;
      strcpy(fBuffer, str);
      fLenBuffer = len;
      fNByte += len;
   } else {
      strcpy(fBuffer + fLenBuffer, str);
      fLenBuffer += len;
      fNByte += len;
   }
   fPrinted = kTRUE;
}

//______________________________________________________________________________
void TVirtualPS::PrintFast(Int_t len, const char *str)
{
   // Fast version of Print

   if( (len + fLenBuffer ) > kMaxBuffer) {
      fStream->write(fBuffer, fLenBuffer);
      fStream->write("\n",1); fNByte++;
      strcpy(fBuffer, str);
      fLenBuffer = len;
   } else {
      strcpy(fBuffer + fLenBuffer, str);
      fLenBuffer += len;
   }
   fNByte += len;
   fPrinted = kTRUE;
}

//______________________________________________________________________________
void TVirtualPS::WriteInteger(Int_t n, Bool_t space )
{
   // Write one Integer to the file
   //
   // n: Integer to be written in the file.
   // space: If TRUE, a space in written before the integer.

   char str[15];
   if (space) {
      sprintf(str," %d", n);
   } else {
      sprintf(str,"%d", n);
   }
   PrintStr(str);
}

//______________________________________________________________________________
void TVirtualPS::WriteReal(Float_t z)
{
   // Write a Real number to the file

   char str[15];
   sprintf(str," %g", z);
   PrintStr(str);
}
<|endoftext|>