<commit_before>#include <iostream>
#include <algorithm>
#include <cstring>
#include <climits>
#include <iomanip>

#define MAX_DEV_NUM 10000

using namespace std;

class Device {
  public:
    int id;
    int bandwidth;
    int price;
};

bool cmp(const Device& a, const Device& b);

int main() {
  int t;
  cin >> t;

  for (int i = 0; i < t; i++) {
    int numOfDevs;
    cin >> numOfDevs;

    Device dev[MAX_DEV_NUM];
    int numOfOpts = 0;
    for (int j = 1; j <= numOfDevs; j++) {
      int b, p;
      int m;
      cin >> m;
      for (int cnt = 0; cnt < m; cnt++) {
        cin >> b >> p;

        dev[numOfOpts].id        = j;
        dev[numOfOpts].price     = p;
        dev[numOfOpts].bandwidth = b;

        numOfOpts++;
      }
    }

    sort(dev, dev + numOfOpts, cmp);

    float result = 0.0, tmp;
    //memset(price, INT_MAX, sizeof(price));
    for (int i = 0; i <= numOfOpts - numOfDevs; i++) {
      int price[numOfDevs];
      memset(price, CHAR_MAX, sizeof(price));

      bool isVisited[numOfDevs];
      memset(isVisited, false, sizeof(isVisited));
      int bandwidth = dev[i].bandwidth;
      price[dev[i].id - 1] = dev[i].price;
      isVisited[dev[i].id - 1] = true;

      for (int j = i + 1; j <= numOfOpts - 1; j++) {

        if (dev[j].id == dev[i].id)
          continue;

        if (price[dev[j].id - 1] > dev[j].price) {
          price[dev[j].id - 1] = dev[j].price;
          isVisited[dev[j].id - 1] = isVisited[dev[j].id - 1] || true;
        }
      }

      bool isAllVisited = true;
      for (int i = 0; i < numOfDevs; i++) {
        if (!isVisited[i]) {
          isAllVisited = false;
          break;
        }
      }

      if (!isAllVisited)
        tmp = 0.0;
      else {
        int totalPrice = 0;
        for (int i = 0; i < numOfDevs; i++)
          totalPrice += price[i];

        tmp = (float)bandwidth / (float)totalPrice;
      }

      /*
      for (int i = 0; i < numOfDevs; i++)
        totalPrice += price[i];

      tmp = bandwidth * 1.0 / totalPrice;
      */

      if (tmp > result) {
        result = tmp;
      }
    }

    cout << setprecision(3) << result << endl;

    /*
    for (int i = 0; i < numOfOpts; i++)
      cout << dev[i].bandwidth << "\t" << dev[i].price << "\t"
        << dev[i].id << endl;
    */

  }
}

bool cmp(const Device& a, const Device& b) {
  if (a.bandwidth != b.bandwidth)
    return a.bandwidth < b.bandwidth;
  else if (a.price != b.price)
    return a.price < b.price;
  else
    return a.id < b.id;
}
<commit_msg>fix output format<commit_after>#include <iostream>
#include <algorithm>
#include <cstring>
#include <climits>
#include <iomanip>

#define MAX_DEV_NUM 10000

using namespace std;

class Device {
  public:
    int id;
    int bandwidth;
    int price;
};

bool cmp(const Device& a, const Device& b);

int main() {
  int t;
  cin >> t;

  for (int i = 0; i < t; i++) {
    int numOfDevs;
    cin >> numOfDevs;

    Device dev[MAX_DEV_NUM];
    int numOfOpts = 0;
    for (int j = 1; j <= numOfDevs; j++) {
      int b, p;
      int m;
      cin >> m;
      for (int cnt = 0; cnt < m; cnt++) {
        cin >> b >> p;

        dev[numOfOpts].id        = j;
        dev[numOfOpts].price     = p;
        dev[numOfOpts].bandwidth = b;

        numOfOpts++;
      }
    }

    sort(dev, dev + numOfOpts, cmp);

    float result = 0.0, tmp;
    //memset(price, INT_MAX, sizeof(price));
    for (int i = 0; i <= numOfOpts - numOfDevs; i++) {
      int price[numOfDevs];
      //memset(price, CHAR_MAX, sizeof(price));

      bool isVisited[numOfDevs];
      memset(isVisited, false, sizeof(isVisited));
      int bandwidth = dev[i].bandwidth;
      price[dev[i].id - 1] = dev[i].price;
      isVisited[dev[i].id - 1] = true;

      for (int j = i + 1; j <= numOfOpts - 1; j++) {

        if (dev[j].id == dev[i].id)
          continue;

        if (price[dev[j].id - 1] > dev[j].price) {
          price[dev[j].id - 1] = dev[j].price;
          isVisited[dev[j].id - 1] = isVisited[dev[j].id - 1] || true;
        }
      }

      bool isAllVisited = true;
      for (int i = 0; i < numOfDevs; i++) {
        if (!isVisited[i]) {
          isAllVisited = false;
          break;
        }
      }

      if (!isAllVisited)
        tmp = 0.0;
      else {
        int totalPrice = 0;
        for (int i = 0; i < numOfDevs; i++)
          totalPrice += price[i];

        tmp = (float)bandwidth / (float)totalPrice;
      }

      /*
      for (int i = 0; i < numOfDevs; i++)
        totalPrice += price[i];

      tmp = bandwidth * 1.0 / totalPrice;
      */

      if (tmp > result) {
        result = tmp;
      }
    }

    cout << fixed << setprecision(3) << result << endl;

    /*
    for (int i = 0; i < numOfOpts; i++)
      cout << dev[i].bandwidth << "\t" << dev[i].price << "\t"
        << dev[i].id << endl;
    */

  }
}

bool cmp(const Device& a, const Device& b) {
  if (a.bandwidth != b.bandwidth)
    return a.bandwidth < b.bandwidth;
  else if (a.price != b.price)
    return a.price < b.price;
  else
    return a.id < b.id;
}
<|endoftext|>


<commit_before>/*
* Key codes for multiple platforms
*
* Copyright (C) 2016 by Sascha Willems - www.saschawillems.de
*
* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
*/

#pragma once

#if defined(_WIN32)
#define KEY_ESCAPE VK_ESCAPE
#define KEY_F1 VK_F1
#define KEY_F2 VK_F2
#define KEY_W 0x57
#define KEY_A 0x41
#define KEY_S 0x53
#define KEY_D 0x44
#define KEY_P 0x50
#elif defined(__ANDROID__)
#elif defined(__linux__)
#define KEY_ESCAPE 0x9
#define KEY_W 0x19
#define KEY_A 0x26
#define KEY_S 0x27
#define KEY_D 0x28
#define KEY_P 0x21
#define KEY_F1 0x43
#define KEY_F2 0x44
#endif

// todo: Android gamepad keycodes outside of define for now
#define GAMEPAD_BUTTON_A 0x1000
#define GAMEPAD_BUTTON_B 0x1001
#define GAMEPAD_BUTTON_X 0x1002
#define GAMEPAD_BUTTON_Y 0x1003
#define GAMEPAD_BUTTON_L1 0x1004
#define GAMEPAD_BUTTON_R1 0x1005
#define GAMEPAD_BUTTON_START 0x1006<commit_msg>Add more Windows and Linux keycodes<commit_after>/*
* Key codes for multiple platforms
*
* Copyright (C) 2016 by Sascha Willems - www.saschawillems.de
*
* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
*/

#pragma once

#if defined(_WIN32)
#define KEY_ESCAPE VK_ESCAPE
#define KEY_F1 VK_F1
#define KEY_F2 VK_F2
#define KEY_W 0x57
#define KEY_A 0x41
#define KEY_S 0x53
#define KEY_D 0x44
#define KEY_P 0x50
//
#define KEY_SPACE 0x20
#define KEY_KPADD 0x6B
#define KEY_KPSUB 0x6D
#define KEY_B 0x42
#define KEY_F 0x46
#define KEY_L 0x4C
#define KEY_N 0x4E
#define KEY_O 0x4F
#define KEY_T 0x54
//
#elif defined(__ANDROID__)
#elif defined(__linux__)
#define KEY_ESCAPE 0x9
#define KEY_F1 0x43
#define KEY_F2 0x44
#define KEY_W 0x19
#define KEY_A 0x26
#define KEY_S 0x27
#define KEY_D 0x28
#define KEY_P 0x21
//
#define KEY_SPACE 0x41
#define KEY_KPADD 0x56
#define KEY_KPSUB 0x52
#define KEY_B 0x38
#define KEY_F 0x29
#define KEY_L 0x2E
#define KEY_N 0x39
#define KEY_O 0x20
#define KEY_T 0x1C
//
#endif

// todo: Android gamepad keycodes outside of define for now
#define GAMEPAD_BUTTON_A 0x1000
#define GAMEPAD_BUTTON_B 0x1001
#define GAMEPAD_BUTTON_X 0x1002
#define GAMEPAD_BUTTON_Y 0x1003
#define GAMEPAD_BUTTON_L1 0x1004
#define GAMEPAD_BUTTON_R1 0x1005
#define GAMEPAD_BUTTON_START 0x1006
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
 *     Copyright 2013 Couchbase, 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
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */

#include "config.h"

#include "backfill.h"
#include "ep_engine.h"
#include "upr-stream.h"

ENGINE_ERROR_CODE UprProducer::addStream(uint16_t vbucket,
                                         uint32_t opaque,
                                         uint32_t stream_flags,
                                         uint64_t start_seqno,
                                         uint64_t end_seqno,
                                         uint64_t vb_uuid,
                                         uint64_t high_seqno,
                                         uint64_t *rollback_seqno) {
    RCPtr<VBucket> vb = engine_.getVBucket(vbucket);
    if (!vb) {
        return ENGINE_NOT_MY_VBUCKET;
    }

    std::map<uint16_t, ActiveStream*>::iterator itr = streams.find(vbucket);
    if (itr != streams.end()) {
        if (itr->second->getState() != STREAM_DEAD) {
            return ENGINE_KEY_EEXISTS;
        } else {
            delete itr->second;
            streams.erase(vbucket);
        }
    }

    *rollback_seqno = 0;
    if(vb->failovers.needsRollback(start_seqno, vb_uuid)) {
        *rollback_seqno = vb->failovers.findRollbackPoint(vb_uuid);
        if((*rollback_seqno) == 0) {
            // rollback point of 0 indicates that the entry was missing entirely,
            // report as key not found per transport spec.
            return ENGINE_KEY_ENOENT;
        }
        return ENGINE_ROLLBACK;
    }

    streams[vbucket] = new ActiveStream(stream_flags, opaque, vbucket,
                                        start_seqno, end_seqno, vb_uuid,
                                        high_seqno, STREAM_ACTIVE);

    if (start_seqno >= end_seqno) {
        streams[vbucket]->push(new StreamEndResponse(opaque, 0, vbucket));
        streams[vbucket]->setState(STREAM_DEAD);
    } else {
        scheduleBackfill(vb, start_seqno, end_seqno);
    }

    return ENGINE_SUCCESS;
}

ENGINE_ERROR_CODE UprProducer::closeStream(uint16_t vbucket)
{
    std::map<uint16_t, ActiveStream*>::iterator itr;
    for (itr = streams.begin() ; itr != streams.end(); ++itr) {
        if (vbucket == itr->second->getVBucket()) {
            // Found the stream for the vbucket.. nuke it!
            // @todo is there any pending tasks that is running for the
            //       stream that I need to wait for?
            Stream *stream = itr->second;
            streams.erase(itr);
            delete stream;
            return ENGINE_SUCCESS;
        }
    }
    return ENGINE_NOT_MY_VBUCKET;
}

void UprProducer::scheduleBackfill(RCPtr<VBucket> &vb, uint64_t start_seqno,
                                   uint64_t end_seqno) {
    item_eviction_policy_t policy = engine_.getEpStore()->getItemEvictionPolicy();
    double num_items = static_cast<double>(vb->getNumItems(policy));

    if (num_items == 0) {
        return;
    }

    KVStore *underlying(engine_.getEpStore()->getAuxUnderlying());
    LOG(EXTENSION_LOG_INFO, "Scheduling backfill from disk for vbucket %d"
        "for seqno %ld to %ld", vb->getId(), start_seqno, end_seqno);
    ExTask task = new BackfillDiskLoad(conn_->name, &engine_,
                                       engine_.getUprConnMap(),
                                       underlying, vb->getId(), start_seqno,
                                       end_seqno, conn_->getConnectionToken(),
                                       Priority::TapBgFetcherPriority,
                                       0, false);
    ExecutorPool::get()->schedule(task, AUXIO_TASK_IDX);
}

void UprProducer::addStats(ADD_STAT add_stat, const void *c) {
    ConnHandler::addStats(add_stat, c);

    LockHolder lh(queueLock);
    std::map<uint16_t, ActiveStream*>::iterator itr;
    for (itr = streams.begin(); itr != streams.end(); ++itr) {
        const int bsize = 32;
        char buffer[bsize];
        Stream* s = itr->second;
        snprintf(buffer, bsize, "stream_%d_flags", s->getVBucket());
        addStat(buffer, s->getFlags(), add_stat, c);
        snprintf(buffer, bsize, "stream_%d_opaque", s->getVBucket());
        addStat(buffer, s->getOpaque(), add_stat, c);
        snprintf(buffer, bsize, "stream_%d_start_seqno", s->getVBucket());
        addStat(buffer, s->getStartSeqno(), add_stat, c);
        snprintf(buffer, bsize, "stream_%d_end_seqno", s->getVBucket());
        addStat(buffer, s->getEndSeqno(), add_stat, c);
        snprintf(buffer, bsize, "stream_%d_vb_uuid", s->getVBucket());
        addStat(buffer, s->getVBucketUUID(), add_stat, c);
        snprintf(buffer, bsize, "stream_%d_high_seqno", s->getVBucket());
        addStat(buffer, s->getHighSeqno(), add_stat, c);
    }
}

void UprProducer::aggregateQueueStats(ConnCounter* aggregator) {
    LockHolder lh(queueLock);
    if (!aggregator) {
        LOG(EXTENSION_LOG_WARNING,
            "%s Pointer to the queue stats aggregator is NULL!!!", logHeader());
        return;
    }

    aggregator->conn_queueBackfillRemaining += totalBackfillBacklogs;
}

UprResponse* UprProducer::getNextItem() {
    LockHolder lh(queueLock);
    std::map<uint16_t, ActiveStream*>::iterator itr = streams.begin();
    for (; itr != streams.end(); ++itr) {
        while (!itr->second->empty()) {
            bool skip = false;
            UprResponse* op = itr->second->front();
            switch (op->getEvent()) {
                case UPR_MUTATION:
                case UPR_DELETION:
                {
                    MutationResponse *m = dynamic_cast<MutationResponse*>(op);
                    skip = shouldSkipMutation(m->getBySeqno(), m->getVBucket());
                    break;
                }
                case UPR_STREAM_END:
                    break;
                default:
                    LOG(EXTENSION_LOG_WARNING, "Producer is attempting to write"
                        " an unexpected event %d", op->getEvent());
                    abort();
            }
            itr->second->pop();
            if (!skip) {
                return op;
            }
            delete op;
        }
    }
    return NULL;
}

bool UprProducer::shouldSkipMutation(uint64_t byseqno, uint16_t vbucket) {
    std::map<uint16_t, ActiveStream*>::iterator itr = streams.find(vbucket);
    if (itr != streams.end() && itr->second->getState() == STREAM_ACTIVE) {
        uint32_t opaque = itr->second->getOpaque();
        if (byseqno >= itr->second->getEndSeqno()) {
            itr->second->setState(STREAM_DEAD);
            itr->second->push(new StreamEndResponse(opaque, 0, vbucket));
            if (byseqno > itr->second->getEndSeqno()) {
                return true;
            }
        }
        return false;
    } else {
        return true;
    }
}

bool UprProducer::isTimeForNoop() {
    // Not Implemented
    return false;
}

void UprProducer::setTimeForNoop() {
    // Not Implemented
}

void UprProducer::clearQueues() {
    LockHolder lh(queueLock);
    std::map<uint16_t, ActiveStream*>::iterator itr = streams.begin();
    for (; itr != streams.end(); ++itr) {
        itr->second->clear();
    }
}

void UprProducer::appendQueue(std::list<queued_item> *q) {
    (void) q;
    abort(); // Not Implemented
}

size_t UprProducer::getBackfillQueueSize() {
    return totalBackfillBacklogs;
}

void UprProducer::completeBackfill() {
    /* Upr connections should not call this function because upr
     * backfills should be scheduled through the BackfillDiskLoad
     * task and not through the BackfillTask. Scheduling through
     * the BackfillDiskLoad task allows the specification of start
     * and end sequence numbers and allows us to schedule one-off
     * backfills.
     */
    abort();
}

void UprProducer::scheduleDiskBackfill() {
    // Not Implemented
}

void UprProducer::completeDiskBackfill() {
    // Not Implemented
}

bool UprProducer::isBackfillCompleted() {
    abort(); // Not Implemented
}

void UprProducer::completeBGFetchJob(Item *item, uint16_t vbid,
                                     bool implicitEnqueue) {
    (void) implicitEnqueue;

    // TODO: This is the wrong way to assign an opaque
    std::map<uint16_t, ActiveStream*>::iterator itr = streams.find(vbid);
    if (itr == streams.end()) {
        return;
    }

    stats.memOverhead.fetch_add(sizeof(Item *));
    assert(stats.memOverhead.load() < GIGANTOR);
    itr->second->push(new MutationResponse(item, itr->second->getOpaque()));
}

bool UprProducer::windowIsFull() {
    abort(); // Not Implemented
}

void UprProducer::flush() {
    abort(); // Not Implemented
}
<commit_msg>Add sanity checks for start/end seqno's when doing a stream request<commit_after>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
 *     Copyright 2013 Couchbase, 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
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */

#include "config.h"

#include "backfill.h"
#include "ep_engine.h"
#include "upr-stream.h"

ENGINE_ERROR_CODE UprProducer::addStream(uint16_t vbucket,
                                         uint32_t opaque,
                                         uint32_t stream_flags,
                                         uint64_t start_seqno,
                                         uint64_t end_seqno,
                                         uint64_t vb_uuid,
                                         uint64_t high_seqno,
                                         uint64_t *rollback_seqno) {
    RCPtr<VBucket> vb = engine_.getVBucket(vbucket);
    if (!vb) {
        return ENGINE_NOT_MY_VBUCKET;
    }

    std::map<uint16_t, ActiveStream*>::iterator itr = streams.find(vbucket);
    if (itr != streams.end()) {
        if (itr->second->getState() != STREAM_DEAD) {
            return ENGINE_KEY_EEXISTS;
        } else {
            delete itr->second;
            streams.erase(vbucket);
        }
    }

    if ((uint64_t)vb->getHighSeqno() < start_seqno || start_seqno > end_seqno) {
        return ENGINE_ERANGE;
    }

    *rollback_seqno = 0;
    if(vb->failovers.needsRollback(start_seqno, vb_uuid)) {
        *rollback_seqno = vb->failovers.findRollbackPoint(vb_uuid);
        if((*rollback_seqno) == 0) {
            // rollback point of 0 indicates that the entry was missing entirely,
            // report as key not found per transport spec.
            return ENGINE_KEY_ENOENT;
        }
        return ENGINE_ROLLBACK;
    }

    streams[vbucket] = new ActiveStream(stream_flags, opaque, vbucket,
                                        start_seqno, end_seqno, vb_uuid,
                                        high_seqno, STREAM_ACTIVE);

    if (start_seqno >= end_seqno) {
        streams[vbucket]->push(new StreamEndResponse(opaque, 0, vbucket));
        streams[vbucket]->setState(STREAM_DEAD);
    } else {
        scheduleBackfill(vb, start_seqno, end_seqno);
    }

    return ENGINE_SUCCESS;
}

ENGINE_ERROR_CODE UprProducer::closeStream(uint16_t vbucket)
{
    std::map<uint16_t, ActiveStream*>::iterator itr;
    for (itr = streams.begin() ; itr != streams.end(); ++itr) {
        if (vbucket == itr->second->getVBucket()) {
            // Found the stream for the vbucket.. nuke it!
            // @todo is there any pending tasks that is running for the
            //       stream that I need to wait for?
            Stream *stream = itr->second;
            streams.erase(itr);
            delete stream;
            return ENGINE_SUCCESS;
        }
    }
    return ENGINE_NOT_MY_VBUCKET;
}

void UprProducer::scheduleBackfill(RCPtr<VBucket> &vb, uint64_t start_seqno,
                                   uint64_t end_seqno) {
    item_eviction_policy_t policy = engine_.getEpStore()->getItemEvictionPolicy();
    double num_items = static_cast<double>(vb->getNumItems(policy));

    if (num_items == 0) {
        return;
    }

    KVStore *underlying(engine_.getEpStore()->getAuxUnderlying());
    LOG(EXTENSION_LOG_INFO, "Scheduling backfill from disk for vbucket %d"
        "for seqno %ld to %ld", vb->getId(), start_seqno, end_seqno);
    ExTask task = new BackfillDiskLoad(conn_->name, &engine_,
                                       engine_.getUprConnMap(),
                                       underlying, vb->getId(), start_seqno,
                                       end_seqno, conn_->getConnectionToken(),
                                       Priority::TapBgFetcherPriority,
                                       0, false);
    ExecutorPool::get()->schedule(task, AUXIO_TASK_IDX);
}

void UprProducer::addStats(ADD_STAT add_stat, const void *c) {
    ConnHandler::addStats(add_stat, c);

    LockHolder lh(queueLock);
    std::map<uint16_t, ActiveStream*>::iterator itr;
    for (itr = streams.begin(); itr != streams.end(); ++itr) {
        const int bsize = 32;
        char buffer[bsize];
        Stream* s = itr->second;
        snprintf(buffer, bsize, "stream_%d_flags", s->getVBucket());
        addStat(buffer, s->getFlags(), add_stat, c);
        snprintf(buffer, bsize, "stream_%d_opaque", s->getVBucket());
        addStat(buffer, s->getOpaque(), add_stat, c);
        snprintf(buffer, bsize, "stream_%d_start_seqno", s->getVBucket());
        addStat(buffer, s->getStartSeqno(), add_stat, c);
        snprintf(buffer, bsize, "stream_%d_end_seqno", s->getVBucket());
        addStat(buffer, s->getEndSeqno(), add_stat, c);
        snprintf(buffer, bsize, "stream_%d_vb_uuid", s->getVBucket());
        addStat(buffer, s->getVBucketUUID(), add_stat, c);
        snprintf(buffer, bsize, "stream_%d_high_seqno", s->getVBucket());
        addStat(buffer, s->getHighSeqno(), add_stat, c);
    }
}

void UprProducer::aggregateQueueStats(ConnCounter* aggregator) {
    LockHolder lh(queueLock);
    if (!aggregator) {
        LOG(EXTENSION_LOG_WARNING,
            "%s Pointer to the queue stats aggregator is NULL!!!", logHeader());
        return;
    }

    aggregator->conn_queueBackfillRemaining += totalBackfillBacklogs;
}

UprResponse* UprProducer::getNextItem() {
    LockHolder lh(queueLock);
    std::map<uint16_t, ActiveStream*>::iterator itr = streams.begin();
    for (; itr != streams.end(); ++itr) {
        while (!itr->second->empty()) {
            bool skip = false;
            UprResponse* op = itr->second->front();
            switch (op->getEvent()) {
                case UPR_MUTATION:
                case UPR_DELETION:
                {
                    MutationResponse *m = dynamic_cast<MutationResponse*>(op);
                    skip = shouldSkipMutation(m->getBySeqno(), m->getVBucket());
                    break;
                }
                case UPR_STREAM_END:
                    break;
                default:
                    LOG(EXTENSION_LOG_WARNING, "Producer is attempting to write"
                        " an unexpected event %d", op->getEvent());
                    abort();
            }
            itr->second->pop();
            if (!skip) {
                return op;
            }
            delete op;
        }
    }
    return NULL;
}

bool UprProducer::shouldSkipMutation(uint64_t byseqno, uint16_t vbucket) {
    std::map<uint16_t, ActiveStream*>::iterator itr = streams.find(vbucket);
    if (itr != streams.end() && itr->second->getState() == STREAM_ACTIVE) {
        uint32_t opaque = itr->second->getOpaque();
        if (byseqno >= itr->second->getEndSeqno()) {
            itr->second->setState(STREAM_DEAD);
            itr->second->push(new StreamEndResponse(opaque, 0, vbucket));
            if (byseqno > itr->second->getEndSeqno()) {
                return true;
            }
        }
        return false;
    } else {
        return true;
    }
}

bool UprProducer::isTimeForNoop() {
    // Not Implemented
    return false;
}

void UprProducer::setTimeForNoop() {
    // Not Implemented
}

void UprProducer::clearQueues() {
    LockHolder lh(queueLock);
    std::map<uint16_t, ActiveStream*>::iterator itr = streams.begin();
    for (; itr != streams.end(); ++itr) {
        itr->second->clear();
    }
}

void UprProducer::appendQueue(std::list<queued_item> *q) {
    (void) q;
    abort(); // Not Implemented
}

size_t UprProducer::getBackfillQueueSize() {
    return totalBackfillBacklogs;
}

void UprProducer::completeBackfill() {
    /* Upr connections should not call this function because upr
     * backfills should be scheduled through the BackfillDiskLoad
     * task and not through the BackfillTask. Scheduling through
     * the BackfillDiskLoad task allows the specification of start
     * and end sequence numbers and allows us to schedule one-off
     * backfills.
     */
    abort();
}

void UprProducer::scheduleDiskBackfill() {
    // Not Implemented
}

void UprProducer::completeDiskBackfill() {
    // Not Implemented
}

bool UprProducer::isBackfillCompleted() {
    abort(); // Not Implemented
}

void UprProducer::completeBGFetchJob(Item *item, uint16_t vbid,
                                     bool implicitEnqueue) {
    (void) implicitEnqueue;

    // TODO: This is the wrong way to assign an opaque
    std::map<uint16_t, ActiveStream*>::iterator itr = streams.find(vbid);
    if (itr == streams.end()) {
        return;
    }

    stats.memOverhead.fetch_add(sizeof(Item *));
    assert(stats.memOverhead.load() < GIGANTOR);
    itr->second->push(new MutationResponse(item, itr->second->getOpaque()));
}

bool UprProducer::windowIsFull() {
    abort(); // Not Implemented
}

void UprProducer::flush() {
    abort(); // Not Implemented
}
<|endoftext|>


<commit_before>// $Id$

//**************************************************************************
//* This file is property of and copyright by the ALICE HLT Project        *
//* ALICE Experiment at CERN, All rights reserved.                         *
//*                                                                        *
//* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no>        *
//*                  for The ALICE HLT Project.                            *
//*                                                                        *
//* Permission to use, copy, modify and distribute this software and its   *
//* documentation strictly for non-commercial purposes is hereby granted   *
//* without fee, provided that the above copyright notice appears in all   *
//* copies and that both the copyright notice and this permission notice   *
//* appear in the supporting documentation. The authors make no claims     *
//* about the suitability of this software for any purpose. It is          *
//* provided "as is" without express or implied warranty.                  *
//**************************************************************************

/** @file   AliHLTGlobalAgent.cxx
    @author Matthias Richter
    @date
    @brief  Agent of the libAliHLTGlobal library
*/

#include <cassert>
#include "AliHLTGlobalAgent.h"
#include "AliHLTConfigurationHandler.h"
#include "TObjString.h"
#include "TObjArray.h"
#include "AliHLTGlobalFlatEsdTestComponent.h"

// header files of library components
#include "AliHLTGlobalTrackMergerComponent.h"
#include "AliHLTGlobalCompareFlatComponent.h"
#include "AliHLTGlobalEsdToFlatConverterComponent.h"
#include "AliHLTGlobalFlatEsdConverterComponent.h"
#include "AliHLTGlobalEsdConverterComponent.h"
#include "AliHLTGlobalVertexerComponent.h"
#include "AliHLTGlobalOfflineVertexerComponent.h"
#include "AliHLTV0HistoComponent.h"
#include "AliHLTdNdPtAnalysisComponent.h"
#include "AliHLTdNdPtAnalysisMergerComponent.h"
#include "AliHLTGlobalVertexerHistoComponent.h"
#include "AliHLTGlobalHistoComponent.h"
#include "AliHLTGlobalHistoCollector.h"
#include "AliHLTGlobalDCSPublisherComponent.h"
#include "AliHLTMultiplicityCorrelationsComponent.h"
#include "AliHLTPrimaryVertexFinderComponent.h"
#include "AliHLTV0FinderComponent.h"
#include "AliHLTAnalysisManagerComponent.h"
#include "AliHLTAsyncTestComponent.h"
#include "AliHLTLumiRegComponent.h"
#include "AliHLTGlobalPromptRecoQAComponent.h"
#include "AliHLTRootObjectMergerComponent.h"
#include "AliHLTAsyncCalibrationComponent.h"
#include "AliHLTZeroComponent.h"
#ifdef ZMQ
#include "AliHLTZMQsink.h"
#include "AliHLTZMQsource.h"
#endif

// header file for preprocessor plugin
#include "AliHLTGlobalPreprocessor.h"

#define NOCOMPRESS

/** global instance for agent registration */
AliHLTGlobalAgent gAliHLTGlobalAgent;

/** ROOT macro for the implementation of ROOT specific class methods */
ClassImp(AliHLTGlobalAgent)

AliHLTGlobalAgent::AliHLTGlobalAgent()
  :
  AliHLTModuleAgent("Global")
{
  // see header file for class documentation
  // or
  // refer to README to build package
  // or
  // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
}

AliHLTGlobalAgent::~AliHLTGlobalAgent()
{
  // see header file for class documentation
}

int AliHLTGlobalAgent::RegisterComponents(AliHLTComponentHandler* pHandler) const
{
  // see header file for class documentation
  assert(pHandler);
  if (!pHandler) return -EINVAL;
  pHandler->AddComponent(new AliHLTGlobalEsdToFlatConverterComponent);
  pHandler->AddComponent(new AliHLTGlobalCompareFlatComponent);
  pHandler->AddComponent(new AliHLTGlobalFlatEsdTestComponent);
  pHandler->AddComponent(new AliHLTGlobalTrackMergerComponent);
  pHandler->AddComponent(new AliHLTGlobalFlatEsdConverterComponent);
  pHandler->AddComponent(new AliHLTGlobalEsdConverterComponent);
  pHandler->AddComponent(new AliHLTGlobalVertexerComponent);
  pHandler->AddComponent(new AliHLTGlobalOfflineVertexerComponent);
  pHandler->AddComponent(new AliHLTGlobalVertexerHistoComponent);
  pHandler->AddComponent(new AliHLTGlobalHistoComponent);
  pHandler->AddComponent(new AliHLTV0HistoComponent );
  //pHandler->AddComponent(new AliHLTdNdPtAnalysisComponent );
  //pHandler->AddComponent(new AliHLTdNdPtAnalysisMergerComponent );
  pHandler->AddComponent(new AliHLTMultiplicityCorrelationsComponent );
  pHandler->AddComponent(new AliHLTPrimaryVertexFinderComponent);
  pHandler->AddComponent(new AliHLTV0FinderComponent);
  pHandler->AddComponent(new AliHLTGlobalHistoCollector );
  pHandler->AddComponent(new AliHLTGlobalDCSPublisherComponent );
  pHandler->AddComponent(new AliHLTAnalysisManagerComponent);
  pHandler->AddComponent(new AliHLTAsyncTestComponent);
  pHandler->AddComponent(new AliHLTAsyncCalibrationComponent);
  pHandler->AddComponent(new AliHLTZeroComponent);
  pHandler->AddComponent(new AliHLTLumiRegComponent);
  pHandler->AddComponent(new AliHLTGlobalPromptRecoQAComponent);
  pHandler->AddComponent(new AliHLTRootObjectMergerComponent);
#ifdef ZMQ
  pHandler->AddComponent(new AliHLTZMQsink);
  pHandler->AddComponent(new AliHLTZMQsource);
#endif
  return 0;
}

int AliHLTGlobalAgent::CreateConfigurations(AliHLTConfigurationHandler* pHandler,
					    AliRawReader* /*rawReader*/,
					    AliRunLoader* /*runloader*/) const
{
  // see header file for class documentation
  if (!pHandler) return -EINVAL;
  TObjArray* pTokens=NULL;

  ///////////////////////////////////////////////////////////////////////////////////////////////////
  //
  // global vertexer component
  //
  // define the inputs
  TString vertexerInputs="TPC-globalmerger ITS-tracker";

  // check for the availibility
  pTokens=vertexerInputs.Tokenize(" ");
  vertexerInputs="";
  if (pTokens) {
    for (int n=0; n<pTokens->GetEntriesFast(); n++) {
      TString module=((TObjString*)pTokens->At(n))->GetString();
      if (pHandler->FindConfiguration(module.Data())) {
	vertexerInputs+=module;
	vertexerInputs+=" ";
      }
    }
    delete pTokens;
    pTokens=NULL;
  }
  if (!vertexerInputs.IsNull()) {
    HLTInfo("\n\nConfiguring inputs to global HLT Vertexer: %s\n\n", vertexerInputs.Data());
    pHandler->CreateConfiguration("GLOBAL-vertexer","GlobalVertexer",vertexerInputs,"");
  } else {
    HLTWarning("\n\nNo inputs to global HLT Vertexer found\n\n");
  }

  /////////////////////////////////////////////////////////////////////////////////////
  //
  // assembly of the global ESD

  // define the inputs to the global ESD
  //TString esdInputs="TPC-globalmerger TPC-mcTrackMarker ITS-tracker TPC-HWCFDecoder TPC-ClusterTransformation GLOBAL-vertexer ITS-SPD-vertexer TPC-dEdx VZERO-RECO ITS-SAPtracker TRD-tracker"; //DISABLE GLOBAL VERTEXER TEMPORARILY
  TString esdInputs="TPC-globalmerger TPC-mcTrackMarker ITS-tracker TPC-HWCFDecoder TPC-ClusterTransformation ITS-SPD-vertexer TPC-dEdx VZERO-RECO ITS-SAPtracker TRD-tracker";

  // check for the availibility
  pTokens=esdInputs.Tokenize(" ");
  esdInputs="";
  if (pTokens) {
    for (int n=0; n<pTokens->GetEntriesFast(); n++) {
      TString module=((TObjString*)pTokens->At(n))->GetString();
      if (pHandler->FindConfiguration(module.Data())) {
	esdInputs+=module;
	esdInputs+=" ";
      }
    }
    delete pTokens;
    pTokens=NULL;
  }

  if (esdInputs.Length()>0) {
    esdInputs+=" TPC-HWCFDecoder TPC-ClusterTransformation";
    HLTInfo("Configuring inputs to global HLT ESD: %s", esdInputs.Data());
  } else {
    HLTWarning("No inputs to global HLT ESD found");
  }
#ifdef NOCOMPRESS
  pHandler->CreateConfiguration("GLOBAL-flat-esd-converter", "GlobalFlatEsdConverter", esdInputs.Data(), "-object-compression=0");
  pHandler->CreateConfiguration("GLOBAL-esd-converter", "GlobalEsdConverter", esdInputs.Data(), "-object-compression=0");
  pHandler->CreateConfiguration("GLOBAL-esd-converter-friends", "GlobalEsdConverter", esdInputs.Data(), "-object-compression=0 -make-friends");
  pHandler->CreateConfiguration("GLOBAL-esd-converter-schema", "GlobalEsdConverter", esdInputs.Data(), "-object-compression=0 -schema");
#endif

#ifndef NOCOMPRESS
  pHandler->CreateConfiguration("GLOBAL-flat-esd-converter", "GlobalFlatEsdConverter", esdInputs.Data(), "");
  pHandler->CreateConfiguration("GLOBAL-esd-converter", "GlobalEsdConverter", esdInputs.Data(), "");
  pHandler->CreateConfiguration("GLOBAL-esd-converter-friends", "GlobalEsdConverter", esdInputs.Data(), "-make-friends");
#endif
  pHandler->CreateConfiguration("GLOBAL-flat-esd-test", "GlobalFlatEsdTest", "GLOBAL-esd-converter GLOBAL-flat-esd-converter", "");
  pHandler->CreateConfiguration("esd-to-flat-conversion", "GlobalEsdToFlatConverter", "GLOBAL-esd-converter-friends", "");
  pHandler->CreateConfiguration("compare-flat", "GlobalCompareFlat", "GLOBAL-flat-esd-converter esd-to-flat-conversion", "");

  ///////////////////////////////////////////////////////////////////////////////////////////////////
  //
  // global histograms
  //
  TString vertexhistoInput="GLOBAL-vertexer ITS-SPD-vertexer";

  // check for the availibility
  pTokens=vertexhistoInput.Tokenize(" ");
  vertexhistoInput="";
  if (pTokens) {
    for (int n=0; n<pTokens->GetEntriesFast(); n++) {
      TString module=((TObjString*)pTokens->At(n))->GetString();
      if (pHandler->FindConfiguration(module.Data())) {
	vertexhistoInput+=module;
	vertexhistoInput+=" ";
      }
    }
    delete pTokens;
    pTokens=NULL;
  }

  if (!vertexhistoInput.IsNull()) {
    HLTInfo("Configuring inputs to global HLT Vertex histogram component: %s", vertexhistoInput.Data());
    pHandler->CreateConfiguration("GLOBAL-vertexhisto","GlobalVertexerHisto", vertexhistoInput.Data(),"");
  } else {
    HLTWarning("No inputs to global HLT Vertex histogram component found");
  }

  //pHandler->CreateConfiguration("GLOBAL-dNdPtAnalysis", "dNdPtAnalysis", "GLOBAL-esd-converter", "");

  pHandler->CreateConfiguration("GLOBAL-MultCorr", "MultiplicityCorrelations", "GLOBAL-esd-converter", "");

  return 0;
}

const char* AliHLTGlobalAgent::GetReconstructionChains(AliRawReader* /*rawReader*/,
						    AliRunLoader* runloader) const
{
  // see header file for class documentation
  if (runloader) {
    // reconstruction chains for AliRoot simulation
    // Note: run loader is only available while running embedded into
    // AliRoot simulation
    return "GLOBAL-esd-converter";
  }
  return NULL;
}

const char* AliHLTGlobalAgent::GetRequiredComponentLibraries() const
{
  // see header file for class documentation

  return "";
}

int AliHLTGlobalAgent::GetHandlerDescription(AliHLTComponentDataType /*dt*/,
					     AliHLTUInt32_t /*spec*/,
					     AliHLTOUTHandlerDesc& /*desc*/) const
{
  // see header file for class documentation

  return 0;
}

AliHLTOUTHandler* AliHLTGlobalAgent::GetOutputHandler(AliHLTComponentDataType /*dt*/,
						      AliHLTUInt32_t /*spec*/)
{
  // see header file for class documentation

  return NULL;
}

int AliHLTGlobalAgent::DeleteOutputHandler(AliHLTOUTHandler* pInstance)
{
  // see header file for class documentation
  if (pInstance==NULL) return -EINVAL;

  return 0;
}

AliHLTModulePreprocessor* AliHLTGlobalAgent::GetPreprocessor()
{
  // create the preprocessor plugin
  return new AliHLTGlobalPreprocessor;
}
<commit_msg>remove trd tracking from esd creation by default to not disturb official simulation / reconstruction when we merge hltdev<commit_after>// $Id$

//**************************************************************************
//* This file is property of and copyright by the ALICE HLT Project        *
//* ALICE Experiment at CERN, All rights reserved.                         *
//*                                                                        *
//* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no>        *
//*                  for The ALICE HLT Project.                            *
//*                                                                        *
//* Permission to use, copy, modify and distribute this software and its   *
//* documentation strictly for non-commercial purposes is hereby granted   *
//* without fee, provided that the above copyright notice appears in all   *
//* copies and that both the copyright notice and this permission notice   *
//* appear in the supporting documentation. The authors make no claims     *
//* about the suitability of this software for any purpose. It is          *
//* provided "as is" without express or implied warranty.                  *
//**************************************************************************

/** @file   AliHLTGlobalAgent.cxx
    @author Matthias Richter
    @date
    @brief  Agent of the libAliHLTGlobal library
*/

#include <cassert>
#include "AliHLTGlobalAgent.h"
#include "AliHLTConfigurationHandler.h"
#include "TObjString.h"
#include "TObjArray.h"
#include "AliHLTGlobalFlatEsdTestComponent.h"

// header files of library components
#include "AliHLTGlobalTrackMergerComponent.h"
#include "AliHLTGlobalCompareFlatComponent.h"
#include "AliHLTGlobalEsdToFlatConverterComponent.h"
#include "AliHLTGlobalFlatEsdConverterComponent.h"
#include "AliHLTGlobalEsdConverterComponent.h"
#include "AliHLTGlobalVertexerComponent.h"
#include "AliHLTGlobalOfflineVertexerComponent.h"
#include "AliHLTV0HistoComponent.h"
#include "AliHLTdNdPtAnalysisComponent.h"
#include "AliHLTdNdPtAnalysisMergerComponent.h"
#include "AliHLTGlobalVertexerHistoComponent.h"
#include "AliHLTGlobalHistoComponent.h"
#include "AliHLTGlobalHistoCollector.h"
#include "AliHLTGlobalDCSPublisherComponent.h"
#include "AliHLTMultiplicityCorrelationsComponent.h"
#include "AliHLTPrimaryVertexFinderComponent.h"
#include "AliHLTV0FinderComponent.h"
#include "AliHLTAnalysisManagerComponent.h"
#include "AliHLTAsyncTestComponent.h"
#include "AliHLTLumiRegComponent.h"
#include "AliHLTGlobalPromptRecoQAComponent.h"
#include "AliHLTRootObjectMergerComponent.h"
#include "AliHLTAsyncCalibrationComponent.h"
#include "AliHLTZeroComponent.h"
#ifdef ZMQ
#include "AliHLTZMQsink.h"
#include "AliHLTZMQsource.h"
#endif

// header file for preprocessor plugin
#include "AliHLTGlobalPreprocessor.h"

#define NOCOMPRESS

/** global instance for agent registration */
AliHLTGlobalAgent gAliHLTGlobalAgent;

/** ROOT macro for the implementation of ROOT specific class methods */
ClassImp(AliHLTGlobalAgent)

AliHLTGlobalAgent::AliHLTGlobalAgent()
  :
  AliHLTModuleAgent("Global")
{
  // see header file for class documentation
  // or
  // refer to README to build package
  // or
  // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
}

AliHLTGlobalAgent::~AliHLTGlobalAgent()
{
  // see header file for class documentation
}

int AliHLTGlobalAgent::RegisterComponents(AliHLTComponentHandler* pHandler) const
{
  // see header file for class documentation
  assert(pHandler);
  if (!pHandler) return -EINVAL;
  pHandler->AddComponent(new AliHLTGlobalEsdToFlatConverterComponent);
  pHandler->AddComponent(new AliHLTGlobalCompareFlatComponent);
  pHandler->AddComponent(new AliHLTGlobalFlatEsdTestComponent);
  pHandler->AddComponent(new AliHLTGlobalTrackMergerComponent);
  pHandler->AddComponent(new AliHLTGlobalFlatEsdConverterComponent);
  pHandler->AddComponent(new AliHLTGlobalEsdConverterComponent);
  pHandler->AddComponent(new AliHLTGlobalVertexerComponent);
  pHandler->AddComponent(new AliHLTGlobalOfflineVertexerComponent);
  pHandler->AddComponent(new AliHLTGlobalVertexerHistoComponent);
  pHandler->AddComponent(new AliHLTGlobalHistoComponent);
  pHandler->AddComponent(new AliHLTV0HistoComponent );
  //pHandler->AddComponent(new AliHLTdNdPtAnalysisComponent );
  //pHandler->AddComponent(new AliHLTdNdPtAnalysisMergerComponent );
  pHandler->AddComponent(new AliHLTMultiplicityCorrelationsComponent );
  pHandler->AddComponent(new AliHLTPrimaryVertexFinderComponent);
  pHandler->AddComponent(new AliHLTV0FinderComponent);
  pHandler->AddComponent(new AliHLTGlobalHistoCollector );
  pHandler->AddComponent(new AliHLTGlobalDCSPublisherComponent );
  pHandler->AddComponent(new AliHLTAnalysisManagerComponent);
  pHandler->AddComponent(new AliHLTAsyncTestComponent);
  pHandler->AddComponent(new AliHLTAsyncCalibrationComponent);
  pHandler->AddComponent(new AliHLTZeroComponent);
  pHandler->AddComponent(new AliHLTLumiRegComponent);
  pHandler->AddComponent(new AliHLTGlobalPromptRecoQAComponent);
  pHandler->AddComponent(new AliHLTRootObjectMergerComponent);
#ifdef ZMQ
  pHandler->AddComponent(new AliHLTZMQsink);
  pHandler->AddComponent(new AliHLTZMQsource);
#endif
  return 0;
}

int AliHLTGlobalAgent::CreateConfigurations(AliHLTConfigurationHandler* pHandler,
					    AliRawReader* /*rawReader*/,
					    AliRunLoader* /*runloader*/) const
{
  // see header file for class documentation
  if (!pHandler) return -EINVAL;
  TObjArray* pTokens=NULL;

  ///////////////////////////////////////////////////////////////////////////////////////////////////
  //
  // global vertexer component
  //
  // define the inputs
  TString vertexerInputs="TPC-globalmerger ITS-tracker";

  // check for the availibility
  pTokens=vertexerInputs.Tokenize(" ");
  vertexerInputs="";
  if (pTokens) {
    for (int n=0; n<pTokens->GetEntriesFast(); n++) {
      TString module=((TObjString*)pTokens->At(n))->GetString();
      if (pHandler->FindConfiguration(module.Data())) {
	vertexerInputs+=module;
	vertexerInputs+=" ";
      }
    }
    delete pTokens;
    pTokens=NULL;
  }
  if (!vertexerInputs.IsNull()) {
    HLTInfo("\n\nConfiguring inputs to global HLT Vertexer: %s\n\n", vertexerInputs.Data());
    pHandler->CreateConfiguration("GLOBAL-vertexer","GlobalVertexer",vertexerInputs,"");
  } else {
    HLTWarning("\n\nNo inputs to global HLT Vertexer found\n\n");
  }

  /////////////////////////////////////////////////////////////////////////////////////
  //
  // assembly of the global ESD

  // define the inputs to the global ESD
  //TString esdInputs="TPC-globalmerger TPC-mcTrackMarker ITS-tracker TPC-HWCFDecoder TPC-ClusterTransformation GLOBAL-vertexer ITS-SPD-vertexer TPC-dEdx VZERO-RECO ITS-SAPtracker TRD-tracker"; // TRD-tracker removed temporarily while it is still developed, DISABLE GLOBAL VERTEXER TEMPORARILY
  TString esdInputs="TPC-globalmerger TPC-mcTrackMarker ITS-tracker TPC-HWCFDecoder TPC-ClusterTransformation ITS-SPD-vertexer TPC-dEdx VZERO-RECO ITS-SAPtracker"; // TRD-tracker removed temporarily while it is still developed

  // check for the availibility
  pTokens=esdInputs.Tokenize(" ");
  esdInputs="";
  if (pTokens) {
    for (int n=0; n<pTokens->GetEntriesFast(); n++) {
      TString module=((TObjString*)pTokens->At(n))->GetString();
      if (pHandler->FindConfiguration(module.Data())) {
	esdInputs+=module;
	esdInputs+=" ";
      }
    }
    delete pTokens;
    pTokens=NULL;
  }

  if (esdInputs.Length()>0) {
    esdInputs+=" TPC-HWCFDecoder TPC-ClusterTransformation";
    HLTInfo("Configuring inputs to global HLT ESD: %s", esdInputs.Data());
  } else {
    HLTWarning("No inputs to global HLT ESD found");
  }
#ifdef NOCOMPRESS
  pHandler->CreateConfiguration("GLOBAL-flat-esd-converter", "GlobalFlatEsdConverter", esdInputs.Data(), "-object-compression=0");
  pHandler->CreateConfiguration("GLOBAL-esd-converter", "GlobalEsdConverter", esdInputs.Data(), "-object-compression=0");
  pHandler->CreateConfiguration("GLOBAL-esd-converter-friends", "GlobalEsdConverter", esdInputs.Data(), "-object-compression=0 -make-friends");
  pHandler->CreateConfiguration("GLOBAL-esd-converter-schema", "GlobalEsdConverter", esdInputs.Data(), "-object-compression=0 -schema");
#endif

#ifndef NOCOMPRESS
  pHandler->CreateConfiguration("GLOBAL-flat-esd-converter", "GlobalFlatEsdConverter", esdInputs.Data(), "");
  pHandler->CreateConfiguration("GLOBAL-esd-converter", "GlobalEsdConverter", esdInputs.Data(), "");
  pHandler->CreateConfiguration("GLOBAL-esd-converter-friends", "GlobalEsdConverter", esdInputs.Data(), "-make-friends");
#endif
  pHandler->CreateConfiguration("GLOBAL-flat-esd-test", "GlobalFlatEsdTest", "GLOBAL-esd-converter GLOBAL-flat-esd-converter", "");
  pHandler->CreateConfiguration("esd-to-flat-conversion", "GlobalEsdToFlatConverter", "GLOBAL-esd-converter-friends", "");
  pHandler->CreateConfiguration("compare-flat", "GlobalCompareFlat", "GLOBAL-flat-esd-converter esd-to-flat-conversion", "");

  ///////////////////////////////////////////////////////////////////////////////////////////////////
  //
  // global histograms
  //
  TString vertexhistoInput="GLOBAL-vertexer ITS-SPD-vertexer";

  // check for the availibility
  pTokens=vertexhistoInput.Tokenize(" ");
  vertexhistoInput="";
  if (pTokens) {
    for (int n=0; n<pTokens->GetEntriesFast(); n++) {
      TString module=((TObjString*)pTokens->At(n))->GetString();
      if (pHandler->FindConfiguration(module.Data())) {
	vertexhistoInput+=module;
	vertexhistoInput+=" ";
      }
    }
    delete pTokens;
    pTokens=NULL;
  }

  if (!vertexhistoInput.IsNull()) {
    HLTInfo("Configuring inputs to global HLT Vertex histogram component: %s", vertexhistoInput.Data());
    pHandler->CreateConfiguration("GLOBAL-vertexhisto","GlobalVertexerHisto", vertexhistoInput.Data(),"");
  } else {
    HLTWarning("No inputs to global HLT Vertex histogram component found");
  }

  //pHandler->CreateConfiguration("GLOBAL-dNdPtAnalysis", "dNdPtAnalysis", "GLOBAL-esd-converter", "");

  pHandler->CreateConfiguration("GLOBAL-MultCorr", "MultiplicityCorrelations", "GLOBAL-esd-converter", "");

  return 0;
}

const char* AliHLTGlobalAgent::GetReconstructionChains(AliRawReader* /*rawReader*/,
						    AliRunLoader* runloader) const
{
  // see header file for class documentation
  if (runloader) {
    // reconstruction chains for AliRoot simulation
    // Note: run loader is only available while running embedded into
    // AliRoot simulation
    return "GLOBAL-esd-converter";
  }
  return NULL;
}

const char* AliHLTGlobalAgent::GetRequiredComponentLibraries() const
{
  // see header file for class documentation

  return "";
}

int AliHLTGlobalAgent::GetHandlerDescription(AliHLTComponentDataType /*dt*/,
					     AliHLTUInt32_t /*spec*/,
					     AliHLTOUTHandlerDesc& /*desc*/) const
{
  // see header file for class documentation

  return 0;
}

AliHLTOUTHandler* AliHLTGlobalAgent::GetOutputHandler(AliHLTComponentDataType /*dt*/,
						      AliHLTUInt32_t /*spec*/)
{
  // see header file for class documentation

  return NULL;
}

int AliHLTGlobalAgent::DeleteOutputHandler(AliHLTOUTHandler* pInstance)
{
  // see header file for class documentation
  if (pInstance==NULL) return -EINVAL;

  return 0;
}

AliHLTModulePreprocessor* AliHLTGlobalAgent::GetPreprocessor()
{
  // create the preprocessor plugin
  return new AliHLTGlobalPreprocessor;
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Emilian Cioca
#include "Jewel3D/Precompiled.h"
#include "RenderPass.h"
#include "Camera.h"
#include "Material.h"
#include "Primitives.h"
#include "RenderTarget.h"
#include "Rendering.h"
#include "Viewport.h"
#include "Jewel3D/Application/Application.h"
#include "Jewel3D/Application/Logging.h"
#include "Jewel3D/Entity/Entity.h"
#include "Jewel3D/Entity/EntityGroup.h"
#include "Jewel3D/Math/Math.h"
#include "Jewel3D/Math/Transform.h"
#include "Jewel3D/Resource/Font.h"
#include "Jewel3D/Resource/Model.h"
#include "Jewel3D/Resource/Shader.h"
#include "Jewel3D/Resource/Texture.h"
#include "Jewel3D/Resource/UniformBuffer.h"
// Renderables
#include "Mesh.h"
#include "ParticleEmitter.h"
#include "Sprite.h"
#include "Text.h"

#include <GLEW/GL/glew.h>

namespace Jwl
{
	RenderPass::RenderPass()
	{
		CreateUniformBuffer();
	}

	RenderPass::RenderPass(const RenderPass& other)
	{
		CreateUniformBuffer();
		*this = other;
	}

	RenderPass& RenderPass::operator=(const RenderPass& other)
	{
		viewport = other.viewport;
		camera = other.camera;
		target = other.target;
		shader = other.shader;
		skybox = other.skybox;

		return *this;
	}

	void RenderPass::SetCamera(Entity::Ptr cam)
	{
		ASSERT(cam, "'cam' cannot be a nullptr.");
		ASSERT(cam->Has<Camera>(), "'cam' must have a camera component.");

		camera = cam;
	}

	void RenderPass::SetShader(Shader::Ptr program)
	{
		shader = program;
	}

	void RenderPass::SetTarget(RenderTarget::Ptr _target)
	{
		target = _target;
	}

	void RenderPass::SetViewport(const Viewport& vp)
	{
		viewport = &vp;
	}

	void RenderPass::SetSkybox(Texture::Ptr sky)
	{
		ASSERT(sky->IsCubeMap(), "'sky' must be a cubemap texture.");

		skybox = sky;
	}

	Entity::Ptr RenderPass::GetCamera() const
	{
		return camera;
	}

	Shader::Ptr RenderPass::GetShader() const
	{
		return shader;
	}

	RenderTarget::Ptr RenderPass::GetTarget() const
	{
		return target;
	}

	const Viewport* RenderPass::GetViewport() const
	{
		return viewport;
	}

	Texture::Ptr RenderPass::GetSkybox() const
	{
		return skybox;
	}

	void RenderPass::Bind()
	{
		if (target)
		{
			target->Bind();
		}

		if (viewport)
		{
			viewport->bind();
		}
		else if (target)
		{
			target->GetViewport().bind();
		}
		else
		{
			Application.GetScreenViewport().bind();
		}

		if (camera)
		{
			camera->Get<Camera>().Bind();
		}

		textures.Bind();
		buffers.Bind();
	}

	void RenderPass::UnBind()
	{
		glBindVertexArray(GL_NONE);

		// UnBind override shader.
		if (shader)
		{
			shader->UnBind();
		}

		textures.UnBind();
		buffers.UnBind();

		if (target)
		{
			RenderTarget::UnBind();
		}

		if (camera != nullptr)
		{
			Camera::UnBind();
		}
	}

	void RenderPass::PostProcess()
	{
		ASSERT(shader != nullptr, "RenderPass must have a Shader attached if it is a post-processing pass.");
		ASSERT(Primitives.IsLoaded(), "Primitives system must be initialized in order to render a post-processing pass.");

		Bind();

		SetBlendFunc(BlendFunc::None);
		SetDepthFunc(DepthFunc::None);

		MVP.Set(mat4::Identity);
		modelView.Set(mat4::Identity);
		model.Set(mat4::Identity);
		invModel.Set(mat4::Identity);
		normalMatrix.Set(mat4::Identity);
		transformBuffer.Bind(static_cast<unsigned>(UniformBufferSlot::Model));

		Primitives.DrawFullScreenQuad(*shader);

		if (skybox)
		{
			Primitives.DrawSkyBox(*skybox);
		}

		UnBind();
	}

	void RenderPass::Render(const Entity& root)
	{
		Bind();

		RenderEntityRecursive(root);

		if (skybox)
		{
			Primitives.DrawSkyBox(*skybox);
		}

		UnBind();
	}

	void RenderPass::Render(const EntityGroup& group)
	{
		Bind();

		for (auto& entity : group.GetEntities())
		{
			RenderEntity(*entity);
		}

		if (skybox)
		{
			Primitives.DrawSkyBox(*skybox);
		}

		UnBind();
	}

	void RenderPass::RenderEntity(const Entity& ent)
	{
		if (!ent.IsEnabled())
		{
			return;
		}

		auto material = ent.Try<Material>();
		if (!material || !material->IsEnabled())
		{
			return;
		}

		auto mesh = ent.Try<Mesh>();
		auto text = ent.Try<Text>();
		auto emitter = ent.Try<ParticleEmitter>();
		auto sprite = ent.Try<Sprite>();
		ASSERT(mesh || text || emitter || sprite, "Entity must have a renderable component.");

		// Bind override shader.
		if (shader)
		{
			material->BindState();
			shader->Bind();
		}
		else
		{
			ASSERT(material->shader != nullptr, "Renderable Entity does not have a Shader and the RenderPass does not have an override attached.");
			material->Bind();
		}

		// Update transform uniforms.
		mat4 worldTransform = ent.GetWorldTransform();

		if (camera)
		{
			auto& cameraComponent = camera->Get<Camera>();

			MVP.Set(cameraComponent.GetViewProjMatrix() * worldTransform);
			modelView.Set(cameraComponent.GetViewMatrix() * worldTransform);
		}
		else
		{
			MVP.Set(mat4::Identity);
			modelView.Set(mat4::Identity);
		}

		model.Set(worldTransform);
		invModel.Set(worldTransform.GetFastInverse());

		if (ent.scale == vec3(1.0f))
		{
			normalMatrix.Set(worldTransform);
		}
		else
		{
			normalMatrix.Set(worldTransform.GetInverse().GetTranspose());
		}

		transformBuffer.Bind(static_cast<unsigned>(UniformBufferSlot::Model));

#pragma region Render Model
		if (mesh && mesh->IsComponentEnabled())
		{
			// Capture pointer to current mesh data.
			auto modelData = mesh->model;
			ASSERT(modelData, "Entity has a Mesh component but does not have a Model to render.");

			glBindVertexArray(modelData->GetVAO());
			glDrawArrays(GL_TRIANGLES, 0, modelData->GetNumVerticies());
		}
#pragma endregion

#pragma region Render Text
		if (text && text->IsComponentEnabled())
		{
			auto font = text->font;
			ASSERT(font != nullptr, "Entity has a Text component but does not have a Font to render with.");

			auto dimensions = font->GetDimensions();
			auto positions = font->GetPositions();
			auto advances = font->GetAdvances();
			auto masks = font->GetMasks();

			// We have to send the vertices of each character we render. We'll store them here.
			float points[18] =
			{
				0.0f, 0.0f, 0.0f,
				0.0f, 0.0f, 0.0f,
				0.0f, 0.0f, 0.0f,

				0.0f, 0.0f, 0.0f,
				0.0f, 0.0f, 0.0f,
				0.0f, 0.0f, 0.0f,
			};

			const vec3 advanceDirection = text->owner.GetWorldTransform().GetRight();
			const vec3 upDirection = text->owner.GetWorldTransform().GetUp();
			const vec3 initialPosition = text->owner.position;
			vec3 linePosition = text->owner.position;
			unsigned currentLine = 1;

			if (text->centeredX)
			{
				text->owner.position -= advanceDirection * (((text->GetLineWidth(currentLine) + text->kernel * text->text.size())) / 2.0f);
			}

			if (text->centeredY)
			{
				text->owner.position -= upDirection * ((font->GetStringHeight() * static_cast<float>(text->GetNumLines())) / 2.0f);
			}

			glBindVertexArray(Font::GetVAO());
			glBindBuffer(GL_ARRAY_BUFFER, Font::GetVBO());

			for (unsigned i = 0; i < text->text.size(); ++i)
			{
				char character = text->text[i];
				unsigned charIndex = static_cast<unsigned>(character) - '!';

				// Handle whitespace.
				if (character == ' ')
				{
					text->owner.position += advanceDirection * (font->GetStringWidth("Z") + text->kernel);
					continue;
				}
				else if (character == '\n')
				{
					linePosition += -upDirection * static_cast<float>(font->GetStringHeight()) * 1.33f;
					text->owner.position = linePosition;
					currentLine++;

					if (text->centeredX)
					{
						text->owner.position -= advanceDirection * (((text->GetLineWidth(currentLine) + text->kernel * text->text.size())) / 2.0f);
					}

					continue;
				}
				else if (character == '\t')
				{
					text->owner.position += advanceDirection * (font->GetStringWidth("Z") + text->kernel) * 4;
					continue;
				}

				if (!masks[charIndex])
				{
					// Character does not exist in this font. Advance to next character.
					text->owner.position += advanceDirection * ((advances[charIndex].x + text->kernel));
					continue;
				}

				/* Adjusts the node's position based on the character. */
				vec3 characterPosition;
				characterPosition += advanceDirection * static_cast<float>(positions[charIndex].x);
				characterPosition += upDirection * static_cast<float>(positions[charIndex].y);
				text->owner.position += characterPosition;

				/* Construct a polygon based on the current character's dimensions. */
				points[3] = static_cast<float>(dimensions[charIndex].x);
				points[7] = static_cast<float>(dimensions[charIndex].y);
				points[9] = static_cast<float>(dimensions[charIndex].x);
				points[12] = static_cast<float>(dimensions[charIndex].x);
				points[13] = static_cast<float>(dimensions[charIndex].y);
				points[16] = static_cast<float>(dimensions[charIndex].y);

				/* Update buffers with the new polygon. */
				glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float) * 18, points);

				/* Render */
				// TODO: these sends' are duplicated. get rid of them!
				if (camera)
				{
					auto& cameraComponent = camera->Get<Camera>();

					MVP.Set(cameraComponent.GetViewProjMatrix() * text->owner.GetWorldTransform());
					modelView.Set(cameraComponent.GetViewMatrix() * text->owner.GetWorldTransform());
				}
				else
				{
					MVP.Set(mat4::Identity);
					modelView.Set(mat4::Identity);
				}
				model.Set(text->owner.GetWorldTransform());
				invModel.Set(text->owner.GetWorldTransform().GetFastInverse());
				transformBuffer.Bind(static_cast<unsigned>(UniformBufferSlot::Model));

				glBindTexture(GL_TEXTURE_2D, font->GetTextures()[charIndex]);
				glDrawArrays(GL_TRIANGLES, 0, 6);

				/* Adjust position for the next node. */
				// Undo character translate.
				text->owner.position -= characterPosition;
				// Advance to next character.
				text->owner.position += advanceDirection * ((advances[charIndex].x + text->kernel));
			}

			glBindBuffer(GL_ARRAY_BUFFER, GL_NONE);

			text->owner.position = initialPosition;
		}
#pragma endregion

#pragma region Render Particles
		if (emitter && emitter->IsComponentEnabled() && emitter->GetNumAliveParticles() > 0)
		{
			emitter->GetBuffer().Bind(static_cast<unsigned>(UniformBufferSlot::Particle));

			glBindVertexArray(emitter->GetVAO());
			glDrawArrays(GL_POINTS, 0, emitter->GetNumAliveParticles());
		}
#pragma endregion

#pragma region Render Sprite
		if (sprite && sprite->IsComponentEnabled())
		{
			ASSERT(Primitives.IsLoaded(), "Primitives system must be initialized in order to render sprites.");

			Primitives.DrawUnitRectangle();
		}
#pragma endregion

		material->UnBind();
	}

	void RenderPass::RenderEntityRecursive(const Entity& ent)
	{
		RenderEntity(ent);

		for (auto& child : ent.GetChildren())
		{
			RenderEntityRecursive(*child);
		}
	}

	void RenderPass::CreateUniformBuffer()
	{
		MVP = transformBuffer.AddUniform<mat4>("MVP");
		modelView = transformBuffer.AddUniform<mat4>("ModelView");
		model = transformBuffer.AddUniform<mat4>("Model");
		invModel = transformBuffer.AddUniform<mat4>("InvModel");
		normalMatrix = transformBuffer.AddUniform<mat4>("normal");

		transformBuffer.InitBuffer();
	}
}
<commit_msg>Fixed font's texture binding unit not being deterministic<commit_after>// Copyright (c) 2017 Emilian Cioca
#include "Jewel3D/Precompiled.h"
#include "RenderPass.h"
#include "Camera.h"
#include "Material.h"
#include "Primitives.h"
#include "RenderTarget.h"
#include "Rendering.h"
#include "Viewport.h"
#include "Jewel3D/Application/Application.h"
#include "Jewel3D/Application/Logging.h"
#include "Jewel3D/Entity/Entity.h"
#include "Jewel3D/Entity/EntityGroup.h"
#include "Jewel3D/Math/Math.h"
#include "Jewel3D/Math/Transform.h"
#include "Jewel3D/Resource/Font.h"
#include "Jewel3D/Resource/Model.h"
#include "Jewel3D/Resource/Shader.h"
#include "Jewel3D/Resource/Texture.h"
#include "Jewel3D/Resource/UniformBuffer.h"
// Renderables
#include "Mesh.h"
#include "ParticleEmitter.h"
#include "Sprite.h"
#include "Text.h"

#include <GLEW/GL/glew.h>

namespace Jwl
{
	RenderPass::RenderPass()
	{
		CreateUniformBuffer();
	}

	RenderPass::RenderPass(const RenderPass& other)
	{
		CreateUniformBuffer();
		*this = other;
	}

	RenderPass& RenderPass::operator=(const RenderPass& other)
	{
		viewport = other.viewport;
		camera = other.camera;
		target = other.target;
		shader = other.shader;
		skybox = other.skybox;

		return *this;
	}

	void RenderPass::SetCamera(Entity::Ptr cam)
	{
		ASSERT(cam, "'cam' cannot be a nullptr.");
		ASSERT(cam->Has<Camera>(), "'cam' must have a camera component.");

		camera = cam;
	}

	void RenderPass::SetShader(Shader::Ptr program)
	{
		shader = program;
	}

	void RenderPass::SetTarget(RenderTarget::Ptr _target)
	{
		target = _target;
	}

	void RenderPass::SetViewport(const Viewport& vp)
	{
		viewport = &vp;
	}

	void RenderPass::SetSkybox(Texture::Ptr sky)
	{
		ASSERT(sky->IsCubeMap(), "'sky' must be a cubemap texture.");

		skybox = sky;
	}

	Entity::Ptr RenderPass::GetCamera() const
	{
		return camera;
	}

	Shader::Ptr RenderPass::GetShader() const
	{
		return shader;
	}

	RenderTarget::Ptr RenderPass::GetTarget() const
	{
		return target;
	}

	const Viewport* RenderPass::GetViewport() const
	{
		return viewport;
	}

	Texture::Ptr RenderPass::GetSkybox() const
	{
		return skybox;
	}

	void RenderPass::Bind()
	{
		if (target)
		{
			target->Bind();
		}

		if (viewport)
		{
			viewport->bind();
		}
		else if (target)
		{
			target->GetViewport().bind();
		}
		else
		{
			Application.GetScreenViewport().bind();
		}

		if (camera)
		{
			camera->Get<Camera>().Bind();
		}

		textures.Bind();
		buffers.Bind();
	}

	void RenderPass::UnBind()
	{
		glBindVertexArray(GL_NONE);

		// UnBind override shader.
		if (shader)
		{
			shader->UnBind();
		}

		textures.UnBind();
		buffers.UnBind();

		if (target)
		{
			RenderTarget::UnBind();
		}

		if (camera != nullptr)
		{
			Camera::UnBind();
		}
	}

	void RenderPass::PostProcess()
	{
		ASSERT(shader != nullptr, "RenderPass must have a Shader attached if it is a post-processing pass.");
		ASSERT(Primitives.IsLoaded(), "Primitives system must be initialized in order to render a post-processing pass.");

		Bind();

		SetBlendFunc(BlendFunc::None);
		SetDepthFunc(DepthFunc::None);

		MVP.Set(mat4::Identity);
		modelView.Set(mat4::Identity);
		model.Set(mat4::Identity);
		invModel.Set(mat4::Identity);
		normalMatrix.Set(mat4::Identity);
		transformBuffer.Bind(static_cast<unsigned>(UniformBufferSlot::Model));

		Primitives.DrawFullScreenQuad(*shader);

		if (skybox)
		{
			Primitives.DrawSkyBox(*skybox);
		}

		UnBind();
	}

	void RenderPass::Render(const Entity& root)
	{
		Bind();

		RenderEntityRecursive(root);

		if (skybox)
		{
			Primitives.DrawSkyBox(*skybox);
		}

		UnBind();
	}

	void RenderPass::Render(const EntityGroup& group)
	{
		Bind();

		for (auto& entity : group.GetEntities())
		{
			RenderEntity(*entity);
		}

		if (skybox)
		{
			Primitives.DrawSkyBox(*skybox);
		}

		UnBind();
	}

	void RenderPass::RenderEntity(const Entity& ent)
	{
		if (!ent.IsEnabled())
		{
			return;
		}

		auto material = ent.Try<Material>();
		if (!material || !material->IsEnabled())
		{
			return;
		}

		auto mesh = ent.Try<Mesh>();
		auto text = ent.Try<Text>();
		auto emitter = ent.Try<ParticleEmitter>();
		auto sprite = ent.Try<Sprite>();
		ASSERT(mesh || text || emitter || sprite, "Entity must have a renderable component.");

		// Bind override shader.
		if (shader)
		{
			material->BindState();
			shader->Bind();
		}
		else
		{
			ASSERT(material->shader != nullptr, "Renderable Entity does not have a Shader and the RenderPass does not have an override attached.");
			material->Bind();
		}

		// Update transform uniforms.
		mat4 worldTransform = ent.GetWorldTransform();

		if (camera)
		{
			auto& cameraComponent = camera->Get<Camera>();

			MVP.Set(cameraComponent.GetViewProjMatrix() * worldTransform);
			modelView.Set(cameraComponent.GetViewMatrix() * worldTransform);
		}
		else
		{
			MVP.Set(mat4::Identity);
			modelView.Set(mat4::Identity);
		}

		model.Set(worldTransform);
		invModel.Set(worldTransform.GetFastInverse());

		if (ent.scale == vec3(1.0f))
		{
			normalMatrix.Set(worldTransform);
		}
		else
		{
			normalMatrix.Set(worldTransform.GetInverse().GetTranspose());
		}

		transformBuffer.Bind(static_cast<unsigned>(UniformBufferSlot::Model));

#pragma region Render Model
		if (mesh && mesh->IsComponentEnabled())
		{
			// Capture pointer to current mesh data.
			auto modelData = mesh->model;
			ASSERT(modelData, "Entity has a Mesh component but does not have a Model to render.");

			glBindVertexArray(modelData->GetVAO());
			glDrawArrays(GL_TRIANGLES, 0, modelData->GetNumVerticies());
		}
#pragma endregion

#pragma region Render Text
		if (text && text->IsComponentEnabled())
		{
			auto font = text->font;
			ASSERT(font != nullptr, "Entity has a Text component but does not have a Font to render with.");

			auto dimensions = font->GetDimensions();
			auto positions = font->GetPositions();
			auto advances = font->GetAdvances();
			auto masks = font->GetMasks();

			// We have to send the vertices of each character we render. We'll store them here.
			float points[18] =
			{
				0.0f, 0.0f, 0.0f,
				0.0f, 0.0f, 0.0f,
				0.0f, 0.0f, 0.0f,

				0.0f, 0.0f, 0.0f,
				0.0f, 0.0f, 0.0f,
				0.0f, 0.0f, 0.0f,
			};

			const vec3 advanceDirection = text->owner.GetWorldTransform().GetRight();
			const vec3 upDirection = text->owner.GetWorldTransform().GetUp();
			const vec3 initialPosition = text->owner.position;
			vec3 linePosition = text->owner.position;
			unsigned currentLine = 1;

			if (text->centeredX)
			{
				text->owner.position -= advanceDirection * (((text->GetLineWidth(currentLine) + text->kernel * text->text.size())) / 2.0f);
			}

			if (text->centeredY)
			{
				text->owner.position -= upDirection * ((font->GetStringHeight() * static_cast<float>(text->GetNumLines())) / 2.0f);
			}

			glBindVertexArray(Font::GetVAO());
			glBindBuffer(GL_ARRAY_BUFFER, Font::GetVBO());
			glActiveTexture(GL_TEXTURE0);

			for (unsigned i = 0; i < text->text.size(); ++i)
			{
				char character = text->text[i];
				unsigned charIndex = static_cast<unsigned>(character) - '!';

				// Handle whitespace.
				if (character == ' ')
				{
					text->owner.position += advanceDirection * (font->GetStringWidth("Z") + text->kernel);
					continue;
				}
				else if (character == '\n')
				{
					linePosition += -upDirection * static_cast<float>(font->GetStringHeight()) * 1.33f;
					text->owner.position = linePosition;
					currentLine++;

					if (text->centeredX)
					{
						text->owner.position -= advanceDirection * (((text->GetLineWidth(currentLine) + text->kernel * text->text.size())) / 2.0f);
					}

					continue;
				}
				else if (character == '\t')
				{
					text->owner.position += advanceDirection * (font->GetStringWidth("Z") + text->kernel) * 4;
					continue;
				}

				if (!masks[charIndex])
				{
					// Character does not exist in this font. Advance to next character.
					text->owner.position += advanceDirection * ((advances[charIndex].x + text->kernel));
					continue;
				}

				/* Adjusts the node's position based on the character. */
				vec3 characterPosition;
				characterPosition += advanceDirection * static_cast<float>(positions[charIndex].x);
				characterPosition += upDirection * static_cast<float>(positions[charIndex].y);
				text->owner.position += characterPosition;

				/* Construct a polygon based on the current character's dimensions. */
				points[3] = static_cast<float>(dimensions[charIndex].x);
				points[7] = static_cast<float>(dimensions[charIndex].y);
				points[9] = static_cast<float>(dimensions[charIndex].x);
				points[12] = static_cast<float>(dimensions[charIndex].x);
				points[13] = static_cast<float>(dimensions[charIndex].y);
				points[16] = static_cast<float>(dimensions[charIndex].y);

				/* Update buffers with the new polygon. */
				glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float) * 18, points);

				/* Render */
				// TODO: these sends' are duplicated. get rid of them!
				if (camera)
				{
					auto& cameraComponent = camera->Get<Camera>();

					MVP.Set(cameraComponent.GetViewProjMatrix() * text->owner.GetWorldTransform());
					modelView.Set(cameraComponent.GetViewMatrix() * text->owner.GetWorldTransform());
				}
				else
				{
					MVP.Set(mat4::Identity);
					modelView.Set(mat4::Identity);
				}
				model.Set(text->owner.GetWorldTransform());
				invModel.Set(text->owner.GetWorldTransform().GetFastInverse());
				transformBuffer.Bind(static_cast<unsigned>(UniformBufferSlot::Model));

				glBindTexture(GL_TEXTURE_2D, font->GetTextures()[charIndex]);
				glDrawArrays(GL_TRIANGLES, 0, 6);

				/* Adjust position for the next node. */
				// Undo character translate.
				text->owner.position -= characterPosition;
				// Advance to next character.
				text->owner.position += advanceDirection * ((advances[charIndex].x + text->kernel));
			}

			glBindBuffer(GL_ARRAY_BUFFER, GL_NONE);

			text->owner.position = initialPosition;
		}
#pragma endregion

#pragma region Render Particles
		if (emitter && emitter->IsComponentEnabled() && emitter->GetNumAliveParticles() > 0)
		{
			emitter->GetBuffer().Bind(static_cast<unsigned>(UniformBufferSlot::Particle));

			glBindVertexArray(emitter->GetVAO());
			glDrawArrays(GL_POINTS, 0, emitter->GetNumAliveParticles());
		}
#pragma endregion

#pragma region Render Sprite
		if (sprite && sprite->IsComponentEnabled())
		{
			ASSERT(Primitives.IsLoaded(), "Primitives system must be initialized in order to render sprites.");

			Primitives.DrawUnitRectangle();
		}
#pragma endregion

		material->UnBind();
	}

	void RenderPass::RenderEntityRecursive(const Entity& ent)
	{
		RenderEntity(ent);

		for (auto& child : ent.GetChildren())
		{
			RenderEntityRecursive(*child);
		}
	}

	void RenderPass::CreateUniformBuffer()
	{
		MVP = transformBuffer.AddUniform<mat4>("MVP");
		modelView = transformBuffer.AddUniform<mat4>("ModelView");
		model = transformBuffer.AddUniform<mat4>("Model");
		invModel = transformBuffer.AddUniform<mat4>("InvModel");
		normalMatrix = transformBuffer.AddUniform<mat4>("normal");

		transformBuffer.InitBuffer();
	}
}
<|endoftext|>


<commit_before>/*

Copyright (c) 2003, Magnus Jonsson & Arvid Norberg
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 author 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.

*/

#include "libtorrent/file.hpp"
#include "libtorrent/utf8.hpp"

#include <sstream>
#include <windows.h>

namespace
{
	// must be used to not leak memory in case something would throw
	class auto_localfree
	{
	public:
		auto_localfree(HLOCAL memory)
			: m_memory(memory)
		{
		}
		~auto_localfree()
		{
			if (m_memory)
				LocalFree(m_memory);
		}
	private:
		HLOCAL m_memory;
	};

	std::string utf8_native(std::string const& s)
	{
		std::wstring ws;
		libtorrent::utf8_wchar(s, ws);
		std::size_t size = wcstombs(0, ws.c_str(), 0);
		if (size == std::size_t(-1)) return s;
		std::string ret(size + 1);
		size = wcstombs(&ret[0], ws.c_str(), size + 1);
		ret.resize(size - 1);
		return ret;
	}

	void throw_exception(const char* thrower)
	{
		DWORD err = GetLastError();

#ifdef UNICODE
		wchar_t *wbuffer = 0;
		FormatMessage(
			FORMAT_MESSAGE_FROM_SYSTEM
			|FORMAT_MESSAGE_ALLOCATE_BUFFER
			, 0, err, 0, (LPWSTR)&wbuffer, 0, 0);
		auto_localfree auto_free(wbuffer);
		std::string tmp_utf8;
		libtorrent::wchar_utf8(wbuffer, tmp_utf8);
		char const* buffer = tmp_utf8.c_str();
#else
		char* buffer = 0;
		FormatMessage(
			FORMAT_MESSAGE_FROM_SYSTEM
			|FORMAT_MESSAGE_ALLOCATE_BUFFER
			, 0, err, 0, (LPSTR)&buffer, 0, 0);
		auto_localfree auto_free(buffer);
#endif

		std::stringstream s;
		s << (thrower ? thrower : "NULL") << ": " << (buffer ? buffer : "NULL");

		throw libtorrent::file_error(s.str());
	}
}

namespace libtorrent
{

	struct file::impl : boost::noncopyable
	{
		enum open_flags
		{
			read_flag = 1,
			write_flag = 2
		};

		enum seek_mode
		{
			seek_begin = FILE_BEGIN,
			seek_from_here = FILE_CURRENT,
			seek_end = FILE_END
		};

		impl()
		{
			m_file_handle = INVALID_HANDLE_VALUE;
		}

		void open(const char *file_name, open_flags flags)
		{
			assert(file_name);
			assert(flags & (read_flag | write_flag));

			DWORD access_mask = 0;
			if (flags & read_flag)
				access_mask |= GENERIC_READ;
			if (flags & write_flag)
				access_mask |= GENERIC_WRITE;

			assert(access_mask & (GENERIC_READ | GENERIC_WRITE));

		#ifdef UNICODE
			std::wstring wfile_name(utf8_wchar(file_name));
			HANDLE new_handle = CreateFile(
				(LPCWSTR)wfile_name.c_str()
				, access_mask
				, FILE_SHARE_READ
				, 0
				, (flags & write_flag)?OPEN_ALWAYS:OPEN_EXISTING
				, FILE_ATTRIBUTE_NORMAL
				, 0);
		#else
			HANDLE new_handle = CreateFile(
				utf8_native(file_name).c_str()
				, access_mask
				, FILE_SHARE_READ
				, 0
				, (flags & write_flag)?OPEN_ALWAYS:OPEN_EXISTING
				, FILE_ATTRIBUTE_NORMAL
				, 0);
		#endif

			if (new_handle == INVALID_HANDLE_VALUE)
			{
				std::stringstream s;
				throw_exception(file_name);
			}
			// will only close old file if the open succeeded
			close();
			m_file_handle = new_handle;
		}

		void close()
		{
			if (m_file_handle != INVALID_HANDLE_VALUE)
			{
				CloseHandle(m_file_handle);
				m_file_handle = INVALID_HANDLE_VALUE;
			}
		}

		~impl()
		{
			close();
		}

		size_type write(const char* buffer, size_type num_bytes)
		{
			assert(buffer);
			assert(num_bytes > 0);
			assert((DWORD)num_bytes == num_bytes);
			DWORD bytes_written = 0;
			if (num_bytes != 0)
			{
				if (FALSE == WriteFile(
					m_file_handle
					, buffer
					, (DWORD)num_bytes
					, &bytes_written
					, 0))
				{
					throw_exception("file::write");
				}
			}
			return bytes_written;
		}

		size_type read(char* buffer, size_type num_bytes)
		{
			assert(buffer);
			assert(num_bytes > 0);
			assert((DWORD)num_bytes == num_bytes);

			DWORD bytes_read = 0;
			if (num_bytes != 0)
			{
				if (FALSE == ReadFile(
					m_file_handle
					, buffer
					, (DWORD)num_bytes
					, &bytes_read
					, 0))
				{
					throw_exception("file::read");
				}
			}
			return bytes_read;
		}

		void seek(size_type pos, seek_mode from_where)
		{
			assert(pos >= 0 || from_where != seek_begin);
			assert(pos <= 0 || from_where != seek_end);
			LARGE_INTEGER offs;
			offs.QuadPart = pos;
			if (FALSE == SetFilePointerEx(
				m_file_handle
				, offs
				, &offs
				, from_where))
			{
				throw_exception("file::seek");
			}
		}

		size_type tell()
		{
			LARGE_INTEGER offs;
			offs.QuadPart = 0;

			// is there any other way to get offset?
			if (FALSE == SetFilePointerEx(
				m_file_handle
				, offs
				, &offs
				, FILE_CURRENT))
			{
				throw_exception("file::tell");
			}

			size_type pos=offs.QuadPart;
			assert(pos>=0);
			return pos;
		}
/*
		size_type size()
		{
			LARGE_INTEGER s;
			if (FALSE == GetFileSizeEx(m_file_handle, &s))
			{
				throw_exception("file::size");
			}

			size_type size = s.QuadPart;
			assert(size >= 0);
			return size;
		}
*/
	private:

		HANDLE m_file_handle;

	};
}

namespace libtorrent
{

	const file::seek_mode file::begin(file::impl::seek_begin);
	const file::seek_mode file::end(file::impl::seek_end);

	const file::open_mode file::in(file::impl::read_flag);
	const file::open_mode file::out(file::impl::write_flag);

	file::file()
		: m_impl(new libtorrent::file::impl())
	{
	}
	file::file(boost::filesystem::path const& p, open_mode m)
		: m_impl(new libtorrent::file::impl())
	{
		open(p,m);
	}

	file::~file()
	{
	}

	void file::open(boost::filesystem::path const& p, open_mode m)
	{
		assert(p.is_complete());
		m_impl->open(p.native_file_string().c_str(), impl::open_flags(m.m_mask));
	}

	void file::close()
	{
		m_impl->close();
	}

	size_type file::write(const char* buffer, size_type num_bytes)
	{
		return m_impl->write(buffer, num_bytes);
	}

	size_type file::read(char* buffer, size_type num_bytes)
	{
		return m_impl->read(buffer, num_bytes);
	}

	void file::seek(size_type pos, seek_mode m)
	{
		m_impl->seek(pos,impl::seek_mode(m.m_val));
	}

	size_type file::tell()
	{
		return m_impl->tell();
	}
}
<commit_msg>*** empty log message ***<commit_after>/*

Copyright (c) 2003, Magnus Jonsson & Arvid Norberg
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 author 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.

*/

#include "libtorrent/file.hpp"
#include "libtorrent/utf8.hpp"

#include <sstream>
#include <windows.h>

namespace
{
	// must be used to not leak memory in case something would throw
	class auto_localfree
	{
	public:
		auto_localfree(HLOCAL memory)
			: m_memory(memory)
		{
		}
		~auto_localfree()
		{
			if (m_memory)
				LocalFree(m_memory);
		}
	private:
		HLOCAL m_memory;
	};

	std::string utf8_native(std::string const& s)
	{
		std::wstring ws;
		libtorrent::utf8_wchar(s, ws);
		std::size_t size = wcstombs(0, ws.c_str(), 0);
		if (size == std::size_t(-1)) return s;
		std::string ret;
		ret.resize(size);
		size = wcstombs(&ret[0], ws.c_str(), size + 1);
		ret.resize(size);
		return ret;
	}

	void throw_exception(const char* thrower)
	{
		DWORD err = GetLastError();

#ifdef UNICODE
		wchar_t *wbuffer = 0;
		FormatMessage(
			FORMAT_MESSAGE_FROM_SYSTEM
			|FORMAT_MESSAGE_ALLOCATE_BUFFER
			, 0, err, 0, (LPWSTR)&wbuffer, 0, 0);
		auto_localfree auto_free(wbuffer);
		std::string tmp_utf8;
		libtorrent::wchar_utf8(wbuffer, tmp_utf8);
		char const* buffer = tmp_utf8.c_str();
#else
		char* buffer = 0;
		FormatMessage(
			FORMAT_MESSAGE_FROM_SYSTEM
			|FORMAT_MESSAGE_ALLOCATE_BUFFER
			, 0, err, 0, (LPSTR)&buffer, 0, 0);
		auto_localfree auto_free(buffer);
#endif

		std::stringstream s;
		s << (thrower ? thrower : "NULL") << ": " << (buffer ? buffer : "NULL");

		throw libtorrent::file_error(s.str());
	}
}

namespace libtorrent
{

	struct file::impl : boost::noncopyable
	{
		enum open_flags
		{
			read_flag = 1,
			write_flag = 2
		};

		enum seek_mode
		{
			seek_begin = FILE_BEGIN,
			seek_from_here = FILE_CURRENT,
			seek_end = FILE_END
		};

		impl()
		{
			m_file_handle = INVALID_HANDLE_VALUE;
		}

		void open(const char *file_name, open_flags flags)
		{
			assert(file_name);
			assert(flags & (read_flag | write_flag));

			DWORD access_mask = 0;
			if (flags & read_flag)
				access_mask |= GENERIC_READ;
			if (flags & write_flag)
				access_mask |= GENERIC_WRITE;

			assert(access_mask & (GENERIC_READ | GENERIC_WRITE));

		#ifdef UNICODE
			std::wstring wfile_name(utf8_wchar(file_name));
			HANDLE new_handle = CreateFile(
				(LPCWSTR)wfile_name.c_str()
				, access_mask
				, FILE_SHARE_READ
				, 0
				, (flags & write_flag)?OPEN_ALWAYS:OPEN_EXISTING
				, FILE_ATTRIBUTE_NORMAL
				, 0);
		#else
			HANDLE new_handle = CreateFile(
				utf8_native(file_name).c_str()
				, access_mask
				, FILE_SHARE_READ
				, 0
				, (flags & write_flag)?OPEN_ALWAYS:OPEN_EXISTING
				, FILE_ATTRIBUTE_NORMAL
				, 0);
		#endif

			if (new_handle == INVALID_HANDLE_VALUE)
			{
				std::stringstream s;
				throw_exception(file_name);
			}
			// will only close old file if the open succeeded
			close();
			m_file_handle = new_handle;
		}

		void close()
		{
			if (m_file_handle != INVALID_HANDLE_VALUE)
			{
				CloseHandle(m_file_handle);
				m_file_handle = INVALID_HANDLE_VALUE;
			}
		}

		~impl()
		{
			close();
		}

		size_type write(const char* buffer, size_type num_bytes)
		{
			assert(buffer);
			assert(num_bytes > 0);
			assert((DWORD)num_bytes == num_bytes);
			DWORD bytes_written = 0;
			if (num_bytes != 0)
			{
				if (FALSE == WriteFile(
					m_file_handle
					, buffer
					, (DWORD)num_bytes
					, &bytes_written
					, 0))
				{
					throw_exception("file::write");
				}
			}
			return bytes_written;
		}

		size_type read(char* buffer, size_type num_bytes)
		{
			assert(buffer);
			assert(num_bytes > 0);
			assert((DWORD)num_bytes == num_bytes);

			DWORD bytes_read = 0;
			if (num_bytes != 0)
			{
				if (FALSE == ReadFile(
					m_file_handle
					, buffer
					, (DWORD)num_bytes
					, &bytes_read
					, 0))
				{
					throw_exception("file::read");
				}
			}
			return bytes_read;
		}

		void seek(size_type pos, seek_mode from_where)
		{
			assert(pos >= 0 || from_where != seek_begin);
			assert(pos <= 0 || from_where != seek_end);
			LARGE_INTEGER offs;
			offs.QuadPart = pos;
			if (FALSE == SetFilePointerEx(
				m_file_handle
				, offs
				, &offs
				, from_where))
			{
				throw_exception("file::seek");
			}
		}

		size_type tell()
		{
			LARGE_INTEGER offs;
			offs.QuadPart = 0;

			// is there any other way to get offset?
			if (FALSE == SetFilePointerEx(
				m_file_handle
				, offs
				, &offs
				, FILE_CURRENT))
			{
				throw_exception("file::tell");
			}

			size_type pos=offs.QuadPart;
			assert(pos>=0);
			return pos;
		}
/*
		size_type size()
		{
			LARGE_INTEGER s;
			if (FALSE == GetFileSizeEx(m_file_handle, &s))
			{
				throw_exception("file::size");
			}

			size_type size = s.QuadPart;
			assert(size >= 0);
			return size;
		}
*/
	private:

		HANDLE m_file_handle;

	};
}

namespace libtorrent
{

	const file::seek_mode file::begin(file::impl::seek_begin);
	const file::seek_mode file::end(file::impl::seek_end);

	const file::open_mode file::in(file::impl::read_flag);
	const file::open_mode file::out(file::impl::write_flag);

	file::file()
		: m_impl(new libtorrent::file::impl())
	{
	}
	file::file(boost::filesystem::path const& p, open_mode m)
		: m_impl(new libtorrent::file::impl())
	{
		open(p,m);
	}

	file::~file()
	{
	}

	void file::open(boost::filesystem::path const& p, open_mode m)
	{
		assert(p.is_complete());
		m_impl->open(p.native_file_string().c_str(), impl::open_flags(m.m_mask));
	}

	void file::close()
	{
		m_impl->close();
	}

	size_type file::write(const char* buffer, size_type num_bytes)
	{
		return m_impl->write(buffer, num_bytes);
	}

	size_type file::read(char* buffer, size_type num_bytes)
	{
		return m_impl->read(buffer, num_bytes);
	}

	void file::seek(size_type pos, seek_mode m)
	{
		m_impl->seek(pos,impl::seek_mode(m.m_val));
	}

	size_type file::tell()
	{
		return m_impl->tell();
	}
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2006-2008 Marc Boris Duerner
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * As a special exception, you may use this file as part of a free
 * software library without restriction. Specifically, if other files
 * instantiate templates or use macros or inline functions from this
 * file, or you compile this file and link it with other files to
 * produce an executable, this file does not by itself cause the
 * resulting executable to be covered by the GNU General Public
 * License. This exception does not however invalidate any other
 * reasons why the executable file might be covered by the GNU Library
 * General Public License.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
#include "fileimpl.h"
#include "directoryimpl.h"
#include "cxxtools/fileinfo.h"
#include "cxxtools/directory.h"
#include "cxxtools/datetime.h"
#include "cxxtools/timespan.h"
#include "cxxtools/systemerror.h"

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

namespace cxxtools
{

static FileInfo::Type doGetType(const std::string& path)
{
    struct stat st;
    if( 0 != ::lstat(path.c_str(), &st) )
    {
        if (errno == ENOENT || errno == ENOTDIR)
            return FileInfo::Invalid;
        else
            throw SystemError(("lstat(" + path + ')').c_str());
    }

    if( S_ISDIR(st.st_mode) )
    {
        return FileInfo::Directory;
    }
    else if( S_ISCHR(st.st_mode) )
    {
        return FileInfo::Chardev;
    }
    else if( S_ISBLK(st.st_mode) )
    {
        return FileInfo::Blockdev;
    }
    else if( S_ISFIFO(st.st_mode) )
    {
        return FileInfo::Fifo;
    }
    else if( S_ISLNK(st.st_mode) )
    {
        return FileInfo::Symlink;
    }
    else if( S_ISSOCK(st.st_mode) )
    {
        return FileInfo::Socket;
    }

    return FileInfo::File;
}

static struct stat doStat(const std::string& path)
{
    struct stat st;
    if (::stat(path.c_str(), &st) == -1)
    {
        if (errno == ENOENT)
            throw FileNotFound(path);
        else
            throw SystemError(("stat(" + path + ')').c_str());
    }

    return st;
}

FileInfo::FileInfo()
: _type(FileInfo::Invalid)
{}

FileInfo::FileInfo(const std::string& path)
: _path(path)
{
    _type = doGetType( path );
}

FileInfo::FileInfo(const DirectoryIterator& it)
: _path(it.path())
{
    _type = doGetType( _path );
}

std::string FileInfo::name() const
{
    std::string::size_type pos = _path.rfind( DirectoryImpl::sep() );

    if (pos != std::string::npos)
    {
        return _path.substr(pos + 1);
    }
    else
    {
        return _path;
    }
}

std::string FileInfo::dirName() const
{
    // Find last slash. This separates the file name from the path.
    std::string::size_type pos = _path.find_last_of( DirectoryImpl::sep() );

    // If there is no separator, the file is relative to the current
    // directory. So an empty path is returned.
    if (pos == std::string::npos)
    {
        return "";
    }

    // Include trailing separator to be able to distinguish between no
    // path ("") and a path which is relative to the root ("/"), for example.
    return _path.substr(0, pos + 1);
}

std::size_t FileInfo::size() const
{
    if(_type == FileInfo::File || _type == FileInfo::Symlink)
    {
        return FileImpl::size( _path );
    }

    return 0;
}

UtcDateTime FileInfo::mtime() const
{
    return mtime(_path);
}

UtcDateTime FileInfo::ctime() const
{
    return ctime(_path);
}

bool FileInfo::isReadingAllowed() const
{
    return isReadingAllowed(_path);
}

bool FileInfo::isWritingAllowed() const
{
    return isWritingAllowed(_path);
}

void FileInfo::remove()
{
    if (_type == FileInfo::Directory)
        DirectoryImpl::remove(_path);
    else
        FileImpl::remove(_path);
    _type = FileInfo::Invalid;
}

void FileInfo::move(const std::string& to)
{
    if(_type == FileInfo::Directory)
        return DirectoryImpl::move(_path, to);
    else
        return FileImpl::move(_path, to);
}

FileInfo& FileInfo::operator+= (const FileInfo& path)
{
    if (_path.empty())
        _path = path.path();
    else if (path.path().empty())
        ;
    else if (_path.back() == DirectoryImpl::sep())
    {
        if (path.path().front() == DirectoryImpl::sep())
            _path += path.path().substr(1);
        else
            _path += path.path();
    }
    else if (path.path().front() == DirectoryImpl::sep())
        _path += path.path();
    else
    {
        _path += DirectoryImpl::sep();
        _path += path.path();
    }

    return *this;
}

bool FileInfo::exists(const std::string& path)
{
    return FileInfo::getType( path ) != FileInfo::Invalid;
}

FileInfo::Type FileInfo::getType(const std::string& path)
{
    return doGetType( path );
}

UtcDateTime FileInfo::mtime(const std::string& path)
{
    struct stat st = doStat(path);

    return DateTime::fromMSecsSinceEpoch(
        Seconds(st.st_mtim.tv_sec)
            + Microseconds(st.st_mtim.tv_nsec / 1000));
}

UtcDateTime FileInfo::ctime(const std::string& path)
{
    struct stat st = doStat(path);

    return DateTime::fromMSecsSinceEpoch(
        Seconds(st.st_ctim.tv_sec)
            + Microseconds(st.st_ctim.tv_nsec / 1000));
}

bool FileInfo::isReadingAllowed(const std::string& path)
{
    struct stat st = doStat(path);
    return (st.st_mode | S_IRUSR) != 0;
}

bool FileInfo::isWritingAllowed(const std::string& path)
{
    struct stat st = doStat(path);
    return (st.st_mode | S_IWUSR) != 0;
}

} // namespace cxxtools
<commit_msg>fix cxxtools::FileINfo::isReadingAllowed and isWritingAllowed<commit_after>/*
 * Copyright (C) 2006-2008 Marc Boris Duerner
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * As a special exception, you may use this file as part of a free
 * software library without restriction. Specifically, if other files
 * instantiate templates or use macros or inline functions from this
 * file, or you compile this file and link it with other files to
 * produce an executable, this file does not by itself cause the
 * resulting executable to be covered by the GNU General Public
 * License. This exception does not however invalidate any other
 * reasons why the executable file might be covered by the GNU Library
 * General Public License.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
#include "fileimpl.h"
#include "directoryimpl.h"
#include "cxxtools/fileinfo.h"
#include "cxxtools/directory.h"
#include "cxxtools/datetime.h"
#include "cxxtools/timespan.h"
#include "cxxtools/systemerror.h"

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

namespace cxxtools
{

static FileInfo::Type doGetType(const std::string& path)
{
    struct stat st;
    if( 0 != ::lstat(path.c_str(), &st) )
    {
        if (errno == ENOENT || errno == ENOTDIR)
            return FileInfo::Invalid;
        else
            throw SystemError(("lstat(" + path + ')').c_str());
    }

    if( S_ISDIR(st.st_mode) )
    {
        return FileInfo::Directory;
    }
    else if( S_ISCHR(st.st_mode) )
    {
        return FileInfo::Chardev;
    }
    else if( S_ISBLK(st.st_mode) )
    {
        return FileInfo::Blockdev;
    }
    else if( S_ISFIFO(st.st_mode) )
    {
        return FileInfo::Fifo;
    }
    else if( S_ISLNK(st.st_mode) )
    {
        return FileInfo::Symlink;
    }
    else if( S_ISSOCK(st.st_mode) )
    {
        return FileInfo::Socket;
    }

    return FileInfo::File;
}

static struct stat doStat(const std::string& path)
{
    struct stat st;
    if (::stat(path.c_str(), &st) == -1)
    {
        if (errno == ENOENT)
            throw FileNotFound(path);
        else
            throw SystemError(("stat(" + path + ')').c_str());
    }

    return st;
}

FileInfo::FileInfo()
: _type(FileInfo::Invalid)
{}

FileInfo::FileInfo(const std::string& path)
: _path(path)
{
    _type = doGetType( path );
}

FileInfo::FileInfo(const DirectoryIterator& it)
: _path(it.path())
{
    _type = doGetType( _path );
}

std::string FileInfo::name() const
{
    std::string::size_type pos = _path.rfind( DirectoryImpl::sep() );

    if (pos != std::string::npos)
    {
        return _path.substr(pos + 1);
    }
    else
    {
        return _path;
    }
}

std::string FileInfo::dirName() const
{
    // Find last slash. This separates the file name from the path.
    std::string::size_type pos = _path.find_last_of( DirectoryImpl::sep() );

    // If there is no separator, the file is relative to the current
    // directory. So an empty path is returned.
    if (pos == std::string::npos)
    {
        return "";
    }

    // Include trailing separator to be able to distinguish between no
    // path ("") and a path which is relative to the root ("/"), for example.
    return _path.substr(0, pos + 1);
}

std::size_t FileInfo::size() const
{
    if(_type == FileInfo::File || _type == FileInfo::Symlink)
    {
        return FileImpl::size( _path );
    }

    return 0;
}

UtcDateTime FileInfo::mtime() const
{
    return mtime(_path);
}

UtcDateTime FileInfo::ctime() const
{
    return ctime(_path);
}

bool FileInfo::isReadingAllowed() const
{
    return isReadingAllowed(_path);
}

bool FileInfo::isWritingAllowed() const
{
    return isWritingAllowed(_path);
}

void FileInfo::remove()
{
    if (_type == FileInfo::Directory)
        DirectoryImpl::remove(_path);
    else
        FileImpl::remove(_path);
    _type = FileInfo::Invalid;
}

void FileInfo::move(const std::string& to)
{
    if(_type == FileInfo::Directory)
        return DirectoryImpl::move(_path, to);
    else
        return FileImpl::move(_path, to);
}

FileInfo& FileInfo::operator+= (const FileInfo& path)
{
    if (_path.empty())
        _path = path.path();
    else if (path.path().empty())
        ;
    else if (_path.back() == DirectoryImpl::sep())
    {
        if (path.path().front() == DirectoryImpl::sep())
            _path += path.path().substr(1);
        else
            _path += path.path();
    }
    else if (path.path().front() == DirectoryImpl::sep())
        _path += path.path();
    else
    {
        _path += DirectoryImpl::sep();
        _path += path.path();
    }

    return *this;
}

bool FileInfo::exists(const std::string& path)
{
    return FileInfo::getType( path ) != FileInfo::Invalid;
}

FileInfo::Type FileInfo::getType(const std::string& path)
{
    return doGetType( path );
}

UtcDateTime FileInfo::mtime(const std::string& path)
{
    struct stat st = doStat(path);

    return DateTime::fromMSecsSinceEpoch(
        Seconds(st.st_mtim.tv_sec)
            + Microseconds(st.st_mtim.tv_nsec / 1000));
}

UtcDateTime FileInfo::ctime(const std::string& path)
{
    struct stat st = doStat(path);

    return DateTime::fromMSecsSinceEpoch(
        Seconds(st.st_ctim.tv_sec)
            + Microseconds(st.st_ctim.tv_nsec / 1000));
}

bool FileInfo::isReadingAllowed(const std::string& path)
{
    struct stat st = doStat(path);
    return (st.st_mode & S_IRUSR) != 0;
}

bool FileInfo::isWritingAllowed(const std::string& path)
{
    struct stat st = doStat(path);
    return (st.st_mode & S_IWUSR) != 0;
}

} // namespace cxxtools
<|endoftext|>